C NtWriteFile-错误\u无效\u参数(错误87)
我为NtWriteFile做了一个简单的包装,但遇到了来自C NtWriteFile-错误\u无效\u参数(错误87),c,winapi,C,Winapi,我为NtWriteFile做了一个简单的包装,但遇到了来自NtWriteFile的错误。这是我的密码: BOOL WINAPI WriteFile(HANDLE hFile, PVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten) { IO_STATUS_BLOCK IOBlock; NTSTATUS Status = NtWriteFile(hFile, NULL, 0, NULL
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
,它指向错误\u无效\u参数
,问题是哪个参数无效?我做错了什么?因为您在代码中准备了状态\u PENDING
,并在NtWriteFile
之后等待。在这种情况下,我假设您使用为异步I/O打开或创建的文件(hFile)。否则在NtWriteFile
之后调用NtWaitForSingleObject
没有意义。因此,我假设在调用NtOpenFile
或NtCreateFile
时,您既不使用FILE\u SYNCHRONOUS\u IO\u ALERT
警报,也不使用FILE\u SYNCHRONOUS\u NONALERT
(或者在CreateFile
调用中使用FILE\u FLAG\u OVERLAPPED
)
在异步I/O的情况下,字节偏移量(倒数第二个)参数是必需的。从windows源代码:
字节偏移量-指定要开始的文件中的起始字节偏移量
写入操作。如果未指定,则该文件将为打开
同步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打开或创建,或者如果我们使用同步文件句柄,NtWriteFile
是neverreturnSTATUS\u PENDING
并且操作总是同步完成,那么我们需要或总是直接使用ByteOffset,这是出于设计。因此,在这种情况下,对状态\u PENDING
没有任何意义检查。您可以删除此检查并NtWaitForSingleObject
(也可以在hFile上等待,但如果同时对文件执行多个操作,则此操作不太正确)
来自 如果调用ZwCreateFile设置其中一个CreateOptions 标志、文件同步IO警报或文件同步IO非警报, I/O管理器维护当前文件位置。如果是,来电者是谁 ZwWriteFile的可以指定当前文件位置偏移 可以使用,而不是显式字节偏移量值。本规范 可以使用以下方法之一进行:
- 指定指向大整数值的指针,其中HighPart成员设置为-1,LowPart成员设置为系统定义的值
文件\使用\文件\指针\位置 - 为字节偏移量传递一个NULL指针
尽管没有明确说明否则会发生什么(没有文件同步IO警报或文件同步IO非警报标志)-可能理解,在这种情况下,I/O管理器不维护当前文件位置,我们不能指定使用当前文件位置偏移量-只有显式字节偏移量值必须是,因为您在代码中准备
状态_PENDING
,并在NtWriteFile
之后等待在这种情况下-我假设您使用为异步i/O打开或创建的文件(hFile)。否则,在NtWriteFile
之后调用NtWaitForSingleObject
没有意义。因此,我假设在调用NtOpenFile
或NtCreateFile
时,您既不使用FILE\u SYNCHRONOUS\u IO\u ALERT
警报,也不使用FILE\u SYNCHRONOUS\u NONALERT
(或者在CreateFile
调用中使用FILE\u FLAG\u OVERLAPPED
)
在异步I/O的情况下,字节偏移量(倒数第二个)参数是必需的。从windows源代码:
字节偏移量-指定要开始的文件中的起始字节偏移量
写入操作。如果未指定,则该文件将为打开
同步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打开或创建,或者如果我们使用同步文件句柄,NtWriteFile
是neverreturnSTATUS\u PENDING
并且操作总是同步完成,那么我们需要或总是直接使用ByteOffset,这是出于设计。因此,在这种情况下,对状态\u PENDING
没有任何意义检查。您可以删除此检查并NtWaitForSingleObject
(也可以在hFile上等待,但如果同时对文件执行多个操作,则此操作不太正确)
来自 如果调用ZwCreateFile设置其中一个CreateOptions 标志、文件同步IO警报或文件同步IO非警报, I/O管理器维护当前文件位置。如果是,来电者是谁 ZwWriteFile的可以指定当前文件位置偏移 可以使用,而不是显式字节偏移量值。本规范 可以使用以下方法之一进行:
- 指定指向大整数值的指针,其中HighPart成员设置为-1,LowPart成员设置为系统定义的值
文件\使用\文件\指针\位置 - 为字节偏移量传递一个NULL指针
A
,它似乎有效吗?只有当函数实际失败时,才应该检查错误代码。@HarryJohnston:。我想您应该检查错误代码