ReadFile 和 WriteFile with Overlapped IO result if not ERROR_IO_PENDING?
ReadFile and WriteFile with Overlapped IO result if not ERROR_IO_PENDING?
WriteFile()
上 FILE_FLAG_OVERLAPPED 的文档说您必须提供 OVERLAP 并建议 lpNumberOfBytesWritten
为 NULL,因为值具有误导性。但是 GetOverlappedResult()
的文档说只有在 WriteFile()
返回 FALSE 且 ERROR_IO_PENDING 时才调用。因此,ReadFile()
/ WriteFile()
在 API 调用本身中完成的情况。你应该如何获得字节数read/written?你认为这是要求的号码吗?但是 WriteFile()
说 "When writing to a non-blocking, byte-mode pipe handle with insufficient buffer space, WriteFile returns TRUE with * lpNumberOfBytesWritten < nNumberOfBytesToWrite".
TIA!!
If hFile was opened with FILE_FLAG_OVERLAPPED
The
lpNumberOfBytesWritten
parameter should be set to NULL.
这不是真的(错误或谎言)。 lpNumberOfBytesWritten可以设置为NULL,但是不应该.如果 I/O 请求在 *lpNumberOfBytesWritten
中成功同步完成,将是有效的字节数。
另请注意,lpNumberOfBytes
不得 指向在操作完成之前有效的位置(如 lpOverlapped
) - 例如,它可以指向函数中的局部变量,您可以在 I/O 完成之前退出函数 - 这也可以。系统只需将 InternalHigh
从 OVERLAPPED
复制到 *lpNumberOfBytes
。所以在伪代码中:
if (lpNumberOfBytes) *lpNumberOfBytes = (ULONG)lpOverlapped->InternalHigh;
*lpNumberOfBytes
中明显的正确值只有在 I/O 已经成功完成时才会出现。所以只能在这种情况下使用它。系统不记得 lpNumberOfBytes
的值 - 因为它必须仅在 [Write|Read]File
调用期间有效,而不是在 I/O 活动期间(可以是如果异步 I/O)
则更长
GetOverlappedResult
我们可以调用 if I/O 请求完成与成功同步(如果 ReadFile
或 WriteFile
,如果 return TRUE
) 如果待处理 returned。只有在 I/O 请求失败(ReadFile
或 WriteFile
return FALSE
和 GetLastError() != ERROR_IO_PENDING
时才能调用此 api
所以最好总是将 not 0 lpNumberOfBytes 传递给 api 并使用它,如果 api 成功完成。否则使用 GetOverlappedResult
或者如果说你使用 BindIoCompletionCallback
- 你直接在回调中得到 dwNumberOfBytesTransfered
。
所以在概念上可以使用下一个代码:
inline ULONG BOOL_TO_ERROR(BOOL f)
{
return f ? NOERROR : GetLastError();
}
HANDLE hFile = CreateFile(*, FILE_GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
UCHAR buf[0x200];
OVERLAPPED ov = {};
ULONG NumberOfBytesRead;
ULONG dwError = BOOL_TO_ERROR(ReadFile(hFile, buf, sizeof(buf), &NumberOfBytesRead, &ov));
switch (dwError)
{
case ERROR_IO_PENDING:
dwError = BOOL_TO_ERROR(GetOverlappedResult(hFile, &ov, &NumberOfBytesRead, TRUE));
if (dwError != NOERROR) goto __default;
[[fallthrough]];
case NOERROR:
DbgPrint("NumberOfBytesRead=%x\n", NumberOfBytesRead);
// use GetOverlappedResult(hFile, &ov, &NumberOfBytesRead, TRUE) here also possible
break;
__default:
default:
DbgPrint("dwError = %u\n", dwError);
}
CloseHandle(hFile);
}
WriteFile()
上 FILE_FLAG_OVERLAPPED 的文档说您必须提供 OVERLAP 并建议 lpNumberOfBytesWritten
为 NULL,因为值具有误导性。但是 GetOverlappedResult()
的文档说只有在 WriteFile()
返回 FALSE 且 ERROR_IO_PENDING 时才调用。因此,ReadFile()
/ WriteFile()
在 API 调用本身中完成的情况。你应该如何获得字节数read/written?你认为这是要求的号码吗?但是 WriteFile()
说 "When writing to a non-blocking, byte-mode pipe handle with insufficient buffer space, WriteFile returns TRUE with * lpNumberOfBytesWritten < nNumberOfBytesToWrite".
TIA!!
If hFile was opened with
FILE_FLAG_OVERLAPPED
ThelpNumberOfBytesWritten
parameter should be set to NULL.
这不是真的(错误或谎言)。 lpNumberOfBytesWritten可以设置为NULL,但是不应该.如果 I/O 请求在 *lpNumberOfBytesWritten
中成功同步完成,将是有效的字节数。
另请注意,lpNumberOfBytes
不得 指向在操作完成之前有效的位置(如 lpOverlapped
) - 例如,它可以指向函数中的局部变量,您可以在 I/O 完成之前退出函数 - 这也可以。系统只需将 InternalHigh
从 OVERLAPPED
复制到 *lpNumberOfBytes
。所以在伪代码中:
if (lpNumberOfBytes) *lpNumberOfBytes = (ULONG)lpOverlapped->InternalHigh;
*lpNumberOfBytes
中明显的正确值只有在 I/O 已经成功完成时才会出现。所以只能在这种情况下使用它。系统不记得 lpNumberOfBytes
的值 - 因为它必须仅在 [Write|Read]File
调用期间有效,而不是在 I/O 活动期间(可以是如果异步 I/O)
GetOverlappedResult
我们可以调用 if I/O 请求完成与成功同步(如果 ReadFile
或 WriteFile
,如果 return TRUE
) 如果待处理 returned。只有在 I/O 请求失败(ReadFile
或 WriteFile
return FALSE
和 GetLastError() != ERROR_IO_PENDING
时才能调用此 api
所以最好总是将 not 0 lpNumberOfBytes 传递给 api 并使用它,如果 api 成功完成。否则使用 GetOverlappedResult
或者如果说你使用 BindIoCompletionCallback
- 你直接在回调中得到 dwNumberOfBytesTransfered
。
所以在概念上可以使用下一个代码:
inline ULONG BOOL_TO_ERROR(BOOL f)
{
return f ? NOERROR : GetLastError();
}
HANDLE hFile = CreateFile(*, FILE_GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
UCHAR buf[0x200];
OVERLAPPED ov = {};
ULONG NumberOfBytesRead;
ULONG dwError = BOOL_TO_ERROR(ReadFile(hFile, buf, sizeof(buf), &NumberOfBytesRead, &ov));
switch (dwError)
{
case ERROR_IO_PENDING:
dwError = BOOL_TO_ERROR(GetOverlappedResult(hFile, &ov, &NumberOfBytesRead, TRUE));
if (dwError != NOERROR) goto __default;
[[fallthrough]];
case NOERROR:
DbgPrint("NumberOfBytesRead=%x\n", NumberOfBytesRead);
// use GetOverlappedResult(hFile, &ov, &NumberOfBytesRead, TRUE) here also possible
break;
__default:
default:
DbgPrint("dwError = %u\n", dwError);
}
CloseHandle(hFile);
}