Hans Leidekker : winhttp: Implement WinHttpReadData.

Alexandre Julliard julliard at winehq.org
Tue Aug 26 07:07:43 CDT 2008


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Aug 26 11:04:43 2008 +0200

winhttp: Implement WinHttpReadData.

---

 dlls/winhttp/main.c          |   12 ----
 dlls/winhttp/request.c       |  133 ++++++++++++++++++++++++++++++++++++++++++
 dlls/winhttp/tests/winhttp.c |    8 +--
 3 files changed, 136 insertions(+), 17 deletions(-)

diff --git a/dlls/winhttp/main.c b/dlls/winhttp/main.c
index 82f0a61..220cc51 100644
--- a/dlls/winhttp/main.c
+++ b/dlls/winhttp/main.c
@@ -106,18 +106,6 @@ BOOL WINAPI WinHttpSetOption (HINTERNET hInternet, DWORD dwOption, LPVOID lpBuff
 }
 
 /***********************************************************************
- *          WinHttpReadData (winhttp.@)
- */
-BOOL WINAPI WinHttpReadData (HINTERNET hInternet, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead,
-                             LPDWORD lpdwNumberOfBytesRead)
-{
-    FIXME("(%d): stub\n", dwNumberOfBytesToRead);
-
-    SetLastError(ERROR_NOT_SUPPORTED);
-    return FALSE;
-}
-
-/***********************************************************************
  *          WinHttpWriteData (winhttp.@)
  */
 BOOL WINAPI WinHttpWriteData (HINTERNET hRequest, LPCVOID lpBuffer,
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 14b57cc..21e59c7 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -976,3 +976,136 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
     release_object( &request->hdr );
     return ret;
 }
+
+static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+{
+    DWORD to_read;
+    int bytes_read;
+
+    to_read = min( size, request->content_length - request->content_read );
+    if (!netconn_recv( &request->netconn, buffer, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
+    {
+        if (bytes_read != to_read)
+        {
+            ERR("not all data received %d/%d\n", bytes_read, to_read);
+        }
+        /* always return success, even if the network layer returns an error */
+        *read = 0;
+        return TRUE;
+    }
+    request->content_read += bytes_read;
+    *read = bytes_read;
+    return TRUE;
+}
+
+static DWORD get_chunk_size( const char *buffer )
+{
+    const char *p;
+    DWORD size = 0;
+
+    for (p = buffer; *p; p++)
+    {
+        if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
+        else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
+        else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
+        else if (*p == ';') break;
+    }
+    return size;
+}
+
+static BOOL read_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
+{
+    char reply[MAX_REPLY_LEN], *p = buffer;
+    DWORD buflen, to_read, to_write = size;
+    int bytes_read;
+
+    *read = 0;
+    for (;;)
+    {
+        if (*read == size) break;
+
+        if (request->content_length == ~0UL) /* new chunk */
+        {
+            buflen = sizeof(reply);
+            if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break;
+
+            if (!(request->content_length = get_chunk_size( reply )))
+            {
+                /* zero sized chunk marks end of transfer; read any trailing headers and return */
+                receive_response( request, FALSE );
+                break;
+            }
+        }
+        to_read = min( to_write, request->content_length - request->content_read );
+
+        if (!netconn_recv( &request->netconn, p, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
+        {
+            if (bytes_read != to_read)
+            {
+                ERR("Not all data received %d/%d\n", bytes_read, to_read);
+            }
+            /* always return success, even if the network layer returns an error */
+            *read = 0;
+            break;
+        }
+        if (!bytes_read) break;
+
+        request->content_read += bytes_read;
+        to_write -= bytes_read;
+        *read += bytes_read;
+        p += bytes_read;
+
+        if (request->content_read == request->content_length) /* chunk complete */
+        {
+            request->content_read = 0;
+            request->content_length = ~0UL;
+
+            buflen = sizeof(reply);
+            if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
+            {
+                ERR("Malformed chunk\n");
+                *read = 0;
+                break;
+            }
+        }
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *          WinHttpReadData (winhttp.@)
+ */
+BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read )
+{
+    static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
+
+    BOOL ret;
+    request_t *request;
+    WCHAR encoding[20];
+    DWORD buflen = sizeof(encoding);
+
+    TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
+
+    if (!(request = (request_t *)grab_object( hrequest )))
+    {
+        set_last_error( ERROR_INVALID_HANDLE );
+        return FALSE;
+    }
+    if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
+    {
+        release_object( &request->hdr );
+        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        return FALSE;
+    }
+
+    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
+        !strcmpiW( encoding, chunked ))
+    {
+        ret = read_data_chunked( request, buffer, to_read, read, request->hdr.flags & WINHTTP_FLAG_ASYNC );
+    }
+    else
+        ret = read_data( request, buffer, to_read, read, request->hdr.flags & WINHTTP_FLAG_ASYNC );
+
+    release_object( &request->hdr );
+    return ret;
+}
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index a247938..fa0249d 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -126,12 +126,10 @@ static void test_SendRequest (void)
 
     bytes_rw = -1;
     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
-    todo_wine ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
+    ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
 
-    todo_wine ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n",
-        bytes_rw, lstrlen(test_post));
-    todo_wine ok(strncmp(buffer, test_post, bytes_rw) == 0,
-        "Data read did not match, got '%s'.\n", buffer);
+    ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", bytes_rw, lstrlen(test_post));
+    ok(strncmp(buffer, test_post, bytes_rw) == 0, "Data read did not match, got '%s'.\n", buffer);
 
     ret = WinHttpCloseHandle(request);
     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);




More information about the wine-cvs mailing list