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

use*_*143 4 c windows winapi cygwin cmd

目前我有一个带有文件过滤器驱动程序的软件,在软件安装过程中,驱动程序以以下方式作为服务启动:

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);
Run Code Online (Sandbox Code Playgroud)

路径在哪里C:\Program Files(x86)\TSU\driver\TSUfsd.sys

我遇到的问题是在卸载软件期间。当软件尝试删除TSUfsd.sys文件时,它会拒绝我的访问。

我检查了软件如何删除驱动程序,结果发现它用DeleteService功能删除它,并等待服务将其状态从 更改SERVICE_STOP_PENDINGSERVICE_STOPPED,如果一段时间后没有发生,它会获取服务PID并用 and 杀死ProcessTerminate它然后尝试删除该文件rmdir /S /Q C:\Program Files(x86)\TSU\

我试图找到可能拥有文件句柄的进程(使用 Process Explorer),但找不到任何进程。然后我想也许该服务仍然存在,所以我输入了sc query TSUfsd但服务也消失了。

我还尝试更改权限并向我的用户授予完全权限,但仍然出现相同的错误。

所以我的问题是:

  1. 还有其他方法可以检查哪个进程(或其他任何进程)可以保存文件吗?

  2. 我还注意到,每当我尝试使用 Cygwin( ) 删除文件时,rm TSUfsd.sys它都会毫无问题地删除该文件。使用 cmd( ) 删除文件和使用 cygwin 删除文件有什么区别del /f <filename>

RbM*_*bMm 9

对于此任务,从 Windows Vista 特殊存在开始FileProcessIdsUsingFileInformation FILE_INFORMATION_CLASS

因此,我们需要使用以下方式打开文件FILE_READ_ATTRIBUTES(即使有人以 0 共享模式打开文件,这也是可能的。如果我们无权访问文件(通过DACL)但具有对父目录的读取访问权限)。NtQueryInformationFile并拨打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 = (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\n", pspi->UniqueProcessId, &pspi->ImageName);
                            break;
                        }
                    } while (--NumberOfProcessIdsInList);

                } while (NextEntryOffset = pspi->NextEntryOffset);
            }

            delete [] buf;
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}
Run Code Online (Sandbox Code Playgroud)