Если hFile был открыт с помощью FILE_FLAG_OVERLAPPED
lpNumberOfBytesWritten
Параметр должен быть установлен на NULL .
это не так (ошибка или ложь). lpNumberOfBytesWritten может быть установлен на NULL , но не должен . если запрос ввода-вывода завершится синхронно с успехом в *lpNumberOfBytesWritten
, будет действительное число байтов.
обратите внимание также, что lpNumberOfBytes
не должен указывать на местоположение, которое будет действовать до завершения операции (например, lpOverlapped
) - оно может указывать на локальную переменную в функции для пример, и вы можете выйти из функции до завершения ввода-вывода - и это тоже будет хорошо. система просто скопирует InternalHigh
из OVERLAPPED
в *lpNumberOfBytes
. так в псевдокоде:
if (lpNumberOfBytes) *lpNumberOfBytes = (ULONG)lpOverlapped->InternalHigh;
двузначное правильное значение в *lpNumberOfBytes
будет только в том случае, если ввод / вывод уже завершен успешно. так и может использовать его только в этом случае. система не запоминает значение lpNumberOfBytes
- потому что оно должно быть действительным только при [Write|Read]File
вызове, но не при активном вводе / выводе (что может быть больше в случае асинхронного ввода / вывода)
GetOverlappedResult
мы можем позвонить, если запрос ввода-вывода завершится синхронно с успехом (в случае ReadFile
или WriteFile
, если вы вернете TRUE
), если ожидание вернулось. этот API нельзя вызвать только в случае сбоя запроса ввода / вывода (ReadFile
или WriteFile
return FALSE
и GetLastError() != ERROR_IO_PENDING
)
так что лучшие всегда передают не 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);
}