Skip to content

Commit

Permalink
winapi: Implement overlapped IO for file read/write
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryzee119 committed May 4, 2024
1 parent ed21e83 commit a21a4f5
Showing 1 changed file with 67 additions and 10 deletions.
77 changes: 67 additions & 10 deletions lib/winapi/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,42 @@ BOOL ReadFile (HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWOR
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;

// overlapped I/O not supported yet
assert(!lpOverlapped);
if (lpOverlapped == NULL) {
// A null pointer makes the code crash on Windows, we'd rather catch it
assert(lpNumberOfBytesRead);
}

if (lpNumberOfBytesRead) {
*lpNumberOfBytesRead = 0;
}

if (lpOverlapped) {
LARGE_INTEGER overlappedOffset = {
.LowPart = lpOverlapped->Offset,
.HighPart = lpOverlapped->OffsetHigh,
};

// Internal contains the status code for the I/O request. Set to STATUS_PENDING at the start of the request.
lpOverlapped->Internal = (DWORD)STATUS_PENDING;
// InternalHigh contains the actual number of bytes transferred for the I/O request
lpOverlapped->InternalHigh = 0;

// A null pointer makes the code crash on Windows, we'd rather catch it
assert(lpNumberOfBytesRead);
*lpNumberOfBytesRead = 0;
status = NtReadFile(hFile, lpOverlapped->hEvent, NULL, NULL, (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
lpBuffer, nNumberOfBytesToRead, &overlappedOffset);

// The read can finish immediately. Handle this case
if (NT_SUCCESS(status) && status != STATUS_PENDING) {
if (lpNumberOfBytesRead) {
*lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
}
return TRUE;
} else if (status == STATUS_END_OF_FILE) {
*lpNumberOfBytesRead = 0;
return TRUE;
}
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}

status = NtReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, lpBuffer, nNumberOfBytesToRead, NULL);

Expand Down Expand Up @@ -139,12 +169,39 @@ BOOL WriteFile (HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPD
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;

// overlapped I/O not supported yet
assert(!lpOverlapped);
if (lpOverlapped == NULL) {
// A null pointer makes the code crash on Windows, we'd rather catch it
assert(lpNumberOfBytesWritten);
}

if (lpNumberOfBytesWritten) {
*lpNumberOfBytesWritten = 0;
}

if (lpOverlapped) {
LARGE_INTEGER overlappedOffset = {
.LowPart = lpOverlapped->Offset,
.HighPart = lpOverlapped->OffsetHigh,
};

// Internal contains the status code for the I/O request. Set to STATUS_PENDING at the start of the request
lpOverlapped->Internal = (DWORD)STATUS_PENDING;
// InternalHigh contains the actual number of bytes transferred for the I/O request
lpOverlapped->InternalHigh = 0;

status = NtWriteFile(hFile, lpOverlapped->hEvent, NULL, NULL, (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
(PVOID)lpBuffer, nNumberOfBytesToWrite, &overlappedOffset);

// A null pointer makes the code crash on Windows, we'd rather catch it
assert(lpNumberOfBytesWritten);
*lpNumberOfBytesWritten = 0;
// The write can finish immediately. Handle this case
if (NT_SUCCESS(status) && status != STATUS_PENDING) {
if (lpNumberOfBytesWritten) {
*lpNumberOfBytesWritten = (DWORD)lpOverlapped->InternalHigh;
}
return TRUE;
}
SetLastError(RtlNtStatusToDosError(status));
return FALSE;
}

status = NtWriteFile(hFile, NULL, NULL, NULL, &ioStatusBlock, (PVOID)lpBuffer, nNumberOfBytesToWrite, NULL);

Expand Down

0 comments on commit a21a4f5

Please sign in to comment.