Hans Leidekker : rpcrt4: Allow all HTTP read requests to be cancelled.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 13 10:25:31 CDT 2015


Module: wine
Branch: master
Commit: f4c59406566839c8c8cc239e80076a0c8eb62491
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f4c59406566839c8c8cc239e80076a0c8eb62491

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed May 13 12:13:47 2015 +0200

rpcrt4: Allow all HTTP read requests to be cancelled.

---

 dlls/rpcrt4/rpc_transport.c | 111 +++++++++++++++++++++++---------------------
 1 file changed, 57 insertions(+), 54 deletions(-)

diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c
index 337e63d..34f434d 100644
--- a/dlls/rpcrt4/rpc_transport.c
+++ b/dlls/rpcrt4/rpc_transport.c
@@ -2207,9 +2207,47 @@ static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
     return RPC_S_OK;
 }
 
+static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event,
+                                  void *buffer, unsigned int count)
+{
+    char *buf = buffer;
+    BOOL ret;
+    unsigned int bytes_left = count;
+    RPC_STATUS status = RPC_S_OK;
+
+    async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
+
+    while (bytes_left)
+    {
+        async_data->inet_buffers.dwBufferLength = bytes_left;
+        prepare_async_request(async_data);
+        ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0);
+        status = wait_async_request(async_data, ret, cancel_event);
+        if (status != RPC_S_OK)
+        {
+            if (status == RPC_S_CALL_CANCELLED)
+                TRACE("call cancelled\n");
+            break;
+        }
+
+        if (!async_data->inet_buffers.dwBufferLength)
+            break;
+        memcpy(buf, async_data->inet_buffers.lpvBuffer,
+               async_data->inet_buffers.dwBufferLength);
+
+        bytes_left -= async_data->inet_buffers.dwBufferLength;
+        buf += async_data->inet_buffers.dwBufferLength;
+    }
+
+    HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
+    async_data->inet_buffers.lpvBuffer = NULL;
+
+    TRACE("%p %p %u -> %u\n", req, buffer, count, status);
+    return status == RPC_S_OK ? count : -1;
+}
+
 static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
 {
-    DWORD bytes_read;
     BYTE buf[20];
     BOOL ret;
     RPC_STATUS status;
@@ -2224,7 +2262,7 @@ static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data,
     status = rpcrt4_http_check_response(req);
     if (status != RPC_S_OK) return status;
 
-    InternetReadFile(req, buf, sizeof(buf), &bytes_read);
+    rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf));
     /* FIXME: do something with retrieved data */
 
     return RPC_S_OK;
@@ -2284,14 +2322,13 @@ static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsync
     return RPC_S_OK;
 }
 
-static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
+static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcHttpAsyncData *async_data,
+                                               HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data)
 {
-    BOOL ret;
-    DWORD bytes_read;
     unsigned short data_len;
+    unsigned int size;
 
-    ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
-    if (!ret)
+    if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0)
         return RPC_S_SERVER_UNAVAILABLE;
     if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
     {
@@ -2300,8 +2337,8 @@ static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr
         return RPC_S_PROTOCOL_ERROR;
     }
 
-    ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
-    if (!ret)
+    size = sizeof(hdr->http) - sizeof(hdr->common);
+    if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0)
         return RPC_S_SERVER_UNAVAILABLE;
 
     data_len = hdr->common.frag_len - sizeof(hdr->http);
@@ -2310,8 +2347,7 @@ static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr
         *data = HeapAlloc(GetProcessHeap(), 0, data_len);
         if (!*data)
             return RPC_S_OUT_OF_RESOURCES;
-        ret = InternetReadFile(request, *data, data_len, &bytes_read);
-        if (!ret)
+        if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0)
         {
             HeapFree(GetProcessHeap(), 0, *data);
             return RPC_S_SERVER_UNAVAILABLE;
@@ -2341,7 +2377,6 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
     BYTE *data_from_server;
     RpcPktHdr pkt_from_server;
     ULONG field1, field3;
-    DWORD bytes_read;
     BYTE buf[20];
 
     if (!authorized)
@@ -2351,7 +2386,7 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
         if (status != RPC_S_OK) return status;
     }
     else
-        InternetReadFile(out_request, buf, sizeof(buf), &bytes_read);
+        rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf));
 
     hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
     if (!hdr) return RPC_S_OUT_OF_RESOURCES;
@@ -2373,8 +2408,8 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
     status = rpcrt4_http_check_response(out_request);
     if (status != RPC_S_OK) return status;
 
-    status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
-                                          &data_from_server);
+    status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
+                                          &pkt_from_server, &data_from_server);
     if (status != RPC_S_OK) return status;
     status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
                                             &field1);
@@ -2384,8 +2419,8 @@ static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsy
 
     for (;;)
     {
-        status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
-                                              &data_from_server);
+        status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
+                                              &pkt_from_server, &data_from_server);
         if (status != RPC_S_OK) return status;
         if (pkt_from_server.http.flags != 0x0001) break;
 
@@ -2790,7 +2825,7 @@ static RPC_STATUS insert_authorization_header(HINTERNET request, ULONG scheme, c
     return status;
 }
 
-static void drain_content(HINTERNET request)
+static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
 {
     DWORD count, len = 0, size = sizeof(len);
     char buf[2048];
@@ -2800,7 +2835,7 @@ static void drain_content(HINTERNET request)
     for (;;)
     {
         count = min(sizeof(buf), len);
-        if (!InternetReadFile(request, buf, count, &count) || !count) return;
+        if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return;
         len -= count;
     }
 }
@@ -2827,7 +2862,7 @@ static RPC_STATUS authorize_request(RpcConnection_http *httpc, HINTERNET request
 
         status = rpcrt4_http_check_response(request);
         if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
-        drain_content(request);
+        drain_content(request, httpc->async_data, httpc->cancel_event);
     }
 
     if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
@@ -2967,7 +3002,7 @@ static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
             HeapFree(GetProcessHeap(), 0, url);
             return status;
         }
-        drain_content(httpc->in_request);
+        drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event);
     }
 
     httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
@@ -3033,39 +3068,7 @@ static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
                                 void *buffer, unsigned int count)
 {
   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
-  char *buf = buffer;
-  BOOL ret;
-  unsigned int bytes_left = count;
-  RPC_STATUS status = RPC_S_OK;
-
-  httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
-
-  while (bytes_left)
-  {
-    httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
-    prepare_async_request(httpc->async_data);
-    ret = InternetReadFileExW(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
-    status = wait_async_request(httpc->async_data, ret, httpc->cancel_event);
-    if(status != RPC_S_OK) {
-        if(status == RPC_S_CALL_CANCELLED)
-            TRACE("call cancelled\n");
-        break;
-    }
-
-    if(!httpc->async_data->inet_buffers.dwBufferLength)
-        break;
-    memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
-           httpc->async_data->inet_buffers.dwBufferLength);
-
-    bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
-    buf += httpc->async_data->inet_buffers.dwBufferLength;
-  }
-
-  HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
-  httpc->async_data->inet_buffers.lpvBuffer = NULL;
-
-  TRACE("%p %p %u -> %u\n", httpc->out_request, buffer, count, status);
-  return status == RPC_S_OK ? count : -1;
+  return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count);
 }
 
 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)




More information about the wine-cvs mailing list