Winapi:获取具有文件特定句柄的进程 [英] Winapi: Get the process which has specific handle of a file
问题描述
目前我有一个带有文件过滤驱动程序的软件,在软件安装过程中,驱动程序以这种方式作为服务启动:
Currently I have a software which has a file filter driver, during installation of software the driver is started as service in this way:
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);
路径是C:Program Files(x86)TSUdriverTSUfsd.sys
.
我遇到的问题是在卸载软件时.当软件尝试删除 TSUFsd.sys
文件时,它让我拒绝访问.
The problem I'm having is during uninstallation of the software. It gives me access denied when software tries to delete TSUfsd.sys
file.
我检查了软件是如何删除驱动程序的,结果是使用DeleteService
函数删除它,并等待服务将其状态从SERVICE_STOP_PENDING
更改为SERVICE_STOPPED
,如果一段时间后它没有发生,它会获取服务 PID
并用 ProcessTerminate
杀死它,然后尝试删除文件rmdir/S/QC:Program Files(x86)TSU
.
I've checked how the software deletes the driver, and turns out it deletes it with DeleteService
function, and waits for service to change its state from SERVICE_STOP_PENDING
to SERVICE_STOPPED
and if it doesn't happen after some time, it gets the service PID
and kills it with ProcessTerminate
and then tries to delete the file with rmdir /S /Q C:Program Files(x86)TSU
.
我试图找到可能有文件句柄的进程(使用进程资源管理器)但找不到任何.然后我想也许该服务还活着,所以我输入了 sc query TSUfsd
但该服务也消失了.
I've tried to find the process which could have had the handle of the file(with Process Explorer) but could not find any. Then I thought maybe the service is still alive so I typed sc query TSUfsd
but the service was gone too.
我也尝试更改权限并向我的用户授予完全权限,但仍然出现相同的错误.
I've also tried to change permissions and grant full permissions to my user but same error still occurred.
所以我的问题是:
是否有其他方法可以检查哪个进程(或其他任何进程)可以保留文件?
Is there any other ways to check which process(or anything else) can have a hold of a file?
我还注意到,每当我尝试使用 Cygwin(rm TSUfsd.sys
) 删除文件时,它都会毫无问题地删除文件.使用 cmd(del/f
) 和使用 cygwin 删除文件有什么区别?
I've also noticed that, whenever I try to delete the file with Cygwin(rm TSUfsd.sys
) it deletes the file without a problem. What is the difference between deleting file with cmd(del /f <filename>
) and with cygwin?
推荐答案
对于此任务,从 Windows Vista 开始特殊存在 FileProcessIdsUsingFileInformation
FILE_INFORMATION_CLASS
.
For this task, starting with Windows Vista special exist FileProcessIdsUsingFileInformation
FILE_INFORMATION_CLASS
.
所以我们需要用 FILE_READ_ATTRIBUTES
打开文件(即使有人用 0 共享模式打开文件,这也是可能的.如果我们无法访问文件(通过它DACL) 但对父目录具有读访问权限).并调用 NtQueryInformationFile
和 FileProcessIdsUsingFileInformation
.返回时,我们得到 FILE_PROCESS_IDS_USING_FILE_INFORMATION
结构(在 wdm.h
中定义),其中包含该文件的 ProcessId
列表(打开文件句柄或映射部分.假设这个文件是 exe/dll - 我们在它加载的地方得到了进程 ID).每个 id 的打印进程名称也很好:
So we need open file with FILE_READ_ATTRIBUTES
(this is possible even if somebody open file with 0 share mode. of if we have no access to file (by it DACL) but have read access to parent directory). and call NtQueryInformationFile
with FileProcessIdsUsingFileInformation
. on return we got FILE_PROCESS_IDS_USING_FILE_INFORMATION
structure (defined in wdm.h
) where list of ProcessId
which hold this file(open file handle or mapped section. say if this file is exe/dll - we got process ids where it loaded). good also with this print process name for every 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 = (ULONG)iosb.Information;
} 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
", pspi->UniqueProcessId, &pspi->ImageName);
break;
}
} while (--NumberOfProcessIdsInList);
} while (NextEntryOffset = pspi->NextEntryOffset);
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
这篇关于Winapi:获取具有文件特定句柄的进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!