[PATCH v2 2/3] winhttp: Execute WinHttpQueryDataAvailable() synchronously if the data is available.

Paul Gofman pgofman at codeweavers.com
Wed Aug 25 04:57:53 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
    v2:
        - fix test for Win7;
        - set last error to reflect actual async status.

 dlls/winhttp/request.c            |  9 ++++++---
 dlls/winhttp/tests/notification.c | 11 +++++++++++
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index b8f5817737e..03f895a7fdb 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -2873,6 +2873,7 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
 {
     DWORD ret;
     struct request *request;
+    BOOL async;
 
     TRACE("%p, %p\n", hrequest, available);
 
@@ -2888,7 +2889,8 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
         return FALSE;
     }
 
-    if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC)
+    if ((async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) && !end_of_read_data( request )
+                                                                   && !query_data_ready( request ))
     {
         struct query_data *q;
 
@@ -2902,12 +2904,13 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
             release_object( &request->hdr );
             free( q );
         }
+        else ret = ERROR_IO_PENDING;
     }
-    else ret = query_data_available( request, available, FALSE );
+    else ret = query_data_available( request, available, async );
 
     release_object( &request->hdr );
     SetLastError( ret );
-    return !ret;
+    return !ret || ret == ERROR_IO_PENDING;
 }
 
 static void CALLBACK task_read_data( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work )
diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c
index 98e4024867f..7d1bfa78a49 100644
--- a/dlls/winhttp/tests/notification.c
+++ b/dlls/winhttp/tests/notification.c
@@ -71,6 +71,8 @@ struct info
     unsigned int index;
     HANDLE wait;
     unsigned int line;
+    DWORD last_thread_id;
+    DWORD last_status;
 };
 
 struct test_request
@@ -85,6 +87,9 @@ static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DW
     BOOL status_ok, function_ok;
     struct info *info = (struct info *)context;
 
+    info->last_status = status;
+    info->last_thread_id = GetCurrentThreadId();
+
     if (status == WINHTTP_CALLBACK_STATUS_HANDLE_CREATED)
     {
         DWORD size = sizeof(struct info *);
@@ -177,6 +182,8 @@ static void setup_test( struct info *info, enum api function, unsigned int line
     ok_(__FILE__,line)(info->test[info->index].function == function,
                        "unexpected function %u, expected %u. probably some notifications were missing\n",
                        info->test[info->index].function, function);
+    info->last_thread_id = 0xdeadbeef;
+    info->last_status = 0xdeadbeef;
 }
 
 static void end_test( struct info *info, unsigned int line )
@@ -597,6 +604,10 @@ static void test_async( void )
     ok(err == ERROR_SUCCESS || err == ERROR_IO_PENDING || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
 
     WaitForSingleObject( info.wait, INFINITE );
+    ok(info.last_status == WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, "got status %#x.\n", status);
+    ok((err == ERROR_SUCCESS && info.last_thread_id == GetCurrentThreadId())
+            || (err == ERROR_IO_PENDING && info.last_thread_id != GetCurrentThreadId()),
+            "Got unexpected thread %#x, err %#x.\n", info.last_thread_id, err);
 
     setup_test( &info, winhttp_read_data, __LINE__ );
     ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
-- 
2.31.1




More information about the wine-devel mailing list