[WINHTTP_WINETEST] Sync with Wine Staging 1.9.23. CORE-12409
[reactos.git] / rostests / winetests / winhttp / winhttp.c
index d7e283c..b961c83 100644 (file)
@@ -2,6 +2,7 @@
  * WinHTTP - tests
  *
  * Copyright 2008 Google (Zac Brown)
+ * Copyright 2015 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 
 #define COBJMACROS
 #include <stdarg.h>
-//#include <stdlib.h>
 #include <windef.h>
 #include <winbase.h>
+#include <winnls.h>
 #include <ole2.h>
 #include <winsock2.h>
 //#include <ws2tcpip.h>
 #include <winhttp.h>
 #include <wincrypt.h>
 #include <winreg.h>
-//#include <winsock.h>
+#include <stdio.h>
 //#include "initguid.h"
 #include <httprequest.h>
+#include <httprequestid.h>
 
 #include <wine/test.h>
 
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
 static const WCHAR test_useragent[] =
     {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
-static const WCHAR test_server[] = {'w','i','n','e','h','q','.','o','r','g',0};
+static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
+static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
 
 static BOOL proxy_active(void)
@@ -49,8 +54,11 @@ static BOOL proxy_active(void)
     WINHTTP_PROXY_INFO proxy_info;
     BOOL active = FALSE;
 
+    SetLastError(0xdeadbeef);
     if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
     {
+        ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+           "got %u\n", GetLastError());
         active = (proxy_info.lpszProxy != NULL);
         if (active)
             GlobalFree(proxy_info.lpszProxy);
@@ -101,6 +109,8 @@ static void test_QueryOption(void)
     SetLastError(0xdeadbeef);
     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
     ok(ret, "failed to query option %u\n", GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+       "got %u\n", GetLastError());
     ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
     ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
        "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
@@ -146,7 +156,7 @@ static void test_QueryOption(void)
        "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    connection = WinHttpConnect(session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
+    connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
 
     feature = WINHTTP_DISABLE_COOKIES;
@@ -215,39 +225,57 @@ static void test_OpenRequest (void)
 {
     BOOL ret;
     HINTERNET session, request, connection;
+    DWORD err;
 
+    SetLastError(0xdeadbeef);
     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+    err = GetLastError();
     ok(session != NULL, "WinHttpOpen failed to open session.\n");
+    ok(err == ERROR_SUCCESS, "got %u\n", err);
 
     /* Test with a bad server name */
     SetLastError(0xdeadbeef);
     connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
+    err = GetLastError();
     ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
-    ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
+    ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
 
     /* Test with a valid server name */
-    connection = WinHttpConnect (session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
-    ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
+    err = GetLastError();
+    ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
+    ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
 
+    SetLastError(0xdeadbeef);
     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
-    if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
+    err = GetLastError();
+    if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
     {
         skip("Network unreachable, skipping.\n");
         goto done;
     }
-    ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
+    ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
+    ok(err == ERROR_SUCCESS, "got %u\n", err);
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
-    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
     {
         skip("Connection failed, skipping.\n");
         goto done;
     }
-    ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
+    ok(ret, "WinHttpSendRequest failed: %u\n", err);
+    ok(err == ERROR_SUCCESS, "got %u\n", err);
+
+    SetLastError(0xdeadbeef);
     ret = WinHttpCloseHandle(request);
-    ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
+    err = GetLastError();
+    ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
+    ok(err == ERROR_SUCCESS, "got %u\n", err);
 
  done:
     ret = WinHttpCloseHandle(connection);
@@ -259,23 +287,30 @@ static void test_OpenRequest (void)
 
 static void test_empty_headers_param(void)
 {
-    static const WCHAR winehq[] = {'w','i','n','e','h','q','.','o','r','g',0};
     static const WCHAR empty[]  = {0};
     HINTERNET ses, con, req;
+    DWORD err;
     BOOL ret;
 
     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
     ok(ses != NULL, "failed to open session %u\n", GetLastError());
 
-    con = WinHttpConnect(ses, winehq, 80, 0);
+    con = WinHttpConnect(ses, test_winehq, 80, 0);
     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
 
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
+ done:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -283,22 +318,19 @@ static void test_empty_headers_param(void)
 
 static void test_SendRequest (void)
 {
-    HINTERNET session, request, connection;
-    DWORD header_len, optional_len, total_len, bytes_rw, size;
-    DWORD_PTR context;
-    BOOL ret;
-    CHAR buffer[256];
-    int i;
-
-    static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
-                                'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
     static const WCHAR content_type[] =
         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
          '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
-    static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
+    static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
     static const WCHAR test_verb[] = {'P','O','S','T',0};
     static CHAR post_data[] = "mode=Test";
-    static CHAR test_post[] = "mode => Test\\0\n";
+    static const char test_post[] = "mode => Test\0\n";
+    HINTERNET session, request, connection;
+    DWORD header_len, optional_len, total_len, bytes_rw, size, err;
+    DWORD_PTR context;
+    BOOL ret;
+    CHAR buffer[256];
+    int i;
 
     header_len = -1L;
     total_len = optional_len = sizeof(post_data);
@@ -308,7 +340,7 @@ static void test_SendRequest (void)
         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
     ok(session != NULL, "WinHttpOpen failed to open session.\n");
 
-    connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
+    connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
 
     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
@@ -327,6 +359,12 @@ static void test_SendRequest (void)
 
     context++;
     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
 
     context = 0;
@@ -338,9 +376,13 @@ static void test_SendRequest (void)
     for (i = 3; post_data[i]; i++)
     {
         bytes_rw = -1;
+        SetLastError(0xdeadbeef);
         ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
         if (ret)
+        {
+          ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
           ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
+        }
         else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
         {
           ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
@@ -348,19 +390,22 @@ static void test_SendRequest (void)
         }
     }
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpReceiveResponse(request, NULL);
+    ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
+       "Expected ERROR_SUCCESS got %u.\n", GetLastError());
     ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
 
     bytes_rw = -1;
     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
     ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
 
-    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);
+    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);
@@ -375,9 +420,25 @@ static void test_WinHttpTimeFromSystemTime(void)
         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
          '1','0',':','0','5',':','5','2',' ','G','M','T',0};
     WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
+    DWORD err;
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpTimeFromSystemTime(&time, NULL);
+    err = GetLastError();
+    ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
+    ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpTimeFromSystemTime(NULL, time_string);
+    err = GetLastError();
+    ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
+    ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpTimeFromSystemTime(&time, time_string);
-    ok(ret == TRUE, "WinHttpTimeFromSystemTime failed: %u\n", GetLastError());
+    err = GetLastError();
+    ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
+    ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
     ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
         "Time string returned did not match expected time string.\n");
 }
@@ -393,14 +454,33 @@ static void test_WinHttpTimeToSystemTime(void)
     static const WCHAR time_string2[] =
         {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
          '1','0',' ','0','5',' ','5','2','\n',0};
+    DWORD err;
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpTimeToSystemTime(time_string1, NULL);
+    err = GetLastError();
+    ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
+    ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpTimeToSystemTime(NULL, &time);
+    err = GetLastError();
+    ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
+    ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpTimeToSystemTime(time_string1, &time);
-    ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
+    err = GetLastError();
+    ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
+    ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpTimeToSystemTime(time_string2, &time);
-    ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
+    err = GetLastError();
+    ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
+    ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
 }
@@ -411,19 +491,22 @@ static void test_WinHttpAddHeaders(void)
     BOOL ret, reverse;
     WCHAR buffer[MAX_PATH];
     WCHAR check_buffer[MAX_PATH];
-    DWORD index, len, oldlen;
+    DWORD err, index, len, oldlen;
 
-    static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
-                                'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
     static const WCHAR test_verb[] = {'P','O','S','T',0};
-
     static const WCHAR test_header_begin[] =
         {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
     static const WCHAR full_path_test_header_begin[] =
-        {'P','O','S','T',' ','h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',':','8','0','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
+        {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
+         '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
     static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
     static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
+    static const WCHAR test_header_name2[] = {'n','a','m','e',0};
+    static const WCHAR test_header_name3[] = {'a',0};
+    static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
+    static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
+    static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
 
     static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
     static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
@@ -439,6 +522,7 @@ static void test_WinHttpAddHeaders(void)
     static const WCHAR field[] = {'f','i','e','l','d',0};
     static const WCHAR value[] = {'v','a','l','u','e',' ',0};
     static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
+    static const WCHAR empty[] = {0};
 
     static const WCHAR test_headers[][14] =
         {
@@ -455,7 +539,9 @@ static void test_WinHttpAddHeaders(void)
             {':','b',0},
             {'c','d',0},
             {' ','e',' ',':','f',0},
-            {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0}
+            {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
+            {'n','a','m','e',':',' ','v','a','l','u','e',0},
+            {'n','a','m','e',':',0}
         };
     static const WCHAR test_indices[][6] =
         {
@@ -469,7 +555,7 @@ static void test_WinHttpAddHeaders(void)
         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
     ok(session != NULL, "WinHttpOpen failed to open session.\n");
 
-    connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
+    connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
 
     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
@@ -486,8 +572,11 @@ static void test_WinHttpAddHeaders(void)
     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
         test_header_name, buffer, &len, &index);
     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
+    SetLastError(0xdeadbeef);
     ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
-    ok(ret == TRUE, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, GetLastError());
+    err = GetLastError();
+    ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
+    ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
 
     index = 0;
     len = sizeof(buffer);
@@ -535,7 +624,7 @@ static void test_WinHttpAddHeaders(void)
         test_header_name, NULL, &len, &index);
     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-        "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
+        "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, got %u\n", GetLastError());
     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
 
@@ -764,6 +853,14 @@ static void test_WinHttpAddHeaders(void)
     ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
     ok(ret, "WinHttpAddRequestHeaders failed\n");
 
+    index = 0;
+    memset(buffer, 0xff, sizeof(buffer));
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_name3, buffer, &len, &index);
+    ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
+    ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
+
     ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
     ok(!ret, "WinHttpAddRequestHeaders failed\n");
 
@@ -784,6 +881,72 @@ static void test_WinHttpAddHeaders(void)
     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
     ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
 
+    SetLastError(0xdeadbeef);
+    ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
+                                   WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
+    err = GetLastError();
+    ok(!ret, "unexpected success\n");
+    ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
+
+    ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
+                                   WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
+    ok(ret, "failed to add header: %u\n", GetLastError());
+
+    index = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_range, buffer, &len, &index);
+    ok(ret, "failed to get range header %u\n", GetLastError());
+    ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
+    ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
+    ok(index == 1, "wrong index %u\n", index);
+
+    index = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_name2, buffer, &len, &index);
+    ok(!ret, "unexpected success\n");
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
+    err = GetLastError();
+    ok(!ret, "unexpected success\n");
+    ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
+
+    ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
+    ok(ret, "got %u\n", GetLastError());
+
+    index = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_name2, buffer, &len, &index);
+    ok(ret, "got %u\n", GetLastError());
+    ok(index == 1, "wrong index %u\n", index);
+    ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
+
+    ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
+    ok(ret, "got %u\n", GetLastError());
+
+    index = 0;
+    len = sizeof(buffer);
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_name2, buffer, &len, &index);
+    err = GetLastError();
+    ok(!ret, "unexpected success\n");
+    ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
+
+    ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
+    ok(ret, "got %u\n", GetLastError());
+
+    index = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              test_header_name2, buffer, &len, &index);
+    ok(ret, "got %u\n", GetLastError());
+    ok(index == 1, "wrong index %u\n", index);
+    ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
+
     ret = WinHttpCloseHandle(request);
     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
  done:
@@ -816,10 +979,9 @@ static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, L
 
 static void test_secure_connection(void)
 {
-    static const WCHAR google[] = {'w','w','w','.','g','o','o','g','l','e','.','c','o','m',0};
-
+    static const char data_start[] = "<!DOCTYPE html PUBLIC";
     HINTERNET ses, con, req;
-    DWORD size, status, policy, bitness, read_size;
+    DWORD size, status, policy, bitness, read_size, err, available_size;
     BOOL ret;
     CERT_CONTEXT *cert;
     WINHTTP_CERTIFICATE_INFO info;
@@ -832,15 +994,19 @@ static void test_secure_connection(void)
     ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
     ok(ret, "failed to set redirect policy %u\n", GetLastError());
 
-    con = WinHttpConnect(ses, google, 443, 0);
+    con = WinHttpConnect(ses, test_winehq, 443, 0);
     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
 
     /* try without setting WINHTTP_FLAG_SECURE */
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
+    ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "setting client cert context returned %x (%u)\n", ret, GetLastError());
+
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
-    if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
     {
         skip("Connection failed, skipping.\n");
         goto cleanup;
@@ -848,32 +1014,38 @@ static void test_secure_connection(void)
     ok(ret, "failed to send request %u\n", GetLastError());
 
     ret = WinHttpReceiveResponse(req, NULL);
-    ok(!ret || proxy_active(), "succeeded unexpectedly\n");
+    ok(ret, "failed to receive response %u\n", GetLastError());
 
-    size = 0;
-    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
-    ok(!ret, "succeeded unexpectedly\n");
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
+    ok(ret, "header query failed %u\n", GetLastError());
+    ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
 
     WinHttpCloseHandle(req);
 
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
+    ok(ret, "failed to set client cert context %u\n", GetLastError());
+
     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)
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
+                 err == ERROR_WINHTTP_TIMEOUT))
     {
         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 );
@@ -883,20 +1055,29 @@ 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());
 
+    available_size = 0;
+    ret = WinHttpQueryDataAvailable(req, &available_size);
+    ok(ret, "failed to query available data %u\n", GetLastError());
+    ok(available_size > 2014, "available_size = %u\n", available_size);
+
+    status = 0xdeadbeef;
     size = sizeof(status);
     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
     ok(ret, "failed unexpectedly %u\n", GetLastError());
-    ok(status == 200, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
 
     size = 0;
     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
@@ -910,8 +1091,11 @@ static void test_secure_connection(void)
         ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
         if (!size) break;
         read_size += size;
+
+        if (read_size <= 32)
+            ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
     }
-    ok(read_size > 2014, "read_size = %u\n", read_size);
+    ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
 
 cleanup:
     WinHttpCloseHandle(req);
@@ -922,8 +1106,6 @@ cleanup:
 static void test_request_parameter_defaults(void)
 {
     static const WCHAR empty[] = {0};
-    static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
-
     HINTERNET ses, con, req;
     DWORD size, status, error;
     WCHAR *version;
@@ -932,22 +1114,34 @@ static void test_request_parameter_defaults(void)
     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
     ok(ses != NULL, "failed to open session %u\n", GetLastError());
 
-    con = WinHttpConnect(ses, codeweavers, 0, 0);
+    con = WinHttpConnect(ses, test_winehq, 0, 0);
     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
 
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    error = GetLastError();
+    if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
     ret = WinHttpReceiveResponse(req, NULL);
+    if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
+    {
+        win_skip("invalid response\n");
+        goto done;
+    }
     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 unexpectedly %u\n", GetLastError());
-    ok(status == 200, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
 
     WinHttpCloseHandle(req);
 
@@ -955,6 +1149,12 @@ 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);
+    error = GetLastError();
+    if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok(ret, "failed to send request %u\n", GetLastError());
 
     ret = WinHttpReceiveResponse(req, NULL);
@@ -973,11 +1173,13 @@ static void test_request_parameter_defaults(void)
     ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
     HeapFree(GetProcessHeap(), 0, version);
 
+    status = 0xdeadbeef;
     size = sizeof(status);
     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
     ok(ret, "failed unexpectedly %u\n", GetLastError());
-    ok(status == 200, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
 
+done:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -1115,9 +1317,11 @@ static void test_set_default_proxy_config(void)
     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
         skip("couldn't set default proxy configuration: access denied\n");
     else
-        ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %d\n",
-           GetLastError());
-
+    {
+        ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
+        ok(GetLastError() == ERROR_SUCCESS ||  broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+           "got %u\n", GetLastError());
+    }
     set_default_proxy_reg_value( saved_proxy_settings, len, type );
 }
 
@@ -1126,8 +1330,6 @@ static void test_Timeouts (void)
     BOOL ret;
     DWORD value, size;
     HINTERNET ses, req, con;
-    static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
-
 
     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
     ok(ses != NULL, "failed to open session %u\n", GetLastError());
@@ -1155,6 +1357,8 @@ static void test_Timeouts (void)
     SetLastError(0xdeadbeef);
     ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
     ok(ret, "%u\n", GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+       "expected ERROR_SUCCESS, got %u\n", GetLastError());
 
     SetLastError(0xdeadbeef);
     ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
@@ -1288,7 +1492,7 @@ static void test_Timeouts (void)
     ok(ret, "%u\n", GetLastError());
     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
 
-    con = WinHttpConnect(ses, codeweavers, 0, 0);
+    con = WinHttpConnect(ses, test_winehq, 0, 0);
     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
 
     /* Timeout values should match the last one set for session */
@@ -1717,11 +1921,8 @@ static void test_Timeouts (void)
 
 static void test_resolve_timeout(void)
 {
-    static const WCHAR codeweavers[] =
-        {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
     static const WCHAR nxdomain[] =
-        {'n','x','d','o','m','a','i','n','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
-
+        {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
     HINTERNET ses, con, req;
     DWORD timeout;
     BOOL ret;
@@ -1743,7 +1944,11 @@ static void test_resolve_timeout(void)
 
         SetLastError(0xdeadbeef);
         ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
-        ok(!ret, "sent request\n");
+        if (ret)
+        {
+            skip("nxdomain returned success. Broken ISP redirects?\n");
+            goto done;
+        }
         ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
            "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
 
@@ -1761,15 +1966,21 @@ static void test_resolve_timeout(void)
     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
     ok(ret, "failed to set resolve timeout %u\n", GetLastError());
 
-    con = WinHttpConnect(ses, codeweavers, 0, 0);
+    con = WinHttpConnect(ses, test_winehq, 0, 0);
     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
 
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
     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);
@@ -1786,30 +1997,62 @@ static const char okmsg[] =
 "Server: winetest\r\n"
 "\r\n";
 
+static const char notokmsg[] =
+"HTTP/1.1 400 Bad Request\r\n"
+"\r\n";
+
+static const char cookiemsg[] =
+"HTTP/1.1 200 OK\r\n"
+"Set-Cookie: name = value \r\n"
+"Set-Cookie: NAME = value \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"
 "Connection: close\r\n"
 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
+"Content-Length: 12\r\n"
+"Content-Type: text/plain\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"
+"Content-Length: 11\r\n"
+"Content-Type: text/plain\r\n"
+"\r\n";
+
+static const char headmsg[] =
+"HTTP/1.1 200 OK\r\n"
+"Content-Length: 100\r\n"
 "\r\n";
 
+static const char unauthorized[] = "Unauthorized";
+static const char hello_world[] = "Hello World";
+
 struct server_info
 {
     HANDLE event;
     int port;
 };
 
+#define BIG_BUFFER_LEN 0x2250
+
 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];
@@ -1838,7 +2081,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++)
@@ -1859,14 +2102,65 @@ 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);
+                send(c, hello_world, sizeof hello_world - 1, 0);
+            }
             else
+            {
                 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
+                send(c, unauthorized, sizeof unauthorized - 1, 0);
+            }
+            continue;
+        }
+        if (strstr(buffer, "/big"))
+        {
+            char msg[BIG_BUFFER_LEN];
+            memset(msg, 'm', sizeof(msg));
+            send(c, okmsg, sizeof(okmsg) - 1, 0);
+            send(c, msg, sizeof(msg), 0);
         }
         if (strstr(buffer, "/no_headers"))
         {
             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"))
+        {
+            if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
+            else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+            continue;
+        }
+        if (strstr(buffer, "HEAD /head"))
+        {
+            send(c, headmsg, sizeof headmsg - 1, 0);
+            continue;
+        }
+        if (strstr(buffer, "GET /cookie3"))
+        {
+            if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
+                broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
+                send(c, okmsg, sizeof(okmsg) - 1, 0);
+            else
+                send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+        }
+        if (strstr(buffer, "GET /cookie2"))
+        {
+            if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
+                broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
+                send(c, okmsg, sizeof(okmsg) - 1, 0);
+            else
+                send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+        }
+        else if (strstr(buffer, "GET /cookie"))
+        {
+            if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
+            else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -1875,6 +2169,7 @@ static DWORD CALLBACK server_thread(LPVOID param)
         }
         shutdown(c, 2);
         closesocket(c);
+        c = -1;
 
     } while (!last_request);
 
@@ -1884,12 +2179,15 @@ static DWORD CALLBACK server_thread(LPVOID param)
 
 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
 {
+    static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
+    static const WCHAR test_header_end_raw[] = {0,0};
     HINTERNET ses, con, req;
     char buffer[0x100];
+    WCHAR buffer2[0x100];
     DWORD count, status, size, error, supported, first, target;
     BOOL ret;
 
-    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
     ok(ses != NULL, "failed to open session %u\n", GetLastError());
 
     con = WinHttpConnect(ses, localhostW, port, 0);
@@ -1904,10 +2202,11 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
     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 query status code %u\n", GetLastError());
-    ok(status == 200, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
 
     supported = first = target = 0xdeadbeef;
     SetLastError(0xdeadbeef);
@@ -1919,6 +2218,21 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
     ok(first == 0xdeadbeef, "got %x\n", first);
     ok(target == 0xdeadbeef, "got %x\n", target);
 
+    size = sizeof(buffer2);
+    memset(buffer2, 0, sizeof(buffer2));
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
+    ok(ret, "failed to query for raw headers: %u\n", GetLastError());
+    ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
+       "WinHttpQueryHeaders returned invalid end of header string\n");
+
+    size = sizeof(buffer2);
+    memset(buffer2, 0, sizeof(buffer2));
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
+    ok(ret, "failed to query for raw headers: %u\n", GetLastError());
+    ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
+       "WinHttpQueryHeaders returned invalid end of header string\n");
+    ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
+
     count = 0;
     memset(buffer, 0, sizeof(buffer));
     ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
@@ -1934,13 +2248,15 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
 static void test_basic_authentication(int port)
 {
     static const WCHAR authW[] = {'/','a','u','t','h',0};
-    static const WCHAR userW[] = {'u','s','e','r',0};
-    static const WCHAR passW[] = {'p','w','d',0};
+    static WCHAR userW[] = {'u','s','e','r',0};
+    static WCHAR passW[] = {'p','w','d',0};
+    static WCHAR pass2W[] = {'p','w','d','2',0};
     HINTERNET ses, con, req;
     DWORD status, size, error, supported, first, target;
+    char buffer[32];
     BOOL ret;
 
-    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
     ok(ses != NULL, "failed to open session %u\n", GetLastError());
 
     con = WinHttpConnect(ses, localhostW, port, 0);
@@ -2004,20 +2320,37 @@ static void test_basic_authentication(int port)
     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 query status code %u\n", GetLastError());
-    ok(status == 401, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
+
+    size = 0;
+    ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
+    error = GetLastError();
+    ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
+    if (ret)
+    {
+        ok(size == 12, "expected 12, got %u\n", size);
+        ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
+    }
 
     supported = first = target = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
-    ok(ret, "failed to query authentication schemes %u\n", GetLastError());
+    error = GetLastError();
+    ok(ret, "failed to query authentication schemes %u\n", error);
+    ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
     ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
     ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
     ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
-    ok(ret, "failed to set credentials %u\n", GetLastError());
+    error = GetLastError();
+    ok(ret, "failed to set credentials %u\n", error);
+    ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
 
     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
     ok(ret, "failed to set credentials %u\n", GetLastError());
@@ -2058,79 +2391,532 @@ static void test_basic_authentication(int port)
     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 query status code %u\n", GetLastError());
-    ok(status == 200, "request failed unexpectedly %u\n", status);
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
+
+    size = 0;
+    ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
+    error = GetLastError();
+    ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
+    if (ret)
+    {
+        ok(size == 11, "expected 11, got %u\n", size);
+        ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
+    }
 
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
-}
 
-static void test_no_headers(int port)
-{
-    static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
-    HINTERNET ses, con, req;
-    DWORD error;
-    BOOL ret;
+    /* credentials set with WinHttpSetCredentials take precedence over those set through options */
 
-    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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_headersW, NULL, NULL, NULL, 0);
+    req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
+    ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
+    ok(ret, "failed to set credentials %u\n", GetLastError());
+
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
+    ok(ret, "failed to set username %u\n", GetLastError());
+
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
+    ok(ret, "failed to set password %u\n", GetLastError());
+
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
     ok(ret, "failed to send request %u\n", GetLastError());
 
-    SetLastError(0xdeadbeef);
     ret = WinHttpReceiveResponse(req, NULL);
-    error = GetLastError();
-    ok(!ret, "expected failure\n");
-    ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
+    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 query status code %u\n", GetLastError());
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
 
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
-}
 
-static void test_bad_header( int port )
-{
-    static const WCHAR bad_headerW[] =
-        {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
-         't','e','x','t','/','h','t','m','l','\n','\r',0};
-    static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
-    static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
-    WCHAR buffer[32];
-    HINTERNET ses, con, req;
-    DWORD index, len;
-    BOOL ret;
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
+    ok(ses != NULL, "failed to open session %u\n", GetLastError());
 
-    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());
 
-    con = WinHttpConnect( ses, localhostW, port, 0 );
-    ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
+    req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
-    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
-    ok( req != NULL, "failed to open a request %u\n", GetLastError() );
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
+    ok(ret, "failed to set username %u\n", GetLastError());
 
-    ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
-    ok( ret, "failed to add header %u\n", GetLastError() );
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
+    ok(ret, "failed to set password %u\n", GetLastError());
 
-    index = 0;
-    buffer[0] = 0;
-    len = sizeof(buffer);
-    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
-                               content_typeW, buffer, &len, &index );
-    ok( ret, "failed to query headers %u\n", GetLastError() );
-    ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
+    ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
+    ok(ret, "failed to set credentials %u\n", GetLastError());
 
-    WinHttpCloseHandle( req );
+    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 query status code %u\n", GetLastError());
+    ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+}
+
+static void test_no_headers(int port)
+{
+    static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
+    HINTERNET ses, con, req;
+    DWORD error;
+    BOOL ret;
+
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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_headersW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    if (!ret)
+    {
+        error = GetLastError();
+        ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
+    }
+    else
+    {
+        SetLastError(0xdeadbeef);
+        ret = WinHttpReceiveResponse(req, NULL);
+        error = GetLastError();
+        ok(!ret, "expected failure\n");
+        ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
+    }
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    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, WINHTTP_ACCESS_TYPE_NO_PROXY, 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");
+
+    status = 0xdeadbeef;
+    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 == HTTP_STATUS_NO_CONTENT, "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);
+
+    SetLastError(0xdeadbeef);
+    size = 12345;
+    ret = WinHttpQueryDataAvailable(req, &size);
+    ok(ret, "expected success\n");
+    ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+       "wrong error %u\n", GetLastError());
+    ok(!size, "expected 0, got %u\n", size);
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpReadData(req, buf, len, &bytes_read);
+    ok(ret, "expected success\n");
+    ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
+       "wrong error %u\n", GetLastError());
+    ok(!bytes_read, "expected 0, got %u\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, WINHTTP_ACCESS_TYPE_NO_PROXY, 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 == HTTP_STATUS_OK, "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 == HTTP_STATUS_CONTINUE, "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',':',' '};
+    static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
+    BOOL ret;
+    HINTERNET session, request, connection;
+    DWORD index, len, status, size, start = GetTickCount();
+    SYSTEMTIME st;
+    WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
+
+    memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
+    GetSystemTime(&st);
+    WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
+
+    session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_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, 0, NULL, 0, 0, 0);
+    ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(request, NULL);
+    ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
+
+    index = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                              ifmodified2W, buffer, &len, &index);
+    ok(ret, "failed to get header %u\n", GetLastError());
+
+    status = 0xdeadbeef;
+    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[] =
+        {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
+         't','e','x','t','/','h','t','m','l','\n','\r',0};
+    static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
+    static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
+    WCHAR buffer[32];
+    HINTERNET ses, con, req;
+    DWORD index, len;
+    BOOL ret;
+
+    ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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, NULL, NULL, NULL, NULL, 0 );
+    ok( req != NULL, "failed to open a request %u\n", GetLastError() );
+
+    ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
+    ok( ret, "failed to add header %u\n", GetLastError() );
+
+    index = 0;
+    buffer[0] = 0;
+    len = sizeof(buffer);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
+                               content_typeW, buffer, &len, &index );
+    ok( ret, "failed to query headers %u\n", GetLastError() );
+    ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
+
+    WinHttpCloseHandle( req );
+    WinHttpCloseHandle( con );
+    WinHttpCloseHandle( ses );
+}
+
+static void test_multiple_reads(int port)
+{
+    static const WCHAR bigW[] = {'b','i','g',0};
+    HINTERNET ses, con, req;
+    DWORD total_len = 0;
+    BOOL ret;
+
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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, bigW, 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 == TRUE, "expected success\n");
+
+    for (;;)
+    {
+        DWORD len = 0xdeadbeef;
+        ret = WinHttpQueryDataAvailable( req, &len );
+        ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
+        if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
+        if (len)
+        {
+            DWORD bytes_read;
+            char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
+
+            ret = WinHttpReadData( req, buf, len, &bytes_read );
+            ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
+
+            HeapFree( GetProcessHeap(), 0, buf );
+            if (!bytes_read) break;
+            total_len += bytes_read;
+        }
+        if (!len) break;
+    }
+    ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+}
+
+static void test_cookies( int port )
+{
+    static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
+    static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
+    static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
+    static const WCHAR cookieheaderW[] =
+        {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
+    HINTERNET ses, con, req;
+    DWORD status, size;
+    BOOL ret;
+
+    ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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, cookieW, 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 query status code %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
+
+    WinHttpCloseHandle( req );
+
+    req = WinHttpOpenRequest( con, NULL, cookie2W, 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 query status code %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
+
+    WinHttpCloseHandle( req );
+    WinHttpCloseHandle( con );
+
+    con = WinHttpConnect( ses, localhostW, port, 0 );
+    ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
+
+    req = WinHttpOpenRequest( con, NULL, cookie2W, 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 query status code %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
+
+    WinHttpCloseHandle( req );
+
+    req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
+    ok( req != NULL, "failed to open a request %u\n", GetLastError() );
+
+    ret = WinHttpSendRequest( req, cookieheaderW, ~0u, 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 query status code %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
+
+    WinHttpCloseHandle( req );
+    WinHttpCloseHandle( con );
+    WinHttpCloseHandle( ses );
+
+    ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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, cookie2W, 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 query status code %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
+
+    WinHttpCloseHandle( req );
     WinHttpCloseHandle( con );
     WinHttpCloseHandle( ses );
 }
@@ -2143,7 +2929,7 @@ static void test_connection_info( int port )
     DWORD size, error;
     BOOL ret;
 
-    ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
+    ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
 
     con = WinHttpConnect( ses, localhostW, port, 0 );
@@ -2178,7 +2964,7 @@ static void test_connection_info( int port )
     memset( &info, 0, sizeof(info) );
     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
-    ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
+    ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
 
     ret = WinHttpReceiveResponse( req, NULL );
     ok( ret, "failed to receive response %u\n", GetLastError() );
@@ -2187,7 +2973,7 @@ static void test_connection_info( int port )
     memset( &info, 0, sizeof(info) );
     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
-    ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
+    ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
 
     WinHttpCloseHandle( req );
     WinHttpCloseHandle( con );
@@ -2315,15 +3101,15 @@ static void test_credentials(void)
     WinHttpCloseHandle(ses);
 }
 
-static void test_IWinHttpRequest(void)
+static void test_IWinHttpRequest(int port)
 {
+    static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
     static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
     static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
-    static const WCHAR url1W[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
-    static const WCHAR url2W[] = {'w','i','n','e','h','q','.','o','r','g',0};
-    static const WCHAR url3W[] = {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
-                                  'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
-                                  'p','o','s','t','t','e','s','t','.','p','h','p',0};
+    static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
+    static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
+    static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
+                                  'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
     static const WCHAR method1W[] = {'G','E','T',0};
     static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
     static const WCHAR method3W[] = {'P','O','S','T',0};
@@ -2332,15 +3118,22 @@ static void test_IWinHttpRequest(void)
     static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
     static const WCHAR dateW[] = {'D','a','t','e',0};
     static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
+    static const WCHAR utf8W[] = {'u','t','f','-','8',0};
+    static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
     HRESULT hr;
     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, cp;
     VARIANT_BOOL succeeded;
     LONG status;
     WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
     SYSTEMTIME st;
+    IStream *stream, *stream2;
+    LARGE_INTEGER pos;
+    char buf[128];
+    WCHAR bufW[128];
+    DWORD count;
 
     GetSystemTime( &st );
     WinHttpTimeFromSystemTime( &st, todayW );
@@ -2392,8 +3185,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 );
@@ -2412,9 +3204,44 @@ 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 );
 
+    V_VT( &cp ) = VT_ERROR;
+    V_ERROR( &cp ) = 0xdeadbeef;
+    hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
+    ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
+
+    V_VT( &cp ) = VT_UI4;
+    V_UI4( &cp ) = CP_ACP;
+    hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    V_VT( &cp ) = VT_ERROR;
+    V_ERROR( &cp ) = 0xdeadbeef;
+    hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
+    ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
+
+    value = SysAllocString( utf8W );
+    V_VT( &cp ) = VT_BSTR;
+    V_BSTR( &cp ) = value;
+    hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
+    ok( hr == S_OK, "got %08x\n", hr );
+    SysFreeString( value );
+
+    V_VT( &cp ) = VT_ERROR;
+    V_ERROR( &cp ) = 0xdeadbeef;
+    hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
+    ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
+
     hr = IWinHttpRequest_Abort( req );
     ok( hr == S_OK, "got %08x\n", hr );
 
@@ -2424,8 +3251,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 );
@@ -2587,6 +3413,7 @@ static void test_IWinHttpRequest(void)
 
     hr = IWinHttpRequest_get_ResponseText( req, &response );
     ok( hr == S_OK, "got %08x\n", hr );
+    ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
     SysFreeString( response );
 
     hr = IWinHttpRequest_get_Status( req, NULL );
@@ -2684,6 +3511,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 );
 
@@ -2713,9 +3575,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;
+    hr = 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 );
@@ -2725,6 +3614,301 @@ static void test_IWinHttpRequest(void)
     SysFreeString( today );
     VariantClear( &proxy_server );
     VariantClear( &bypass_list );
+
+    hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    url = SysAllocString( test_winehq_https );
+    method = SysAllocString( method3W );
+    V_VT( &async ) = VT_BOOL;
+    V_BOOL( &async ) = VARIANT_FALSE;
+    hr = IWinHttpRequest_Open( req, method, url, async );
+    ok( hr == S_OK, "got %08x\n", hr );
+    SysFreeString( method );
+    SysFreeString( url );
+
+    hr = IWinHttpRequest_Send( req, empty );
+    ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr );
+    if (hr == S_OK)
+    {
+        hr = IWinHttpRequest_get_ResponseText( req, &response );
+        ok( hr == S_OK, "got %08x\n", hr );
+        ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
+        SysFreeString( response );
+    }
+
+    IWinHttpRequest_Release( req );
+
+    hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    sprintf( buf, "http://localhost:%d/auth", port );
+    MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) );
+    url = SysAllocString( bufW );
+    method = SysAllocString( method3W );
+    V_VT( &async ) = VT_BOOL;
+    V_BOOL( &async ) = VARIANT_FALSE;
+    hr = IWinHttpRequest_Open( req, method, url, async );
+    ok( hr == S_OK, "got %08x\n", hr );
+    SysFreeString( method );
+    SysFreeString( url );
+
+    hr = IWinHttpRequest_get_Status( req, &status );
+    ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
+
+    V_VT( &data ) = VT_BSTR;
+    V_BSTR( &data ) = SysAllocString( test_dataW );
+    hr = IWinHttpRequest_Send( req, data );
+    ok( hr == S_OK, "got %08x\n", hr );
+    SysFreeString( V_BSTR( &data ) );
+
+    hr = IWinHttpRequest_get_ResponseText( req, &response );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
+    SysFreeString( response );
+
+    status = 0xdeadbeef;
+    hr = IWinHttpRequest_get_Status( req, &status );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
+
+    IWinHttpRequest_Release( req );
+
+    CoUninitialize();
+}
+
+static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
+{
+    DISPPARAMS params;
+    VARIANT arg;
+    HRESULT hr;
+
+    memset(&params, 0, sizeof(params));
+    params.cNamedArgs = 0;
+    params.rgdispidNamedArgs = NULL;
+    params.cArgs = 1;
+    params.rgvarg = &arg;
+    VariantInit(&arg);
+    V_VT(&arg) = VT_I4;
+    V_I4(&arg) = property;
+    VariantInit(ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
+                                DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+}
+
+static void test_IWinHttpRequest_Invoke(void)
+{
+    static const WCHAR utf8W[] = {'U','T','F','-','8',0};
+    static const WCHAR regid[] = {'W','i','n','H','t','t','p','.','W','i','n','H','t','t','p','R','e','q','u','e','s','t','.','5','.','1',0};
+    WCHAR openW[] = {'O','p','e','n',0};
+    WCHAR optionW[] = {'O','p','t','i','o','n',0};
+    OLECHAR *open = openW, *option = optionW;
+    BSTR utf8;
+    CLSID clsid;
+    IWinHttpRequest *request;
+    IDispatch *dispatch;
+    DISPID id;
+    DISPPARAMS params;
+    VARIANT arg[3], ret;
+    UINT err;
+    BOOL bret;
+    HRESULT hr;
+
+    CoInitialize(NULL);
+
+    hr = CLSIDFromProgID(regid, &clsid);
+    ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
+    bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
+    ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
+
+    hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
+    ok(hr == S_OK, "error %#x\n", hr);
+    IDispatch_Release(dispatch);
+
+    hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
+    ok(hr == S_OK, "error %#x\n", hr);
+    ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
+
+    hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
+    ok(hr == S_OK, "error %#x\n", hr);
+    ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    memset(&params, 0, sizeof(params));
+    params.cArgs = 2;
+    params.cNamedArgs = 0;
+    params.rgvarg = arg;
+    V_VT(&arg[0]) = VT_I4;
+    V_I4(&arg[0]) = 1252;
+    V_VT(&arg[1]) = VT_R8;
+    V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
+                                DISPATCH_METHOD, &params, NULL, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    memset(&params, 0, sizeof(params));
+    params.cArgs = 2;
+    params.cNamedArgs = 0;
+    params.rgvarg = arg;
+    V_VT(&arg[0]) = VT_I4;
+    V_I4(&arg[0]) = 1252;
+    V_VT(&arg[1]) = VT_R8;
+    V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
+                                DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    memset(&params, 0, sizeof(params));
+    params.cArgs = 2;
+    params.cNamedArgs = 0;
+    params.rgvarg = arg;
+    V_VT(&arg[0]) = VT_I4;
+    V_I4(&arg[0]) = 1252;
+    V_VT(&arg[1]) = VT_R8;
+    V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
+                                DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
+
+    memset(&params, 0, sizeof(params));
+    params.cArgs = 2;
+    params.cNamedArgs = 0;
+    params.rgvarg = arg;
+    V_VT(&arg[0]) = VT_BSTR;
+    utf8 = SysAllocString(utf8W);
+    V_BSTR(&arg[0]) = utf8;
+    V_VT(&arg[1]) = VT_R8;
+    V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
+    hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
+
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
+
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
+    ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
+
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
+    ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
+
+    VariantInit(&ret);
+    if (0) /* crashes */
+        hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
+
+    params.cArgs = 1;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
+    ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
+
+    VariantInit(&arg[2]);
+    params.cArgs = 3;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
+todo_wine
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    VariantInit(&arg[0]);
+    VariantInit(&arg[1]);
+    VariantInit(&arg[2]);
+
+    params.cArgs = 1;
+    V_VT(&arg[0]) = VT_I4;
+    V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    V_VT(&ret) = 0xdead;
+    V_I4(&ret) = 0xbeef;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    V_VT(&ret) = 0xdead;
+    V_I4(&ret) = 0xbeef;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+    ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
+
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    V_VT(&ret) = 0xdead;
+    V_I4(&ret) = 0xbeef;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+    ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
+    ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
+
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
+    ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
+
+    params.cArgs = 2;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
+todo_wine
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    params.cArgs = 0;
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
+    ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
+
+    SysFreeString(utf8);
+
+    params.cArgs = 1;
+    V_VT(&arg[0]) = VT_I4;
+    V_I4(&arg[0]) = AutoLogonPolicy_Never;
+    VariantInit(&ret);
+    hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
+                                DISPATCH_METHOD, &params, &ret, NULL, NULL);
+    ok(hr == S_OK, "error %#x\n", hr);
+
+    IWinHttpRequest_Release(request);
+
     CoUninitialize();
 }
 
@@ -2764,7 +3948,7 @@ if (0) /* crashes on some win2k systems */
     if (!ret)
     {
         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
-        ok( url == (WCHAR *)0xdeadbeef, "got %p\n", url );
+        ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
     }
     else
     {
@@ -2779,10 +3963,11 @@ if (0) /* crashes on some win2k systems */
     if (!ret)
     {
         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
-        ok( url == (WCHAR *)0xdeadbeef, "got %p\n", url );
+        ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
     }
     else
     {
+        ok( error == ERROR_SUCCESS, "got %u\n", error );
         trace("%s\n", wine_dbgstr_w(url));
         GlobalFree( url );
     }
@@ -2802,8 +3987,12 @@ static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
     ok( !ret, "expected failure\n" );
     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
 
+    SetLastError(0xdeadbeef);
     ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
+    error = GetLastError();
     ok( ret, "expected success\n" );
+    ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
+
     trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
     trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
     trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
@@ -2893,10 +4082,9 @@ static void test_WinHttpGetProxyForUrl(void)
     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)
     {
+        ok( error == ERROR_SUCCESS, "got %u\n", error );
         trace("Proxy.AccessType=%u\n", info.dwAccessType);
         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
         trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
@@ -2909,11 +4097,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));
@@ -2926,11 +4111,10 @@ static void test_WinHttpGetProxyForUrl(void)
 
 static void test_chunked_read(void)
 {
-    static const WCHAR host[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
     static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
     static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
     WCHAR header[32];
-    DWORD len;
+    DWORD len, err;
     HINTERNET ses, con = NULL, req = NULL;
     BOOL ret;
 
@@ -2940,7 +4124,7 @@ static void test_chunked_read(void)
     ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
     if (!ses) goto done;
 
-    con = WinHttpConnect( ses, host, 0, 0 );
+    con = WinHttpConnect( ses, test_winehq, 0, 0 );
     ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
     if (!con) goto done;
 
@@ -2949,6 +4133,12 @@ static void test_chunked_read(void)
     if (!req) goto done;
 
     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
+    err = GetLastError();
+    if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
+    {
+        skip("connection failed, skipping\n");
+        goto done;
+    }
     ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
 
     ret = WinHttpReceiveResponse( req, NULL );
@@ -3022,13 +4212,13 @@ START_TEST (winhttp)
     test_Timeouts();
     test_resolve_timeout();
     test_credentials();
-    test_IWinHttpRequest();
+    test_IWinHttpRequest_Invoke();
     test_WinHttpDetectAutoProxyConfigUrl();
     test_WinHttpGetIEProxyConfigForCurrentUser();
     test_WinHttpGetProxyForUrl();
     test_chunked_read();
 
-    si.event = CreateEvent(NULL, 0, 0, NULL);
+    si.event = CreateEventW(NULL, 0, 0, NULL);
     si.port = 7532;
 
     thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
@@ -3039,11 +4229,17 @@ START_TEST (winhttp)
     if (ret != WAIT_OBJECT_0)
         return;
 
+    test_IWinHttpRequest(si.port);
     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);
+    test_cookies(si.port);
 
     /* send the basic request again to shutdown the server thread */
     test_basic_request(si.port, NULL, quitW);