reactos/dll/win32/kernel32/client/file/rw.c
Timo Kreuzer cfd1647914
[REACTOS] Fix misc 64 bit issues (#783)
* [WIN32K] Fix handle calculation in DbgGdiHTIntegrityCheck
* [NOTEPAD] Fix MSVC warnings
* [PSDK] Simplify *PROC definitions in windef.h
* [VIDEOPRT] Don't try to use NtVdmControl on x64
* [FREELDR] Fix some macros
* [CRT] Make qsort 64 bit compatible
* [NTOS] Use #ifndef _WIN64 instead of #ifdef _M_IX86 around C_ASSERTs
* [FAST486] Fix 64 bit warnings and change DWORD to ULONG, so it can be used in kernel mode
* [APPHELP_APITEST] Fix 64 bit issue
2019-01-05 10:50:11 +01:00

417 lines
11 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: dll/win32/kernel32/client/file/rw.c
* PURPOSE: Read/write functions
* PROGRAMMER: Ariadne (ariadne@xs4all.nl)
* UPDATE HISTORY:
* Created 01/11/98
*/
/* INCLUDES ****************************************************************/
#include <k32.h>
#define NDEBUG
#include <debug.h>
DEBUG_CHANNEL(kernel32file);
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
BOOL WINAPI
WriteFile(IN HANDLE hFile,
IN LPCVOID lpBuffer,
IN DWORD nNumberOfBytesToWrite OPTIONAL,
OUT LPDWORD lpNumberOfBytesWritten,
IN LPOVERLAPPED lpOverlapped OPTIONAL)
{
NTSTATUS Status;
TRACE("WriteFile(hFile %p)\n", hFile);
if (lpNumberOfBytesWritten != NULL) *lpNumberOfBytesWritten = 0;
hFile = TranslateStdHandle(hFile);
if (IsConsoleHandle(hFile))
{
return WriteConsoleA(hFile,
lpBuffer,
nNumberOfBytesToWrite,
lpNumberOfBytesWritten,
lpOverlapped);
}
if (lpOverlapped != NULL)
{
LARGE_INTEGER Offset;
PVOID ApcContext;
Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh;
lpOverlapped->Internal = STATUS_PENDING;
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
Status = NtWriteFile(hFile,
lpOverlapped->hEvent,
NULL,
ApcContext,
(PIO_STATUS_BLOCK)lpOverlapped,
(PVOID)lpBuffer,
nNumberOfBytesToWrite,
&Offset,
NULL);
/* return FALSE in case of failure and pending operations! */
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
{
BaseSetLastNTError(Status);
return FALSE;
}
if (lpNumberOfBytesWritten != NULL)
*lpNumberOfBytesWritten = lpOverlapped->InternalHigh;
}
else
{
IO_STATUS_BLOCK Iosb;
Status = NtWriteFile(hFile,
NULL,
NULL,
NULL,
&Iosb,
(PVOID)lpBuffer,
nNumberOfBytesToWrite,
NULL,
NULL);
/* Wait in case operation is pending */
if (Status == STATUS_PENDING)
{
Status = NtWaitForSingleObject(hFile, FALSE, NULL);
if (NT_SUCCESS(Status)) Status = Iosb.Status;
}
if (NT_SUCCESS(Status))
{
/*
* lpNumberOfBytesWritten must not be NULL here, in fact Win doesn't
* check that case either and crashes (only after the operation
* completed).
*/
*lpNumberOfBytesWritten = Iosb.Information;
}
else
{
BaseSetLastNTError(Status);
return FALSE;
}
}
TRACE("WriteFile() succeeded\n");
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
ReadFile(IN HANDLE hFile,
IN LPVOID lpBuffer,
IN DWORD nNumberOfBytesToRead,
OUT LPDWORD lpNumberOfBytesRead OPTIONAL,
IN LPOVERLAPPED lpOverlapped OPTIONAL)
{
NTSTATUS Status;
TRACE("ReadFile(hFile %p)\n", hFile);
if (lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = 0;
hFile = TranslateStdHandle(hFile);
if (IsConsoleHandle(hFile))
{
if (ReadConsoleA(hFile,
lpBuffer,
nNumberOfBytesToRead,
lpNumberOfBytesRead,
NULL))
{
DWORD dwMode;
GetConsoleMode(hFile, &dwMode);
if ((dwMode & ENABLE_PROCESSED_INPUT) && *(PCHAR)lpBuffer == 0x1a)
{
/* EOF character entered; simulate end-of-file */
*lpNumberOfBytesRead = 0;
}
return TRUE;
}
return FALSE;
}
if (lpOverlapped != NULL)
{
LARGE_INTEGER Offset;
PVOID ApcContext;
Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh;
lpOverlapped->Internal = STATUS_PENDING;
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
Status = NtReadFile(hFile,
lpOverlapped->hEvent,
NULL,
ApcContext,
(PIO_STATUS_BLOCK)lpOverlapped,
lpBuffer,
nNumberOfBytesToRead,
&Offset,
NULL);
/* return FALSE in case of failure and pending operations! */
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
{
if (Status == STATUS_END_OF_FILE && lpNumberOfBytesRead != NULL)
*lpNumberOfBytesRead = 0;
BaseSetLastNTError(Status);
return FALSE;
}
if (lpNumberOfBytesRead != NULL)
*lpNumberOfBytesRead = lpOverlapped->InternalHigh;
}
else
{
IO_STATUS_BLOCK Iosb;
Status = NtReadFile(hFile,
NULL,
NULL,
NULL,
&Iosb,
lpBuffer,
nNumberOfBytesToRead,
NULL,
NULL);
/* Wait in case operation is pending */
if (Status == STATUS_PENDING)
{
Status = NtWaitForSingleObject(hFile, FALSE, NULL);
if (NT_SUCCESS(Status)) Status = Iosb.Status;
}
if (Status == STATUS_END_OF_FILE)
{
/*
* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
* check that case either and crashes (only after the operation
* completed).
*/
*lpNumberOfBytesRead = 0;
return TRUE;
}
if (NT_SUCCESS(Status))
{
/*
* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
* check that case either and crashes (only after the operation
* completed).
*/
*lpNumberOfBytesRead = Iosb.Information;
}
else
{
BaseSetLastNTError(Status);
return FALSE;
}
}
TRACE("ReadFile() succeeded\n");
return TRUE;
}
VOID WINAPI
ApcRoutine(PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved)
{
DWORD dwErrorCode;
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine =
(LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext;
dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status);
lpCompletionRoutine(dwErrorCode,
IoStatusBlock->Information,
(LPOVERLAPPED)IoStatusBlock);
}
/*
* @implemented
*/
BOOL WINAPI
WriteFileEx(IN HANDLE hFile,
IN LPCVOID lpBuffer,
IN DWORD nNumberOfBytesToWrite OPTIONAL,
IN LPOVERLAPPED lpOverlapped,
IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
LARGE_INTEGER Offset;
NTSTATUS Status;
Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh;
lpOverlapped->Internal = STATUS_PENDING;
Status = NtWriteFile(hFile,
NULL,
ApcRoutine,
lpCompletionRoutine,
(PIO_STATUS_BLOCK)lpOverlapped,
(PVOID)lpBuffer,
nNumberOfBytesToWrite,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
ReadFileEx(IN HANDLE hFile,
IN LPVOID lpBuffer,
IN DWORD nNumberOfBytesToRead OPTIONAL,
IN LPOVERLAPPED lpOverlapped,
IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
LARGE_INTEGER Offset;
NTSTATUS Status;
Offset.u.LowPart = lpOverlapped->Offset;
Offset.u.HighPart = lpOverlapped->OffsetHigh;
lpOverlapped->Internal = STATUS_PENDING;
Status = NtReadFile(hFile,
NULL,
ApcRoutine,
lpCompletionRoutine,
(PIO_STATUS_BLOCK)lpOverlapped,
lpBuffer,
nNumberOfBytesToRead,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
WINAPI
ReadFileScatter(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[],
DWORD nNumberOfBytesToRead,
LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
{
PIO_STATUS_BLOCK pIOStatus;
LARGE_INTEGER Offset;
NTSTATUS Status;
DPRINT("(%p %p %u %p)\n", hFile, aSegmentArray, nNumberOfBytesToRead, lpOverlapped);
Offset.LowPart = lpOverlapped->Offset;
Offset.HighPart = lpOverlapped->OffsetHigh;
pIOStatus = (PIO_STATUS_BLOCK) lpOverlapped;
pIOStatus->Status = STATUS_PENDING;
pIOStatus->Information = 0;
Status = NtReadFileScatter(hFile,
NULL,
NULL,
NULL,
pIOStatus,
aSegmentArray,
nNumberOfBytesToRead,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
WINAPI
WriteFileGather(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[],
DWORD nNumberOfBytesToWrite,
LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
{
PIO_STATUS_BLOCK IOStatus;
LARGE_INTEGER Offset;
NTSTATUS Status;
DPRINT("%p %p %u %p\n", hFile, aSegmentArray, nNumberOfBytesToWrite, lpOverlapped);
Offset.LowPart = lpOverlapped->Offset;
Offset.HighPart = lpOverlapped->OffsetHigh;
IOStatus = (PIO_STATUS_BLOCK) lpOverlapped;
IOStatus->Status = STATUS_PENDING;
IOStatus->Information = 0;
Status = NtWriteFileGather(hFile,
NULL,
NULL,
NULL,
IOStatus,
aSegmentArray,
nNumberOfBytesToWrite,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/* EOF */