diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index c42ec44b66a..529402825e1 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -291,7 +291,7 @@ @ stdcall CreateHardLinkTransactedA(str str ptr ptr) @ stdcall CreateHardLinkTransactedW(wstr wstr ptr ptr) @ stdcall CreateHardLinkW(wstr wstr ptr) -@ stdcall CreateIoCompletionPort(long long long long) +@ stdcall -import CreateIoCompletionPort(long long long long) @ stdcall CreateJobObjectA(ptr str) @ stdcall CreateJobObjectW(ptr wstr) # @ stub CreateJobSet @@ -803,8 +803,8 @@ @ stdcall GetProfileSectionW(wstr ptr long) @ stdcall GetProfileStringA(str str str ptr long) @ stdcall GetProfileStringW(wstr wstr wstr ptr long) -@ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) -@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) +@ stdcall -import GetQueuedCompletionStatus(long ptr ptr ptr long) +@ stdcall -import GetQueuedCompletionStatusEx(ptr ptr long ptr long long) @ stub -i386 GetSLCallbackTarget @ stub -i386 GetSLCallbackTemplate @ stdcall GetShortPathNameA(str ptr long) @@ -1139,7 +1139,7 @@ @ stdcall PeekConsoleInputA(ptr ptr long ptr) @ stdcall PeekConsoleInputW(ptr ptr long ptr) @ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) -@ stdcall PostQueuedCompletionStatus(long long ptr ptr) +@ stdcall -import PostQueuedCompletionStatus(long long ptr ptr) @ stdcall PowerClearRequest(long long) @ stdcall PowerCreateRequest(ptr) @ stdcall PowerSetRequest(long long) diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index be92aee76b9..e4c54c52685 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -1598,121 +1598,6 @@ BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout) } -/****************************************************************************** - * CreateIoCompletionPort (KERNEL32.@) - */ -HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort, - ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads) -{ - NTSTATUS status; - HANDLE ret = 0; - - TRACE("(%p, %p, %08lx, %08x)\n", - hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads); - - if (hExistingCompletionPort && hFileHandle == INVALID_HANDLE_VALUE) - { - SetLastError( ERROR_INVALID_PARAMETER); - return NULL; - } - - if (hExistingCompletionPort) - ret = hExistingCompletionPort; - else - { - status = NtCreateIoCompletion( &ret, IO_COMPLETION_ALL_ACCESS, NULL, dwNumberOfConcurrentThreads ); - if (status != STATUS_SUCCESS) goto fail; - } - - if (hFileHandle != INVALID_HANDLE_VALUE) - { - FILE_COMPLETION_INFORMATION info; - IO_STATUS_BLOCK iosb; - - info.CompletionPort = ret; - info.CompletionKey = CompletionKey; - status = NtSetInformationFile( hFileHandle, &iosb, &info, sizeof(info), FileCompletionInformation ); - if (status != STATUS_SUCCESS) goto fail; - } - - return ret; - -fail: - if (ret && !hExistingCompletionPort) - CloseHandle( ret ); - SetLastError( RtlNtStatusToDosError(status) ); - return 0; -} - -/****************************************************************************** - * GetQueuedCompletionStatus (KERNEL32.@) - */ -BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, - PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped, - DWORD dwMilliseconds ) -{ - NTSTATUS status; - IO_STATUS_BLOCK iosb; - LARGE_INTEGER wait_time; - - TRACE("(%p,%p,%p,%p,%d)\n", - CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds); - - *lpOverlapped = NULL; - - status = NtRemoveIoCompletion( CompletionPort, pCompletionKey, (PULONG_PTR)lpOverlapped, - &iosb, get_nt_timeout( &wait_time, dwMilliseconds ) ); - if (status == STATUS_SUCCESS) - { - *lpNumberOfBytesTransferred = iosb.Information; - if (iosb.u.Status >= 0) return TRUE; - SetLastError( RtlNtStatusToDosError(iosb.u.Status) ); - return FALSE; - } - - if (status == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT ); - else SetLastError( RtlNtStatusToDosError(status) ); - return FALSE; -} - -/****************************************************************************** - * GetQueuedCompletionStatusEx (KERNEL32.@) - */ -BOOL WINAPI GetQueuedCompletionStatusEx( HANDLE port, OVERLAPPED_ENTRY *entries, ULONG count, - ULONG *written, DWORD timeout, BOOL alertable ) -{ - LARGE_INTEGER time; - NTSTATUS ret; - - TRACE("%p %p %u %p %u %u\n", port, entries, count, written, timeout, alertable); - - ret = NtRemoveIoCompletionEx( port, (FILE_IO_COMPLETION_INFORMATION *)entries, count, - written, get_nt_timeout( &time, timeout ), alertable ); - if (ret == STATUS_SUCCESS) return TRUE; - else if (ret == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT ); - else if (ret == STATUS_USER_APC) SetLastError( WAIT_IO_COMPLETION ); - else SetLastError( RtlNtStatusToDosError(ret) ); - return FALSE; -} - -/****************************************************************************** - * PostQueuedCompletionStatus (KERNEL32.@) - */ -BOOL WINAPI PostQueuedCompletionStatus( HANDLE CompletionPort, DWORD dwNumberOfBytes, - ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped) -{ - NTSTATUS status; - - TRACE("%p %d %08lx %p\n", CompletionPort, dwNumberOfBytes, dwCompletionKey, lpOverlapped ); - - status = NtSetIoCompletion( CompletionPort, dwCompletionKey, (ULONG_PTR)lpOverlapped, - STATUS_SUCCESS, dwNumberOfBytes ); - - if (status == STATUS_SUCCESS) return TRUE; - SetLastError( RtlNtStatusToDosError(status) ); - return FALSE; -} - /****************************************************************************** * BindIoCompletionCallback (KERNEL32.@) */ diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 52982b23e3e..2d4b6c057fc 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -193,7 +193,7 @@ @ stdcall CreateFileW(wstr long long ptr long long long) kernel32.CreateFileW @ stdcall CreateHardLinkA(str str ptr) kernel32.CreateHardLinkA @ stdcall CreateHardLinkW(wstr wstr ptr) kernel32.CreateHardLinkW -@ stdcall CreateIoCompletionPort(long long long long) kernel32.CreateIoCompletionPort +@ stdcall CreateIoCompletionPort(long long long long) @ stdcall CreateMemoryResourceNotification(long) kernel32.CreateMemoryResourceNotification @ stdcall CreateMutexA(ptr long str) @ stdcall CreateMutexExA(ptr str long long) @@ -645,8 +645,8 @@ @ stub GetPtrCalDataArray # @ stub GetPublisherCacheFolder # @ stub GetPublisherRootFolder -@ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) kernel32.GetQueuedCompletionStatus -@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) kernel32.GetQueuedCompletionStatusEx +@ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) +@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) # @ stub GetRegistryExtensionFlags # @ stub GetRoamingLastObservedChangeTime @ stdcall GetSecurityDescriptorControl(ptr ptr ptr) @@ -1160,7 +1160,7 @@ @ stdcall PerfStartProviderEx(ptr ptr ptr) @ stdcall PerfStopProvider(long) # @ stub PoolPerAppKeyStateInternal -@ stdcall PostQueuedCompletionStatus(long long ptr ptr) kernel32.PostQueuedCompletionStatus +@ stdcall PostQueuedCompletionStatus(long long ptr ptr) # @ stub PrefetchVirtualMemory @ stub PrivCopyFileExW @ stdcall PrivilegeCheck(ptr ptr ptr) diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index ba64b853ed5..bb5ae935e00 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -757,3 +757,112 @@ BOOL WINAPI DECLSPEC_HOTPATCH SleepConditionVariableSRW( RTL_CONDITION_VARIABLE return set_ntstatus( RtlSleepConditionVariableSRW( variable, lock, get_nt_timeout( &time, timeout ), flags )); } + + +/*********************************************************************** + * I/O completions + ***********************************************************************/ + + +/****************************************************************************** + * CreateIoCompletionPort (kernelbase.@) + */ +HANDLE WINAPI DECLSPEC_HOTPATCH CreateIoCompletionPort( HANDLE handle, HANDLE port, + ULONG_PTR key, DWORD threads ) +{ + FILE_COMPLETION_INFORMATION info; + IO_STATUS_BLOCK iosb; + NTSTATUS status; + HANDLE ret = port; + + TRACE( "(%p, %p, %08lx, %08x)\n", handle, port, key, threads ); + + if (!port) + { + if ((status = NtCreateIoCompletion( &ret, IO_COMPLETION_ALL_ACCESS, NULL, threads ))) + { + SetLastError( RtlNtStatusToDosError(status) ); + return 0; + } + } + else if (handle == INVALID_HANDLE_VALUE) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + if (handle != INVALID_HANDLE_VALUE) + { + info.CompletionPort = ret; + info.CompletionKey = key; + if ((status = NtSetInformationFile( handle, &iosb, &info, sizeof(info), FileCompletionInformation ))) + { + if (!port) CloseHandle( ret ); + SetLastError( RtlNtStatusToDosError(status) ); + return 0; + } + } + return ret; +} + + +/****************************************************************************** + * GetQueuedCompletionStatus (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatus( HANDLE port, LPDWORD count, PULONG_PTR key, + LPOVERLAPPED *overlapped, DWORD timeout ) +{ + NTSTATUS status; + IO_STATUS_BLOCK iosb; + LARGE_INTEGER wait_time; + + TRACE( "(%p,%p,%p,%p,%d)\n", port, count, key, overlapped, timeout ); + + *overlapped = NULL; + status = NtRemoveIoCompletion( port, key, (PULONG_PTR)overlapped, &iosb, + get_nt_timeout( &wait_time, timeout ) ); + if (status == STATUS_SUCCESS) + { + *count = iosb.Information; + if (iosb.u.Status >= 0) return TRUE; + SetLastError( RtlNtStatusToDosError(iosb.u.Status) ); + return FALSE; + } + + if (status == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT ); + else SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; +} + +/****************************************************************************** + * GetQueuedCompletionStatusEx (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetQueuedCompletionStatusEx( HANDLE port, OVERLAPPED_ENTRY *entries, + ULONG count, ULONG *written, + DWORD timeout, BOOL alertable ) +{ + LARGE_INTEGER time; + NTSTATUS ret; + + TRACE( "%p %p %u %p %u %u\n", port, entries, count, written, timeout, alertable ); + + ret = NtRemoveIoCompletionEx( port, (FILE_IO_COMPLETION_INFORMATION *)entries, count, + written, get_nt_timeout( &time, timeout ), alertable ); + if (ret == STATUS_SUCCESS) return TRUE; + else if (ret == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT ); + else if (ret == STATUS_USER_APC) SetLastError( WAIT_IO_COMPLETION ); + else SetLastError( RtlNtStatusToDosError(ret) ); + return FALSE; +} + + +/****************************************************************************** + * PostQueuedCompletionStatus (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH PostQueuedCompletionStatus( HANDLE port, DWORD count, + ULONG_PTR key, LPOVERLAPPED overlapped ) +{ + TRACE( "%p %d %08lx %p\n", port, count, key, overlapped ); + + return set_ntstatus( NtSetIoCompletion( port, key, (ULONG_PTR)overlapped, STATUS_SUCCESS, count )); +}