windows源码ReadFile函数的实现
windows源码ReadFile函数的实现
文章目录
- windows源码ReadFile函数的实现
- ReadFile
ReadFile
BOOL
WINAPI
ReadFile(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped)/*++Routine Description:Data can be read from a file using ReadFile.This API is used to read data from a file. Data is read from thefile from the position indicated by the file pointer. After theread completes, the file pointer is adjusted by the number of bytesactually read. A return value of TRUE coupled with a bytes read of0 indicates that the file pointer was beyond the current end of thefile at the time of the read.Arguments:hFile - Supplies an open handle to a file that is to be read. Thefile handle must have been created with GENERIC_READ access tothe file.lpBuffer - Supplies the address of a buffer to receive the data readfrom the file.nNumberOfBytesToRead - Supplies the number of bytes to read from thefile.lpNumberOfBytesRead - Returns the number of bytes read by this call.This parameter is always set to 0 before doing any IO or errorchecking.lpOverlapped - Optionally points to an OVERLAPPED structure to be used with therequest. If NULL then the transfer starts at the current file positionand ReadFile will not return until the operation completes.If the handle hFile was created without specifying FILE_FLAG_OVERLAPPEDthe file pointer is moved to the specified offset pluslpNumberOfBytesRead before ReadFile returns. ReadFile will wait for therequest to complete before returning (it will not returnERROR_IO_PENDING).When FILE_FLAG_OVERLAPPED is specified, ReadFile may returnERROR_IO_PENDING to allow the calling function to continue processingwhile the operation completes. The event (or hFile if hEvent is NULL) willbe set to the signalled state upon completion of the request.When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlappedis set to NULL, ReadFile will return ERROR_INVALID_PARAMTER becausethe file offset is required.Return Value:TRUE - The operation was successul.FALSE - The operation failed. Extended error status is availableusing GetLastError.--*/{NTSTATUS Status;IO_STATUS_BLOCK IoStatusBlock;PPEB Peb;DWORD InputMode;if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {*lpNumberOfBytesRead = 0;}Peb = NtCurrentPeb();switch( HandleToUlong(hFile) ) {case STD_INPUT_HANDLE: hFile = Peb->ProcessParameters->StandardInput;break;case STD_OUTPUT_HANDLE: hFile = Peb->ProcessParameters->StandardOutput;break;case STD_ERROR_HANDLE: hFile = Peb->ProcessParameters->StandardError;break;}if (CONSOLE_HANDLE(hFile)) {if (ReadConsoleA(hFile,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped)) {Status = STATUS_SUCCESS;if (!GetConsoleMode( hFile, &InputMode )) {InputMode = 0;}if (InputMode & ENABLE_PROCESSED_INPUT) {try {if (*(PCHAR)lpBuffer == 0x1A) {*lpNumberOfBytesRead = 0;}}except( EXCEPTION_EXECUTE_HANDLER ) {Status = GetExceptionCode();}}if (NT_SUCCESS(Status)) {return TRUE;}else {BaseSetLastNTError(Status);return FALSE;}}else {return FALSE;}}if ( ARGUMENT_PRESENT( lpOverlapped ) ) {LARGE_INTEGER Li;lpOverlapped->Internal = (DWORD)STATUS_PENDING;Li.LowPart = lpOverlapped->Offset;Li.HighPart = lpOverlapped->OffsetHigh;Status = NtReadFile(hFile,lpOverlapped->hEvent,NULL,(ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,(PIO_STATUS_BLOCK)&lpOverlapped->Internal,lpBuffer,nNumberOfBytesToRead,&Li,NULL);if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {try {*lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;}except(EXCEPTION_EXECUTE_HANDLER) {*lpNumberOfBytesRead = 0;}}return TRUE;}elseif (Status == STATUS_END_OF_FILE) {if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {*lpNumberOfBytesRead = 0;}BaseSetLastNTError(Status);return FALSE;}else {BaseSetLastNTError(Status);return FALSE;}}else{Status = NtReadFile(hFile,NULL,NULL,NULL,&IoStatusBlock,lpBuffer,nNumberOfBytesToRead,NULL,NULL);if ( Status == STATUS_PENDING) {// Operation must complete before return & IoStatusBlock destroyedStatus = NtWaitForSingleObject( hFile, FALSE, NULL );if ( NT_SUCCESS(Status)) {Status = IoStatusBlock.Status;}}if ( NT_SUCCESS(Status) ) {*lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;return TRUE;}elseif (Status == STATUS_END_OF_FILE) {*lpNumberOfBytesRead = 0;return TRUE;}else {if ( NT_WARNING(Status) ) {*lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;}BaseSetLastNTError(Status);return FALSE;}}
}