diff --git a/lib/winapi/Makefile b/lib/winapi/Makefile index 78e993d73..47e8d2f1d 100644 --- a/lib/winapi/Makefile +++ b/lib/winapi/Makefile @@ -10,6 +10,7 @@ WINAPI_SRCS := \ $(NXDK_DIR)/lib/winapi/filemanip.c \ $(NXDK_DIR)/lib/winapi/findfile.c \ $(NXDK_DIR)/lib/winapi/handleapi.c \ + $(NXDK_DIR)/lib/winapi/ioapi.c \ $(NXDK_DIR)/lib/winapi/memory.c \ $(NXDK_DIR)/lib/winapi/libloaderapi.c \ $(NXDK_DIR)/lib/winapi/profiling.c \ diff --git a/lib/winapi/ioapi.c b/lib/winapi/ioapi.c new file mode 100644 index 000000000..eae069803 --- /dev/null +++ b/lib/winapi/ioapi.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT + +// SPDX-FileCopyrightText: 2023 Ryan Wendland + +#include +#include +#include +#include + +BOOL GetOverlappedResult (HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait) +{ + DWORD status; + HANDLE waitHandle; + + status = (DWORD)lpOverlapped->Internal; + + if (status == STATUS_PENDING && bWait == FALSE) { + SetLastError(ERROR_IO_INCOMPLETE); + return FALSE; + } + + // If the hEvent member of the OVERLAPPED structure is NULL, the system + // uses the state of the hFile handle to signal when the operation has been completed + if (lpOverlapped->hEvent == NULL) { + waitHandle = hFile; + } else { + waitHandle = lpOverlapped->hEvent; + } + + if (status == STATUS_PENDING) { + if (WaitForSingleObject(waitHandle, INFINITE) != WAIT_OBJECT_0) { + SetLastError(ERROR_IO_INCOMPLETE); + return FALSE; + } + // Get final status of the transfer + status = (DWORD)lpOverlapped->Internal; + } + + // InternalHigh contains the actual number of bytes transferred for the I/O request + *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh; + + if (!NT_SUCCESS(status)) { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; +} diff --git a/lib/winapi/winbase.h b/lib/winapi/winbase.h index 063596fbe..e7afcd09a 100644 --- a/lib/winapi/winbase.h +++ b/lib/winapi/winbase.h @@ -134,6 +134,8 @@ void WINAPI OutputDebugStringA (LPCTSTR lpOutputString); BOOL IsBadWritePtr (LPVOID lp, UINT_PTR ucb); +BOOL GetOverlappedResult (HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait); + #ifndef UNICODE #define OutputDebugString OutputDebugStringA #else