[PATCH] wininet: Use 64-bit size for contentLength.

Daniel Lehman dlehman25 at gmail.com
Mon Aug 19 23:26:44 CDT 2019


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>

---
not sure how to add a permanent standalone test for this
because of how long it runs, but i tested it locally:

1) create a file > 4GB:
    sudo dd if=/dev/zero of=/var/lib/tomcat8/webapps/ROOT/6GBFILE bs=1G count=6

2) add wininet test (run on Ubuntu 18.04.3 and Win10 1903):
- wine/dlls/wininet/tests/http.c

static void test_large_file(void)
{
    BOOL res;
    DWORD nread;
    DWORD64 sum;
    HINTERNET session;
    HINTERNET request;
    HINTERNET connection;
    const char *types[2] = { "*", NULL };
    char buffer[65536] = {0};

    session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    ok(!!session, "failed gle %d\n", GetLastError());

    connection = InternetConnectA(session,
                    "192.168.2.242", 8080,
                    NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
    ok(!!connection, "failed gle %d\n", GetLastError());

    request = HttpOpenRequestA(connection, "GET", "/6GBFILE", NULL, NULL, types,
                           INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
                           0xdeadbead);
    ok(!!request, "failed gle %d\n", GetLastError());

    res = HttpSendRequestA(request, "", -1, NULL, 0);
    ok(res, "failed gle %d\n", GetLastError());

    sum = 0;
    nread = 0;
    do
    {
        res = InternetReadFile(request, buffer, sizeof(buffer), &nread);
        ok(res, "failed gle %d\n", GetLastError());
        sum += nread;
    } while (nread > 0);
    ok(sum == (DWORD64)0x180000000, "failed to read all bytes: %x%08x\n",
        (DWORD)(sum >> 32), (DWORD)sum);

    InternetCloseHandle(request);
    InternetCloseHandle(connection);
    InternetCloseHandle(session);
}

Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/wininet/http.c     | 28 ++++++++++++++++++----------
 dlls/wininet/internet.h |  6 +++---
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 538fc2bf6b..871418e2e3 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -2440,7 +2440,7 @@ static void create_cache_entry(http_request_t *req)
         return;
     }
 
-    b = CreateUrlCacheEntryW(url, req->contentLength == ~0u ? 0 : req->contentLength, NULL, file_name, 0);
+    b = CreateUrlCacheEntryW(url, req->contentLength == ~0 ? 0 : req->contentLength, NULL, file_name, 0);
     if(!b) {
         WARN("Could not create cache entry: %08x\n", GetLastError());
         return;
@@ -2644,7 +2644,7 @@ static DWORD netconn_drain_content(data_stream_t *stream, http_request_t *req, B
     int len, res;
     size_t size;
 
-    if(netconn_stream->content_length == ~0u)
+    if(netconn_stream->content_length == ~0)
         return WSAEISCONN;
 
     while(netconn_stream->content_read < netconn_stream->content_length) {
@@ -2750,7 +2750,7 @@ static DWORD chunked_read(data_stream_t *stream, http_request_t *req, BYTE *buf,
                 TRACE("reading %u byte chunk\n", chunked_stream->chunk_size);
                 chunked_stream->buf_size++;
                 chunked_stream->buf_pos--;
-                if(req->contentLength == ~0u) req->contentLength = chunked_stream->chunk_size;
+                if(req->contentLength == ~0) req->contentLength = chunked_stream->chunk_size;
                 else req->contentLength += chunked_stream->chunk_size;
                 chunked_stream->state = CHUNKED_STREAM_STATE_DISCARD_EOL_AFTER_SIZE;
             }
@@ -2883,7 +2883,7 @@ static DWORD set_content_length(http_request_t *request)
     size = sizeof(request->contentLength);
     if (HTTP_HttpQueryInfoW(request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
                             &request->contentLength, &size, NULL) != ERROR_SUCCESS)
-        request->contentLength = ~0u;
+        request->contentLength = ~0;
     request->netconn_stream.content_length = request->contentLength;
     request->netconn_stream.content_read = request->read_size;
 
@@ -2909,7 +2909,7 @@ static DWORD set_content_length(http_request_t *request)
         }
 
         request->data_stream = &chunked_stream->data_stream;
-        request->contentLength = ~0u;
+        request->contentLength = ~0;
     }
 
     if(request->hdr.decoding) {
@@ -3299,7 +3299,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
     request->hdr.dwFlags = dwFlags;
     request->hdr.dwContext = dwContext;
     request->hdr.decoding = session->hdr.decoding;
-    request->contentLength = ~0u;
+    request->contentLength = ~0;
 
     request->netconn_stream.data_stream.vtbl = &netconn_stream_vtbl;
     request->data_stream = &request->netconn_stream.data_stream;
@@ -3724,9 +3724,17 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
     /* coalesce value to requested type */
     if (dwInfoLevel & HTTP_QUERY_FLAG_NUMBER && lpBuffer)
     {
-        *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
-        TRACE(" returning number: %d\n", *(int *)lpBuffer);
-     }
+        if (*lpdwBufferLength == sizeof(ULONGLONG))
+        {
+            *(ULONGLONG *)lpBuffer = strtoulW(lphttpHdr->lpszValue, NULL, 10);
+            TRACE(" returning number: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)lpBuffer));
+        }
+        else
+        {
+            *(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
+            TRACE(" returning number: %d\n", *(int *)lpBuffer);
+        }
+    }
     else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
     {
         time_t tmpTime;
@@ -4907,7 +4915,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
         loop_next = FALSE;
 
         if(redirected) {
-            request->contentLength = ~0u;
+            request->contentLength = ~0;
             request->bytesToWrite = 0;
         }
 
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index f712fb6b64..40e51bec32 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -335,8 +335,8 @@ typedef struct {
 
 typedef struct {
     data_stream_t data_stream;
-    DWORD content_length;
-    DWORD content_read;
+    ULONGLONG content_length;
+    ULONGLONG content_read;
 } netconn_stream_t;
 
 #define READ_BUFFER_SIZE 8192
@@ -372,7 +372,7 @@ typedef struct
     struct HttpAuthInfo *proxyAuthInfo;
 
     CRITICAL_SECTION read_section;  /* section to protect the following fields */
-    DWORD contentLength;  /* total number of bytes to be read */
+    ULONGLONG contentLength;  /* total number of bytes to be read */
     BOOL  read_gzip;      /* are we reading in gzip mode? */
     DWORD read_pos;       /* current read position in read_buf */
     DWORD read_size;      /* valid data size in read_buf */
-- 
2.17.1




More information about the wine-devel mailing list