首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何获得USN日志查询的完整路径?

如何获得USN日志查询的完整路径?
EN

Stack Overflow用户
提问于 2015-08-01 14:58:27
回答 2查看 3.5K关注 0票数 6

我正在尝试学习MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365736%28v=vs.85%29.aspx)上关于如何查询USN日志的示例,以便跟踪NTFS驱动器上的文件更改。示例代码运行良好。

但是,在这个示例代码中,USN_RECORD结构只返回文件引用号和文件名。它不会返回文件的完整路径。有没有人知道如何查询USN日志以返回完整路径?或者有一种从文件引用号获取完整路径的方法?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-03 01:23:00

ParentFileReferenceNumber结构的USN_RECORD成员是包含文件的目录的引用号。

您可以使用FSCTL_ENUM_USN_DATA查找文件(或目录!)参考号码。您将需要迭代树来构建完整的路径。这个答案中有一些代码可以作为一个示例提供帮助。

这段代码查找根目录的引用号,这样您就可以知道何时完成:

代码语言:javascript
复制
HANDLE rootdir_handle;
USN_RECORD * rootdir_usn;

printf("Opening root directory.\n");

rootdir_handle = CreateFile(L"\\\\?\\C:\\", GENERIC_READ, 
                            FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);

if (rootdir_handle == INVALID_HANDLE_VALUE)
{
    printf("CreateFile: %u\n", GetLastError());
    return 0;
}

if (!DeviceIoControl(rootdir_handle, FSCTL_READ_FILE_USN_DATA, NULL, 0, 
                     buffer, BUFFER_SIZE, &bytecount, NULL))
{
    printf("FSCTL_READ_FILE_USN_DATA: %u\n", GetLastError());
}
else
{
    rootdir_usn = (USN_RECORD *)buffer;
    show_record(rootdir_usn, FALSE);
    rootdir = rootdir_usn->FileReferenceNumber;
}
票数 3
EN

Stack Overflow用户

发布于 2018-03-27 17:47:57

我一直试图避免递归父目录搜索以获得完整路径,因为我的初始测试增加了解析路径所需的全部时间。

在花了几个小时与风车和一些帮助,从OSR在线四百万,我终于得到它。

张贴答案,以帮助其他人谁结束了同样的问题。

我目前的解决办法如下。

USN_RECORD-> FileReferenceNumber完全依赖于USN_RECORD的版本,一旦从FileReferenceNumber提取了FILE_ID_DESCRIPTOR,就可以调用OpenFileById()并传递FILE_ID_DESCRIPTOR来获取父文件夹的句柄。

然后,您可以调用GetFinalPathNameByHandle()来获取ParentDirectory路径。

下面是我最后提取FILE_ID_DESCRIPTOR的代码

如果FileId在USN_RECORD_V2,则FileReferenceNu DWORDLONG。

代码语言:javascript
复制
FILE_ID_DESCRIPTOR getFileIdDescriptor(const DWORDLONG fileId)
{
    FILE_ID_DESCRIPTOR fileDescriptor;
    fileDescriptor.Type = FileIdType;
    fileDescriptor.FileId.QuadPart = fileId;
    fileDescriptor.dwSize = sizeof(fileDescriptor);

    return fileDescriptor;
}

如果您具有UNS_RECORD_V3,那么FileId是FILE_ID_128类型的,下面是提取fileId的代码。

代码语言:javascript
复制
FILE_ID_DESCRIPTOR getFileIdDescriptor(const FILE_ID_128& fileId)
{
    FILE_ID_DESCRIPTOR fileDescriptor;
    fileDescriptor.Type = ExtendedFileIdType;
    fileDescriptor.ExtendedFileId = fileId;
    fileDescriptor.dwSize = sizeof(fileDescriptor);
    return fileDescriptor;
}

提取FileId之后,下面是获取父路径的方法。

代码语言:javascript
复制
TCHAR filePath[MAX_PATH];
HANDLE hh= OpenFileById(volume_, &(getFileIdDescriptor(UsnRecord->FileReferenceNumber)), 0, 0, 0, 0);
GetFinalPathNameByHandle(hh,filePath, MAX_PATH, 0);

您可以找到引用实现@ https://github.com/kirankumarcelestial/NTFSChangeJournalUserMode

然而,我发现GetFilePathNameByHandle()实际上很慢,这个API最终会调用GetFileInformationByHandleEx(),而GetFileInformationByHandleEx()是对KernelMode的单个调用,这将是获取父级信息的有效方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31763195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档