我为NtWriteFile做了一个简单的包装,我遇到了来自NtWriteFile
的错误。这是我的代码:
BOOL WINAPI WriteFile(HANDLE hFile, PVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten) {
IO_STATUS_BLOCK IOBlock;
NTSTATUS Status = NtWriteFile(hFile, NULL, 0, NULL, &IOBlock, lpBuffer, nNumberOfBytesToWrite, 0, NULL);
DWORD A = RtlNtStatusToDosError(Status); // just to get the error code
if (Status == STATUS_PENDING) {
Status = NtWaitForSingleObject(hFile, FALSE, NULL);
if (NT_SUCCESS(Status)) Status = IOBlock.Status;
}
if (NT_SUCCESS(Status)) {
*lpNumberOfBytesWritten = IOBlock.uInformation;
return TRUE;
}
return FALSE;
}
在A
之后的行87
上设置断点后ERROR_INVALID_PARAMETR
的值为make -j4
,问题是哪个参数无效?我做错了什么?
答案 0 :(得分:2)
因为您在代码中准备STATUS_PENDING
并在NtWriteFile
之后等待 - 在这种情况下 - 我假设您使用为异步I /打开或创建的文件( hFile ) O.否则NtWaitForSingleObject
无意义之后请致电NtWriteFile
。所以我假设您在致电FILE_SYNCHRONOUS_IO_ALERT
或FILE_SYNCHRONOUS_IO_NONALERT
时使用NtOpenFile
或NtCreateFile
(或者在FILE_FLAG_OVERLAPPED
来电时使用CreateFile
)
在异步I / O的情况下, ByteOffset (倒数第二个)参数是必需的。来自windows源代码:
ByteOffset - 指定要开始的文件中的起始字节偏移量 写操作。如果未指定且文件已打开 同步I / O,然后使用当前文件位置。 如果 没有为同步I / O打开文件,参数不是 指定,然后是错误的。
和一段代码,你在内核中失败了:
} else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) {
//
// The file is not open for synchronous I/O operations, but the
// caller did not specify a ByteOffset parameter. This is an error
// situation, so cleanup and return with the appropriate status.
//
if (eventObject) {
ObDereferenceObject( eventObject );
}
ObDereferenceObject( fileObject );
return STATUS_INVALID_PARAMETER;
}
因此,如果我们为异步I / O打开或创建,我们需要或始终直接使用 ByteOffset 。或者如果我们使用同步文件句柄 - NtWriteFile
从不返回STATUS_PENDING
并且操作始终同步完成 - 这是设计使然。所以在这种情况下没有任何意义检查STATUS_PENDING
。你可以放弃这个检查和NtWaitForSingleObject
(如果同时在文件上进行多个操作,也可以等待hFile但不是很正确)
和MSDN
如果对 ZwCreateFile 的调用设置了 CreateOptions flags, FILE_SYNCHRONOUS_IO_ALERT 或 FILE_SYNCHRONOUS_IO_NONALERT , I / O管理器维护当前文件位置。如果是这样,来电者 ZwWriteFile 可以指定当前文件位置偏移量 用来代替显式的 ByteOffset 值。这个规范 可以使用以下方法之一进行:
- 指定指向LARGE_INTEGER值的指针,其中HighPart成员设置为-1,LowPart成员设置为系统定义的值
FILE_USE_FILE_POINTER_POSITION。- 为 ByteOffset 传递 NULL 指针。
尽管没有明确说明将会是什么(没有 FILE_SYNCHRONOUS_IO_ALERT 或 FILE_SYNCHRONOUS_IO_NONALERT 标志) - 可能理解在这种情况下I / O管理器不维护当前文件位置,我们不能指定使用当前文件位置偏移 - 只有显式 ByteOffset 值必须