gpt4 book ai didi

winapi - 在 Windows 10 上浏览 NTFS 更改日志

转载 作者:行者123 更新时间:2023-12-03 14:59:35 26 4
gpt4 key购买 nike

我正在尝试阅读 NTFS 更改日志,但我注意到我能找到的所有示例代码在 Windows 10 上都失败了,即使它在 Windows 7 上也能运行。

比如微软自己的例子Walking a Buffer of Change Journal Records适用于 Windows 7 但当我在 Windows 10 上运行相同的代码时,当我使用 FSCTL_READ_USN_JOURNAL 调用 DeviceIoControl 时,我收到错误 87(参数不正确)(请注意,较早使用 FSCTL_QUERY_USN_JOURNAL 对 DeviceIoControl 的调用成功完成并返回有效数据。)。

我什至将 EXE 编译并在 Windows 7 上运行并将其复制到 Windows 10 机器,但它仍然失败,所以我相信 Windows 10 可能对参数验证或类似的东西更严格?

我以管理员身份运行代码,所以这不是问题。

我找不到对此问题的任何其他引用,但是如果我采用其他人的示例代码并尝试在 Windows 10 上运行它,我会遇到同样的问题。

编辑:

代码本身:

#include <Windows.h>
#include <WinIoCtl.h>
#include <stdio.h>

#define BUF_LEN 4096

void main()
{
HANDLE hVol;
CHAR Buffer[BUF_LEN];

USN_JOURNAL_DATA JournalData;
READ_USN_JOURNAL_DATA ReadData = {0, 0xFFFFFFFF, FALSE, 0, 0};
PUSN_RECORD UsnRecord;

DWORD dwBytes;
DWORD dwRetBytes;
int I;

hVol = CreateFile( TEXT("\\\\.\\c:"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

if( hVol == INVALID_HANDLE_VALUE )
{
printf("CreateFile failed (%d)\n", GetLastError());
return;
}

if( !DeviceIoControl( hVol,
FSCTL_QUERY_USN_JOURNAL,
NULL,
0,
&JournalData,
sizeof(JournalData),
&dwBytes,
NULL) )
{
printf( "Query journal failed (%d)\n", GetLastError());
return;
}

ReadData.UsnJournalID = JournalData.UsnJournalID;

printf( "Journal ID: %I64x\n", JournalData.UsnJournalID );
printf( "FirstUsn: %I64x\n\n", JournalData.FirstUsn );

for(I=0; I<=10; I++)
{
memset( Buffer, 0, BUF_LEN );

if( !DeviceIoControl( hVol,
FSCTL_READ_USN_JOURNAL,
&ReadData,
sizeof(ReadData),
&Buffer,
BUF_LEN,
&dwBytes,
NULL) )
{
printf( "Read journal failed (%d)\n", GetLastError());
return;
}

dwRetBytes = dwBytes - sizeof(USN);

// Find the first record
UsnRecord = (PUSN_RECORD)(((PUCHAR)Buffer) + sizeof(USN));

printf( "****************************************\n");

// This loop could go on for a long time, given the current buffer size.
while( dwRetBytes > 0 )
{
printf( "USN: %I64x\n", UsnRecord->Usn );
printf("File name: %.*S\n",
UsnRecord->FileNameLength/2,
UsnRecord->FileName );
printf( "Reason: %x\n", UsnRecord->Reason );
printf( "\n" );

dwRetBytes -= UsnRecord->RecordLength;

// Find the next record
UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord) +
UsnRecord->RecordLength);
}
// Update starting USN for next call
ReadData.StartUsn = *(USN *)&Buffer;
}

CloseHandle(hVol);
}

最佳答案

我已经设法弄清楚问题是什么。

示例 Microsoft 代码创建了一个定义为 READ_USN_JOURNAL_DATA 的局部变量,其定义为:

#if (NTDDI_VERSION >= NTDDI_WIN8)
typedef READ_USN_JOURNAL_DATA_V1 READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA;
#else
typedef READ_USN_JOURNAL_DATA_V0 READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA;
#endif

在我的系统(Win10 和 Win7 系统)上,这评估为 READ_USN_JOURNAL_DATA_V1。

查看 READ_USN_JOURNAL_DATA_V0 和 READ_USN_JOURNAL_DATA_V1 之间的差异,我们可以看到 V0 定义为:
typedef struct {
USN StartUsn;
DWORD ReasonMask;
DWORD ReturnOnlyOnClose;
DWORDLONG Timeout;
DWORDLONG BytesToWaitFor;
DWORDLONG UsnJournalID;
} READ_USN_JOURNAL_DATA_V0, *PREAD_USN_JOURNAL_DATA_V0;

V1 版本定义为:
typedef struct {
USN StartUsn;
DWORD ReasonMask;
DWORD ReturnOnlyOnClose;
DWORDLONG Timeout;
DWORDLONG BytesToWaitFor;
DWORDLONG UsnJournalID;
WORD MinMajorVersion;
WORD MaxMajorVersion;
} READ_USN_JOURNAL_DATA_V1, *PREAD_USN_JOURNAL_DATA_V1;

请注意新的 Min 和 Max Major 版本成员。

因此,Microsoft 代码定义了一个名为 ReadData 的局部变量,它实际上是一个 V1 结构,但它似乎在假设它是 V0 结构的情况下填充数据。即它不设置 Min 和 Max 元素。

看来Win7对此没问题,但Win10拒绝它并返回错误87(参数不正确)。

果然,如果我将 ReadData 变量明确定义为 READ_USN_JOURNAL_DATA_V0,那么该代码适用于 Win7 和 Win10,而如果我将其明确定义为 READ_USN_JOURNAL_DATA_V1,则它继续适用于 Win7,但不适用于 Win10。

奇怪的是 READ_USN_JOURNAL_DATA_V1 structure的API文档声明它仅在 Windows 8 上受支持,因此它完全适用于 Windows 7 很奇怪。我想它只是将它解释为 READ_USN_JOURNAL_DATA_V0 结构,因为 V1 版本是 V0 结构的扩展。如果是这样,那么它必须忽略传递到 DeviceIOControl 的大小参数。

无论如何,现在都在工作。我希望将来有人会发现这是一个有用的引用。

关于winapi - 在 Windows 10 上浏览 NTFS 更改日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46978678/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com