首页 > 系统相关 >windows源码ReadFile函数的实现

windows源码ReadFile函数的实现

时间:2024-09-21 23:48:27浏览次数:11  
标签:Status return file windows ReadFile lpOverlapped 源码 lpNumberOfBytesRead hFile

windows源码ReadFile函数的实现

windows源码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 the
    file from the position indicated by the file pointer.  After the
    read completes, the file pointer is adjusted by the number of bytes
    actually read.  A return value of TRUE coupled with a bytes read of
    0 indicates that the file pointer was beyond the current end of the
    file at the time of the read.

Arguments:

    hFile - Supplies an open handle to a file that is to be read.  The
        file handle must have been created with GENERIC_READ access to
        the file.

    lpBuffer - Supplies the address of a buffer to receive the data read
        from the file.

    nNumberOfBytesToRead - Supplies the number of bytes to read from the
        file.

    lpNumberOfBytesRead - Returns the number of bytes read by this call.
        This parameter is always set to 0 before doing any IO or error
        checking.

    lpOverlapped - Optionally points to an OVERLAPPED structure to be used with the
    request. If NULL then the transfer starts at the current file position
    and ReadFile will not return until the operation completes.

    If the handle hFile was created without specifying FILE_FLAG_OVERLAPPED
    the file pointer is moved to the specified offset plus
    lpNumberOfBytesRead before ReadFile returns. ReadFile will wait for the
    request to complete before returning (it will not return
    ERROR_IO_PENDING).

    When FILE_FLAG_OVERLAPPED is specified, ReadFile may return
    ERROR_IO_PENDING to allow the calling function to continue processing
    while the operation completes. The event (or hFile if hEvent is NULL) will
    be set to the signalled state upon completion of the request.

    When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
    is set to NULL, ReadFile will return ERROR_INVALID_PARAMTER because
    the file offset is required.


Return Value:

    TRUE - The operation was successul.

    FALSE - The operation failed.  Extended error status is available
        using 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;
            }
        else
        if (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 destroyed
            Status = NtWaitForSingleObject( hFile, FALSE, NULL );
            if ( NT_SUCCESS(Status)) {
                Status = IoStatusBlock.Status;
                }
            }

        if ( NT_SUCCESS(Status) ) {
            *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
            return TRUE;
            }
        else
        if (Status == STATUS_END_OF_FILE) {
            *lpNumberOfBytesRead = 0;
            return TRUE;
            }
        else {
            if ( NT_WARNING(Status) ) {
                *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
                }
            BaseSetLastNTError(Status);
            return FALSE;
            }
        }
}

标签:Status,return,file,windows,ReadFile,lpOverlapped,源码,lpNumberOfBytesRead,hFile
From: https://blog.csdn.net/zhyjhacker/article/details/142427109

相关文章