From 216530f230d270c6bc86f9254f37ed58b843e44d Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 28 Nov 2019 18:19:21 -0600 Subject: [PATCH] kernelbase: Implement GetOverlappedResultEx(). Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38830 Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- .../api-ms-win-core-io-l1-1-1.spec | 2 +- dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/tests/pipe.c | 54 +++++++++++++++++++ dlls/kernelbase/file.c | 25 +++++++-- dlls/kernelbase/kernelbase.spec | 2 +- include/winbase.h | 1 + 6 files changed, 79 insertions(+), 6 deletions(-) diff --git a/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec b/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec index 907c0b4a97c..87039aef0c9 100644 --- a/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec +++ b/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec @@ -4,7 +4,7 @@ @ stdcall CreateIoCompletionPort(long long long long) kernel32.CreateIoCompletionPort @ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) kernel32.DeviceIoControl @ stdcall GetOverlappedResult(long ptr ptr long) kernel32.GetOverlappedResult -@ stub GetOverlappedResultEx +@ stdcall GetOverlappedResultEx(long ptr ptr long long) kernel32.GetOverlappedResultEx @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) kernel32.GetQueuedCompletionStatus @ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) kernel32.GetQueuedCompletionStatusEx @ stdcall PostQueuedCompletionStatus(long long ptr ptr) kernel32.PostQueuedCompletionStatus diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 82e10850a8c..172be2a6e26 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -760,6 +760,7 @@ @ stdcall GetNumberOfConsoleMouseButtons(ptr) @ stdcall -import GetOEMCP() @ stdcall -import GetOverlappedResult(long ptr ptr long) +@ stdcall -import GetOverlappedResultEx(long ptr ptr long long) @ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) @ stdcall GetPackageFullName(long ptr ptr) @ stdcall -import GetPhysicallyInstalledSystemMemory(ptr) diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index d8d5726f1a5..20f3450c6d0 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -42,6 +42,7 @@ static BOOL (WINAPI *pGetNamedPipeClientProcessId)(HANDLE,ULONG*); static BOOL (WINAPI *pGetNamedPipeServerProcessId)(HANDLE,ULONG*); static BOOL (WINAPI *pGetNamedPipeClientSessionId)(HANDLE,ULONG*); static BOOL (WINAPI *pGetNamedPipeServerSessionId)(HANDLE,ULONG*); +static BOOL (WINAPI *pGetOverlappedResultEx)(HANDLE,OVERLAPPED *,DWORD *,DWORD,BOOL); static BOOL user_apc_ran; static void CALLBACK user_apc(ULONG_PTR param) @@ -4065,6 +4066,57 @@ static void test_nowait(DWORD pipe_type) ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n"); } +static void test_GetOverlappedResultEx(void) +{ + HANDLE client, server; + OVERLAPPED ovl; + char buffer[8000]; + DWORD ret_size; + BOOL ret; + + if (!pGetOverlappedResultEx) + { + win_skip("GetOverlappedResultEx() is not available\n"); + return; + } + + create_overlapped_pipe(PIPE_TYPE_BYTE, &client, &server); + + overlapped_write_async(client, buffer, sizeof(buffer), &ovl); + + user_apc_ran = FALSE; + QueueUserAPC(user_apc, GetCurrentThread(), 0); + + SetLastError(0xdeadbeef); + ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, FALSE); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError()); + ok(!user_apc_ran, "APC should not have run\n"); + + SetLastError(0xdeadbeef); + ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 0, TRUE); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError()); + ok(!user_apc_ran, "APC should not have run\n"); + + SetLastError(0xdeadbeef); + ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, FALSE); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError()); + ok(!user_apc_ran, "APC should not have run\n"); + + SetLastError(0xdeadbeef); + ret = pGetOverlappedResultEx(client, &ovl, &ret_size, 10, TRUE); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_IO_COMPLETION, "wrong error %u\n", GetLastError()); + ok(user_apc_ran, "APC should have run\n"); + + CloseHandle(ovl.hEvent); + + CloseHandle(client); + CloseHandle(server); +} + START_TEST(pipe) { char **argv; @@ -4080,6 +4132,7 @@ START_TEST(pipe) pGetNamedPipeServerProcessId = (void *) GetProcAddress(hmod, "GetNamedPipeServerProcessId"); pGetNamedPipeClientSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeClientSessionId"); pGetNamedPipeServerSessionId = (void *) GetProcAddress(hmod, "GetNamedPipeServerSessionId"); + pGetOverlappedResultEx = (void *)GetProcAddress(hmod, "GetOverlappedResultEx"); argc = winetest_get_mainargs(&argv); @@ -4134,4 +4187,5 @@ START_TEST(pipe) test_wait_pipe(); test_nowait(PIPE_TYPE_BYTE); test_nowait(PIPE_TYPE_MESSAGE); + test_GetOverlappedResultEx(); } diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index aa2ebfcc699..77a73985806 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -2003,20 +2003,37 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetFileType( HANDLE file ) BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResult( HANDLE file, LPOVERLAPPED overlapped, LPDWORD result, BOOL wait ) { - NTSTATUS status; + return GetOverlappedResultEx( file, overlapped, result, wait ? INFINITE : 0, FALSE ); +} - TRACE( "(%p %p %p %x)\n", file, overlapped, result, wait ); + +/*********************************************************************** + * GetOverlappedResultEx (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH GetOverlappedResultEx( HANDLE file, OVERLAPPED *overlapped, + DWORD *result, DWORD timeout, BOOL alertable ) +{ + NTSTATUS status; + DWORD ret; + + TRACE( "(%p %p %p %u %d)\n", file, overlapped, result, timeout, alertable ); status = overlapped->Internal; if (status == STATUS_PENDING) { - if (!wait) + if (!timeout) { SetLastError( ERROR_IO_INCOMPLETE ); return FALSE; } - if (WaitForSingleObject( overlapped->hEvent ? overlapped->hEvent : file, INFINITE ) == WAIT_FAILED) + ret = WaitForSingleObjectEx( overlapped->hEvent ? overlapped->hEvent : file, timeout, alertable ); + if (ret == WAIT_FAILED) return FALSE; + else if (ret) + { + SetLastError( ret ); + return FALSE; + } status = overlapped->Internal; if (status == STATUS_PENDING) status = STATUS_SUCCESS; diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 14ee402089c..ed5d1f73f85 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -584,7 +584,7 @@ # @ stub GetOsManufacturingMode # @ stub GetOsSafeBootMode @ stdcall GetOverlappedResult(long ptr ptr long) -# @ stub GetOverlappedResultEx +@ stdcall GetOverlappedResultEx(long ptr ptr long long) # @ stub GetPackageApplicationContext # @ stub GetPackageApplicationIds # @ stub GetPackageApplicationProperty diff --git a/include/winbase.h b/include/winbase.h index 8b30c5a69a6..2d01dcb606b 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2215,6 +2215,7 @@ WINBASEAPI BOOL WINAPI GetNumaProximityNodeEx(ULONG,PUSHORT); WINADVAPI BOOL WINAPI GetNumberOfEventLogRecords(HANDLE,PDWORD); WINADVAPI BOOL WINAPI GetOldestEventLogRecord(HANDLE,PDWORD); WINBASEAPI BOOL WINAPI GetOverlappedResult(HANDLE,LPOVERLAPPED,LPDWORD,BOOL); +WINBASEAPI BOOL WINAPI GetOverlappedResultEx(HANDLE,OVERLAPPED*,DWORD*,DWORD,BOOL); WINBASEAPI DWORD WINAPI GetPriorityClass(HANDLE); WINADVAPI BOOL WINAPI GetPrivateObjectSecurity(PSECURITY_DESCRIPTOR,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR,DWORD,PDWORD); WINBASEAPI UINT WINAPI GetPrivateProfileIntA(LPCSTR,LPCSTR,INT,LPCSTR);