[WINHTTP_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
[reactos.git] / rostests / winetests / winhttp / winhttp.c
index ddf0f1a..6106cba 100644 (file)
@@ -24,7 +24,6 @@
 
 #define COBJMACROS
 #include <stdarg.h>
-//#include <stdlib.h>
 #include <windef.h>
 #include <winbase.h>
 #include <ole2.h>
@@ -33,7 +32,6 @@
 #include <winhttp.h>
 #include <wincrypt.h>
 #include <winreg.h>
-//#include <winsock.h>
 //#include "initguid.h"
 #include <httprequest.h>
 
@@ -273,8 +271,14 @@ static void test_empty_headers_param(void)
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
+    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
+ done:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -323,6 +327,11 @@ static void test_SendRequest (void)
 
     context++;
     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
+    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
 
     context = 0;
@@ -354,9 +363,9 @@ static void test_SendRequest (void)
     ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
     ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
 
+ done:
     ret = WinHttpCloseHandle(request);
     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
- done:
     ret = WinHttpCloseHandle(connection);
     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
     ret = WinHttpCloseHandle(session);
@@ -853,18 +862,17 @@ static void test_secure_connection(void)
     WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
 
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
-    ok(ret, "failed to send request %u\n", GetLastError());
-    if (!ret)
+    if (!ret && (GetLastError() == ERROR_WINHTTP_SECURE_FAILURE || GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT))
     {
         skip("secure connection failed, skipping remaining secure tests\n");
         goto cleanup;
     }
+    ok(ret, "failed to send request %u\n", GetLastError());
 
     size = sizeof(cert);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
     ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
-    if (ret)
-        CertFreeCertificateContext(cert);
+    if (ret) CertFreeCertificateContext(cert);
 
     size = sizeof(bitness);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
@@ -874,12 +882,15 @@ static void test_secure_connection(void)
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
     ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
 
-    trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
-    trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
-    trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
-    trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
-    trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
-    trace("dwKeySize %u\n", info.dwKeySize);
+    if (ret)
+    {
+        trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
+        trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
+        trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
+        trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
+        trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
+        trace("dwKeySize %u\n", info.dwKeySize);
+    }
 
     ret = WinHttpReceiveResponse(req, NULL);
     ok(ret, "failed to receive response %u\n", GetLastError());
@@ -928,6 +939,11 @@ static void test_request_parameter_defaults(void)
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
     ret = WinHttpReceiveResponse(req, NULL);
@@ -944,6 +960,11 @@ static void test_request_parameter_defaults(void)
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    if (!ret && (GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT || GetLastError() == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
     ret = WinHttpReceiveResponse(req, NULL);
@@ -967,6 +988,7 @@ static void test_request_parameter_defaults(void)
     ok(ret, "failed unexpectedly %u\n", GetLastError());
     ok(status == 200, "request failed unexpectedly %u\n", status);
 
+done:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -1727,12 +1749,11 @@ static void test_resolve_timeout(void)
 
         SetLastError(0xdeadbeef);
         ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
-        if(ret == 1)
+        if (ret)
         {
             skip("nxdomain returned success. Broken ISP redirects?\n");
-            return;
+            goto done;
         }
-        ok(!ret, "sent request\n");
         ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
            "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
 
@@ -1757,8 +1778,14 @@ static void test_resolve_timeout(void)
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request\n");
 
+ done:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -1775,6 +1802,15 @@ static const char okmsg[] =
 "Server: winetest\r\n"
 "\r\n";
 
+static const char nocontentmsg[] =
+"HTTP/1.1 204 No Content\r\n"
+"Server: winetest\r\n"
+"\r\n";
+
+static const char notmodified[] =
+"HTTP/1.1 304 Not Modified\r\n"
+"\r\n";
+
 static const char noauthmsg[] =
 "HTTP/1.1 401 Unauthorized\r\n"
 "Server: winetest\r\n"
@@ -1782,11 +1818,15 @@ static const char noauthmsg[] =
 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
 "\r\n";
 
-static const char proxymsg[] =
-"HTTP/1.1 407 Proxy Authentication Required\r\n"
+static const char okauthmsg[] =
+"HTTP/1.1 200 OK\r\n"
 "Server: winetest\r\n"
-"Proxy-Connection: close\r\n"
-"Proxy-Authenticate: Basic realm=\"placebo\"\r\n"
+"Connection: close\r\n"
+"\r\n";
+
+static const char headmsg[] =
+"HTTP/1.1 200 OK\r\n"
+"Content-Length: 100\r\n"
 "\r\n";
 
 struct server_info
@@ -1800,7 +1840,7 @@ struct server_info
 static DWORD CALLBACK server_thread(LPVOID param)
 {
     struct server_info *si = param;
-    int r, c, i, on;
+    int r, c = -1, i, on;
     SOCKET s;
     struct sockaddr_in sa;
     char buffer[0x100];
@@ -1829,7 +1869,7 @@ static DWORD CALLBACK server_thread(LPVOID param)
     SetEvent(si->event);
     do
     {
-        c = accept(s, NULL, NULL);
+        if (c == -1) c = accept(s, NULL, NULL);
 
         memset(buffer, 0, sizeof buffer);
         for(i = 0; i < sizeof buffer - 1; i++)
@@ -1850,7 +1890,7 @@ static DWORD CALLBACK server_thread(LPVOID param)
         if (strstr(buffer, "/auth"))
         {
             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
-                send(c, okmsg, sizeof okmsg - 1, 0);
+                send(c, okauthmsg, sizeof okauthmsg - 1, 0);
             else
                 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
         }
@@ -1865,6 +1905,21 @@ static DWORD CALLBACK server_thread(LPVOID param)
         {
             send(c, page1, sizeof page1 - 1, 0);
         }
+        if (strstr(buffer, "GET /no_content"))
+        {
+            send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
+            continue;
+        }
+        if (strstr(buffer, "GET /not_modified"))
+        {
+            send(c, notmodified, sizeof notmodified - 1, 0);
+            continue;
+        }
+        if (strstr(buffer, "HEAD /head"))
+        {
+            send(c, headmsg, sizeof headmsg - 1, 0);
+            continue;
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -1873,6 +1928,7 @@ static DWORD CALLBACK server_thread(LPVOID param)
         }
         shutdown(c, 2);
         closesocket(c);
+        c = -1;
 
     } while (!last_request);
 
@@ -2102,6 +2158,192 @@ static void test_no_headers(int port)
     WinHttpCloseHandle(ses);
 }
 
+static void test_no_content(int port)
+{
+    static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
+    HINTERNET ses, con, req;
+    char buf[128];
+    DWORD size, len = sizeof(buf), bytes_read, status;
+    BOOL ret;
+
+    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ok(ses != NULL, "failed to open session %u\n", GetLastError());
+
+    con = WinHttpConnect(ses, localhostW, port, 0);
+    ok(con != NULL, "failed to open a connection %u\n", GetLastError());
+
+    req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
+
+    size = 12345;
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryDataAvailable(req, &size);
+    todo_wine {
+    ok(!ret, "expected error\n");
+    ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
+       "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
+    ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
+       "expected 12345, got %u\n", size);
+    }
+
+    ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    ok(ret, "expected success\n");
+
+    ret = WinHttpReceiveResponse(req, NULL);
+    ok(ret, "expected success\n");
+
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, NULL);
+    ok(ret, "expected success\n");
+    ok(status == 204, "expected status 204, got %d\n", status);
+
+    SetLastError(0xdeadbeef);
+    size = sizeof(status);
+    status = 12345;
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, 0);
+    ok(!ret, "expected no content-length header\n");
+    ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND,
+       "wrong error %u\n", GetLastError() );
+    ok(status == 12345, "expected 0, got %d\n", status);
+
+    size = 12345;
+    ret = WinHttpQueryDataAvailable(req, &size);
+    ok(ret, "expected success\n");
+    ok(size == 0, "expected 0, got %d\n", size);
+
+    ret = WinHttpReadData(req, buf, len, &bytes_read);
+    ok(ret, "expected success\n");
+    ok( bytes_read == 0, "expected 0, got %u available\n", bytes_read );
+
+    size = 12345;
+    ret = WinHttpQueryDataAvailable(req, &size);
+    ok(ret, "expected success\n");
+    ok(size == 0, "expected 0, got %d\n", size);
+
+    WinHttpCloseHandle(req);
+
+    size = 12345;
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryDataAvailable(req, &size);
+    ok(!ret, "expected error\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE,
+       "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
+    ok(size == 12345, "expected 12345, got %u\n", size);
+
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+}
+
+static void test_head_request(int port)
+{
+    static const WCHAR verbW[] = {'H','E','A','D',0};
+    static const WCHAR headW[] = {'/','h','e','a','d',0};
+    HINTERNET ses, con, req;
+    char buf[128];
+    DWORD size, len, count, status;
+    BOOL ret;
+
+    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ok(ses != NULL, "failed to open session %u\n", GetLastError());
+
+    con = WinHttpConnect(ses, localhostW, port, 0);
+    ok(con != NULL, "failed to open a connection %u\n", GetLastError());
+
+    req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    ok(ret, "failed to send request %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(req, NULL);
+    ok(ret, "failed to receive response %u\n", GetLastError());
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, NULL);
+    ok(ret, "failed to get status code %u\n", GetLastError());
+    ok(status == 200, "got %u\n", status);
+
+    len = 0xdeadbeef;
+    size = sizeof(len);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &len, &size, 0);
+    ok(ret, "failed to get content-length header %u\n", GetLastError());
+    ok(len == 100, "got %u\n", len);
+
+    count = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(req, &count);
+    ok(ret, "failed to query data available %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    len = sizeof(buf);
+    count = 0xdeadbeef;
+    ret = WinHttpReadData(req, buf, len, &count);
+    ok(ret, "failed to read data %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    count = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(req, &count);
+    ok(ret, "failed to query data available %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+}
+
+static void test_not_modified(int port)
+{
+    static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
+    static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
+    BOOL ret;
+    HINTERNET session, request, connection;
+    DWORD status, size, start = GetTickCount();
+    SYSTEMTIME st;
+    WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3];
+
+    memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
+    GetSystemTime(&st);
+    WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
+
+    session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+        WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+    ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
+
+    connection = WinHttpConnect(session, localhostW, port, 0);
+    ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
+
+    request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
+        WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
+    ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(request, today, ~0u, NULL, 0, 0, 0);
+    ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(request, NULL);
+    ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
+
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, NULL);
+    ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
+    ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
+
+    size = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(request, &size);
+    ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
+    ok(!size, "got %u\n", size);
+
+    WinHttpCloseHandle(request);
+    WinHttpCloseHandle(connection);
+    WinHttpCloseHandle(session);
+    start = GetTickCount() - start;
+    ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
+}
+
 static void test_bad_header( int port )
 {
     static const WCHAR bad_headerW[] =
@@ -2388,11 +2630,15 @@ static void test_IWinHttpRequest(void)
     IWinHttpRequest *req;
     BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
     BSTR date, today, connection, value = NULL;
-    VARIANT async, empty, timeout, body, proxy_server, bypass_list, data;
+    VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data;
     VARIANT_BOOL succeeded;
     LONG status;
     WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
     SYSTEMTIME st;
+    IStream *stream, *stream2;
+    LARGE_INTEGER pos;
+    char buf[128];
+    DWORD count;
 
     GetSystemTime( &st );
     WinHttpTimeFromSystemTime( &st, todayW );
@@ -2444,8 +2690,7 @@ static void test_IWinHttpRequest(void)
     hr = IWinHttpRequest_Abort( req );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = IWinHttpRequest_Release( req );
-    ok( hr == S_OK, "got %08x\n", hr );
+    IWinHttpRequest_Release( req );
 
     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
     ok( hr == S_OK, "got %08x\n", hr );
@@ -2464,6 +2709,8 @@ static void test_IWinHttpRequest(void)
     method = SysAllocString( method1W );
     SysFreeString( url );
     url = SysAllocString( url1W );
+    V_VT( &async ) = VT_ERROR;
+    V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
     hr = IWinHttpRequest_Open( req, method, url, async );
     ok( hr == S_OK, "got %08x\n", hr );
 
@@ -2476,8 +2723,7 @@ static void test_IWinHttpRequest(void)
     hr = IWinHttpRequest_Abort( req );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = IWinHttpRequest_Release( req );
-    ok( hr == S_OK, "got %08x\n", hr );
+    IWinHttpRequest_Release( req );
 
     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
     ok( hr == S_OK, "got %08x\n", hr );
@@ -2736,6 +2982,41 @@ static void test_IWinHttpRequest(void)
     hr = VariantClear( &body );
     ok( hr == S_OK, "got %08x\n", hr );
 
+    VariantInit( &body );
+    V_VT( &body ) = VT_ERROR;
+    hr = IWinHttpRequest_get_ResponseStream( req, &body );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
+
+    hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
+
+    buf[0] = 0;
+    count = 0xdeadbeef;
+    hr = IStream_Read( stream, buf, 128, &count );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( count != 0xdeadbeef, "count not set\n" );
+    ok( buf[0], "no data\n" );
+
+    VariantInit( &body2 );
+    V_VT( &body2 ) = VT_ERROR;
+    hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
+    ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
+
+    hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
+    IStream_Release( stream2 );
+
+    hr = VariantClear( &body );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = VariantClear( &body2 );
+    ok( hr == S_OK, "got %08x\n", hr );
+
     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
     ok( hr == S_OK, "got %08x\n", hr );
 
@@ -2765,9 +3046,36 @@ static void test_IWinHttpRequest(void)
     hr = IWinHttpRequest_Abort( req );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = IWinHttpRequest_Release( req );
+    IWinHttpRequest_Release( req );
+
+    pos.QuadPart = 0;
+    IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    buf[0] = 0;
+    count = 0xdeadbeef;
+    hr = IStream_Read( stream, buf, 128, &count );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( count != 0xdeadbeef, "count not set\n" );
+    ok( buf[0], "no data\n" );
+    IStream_Release( stream );
+
+    hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    V_VT( &async ) = VT_I4;
+    V_I4( &async ) = 1;
+    hr = IWinHttpRequest_Open( req, method, url, async );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = IWinHttpRequest_Send( req, empty );
     ok( hr == S_OK, "got %08x\n", hr );
 
+    hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    IWinHttpRequest_Release( req );
+
     SysFreeString( method );
     SysFreeString( url );
     SysFreeString( username );
@@ -2942,12 +3250,8 @@ static void test_WinHttpGetProxyForUrl(void)
     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
 
     memset( &info, 0, sizeof(info) );
-    SetLastError(0xdeadbeef);
     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
-    error = GetLastError();
-    if (!ret) ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED ||
-                  error == ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT, "got %u\n", error );
-    else
+    if (ret)
     {
         trace("Proxy.AccessType=%u\n", info.dwAccessType);
         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
@@ -2961,11 +3265,8 @@ static void test_WinHttpGetProxyForUrl(void)
     options.lpszAutoConfigUrl = wpadW;
 
     memset( &info, 0, sizeof(info) );
-    SetLastError(0xdeadbeef);
     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
-    error = GetLastError();
-    if (!ret) ok( error == ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT, "got %u\n", error );
-    else
+    if (ret)
     {
         trace("Proxy.AccessType=%u\n", info.dwAccessType);
         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
@@ -3000,6 +3301,11 @@ static void test_chunked_read(void)
     if (!req) goto done;
 
     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
+    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
 
     ret = WinHttpReceiveResponse( req, NULL );
@@ -3093,6 +3399,9 @@ START_TEST (winhttp)
     test_connection_info(si.port);
     test_basic_request(si.port, NULL, basicW);
     test_no_headers(si.port);
+    test_no_content(si.port);
+    test_head_request(si.port);
+    test_not_modified(si.port);
     test_basic_authentication(si.port);
     test_bad_header(si.port);
     test_multiple_reads(si.port);