Winapi:获取具有特定文件句柄的进程

目前我有一个软件,它有一个文件filter驱动程序,在安装软件时,驱动程序以这种方式启动服务:

CreateService(serviceManager, name, displayName, SERVICE_START | DELETE | SERVICE_QUERY_STATUS | SERVICE_STOP, SERVICE_FILE_SYSTEM_DRIVER, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, NULL, NULL, NULL, NULL, NULL); 

其中path是C:\Program Files(x86)\TSU\driver\TSUfsd.sys

我遇到的问题是在卸载软件的过程中。 当软件试图删除TSUfsd.sys文件时,它使我拒绝访问。

我已经检查过软件是如何删除驱动程序的,并且使用DeleteService函数删除它,并等待服务将其状态从SERVICE_STOP_PENDING更改为SERVICE_STOPPED ,如果在一段时间之后没有发生,则获取服务PID和使用ProcessTerminate杀死它,然后尝试使用rmdir /S /QC:\Program Files(x86)\TSU\删除该文件。

我试图find可能有文件句柄(使用Process Explorer)的进程,但是找不到任何文件。 然后我想也许这个服务还活着,所以我input了sc query TSUfsd但是服务也没有了。

我也尝试更改权限并将完全权限授予我的用户,但同样的错误仍然发生。

所以我的问题是:

  1. 有没有其他的方法来检查哪个进程(或其他)可以拥有一个文件?

  2. 我也注意到,每当我尝试用Cygwin( rm TSUfsd.sys )删除文件时,它都会删除文件,而不会出现问题。 用cmddel /f <filename> )和cygwin删除文件有什么区别?

Solutions Collecting From Web of "Winapi:获取具有特定文件句柄的进程"

对于这个任务,从Windows Vista开始特别存在FileProcessIdsUsingFileInformation FILE_INFORMATION_CLASS

所以我们需要使用FILE_READ_ATTRIBUTES打开文件(即使有人用0共享模式打开文件,如果我们无法访问文件(通过它DACL ),但是具有对父目录的读取访问权,也可以这样做)。 并用FileProcessIdsUsingFileInformation调用FileProcessIdsUsingFileInformation 。 在返回时,我们得到了FILE_PROCESS_IDS_USING_FILE_INFORMATION结构(在wdm.h定义),其中包含该文件的ProcessId列表(打开文件句柄或映射区段,如果这个文件是exe / dll – 我们获得了加载它的进程ID)。 这个打印过程的名字也适用于每个ID:

 volatile UCHAR guz = 0; NTSTATUS PrintProcessesUsingFile(HANDLE hFile) { NTSTATUS status; IO_STATUS_BLOCK iosb; ULONG cb = 0, rcb = FIELD_OFFSET(FILE_PROCESS_IDS_USING_FILE_INFORMATION, ProcessIdList[64]); union { PVOID buf; PFILE_PROCESS_IDS_USING_FILE_INFORMATION ppiufi; }; PVOID stack = alloca(guz); do { if (cb < rcb) { cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack); } if (0 <= (status = NtQueryInformationFile(hFile, &iosb, ppiufi, cb, FileProcessIdsUsingFileInformation))) { if (ppiufi->NumberOfProcessIdsInList) { PrintProcessesUsingFile(ppiufi); } } rcb = FIELD_OFFSET(FILE_PROCESS_IDS_USING_FILE_INFORMATION, ProcessIdList[ppiufi->NumberOfProcessIdsInList]); } while (status == STATUS_INFO_LENGTH_MISMATCH); return status; } NTSTATUS PrintProcessesUsingFile(POBJECT_ATTRIBUTES poa) { IO_STATUS_BLOCK iosb; HANDLE hFile; NTSTATUS status; if (0 <= (status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, 0))) { status = PrintProcessesUsingFile(hFile); NtClose(hFile); } return status; } NTSTATUS PrintProcessesUsingFile(PCWSTR FileName) { UNICODE_STRING ObjectName; NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(FileName, &ObjectName, 0, 0); if (0 <= status) { OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName }; status = PrintProcessesUsingFile(&oa); RtlFreeUnicodeString(&ObjectName); } return status; } NTSTATUS PrintProcessesUsingFile(PFILE_PROCESS_IDS_USING_FILE_INFORMATION ppiufi) { NTSTATUS status; ULONG cb = 0x8000; do { status = STATUS_INSUFFICIENT_RESOURCES; if (PVOID buf = new BYTE[cb]) { if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb))) { union { PVOID pv; PBYTE pb; PSYSTEM_PROCESS_INFORMATION pspi; }; pv = buf; ULONG NextEntryOffset = 0; do { pb += NextEntryOffset; ULONG NumberOfProcessIdsInList = ppiufi->NumberOfProcessIdsInList; PULONG_PTR ProcessIdList = ppiufi->ProcessIdList; do { if (*ProcessIdList++ == (ULONG_PTR)pspi->UniqueProcessId) { DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName); break; } } while (--NumberOfProcessIdsInList); } while (NextEntryOffset = pspi->NextEntryOffset); } delete [] buf; } } while (status == STATUS_INFO_LENGTH_MISMATCH); return status; }