Author: ion Date: Tue Feb 21 21:31:01 2012 New Revision: 55793
URL: http://svn.reactos.org/svn/reactos?rev=55793&view=rev Log: [KERNEL32]: Format, comment, annotate, cleanup the I/O completion APIs.
Modified: trunk/reactos/dll/win32/kernel32/client/file/iocompl.c
Modified: trunk/reactos/dll/win32/kernel32/client/file/iocompl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/f... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/file/iocompl.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/file/iocompl.c [iso-8859-1] Tue Feb 21 21:31:01 2012 @@ -13,164 +13,160 @@ #define NDEBUG #include <debug.h>
-#define NANOS_TO_100NS(nanos) (((LONGLONG)(nanos)) / 100) -#define MICROS_TO_100NS(micros) (((LONGLONG)(micros)) * NANOS_TO_100NS(1000)) -#define MILLIS_TO_100NS(milli) (((LONGLONG)(milli)) * MICROS_TO_100NS(1000)) - /* * @implemented */ HANDLE WINAPI -CreateIoCompletionPort( - HANDLE FileHandle, - HANDLE ExistingCompletionPort, - ULONG_PTR CompletionKey, - DWORD NumberOfConcurrentThreads - ) -{ - HANDLE CompletionPort = NULL; - NTSTATUS errCode; - FILE_COMPLETION_INFORMATION CompletionInformation; - IO_STATUS_BLOCK IoStatusBlock; - - if ( FileHandle == INVALID_HANDLE_VALUE && ExistingCompletionPort != NULL ) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ( ExistingCompletionPort != NULL ) - { - CompletionPort = ExistingCompletionPort; - } - else - { - - errCode = NtCreateIoCompletion(&CompletionPort, - IO_COMPLETION_ALL_ACCESS, - NULL,//ObjectAttributes - NumberOfConcurrentThreads); - - if (!NT_SUCCESS(errCode) ) - { - BaseSetLastNTError (errCode); - return FALSE; - } - - } - - if ( FileHandle != INVALID_HANDLE_VALUE ) - { - CompletionInformation.Port = CompletionPort; - CompletionInformation.Key = (PVOID)CompletionKey; - - errCode = NtSetInformationFile(FileHandle, - &IoStatusBlock, - &CompletionInformation, - sizeof(FILE_COMPLETION_INFORMATION), - FileCompletionInformation); - - if ( !NT_SUCCESS(errCode) ) - { - if ( ExistingCompletionPort == NULL ) - { - NtClose(CompletionPort); - } - - BaseSetLastNTError (errCode); - return FALSE; - } - } - - return CompletionPort; -} - - -/* - * @implemented - */ -BOOL -WINAPI -GetQueuedCompletionStatus( - HANDLE CompletionHandle, - LPDWORD lpNumberOfBytesTransferred, - PULONG_PTR lpCompletionKey, - LPOVERLAPPED *lpOverlapped, - DWORD dwMilliseconds - ) -{ - NTSTATUS errCode; - IO_STATUS_BLOCK IoStatus; - ULONG_PTR CompletionKey; - LARGE_INTEGER Time; - PLARGE_INTEGER TimePtr; - - if (!lpNumberOfBytesTransferred || !lpCompletionKey || !lpOverlapped) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Convert the timeout */ - TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); - - errCode = NtRemoveIoCompletion(CompletionHandle, +CreateIoCompletionPort(IN HANDLE FileHandle, + IN HANDLE ExistingCompletionPort, + IN ULONG_PTR CompletionKey, + IN DWORD NumberOfConcurrentThreads) +{ + NTSTATUS Status; + HANDLE NewPort; + FILE_COMPLETION_INFORMATION CompletionInformation; + IO_STATUS_BLOCK IoStatusBlock; + + /* Check if this is a new port */ + NewPort = ExistingCompletionPort; + if (!ExistingCompletionPort) + { + /* Create it */ + Status = NtCreateIoCompletion(&NewPort, + IO_COMPLETION_ALL_ACCESS, + NULL, + NumberOfConcurrentThreads); + if (!NT_SUCCESS(Status)) + { + /* Convert error and fail */ + BaseSetLastNTError(Status); + return FALSE; + } + } + + /* Check if no actual file is being associated with the completion port */ + if (FileHandle == INVALID_HANDLE_VALUE) + { + /* Was there a port already associated? */ + if (ExistingCompletionPort) + { + /* You are not allowed using an old port and dropping the handle */ + NewPort = NULL; + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + } + } + else + { + /* We have a file handle, so associated it with this completion port */ + CompletionInformation.Port = NewPort; + CompletionInformation.Key = (PVOID)CompletionKey; + Status = NtSetInformationFile(FileHandle, + &IoStatusBlock, + &CompletionInformation, + sizeof(FILE_COMPLETION_INFORMATION), + FileCompletionInformation); + if (!NT_SUCCESS(Status)) + { + /* Convert the error code and close the newly created port, if any */ + BaseSetLastNTError(Status); + if (!ExistingCompletionPort) NtClose(NewPort); + return FALSE; + } + } + + /* Return the newly created port, if any */ + return NewPort; +} + +/* + * @implemented + */ +BOOL +WINAPI +GetQueuedCompletionStatus(IN HANDLE CompletionHandle, + IN LPDWORD lpNumberOfBytesTransferred, + OUT PULONG_PTR lpCompletionKey, + OUT LPOVERLAPPED *lpOverlapped, + IN DWORD dwMilliseconds) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + ULONG_PTR CompletionKey; + LARGE_INTEGER Time; + PLARGE_INTEGER TimePtr; + + /* Convert the timeout and then call the native API */ + TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); + Status = NtRemoveIoCompletion(CompletionHandle, (PVOID*)&CompletionKey, (PVOID*)lpOverlapped, &IoStatus, TimePtr); - - if (!NT_SUCCESS(errCode) || errCode == STATUS_TIMEOUT) { - *lpOverlapped = NULL; - - if(errCode == STATUS_TIMEOUT) - SetLastError(WAIT_TIMEOUT); - else - BaseSetLastNTError(errCode); - - return FALSE; - } - - *lpCompletionKey = CompletionKey; - *lpNumberOfBytesTransferred = IoStatus.Information; - - if (!NT_SUCCESS(IoStatus.Status)){ - //failed io operation - BaseSetLastNTError(IoStatus.Status); - return FALSE; - } - - return TRUE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -PostQueuedCompletionStatus( - HANDLE CompletionHandle, - DWORD dwNumberOfBytesTransferred, - ULONG_PTR dwCompletionKey, - LPOVERLAPPED lpOverlapped - ) -{ - NTSTATUS errCode; - - errCode = NtSetIoCompletion(CompletionHandle, - (PVOID)dwCompletionKey, // KeyContext - (PVOID)lpOverlapped, // ApcContext - STATUS_SUCCESS, // IoStatusBlock->Status - dwNumberOfBytesTransferred); // IoStatusBlock->Information - - if ( !NT_SUCCESS(errCode) ) - { - BaseSetLastNTError (errCode); - return FALSE; - } - return TRUE; + if (!(NT_SUCCESS(Status)) || (Status == STATUS_TIMEOUT)) + { + /* Clear out the overlapped output */ + *lpOverlapped = NULL; + + /* Check what kind of error we got */ + if (Status == STATUS_TIMEOUT) + { + /* Timeout error is set directly since there's no conversion */ + SetLastError(WAIT_TIMEOUT); + } + else + { + /* Any other error gets converted */ + BaseSetLastNTError(Status); + } + + /* This is a failure case */ + return FALSE; + } + + /* Write back the output parameters */ + *lpCompletionKey = CompletionKey; + *lpNumberOfBytesTransferred = IoStatus.Information; + + /* Check for error */ + if (!NT_SUCCESS(IoStatus.Status)) + { + /* Convert and fail */ + BaseSetLastNTError(IoStatus.Status); + return FALSE; + } + + /* Return success */ + return TRUE; +} + +/* + * @implemented + */ +BOOL +WINAPI +PostQueuedCompletionStatus(IN HANDLE CompletionHandle, + IN DWORD dwNumberOfBytesTransferred, + IN ULONG_PTR dwCompletionKey, + IN LPOVERLAPPED lpOverlapped) +{ + NTSTATUS Status; + + /* Call the native API */ + Status = NtSetIoCompletion(CompletionHandle, + (PVOID)dwCompletionKey, + (PVOID)lpOverlapped, + STATUS_SUCCESS, + dwNumberOfBytesTransferred); + if (!NT_SUCCESS(Status)) + { + /* Convert the error and fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Success path */ + return TRUE; }
/* @@ -211,7 +207,7 @@ }
/* Fail if we had an error -- the last error is already set */ - if (WaitStatus != 0) return FALSE; + if (WaitStatus) return FALSE; }
/* Return bytes transferred */ @@ -234,24 +230,24 @@ */ BOOL WINAPI -BindIoCompletionCallback(HANDLE FileHandle, - LPOVERLAPPED_COMPLETION_ROUTINE Function, - ULONG Flags) -{ - NTSTATUS Status = 0; - - DPRINT("(%p, %p, %d)\n", FileHandle, Function, Flags); - +BindIoCompletionCallback(IN HANDLE FileHandle, + IN LPOVERLAPPED_COMPLETION_ROUTINE Function, + IN ULONG Flags) +{ + NTSTATUS Status; + + /* Call RTL */ Status = RtlSetIoCompletionCallback(FileHandle, (PIO_APC_ROUTINE)Function, Flags); - if (!NT_SUCCESS(Status)) { - SetLastError(RtlNtStatusToDosError(Status)); - return FALSE; - } - + /* Set error and fail */ + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return success */ return TRUE; }