参考于:
有别于我之前写的文章,这个方法对DLL貌似并不适用,猜测Windows上dll并不算是文件句柄,没办法被NtQuerySystemInformation识别到
之前的文章:
底下是使用方法:
查看文件是否其他进程占用
METHOD:
主要使用BOOL FindFileHandle(LPCTSTR lpName, vector& handles); 底下定义tstring类似于wstring,说实在我对这块不清楚,可能为了配合WINAPI才define这个数据类型,毕竟底下很多API和数据类型和枚举变量都被Windows藏起来了
PARAMETER:
LPCTSTR lpName:输入值,文件的完整地址
vector& handles:输出值,存储着占用文件的进程详细信息的容器
RETURN:
成功为1,失败为0
WARNING:
函数要遍历所有文件句柄,找出与文件路径匹配的文件句柄,并通过文件句柄找到占用他的进程句柄,所以耗时很久,常规要一秒到两秒左右,谨慎使用
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include [span style=//代码效果参考:http://www.lyjsj.net.cn/wz/art_23801.html
"color: rgba(0, 0, 255, 1)">string#include
#include
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "shlwapi")
using namespace std;
typedef std::basic_string
#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof((array)【0】))
#endif
EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax);
EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax);
#ifdef UNICODE
#define GetFilePathFromHandle GetFilePathFromHandleW
#else
#define GetFilePathFromHandle GetFilePathFromHandleA
#endif
#define NT_SUCCESS(status) (status == (NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define SystemHandleInformation ((SYSTEM_INFORMATION_CLASS)16)
// NTQUERYOBJECT
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
WCHAR NameBuffer【1】;
} OBJECT_NAME_INFORMATION, POBJECT_NAME_INFORMATION;
//winternl.h中以定义,微软未放出134的定义,需自己手动定义
typedef enum _OBJECT_INFORMATION_CLASS_SELFDEFINE {
//ObjectBasicInformation,
ObjectNameInformation=1,
//ObjectTypeInformation,
ObjectAllInformation=3,
ObjectDataInformation=4
} OBJECT_INFORMATION_CLASS_SELFDEFINE, POBJECT_INFORMATION_CLASS_SELFDEFINE;
typedef NTSTATUS(WINAPI NTQUERYOBJECT)(
_Inopt HANDLE Handle,
In OBJECT_INFORMATION_CLASS_SELFDEFINE ObjectInformationClass,
_Outopt PVOID ObjectInformation,
In ULONG ObjectInformationLength,
_Outopt PULONG ReturnLength);
// NTQUERYSYSTEMINFORMATION
typedef struct _SYSTEM_HANDLE {
DWORD dwProcessId;
BYTE bObjectType;
BYTE bFlags;
WORD wValue;
PVOID pAddress;
DWORD GrantedAccess;
} SYSTEM_HANDLE, PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION {
DWORD dwCount;
SYSTEM_HANDLE Handles【1】;
} SYSTEM_HANDLE_INFORMATION, PSYSTEM_HANDLE_INFORMATION;
typedef NTSTATUS(WINAPI NTQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);
//typedef struct _IO_STATUS_BLOCK {
// LONG Status;
// LONG Information;
//} IO_STATUS_BLOCK, PIO_STATUS_BLOCK;
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName【MAX_PATH】;
} FILE_NAME_INFORMATION;
declspec(dllimport) LONG stdcall ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN ULONG FileInformationClass
);
typedef LONG(__stdcall PFN_ZwQueryInformationFile) (
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN ULONG FileInformationClass
);
//
// NtQueryInformationFile
//
#define FileNameInformation ((FILE_INFORMATION_CLASS)9)
// typedef struct _FILE_NAME_INFORMATION {
// ULONG FileNameLength;
// WCHAR FileName【1】;
// } FILE_NAME_INFORMATION, PFILE_NAME_INFORMATION;
typedef NTSTATUS(WINAPI NTQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
// typedef struct _CLIENT_ID {
// HANDLE UniqueProcess;
// HANDLE UniqueThread;
// } CLIENT_ID, PCLIENT_ID;
// ncScopedHandle
class ncScopedHandle
{
ncScopedHandle(const ncScopedHandle&);
ncScopedHandle& operator=(const ncScopedHandle&);
public:
ncScopedHandle(HANDLE handle)
: _handle(handle)
{
}
~ncScopedHandle()
{
if (_handle != NULL) {
CloseHandle(_handle);
}
}
operator HANDLE() const
{
return _handle;
}
PHANDLE operator& ()
{
return &_handle;
}
void operator=(HANDLE handle)
{
if (_handle != NULL) {
CloseHandle(_handle);
}
_handle = handle;
}
private:
HANDLE _handle;
};
// ncFileHandle
struct ncFileHandle
{
SYSTEM_HANDLE _handle;//占用文件的进程句柄详细信息
tstring _filePath;//文件的完整路径,tstring等同于wstring
tstring _path;//占用进程的程序磁盘位置
ncFileHandle(SYSTEM_HANDLE handle, const tstring& filePath, const tstring& path)
: _handle(handle)
, _filePath(filePath)
, _path(path)
{
}
};
//根据文件句柄获取文件所在磁盘名
EXTERN_C BOOL GetVolumeNameByHandle(HANDLE hFile, LPWSTR szVolumeName, UINT cchMax)
{
BOOL bResult = FALSE;
WCHAR szBuf【500】 = { 0 };
WCHAR pIter = szBuf;
int i = 0;
BY_HANDLE_FILE_INFORMATION stFileInfo = { 0 };
do
{
if (FALSE == GetFileInformationByHandle(hFile, &stFileInfo)) {
break;
}
if (0 == GetLogicalDriveStringsW(_countof(szBuf), szBuf)) {
break;
}
for (; pIter; pIter += 4)
{
DWORD dwVolumeSerialNumber = 0;
if (GetVolumeInformationW(pIter, NULL, 0, &dwVolumeSerialNumber,
NULL, NULL, NULL, 0))
{
if (dwVolumeSerialNumber == stFileInfo.dwVolumeSerialNumber)
{
lstrcpynW(szVolumeName, pIter, cchMax);
bResult = TRUE;
break;
}
}
}
} while (FALSE);
return bResult;
}
EXTERN_C BOOL GetFilePathFromHandleW(HANDLE hFile, LPWSTR lpszPath, UINT cchMax)
{
BOOL bResult = FALSE;
WCHAR szValue【MAX_PATH】 = { 0 };
IO_STATUS_BLOCK isb = { 0 };
FILE_NAME_INFORMATION fni = { 0 };
HMODULE hNtDLL = NULL;
PFN_ZwQueryInformationFile pfn_ZwQueryInformationFile = NULL;
do
{
if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {
break;
}
hNtDLL = LoadLibraryW(L"ntdll.dll");
if (hNtDLL == NULL)
{
break;
}
pfn_ZwQueryInformationFile = (PFN_ZwQueryInformationFile)GetProcAddress(hNtDLL, "ZwQueryInformationFile");
if (NULL == pfn_ZwQueryInformationFile) {
break;
}
// 9 == FileNameInformation
if (0 != pfn_ZwQueryInformationFile(hFile, &isb, &fni, sizeof(fni), 9)) {
break;
}
if (FALSE == GetVolumeNameByHandle(hFile, szValue, _countof(szValue))) {
break;
}
PathAppendW(szValue, fni.FileName);
lstrcpynW(lpszPath, szValue, cchMax);
bResult = TRUE;
} while (FALSE);
return bResult;
}
EXTERN_C BOOL GetFilePathFromHandleA(HANDLE hFile, LPSTR lpszPath, UINT cchMax)
{
BOOL bResult = FALSE;
WCHAR szTmep【MAX_PATH】 = { 0 };
do
{
if (INVALID_HANDLE_VALUE == hFile || NULL == lpszPath || 0 == cchMax) {
break;
}
if (FALSE == GetFilePathFromHandleW(hFile, szTmep, _countof(szTmep))) {
break;
}
if (0 == WideCharToMultiByte(CP_ACP, 0,
szTmep, lstrlenW(szTmep),
lpszPath, cchMax, NULL, NULL))
{
break;
}
bResult = TRUE;
} while (FALSE);
return bResult;
}
// GetDeviceDriveMap
void GetDeviceDriveMap(std::map& mapDeviceDrive)
{
TCHAR szDrives【512】;
if (!GetLogicalDriveStrings(_countof(szDrives) - 1, szDrives)) {
return;
}
TCHAR lpDrives = szDrives;
TCHAR szDevice【MAX_PATH】;
TCHAR szDrive【3】 = _T(" :");
do {
szDrive = lpDrives;
if (QueryDosDevice(szDrive, szDevice, MAX_PATH)) {
mapDeviceDrive【szDevice】 = szDrive;
}
while (lpDrives++);
} while (lpDrives);
}
// DevicePathToDrivePath
BOOL DevicePathToDrivePath(tstring& path)
{
static std::map mapDeviceDrive;
if (mapDeviceDrive.empty()) {
GetDeviceDriveMap(mapDeviceDrive);
}
for (std::map::const_iterator it = mapDeviceDrive.begin(); it != mapDeviceDrive.end(); ++it) {
size_t nLength = it->first.length();
if (_tcsnicmp(it->first.c_str(), path.c_str(), nLength) == 0) {
path.replace(0, nLength, it->second);
return TRUE;
}
}
return FALSE;
}
// GetHandlePath
BOOL GetHandlePath(HANDLE handle, tstring& path)
{
static NTQUERYOBJECT fpNtQueryObject =
(NTQUERYOBJECT)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryObject");
if (fpNtQueryObject == NULL) {
return FALSE;
}
DWORD dwLength = 0;
OBJECT_NAME_INFORMATION info;
NTSTATUS status = fpNtQueryObject(handle, ObjectNameInformation, &info, sizeof(info), &dwLength);
if (status != STATUS_BUFFER_OVERFLOW) {
return FALSE;
}
POBJECT_NAME_INFORMATION pInfo = (POBJECT_NAME_INFORMATION)malloc(dwLength);
while (true) {
status = fpNtQueryObject(handle, ObjectNameInformation, pInfo, dwLength, &dwLength);
if (status != STATUS_BUFFER_OVERFLOW) {
break;
}
pInfo = (POBJECT_NAME_INFORMATION)realloc(pInfo, dwLength);
}
BOOL bRes = FALSE;
if (NT_SUCCESS(status)) {
path = pInfo->Name.Buffer;
bRes = DevicePathToDrivePath(path);
}
free(pInfo);
return bRes;
}
// GetSystemHandleInfo
PSYSTEM_HANDLE_INFORMATION GetSystemHandleInfo()
{
static NTQUERYSYSTEMINFORMATION fpNtQuerySystemInformation =
(NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQuerySystemInformation");
if (fpNtQuerySystemInformation == NULL) {
return NULL;
}
DWORD dwLength = 0;
SYSTEM_HANDLE_INFORMATION shi;
NTSTATUS status = fpNtQuerySystemInformation(SystemHandleInformation, &shi, sizeof(shi), &dwLength);
if (status != STATUS_INFO_LENGTH_MISMATCH) {
return NULL;
}
PSYSTEM_HANDLE_INFORMATION pshi = (PSYSTEM_HANDLE_INFORMATION)malloc(dwLength);
while (true) {
status = fpNtQuerySystemInformation(SystemHandleInformation, pshi, dwLength, &dwLength);
if (status != STATUS_INFO_LENGTH_MISMATCH) {
break;
}
pshi = (PSYSTEM_HANDLE_INFORMATION)realloc(pshi, dwLength);
}
if (!NT_SUCCESS(status)) {
free(pshi);
pshi = NULL;
}
return pshi;
}
//
// 检测指定句柄是否可能导致NtQueryObject卡死:
// 1.注意必须使用NtQueryInformationFile而不是NtQueryObject进行检测,否则可能导致WinXP系统
// 下进程死锁而无法结束。
//
void CheckBlockThreadFunc(void param)
{
static NTQUERYINFORMATIONFILE fpNtQueryInformationFile =
(NTQUERYINFORMATIONFILE)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationFile");
if (fpNtQueryInformationFile != NULL) {
BYTE buf【1024】;
IO_STATUS_BLOCK ioStatus;
fpNtQueryInformationFile((HANDLE)param, &ioStatus, buf, 1024, FileNameInformation);
}
}
// IsBlockingHandle
BOOL IsBlockingHandle(HANDLE handle)
{
HANDLE hThread = (HANDLE)_beginthread(CheckBlockThreadFunc, 0, (void*<span style="