使用NtCreateFile()打开文件索引需要帮助

6
我编写了一个程序,可以查询变更日志记录并将其列出。变更日志返回:
1) 文件引用号(文件索引高位和低位的组合) 2) 父文件引用号(与上述相同,但是用于目录) 3) szReason(它在变更记录中出现的原因) 4) 文件名和文件长度。
我想找到在变更日志中列出的此文件的路径。我看到的大多数实现都跟踪所有的文件引用号并查询以进行比较,或者使用FindNextFile()函数遍历整个卷。
我遇到了一个讨论,他们说,他们可以仅使用文件引用号打开文件句柄。http://www.tech-archive.net/Archive/Windows/microsoft.public.windows.file_system/2004-11/0244.html

这篇msdn文章说,在调用内部API之前,我们需要加载一个库http://msdn.microsoft.com/en-us/library/bb432380%28v=vs.85%29.aspx

有人能指点我正确的方向并告诉我该怎么做吗?如何使用NtCreateFile()?

或者,是否有一种方法可以仅使用文件引用号来访问文件路径?


1
这并不是StackOverflow应该运作的方式。问题留给未来的人们来寻找答案。 - Zan Lynx
抱歉@Zan Lynx,我有点绝望,所以发了这个问题。既然我欠大家一个答案,我也在下面发布了它。 - roymustang86
1个回答

5
这是我使用的代码: http://www.ragestorm.net/blogs/?cat=7
 #include windows.h
 typedef ULONG (__stdcall *pNtCreateFile)(
   PHANDLE FileHandle,
   ULONG DesiredAccess,
   PVOID ObjectAttributes,
   PVOID IoStatusBlock,
   PLARGE_INTEGER AllocationSize,
   ULONG FileAttributes,
   ULONG ShareAccess,
   ULONG CreateDisposition,
   ULONG CreateOptions,
   PVOID EaBuffer,
   ULONG EaLength
 );

 typedef ULONG (__stdcall *pNtReadFile)(
    IN HANDLE  FileHandle,
    IN HANDLE  Event  OPTIONAL,
    IN PVOID  ApcRoutine  OPTIONAL,
    IN PVOID  ApcContext  OPTIONAL,
    OUT PVOID  IoStatusBlock,
    OUT PVOID  Buffer,
    IN ULONG  Length,
    IN PLARGE_INTEGER  ByteOffset  OPTIONAL,
    IN PULONG  Key  OPTIONAL    );

 typedef struct _UNICODE_STRING {
    USHORT Length, MaximumLength;
    PWCH Buffer;
 } UNICODE_STRING, *PUNICODE_STRING;

 typedef struct _OBJECT_ATTRIBUTES {
 ULONG Length;
 HANDLE RootDirectory;
 PUNICODE_STRING ObjectName;
 ULONG Attributes;
 PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
 } OBJECT_ATTRIBUTES;

 #define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
(p)->RootDirectory = r;                             \
(p)->Attributes = a;                                \
(p)->ObjectName = n;                                \
(p)->SecurityDescriptor = s;                        \
(p)->SecurityQualityOfService = NULL;               \
}

 #define OBJ_CASE_INSENSITIVE  0x00000040L
 #define FILE_NON_DIRECTORY_FILE  0×00000040
 #define FILE_OPEN_BY_FILE_ID  0×00002000
 #define FILE_OPEN   0×00000001

 int main(int argc, char* argv[])
 {
    HANDLE d = CreateFile(L"\\\\.\\c:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0  );
    BY_HANDLE_FILE_INFORMATION i;
    HANDLE f = CreateFile(L"c:\\bla.bla", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    ULONG bla;
    WriteFile(f, "helloworld", 11, &bla, NULL);
    printf("%x, %d\n", f, GetLastError());
    GetFileInformationByHandle(f, &i);
    printf("id:%08x-%08x\n", i.nFileIndexHigh, i.nFileIndexLow);
    CloseHandle(f);

    pNtCreateFile NtCreatefile = (pNtCreateFile)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateFile");
    pNtReadFile NtReadFile = (pNtReadFile)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtReadFile");

    ULONG fid[2] = {i.nFileIndexLow, i.nFileIndexHigh};
    UNICODE_STRING fidstr = {8, 8, (PWSTR) fid};

    OBJECT_ATTRIBUTES oa = {0};
     InitializeObjectAttributes (&oa, &fidstr, OBJ_CASE_INSENSITIVE, d, NULL);

     ULONG iosb[2];
     ULONG status = NtCreatefile(&f, GENERIC_ALL, &oa, iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_OPEN_BY_FILE_ID | FILE_NON_DIRECTORY_FILE, NULL, 0);
    printf("status: %X, handle: %x\n", status, f);
    UCHAR buf[11] = {0};
    LONG Off[2] = {0};
    status = NtReadFile(f, NULL, NULL, NULL, (PVOID)&iosb, (PVOID)buf, sizeof(buf), (PLARGE_INTEGER)&Off, NULL);
    printf("status: %X, bytes: %d\n", status, iosb[1]);
    printf("buf: %s\n", buf);
    CloseHandle(f);
    CloseHandle(d);
 }

正如您所看到的,一旦提供了 filereferencenumber 的 fileindex.high 和 fileindex.low 部分,就会给您一个文件句柄。我使用了 psapi 中的 getFileMapping 函数来获取完整路径。对于那些好奇的人,可以参考这个链接:http://msdn.microsoft.com/en-us/library/aa366789.aspx


1
专业提示:ULONG iosb[2]仅适用于32位。如果您不打算使用实际的IO_STATUS_BLOCK,那么也许ULONG_PTR iosb[2];会更好。 - David Wohlferd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接