如果没有,则IO重叠的ReadFile和WriteFile结果是否为ERROR_IO_PENDING?

时间:2019-07-11 05:47:25

标签: windows winapi storage

WriteFile()上FILE_FLAG_OVERLAPPED的文档说,您必须提供OVERLAP并为lpNumberOfBytesWritten建议使用NULL,因为值会产生误导。但是GetOverlappedResult()的文档说只有在WriteFile()返回FALSE并带有ERROR_IO_PENDING时才调用。这样就剩下了ReadFile() / WriteFile()在API调用本身中完成的情况。您应该如何获得读取/写入的字节数?你以为是要求的电话号码吗?但是WriteFile()说:“当写入缓冲区空间不足的非阻塞字节模式管道句柄时,WriteFile返回TRUE,并带有* lpNumberOfBytesWritten

TIA !!

1 个答案:

答案 0 :(得分:2)

  

如果 hFile 是用FILE_FLAG_OVERLAPPED打开的    lpNumberOfBytesWritten 参数应设置为 NULL

这不是真的(错误或说谎)。可以将 lpNumberOfBytesWritten 设置为 NULL ,但不应该。如果 *lpNumberOfBytesWritten 中I / O请求完成并成功完成同步,将是有效字节数。

还请注意,lpNumberOfBytes 一定不能指向在操作完成之前才有效的位置(例如 lpOverlapped )-它可以指向例如到函数中的局部变量,您可以在I / O完成之前从函数退出-这也可以。系统只需将InternalHighOVERLAPPED复制到 *lpNumberOfBytes 。所以在伪代码中:

if (lpNumberOfBytes) *lpNumberOfBytes = (ULONG)lpOverlapped->InternalHigh;
仅当I / O已成功完成时, *lpNumberOfBytes 中的

正确的正确值。因此,只能在这种情况下使用。系统不记得 lpNumberOfBytes 的值-因为它必须仅在[Write|Read]File调用期间有效,而在I / O活动期间无效(如果异步I / O)

GetOverlappedResult,如果I / O请求成功完成并成功同步(在ReadFileWriteFile,如果返回TRUE的情况下),则可以调用是否返回未决。仅在I / O请求只是失败(ReadFileWriteFile返回FALSEGetLastError() != ERROR_IO_PENDING)的情况下,才能调用此api

因此,如果api成功完成,最好将始终不传递0 lpNumberOfBytes 到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);
}