[WINHTTP_WINETEST] Sync with Wine Staging 4.18. CORE-16441
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 7 Dec 2019 12:06:11 +0000 (13:06 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 7 Dec 2019 12:06:11 +0000 (13:06 +0100)
modules/rostests/winetests/winhttp/notification.c
modules/rostests/winetests/winhttp/url.c
modules/rostests/winetests/winhttp/winhttp.c

index 494d474..75bfc64 100644 (file)
@@ -187,7 +187,7 @@ static void test_connection_cache( void )
     struct info info, *context = &info;
 
     info.test  = cache_test;
-    info.count = sizeof(cache_test) / sizeof(cache_test[0]);
+    info.count = ARRAY_SIZE( cache_test );
     info.index = 0;
     info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
 
@@ -427,7 +427,7 @@ static void test_redirect( void )
     struct info info, *context = &info;
 
     info.test  = redirect_test;
-    info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
+    info.count = ARRAY_SIZE( redirect_test );
     info.index = 0;
     info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
 
@@ -508,7 +508,7 @@ static void test_async( void )
     char buffer[1024];
 
     info.test  = async_test;
-    info.count = sizeof(async_test) / sizeof(async_test[0]);
+    info.count = ARRAY_SIZE( async_test );
     info.index = 0;
     info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
 
@@ -779,12 +779,12 @@ static void open_async_request(int port, struct test_request *req, struct info *
     if (reuse_connection)
     {
         info->test  = reuse_socket_request_test;
-        info->count = sizeof(reuse_socket_request_test) / sizeof(reuse_socket_request_test[0]);
+        info->count = ARRAY_SIZE( reuse_socket_request_test );
     }
     else
     {
         info->test  = open_socket_request_test;
-        info->count = sizeof(open_socket_request_test) / sizeof(open_socket_request_test[0]);
+        info->count = ARRAY_SIZE( open_socket_request_test );
     }
 
     req->session = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
@@ -830,7 +830,7 @@ static void server_send_reply(struct test_request *req, struct info *info, const
     WaitForSingleObject( info->wait, INFINITE );
 
     info->test  = server_reply_test;
-    info->count = sizeof(server_reply_test) / sizeof(server_reply_test[0]);
+    info->count = ARRAY_SIZE( server_reply_test );
     info->index = 0;
     setup_test( info, winhttp_send_request, __LINE__ );
     ret = WinHttpReceiveResponse( req->request, NULL );
@@ -879,12 +879,12 @@ static void close_request(struct test_request *req, struct info *info, BOOL allo
     if (allow_closing_connection)
     {
         info->test = close_allow_connection_close_request_test;
-        info->count = sizeof(close_allow_connection_close_request_test)/sizeof(*close_allow_connection_close_request_test);
+        info->count = ARRAY_SIZE( close_allow_connection_close_request_test );
     }
     else
     {
         info->test = close_request_test;
-        info->count = sizeof(close_request_test)/sizeof(*close_request_test);
+        info->count = ARRAY_SIZE( close_request_test );
     }
     info->index = 0;
     setup_test( info, winhttp_close_handle, __LINE__ );
@@ -920,25 +920,24 @@ static const struct notification read_allow_close_test[] =
 static void _read_request_data(struct test_request *req, struct info *info, const char *expected_data, BOOL closing_connection, unsigned line)
 {
     char buffer[1024];
-    DWORD read, len;
+    DWORD len;
     BOOL ret;
 
     if (closing_connection)
     {
         info->test = read_allow_close_test;
-        info->count = sizeof(read_allow_close_test)/sizeof(*read_allow_close_test);
+        info->count = ARRAY_SIZE( read_allow_close_test );
     }
     else
     {
         info->test = read_test;
-        info->count = sizeof(read_test)/sizeof(*read_test);
+        info->count = ARRAY_SIZE( read_test );
     }
     info->index = 0;
 
     setup_test( info, winhttp_read_data, line );
     memset(buffer, '?', sizeof(buffer));
-    read = 0xdeadbeef;
-    ret = WinHttpReadData( req->request, buffer, sizeof(buffer), &read );
+    ret = WinHttpReadData( req->request, buffer, sizeof(buffer), NULL );
     ok(ret, "failed to read data %u\n", GetLastError());
 
     WaitForSingleObject( info->wait, INFINITE );
@@ -1024,7 +1023,7 @@ START_TEST (notification)
     si.event = CreateEventW( NULL, 0, 0, NULL );
     si.port = 7533;
 
-    thread = CreateThread( NULL, 0, server_thread, (LPVOID)&si, 0, NULL );
+    thread = CreateThread( NULL, 0, server_thread, &si, 0, NULL );
     ok(thread != NULL, "failed to create thread %u\n", GetLastError());
 
     server_socket_available = CreateEventW( NULL, 0, 0, NULL );
index 6bde1de..37a6e4a 100644 (file)
@@ -34,6 +34,9 @@ static WCHAR password[] = {'p','a','s','s','w','o','r','d',0};
 static WCHAR about[]    = {'/','s','i','t','e','/','a','b','o','u','t',0};
 static WCHAR query[]    = {'?','q','u','e','r','y',0};
 static WCHAR escape[]   = {' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`','{','|','}','~',0};
+static WCHAR escape2[]  = {'\r',0x1f,' ','\n',0x7f,'\r','\n',0};
+static WCHAR escape3[]  = {'?','t','e','x','t','=',0xfb00,0};
+static WCHAR escape4[]  = {'/','t','e','x','t','=',0xfb00,0};
 
 static const WCHAR url1[]  =
     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
@@ -72,6 +75,16 @@ static const WCHAR url14[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i
 static const WCHAR url15[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','6','5','5','3','6',0};
 static const WCHAR url16[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','0',0};
 static const WCHAR url17[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':',0};
+static const WCHAR url18[] =
+    {'h','t','t','p',':','/','/','%','0','D','%','1','F','%','2','0','%','0','A','%','7','F','%','0','D','%','0','A',0};
+static const WCHAR url19[] =
+    {'h','t','t','p',':','/','/','?','t','e','x','t','=',0xfb00,0};
+static const WCHAR url20[] =
+    {'h','t','t','p',':','/','/','/','t','e','x','t','=',0xfb00,0};
+static const WCHAR url21[] =
+    {'h','t','t','p','s',':','/','/','n','b','a','2','k','1','9','-','w','s','.','2','k','s','p','o','r','t','s','.','c','o','m',':','1','9','1','3','3',
+     '/','n','b','a','/','v','4','/','A','c','c','o','u','n','t','s','/','g','e','t','_','a','c','c','o','u','n','t','?','x','=','3','7','8','9','5','2',
+     '6','7','7','5','2','6','5','6','6','3','8','7','6',0};
 
 static const WCHAR url_k1[]  =
     {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
@@ -301,7 +314,87 @@ static void WinHttpCreateUrl_test( void )
     ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
     ok( ret, "expected success\n" );
     ok( len == 113, "expected len 113 got %u\n", len );
-    ok( !lstrcmpW( url, url7 ), "url doesn't match\n" );
+    ok( !lstrcmpW( url, url7 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
+
+    /* escape extra info */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszExtraInfo = escape2;
+    uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
+    url[0] = 0;
+    len = 256;
+    ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
+    ok( ret, "expected success\n" );
+    ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len );
+    ok( !lstrcmpW( url, url18 ), "url doesn't match\n" );
+
+    /* extra info with Unicode characters */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszExtraInfo = escape3;
+    uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
+    url[0] = 0;
+    len = 256;
+    SetLastError( 0xdeadbeef );
+    ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
+    err = GetLastError();
+    ok( !ret, "expected failure\n" );
+    ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err );
+
+    /* extra info with Unicode characters, no ICU_ESCAPE */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszExtraInfo = escape3;
+    uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo );
+    url[0] = 0;
+    len = 256;
+    ret = WinHttpCreateUrl( &uc, 0, url, &len );
+    ok( ret || broken(!ret) /* < win7 */, "expected success\n" );
+    if (ret)
+    {
+        ok( len == lstrlenW(url19), "expected len %u got %u\n", lstrlenW(url19), len );
+        ok( !lstrcmpW( url, url19 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
+    }
+
+    /* escape path */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszUrlPath = escape2;
+    uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
+    url[0] = 0;
+    len = 256;
+    ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
+    ok( ret, "expected success\n" );
+    ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len );
+    ok( !lstrcmpW( url, url18 ), "url doesn't match\n" );
+
+    /* path with Unicode characters */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszUrlPath = escape4;
+    uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
+    url[0] = 0;
+    len = 256;
+    SetLastError( 0xdeadbeef );
+    ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
+    err = GetLastError();
+    ok( !ret, "expected failure\n" );
+    ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err );
+
+    /* path with Unicode characters, no ICU_ESCAPE */
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize = sizeof(uc);
+    uc.lpszUrlPath = escape4;
+    uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath );
+    url[0] = 0;
+    len = 256;
+    ret = WinHttpCreateUrl( &uc, 0, url, &len );
+    ok( ret || broken(!ret) /* < win7 */, "expected success\n" );
+    if (ret)
+    {
+        ok( len == lstrlenW(url20), "expected len %u got %u\n", lstrlenW(url20), len );
+        ok( !lstrcmpW( url, url20 ), "url doesn't match %s\n", wine_dbgstr_w(url) );
+    }
 
     /* NULL lpszScheme, 0 nScheme and nPort */
     fill_url_components( &uc );
@@ -339,7 +432,7 @@ static void WinHttpCrackUrl_test( void )
     static const WCHAR pathW[] =
         {'/','p','a','t','h','%','2','0','w','i','t','h','%','2','0','s','p','a','c','e','s',0};
     URL_COMPONENTSW uc;
-    WCHAR scheme[20], user[20], pass[20], host[20], path[80], extra[40];
+    WCHAR scheme[20], user[20], pass[20], host[40], path[80], extra[40];
     DWORD error;
     BOOL ret;
 
@@ -667,6 +760,7 @@ static void WinHttpCrackUrl_test( void )
     ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() );
     ok( !lstrcmpW( uc.lpszHostName, hostnameW ), "unexpected host name\n" );
     ok( !lstrcmpW( uc.lpszUrlPath, pathW ), "unexpected path\n" );
+    ok( uc.dwUrlPathLength == lstrlenW(pathW), "got %u\n", uc.dwUrlPathLength );
 
     uc.dwStructSize = sizeof(uc);
     uc.lpszScheme = NULL;
@@ -753,6 +847,19 @@ static void WinHttpCrackUrl_test( void )
     ret = WinHttpCrackUrl( url17, 0, 0, &uc );
     ok( ret, "got %u\n", GetLastError() );
     todo_wine ok( uc.nPort == 80, "got %u\n", uc.nPort );
+
+    memset( &uc, 0, sizeof(uc) );
+    uc.dwStructSize      = sizeof(uc);
+    uc.lpszScheme        = scheme;
+    uc.dwSchemeLength    = ARRAY_SIZE(scheme);
+    uc.lpszHostName      = host;
+    uc.dwHostNameLength  = ARRAY_SIZE(host);
+    uc.lpszUrlPath       = path;
+    uc.dwUrlPathLength   = ARRAY_SIZE(path);
+    ret = WinHttpCrackUrl( url21, 0, 0, &uc );
+    ok( ret, "got %u\n", GetLastError() );
+    ok( !lstrcmpW( uc.lpszUrlPath, url21 + 37 ), "unexpected path %s\n", wine_dbgstr_w(uc.lpszUrlPath) );
+    ok( uc.dwUrlPathLength == 50, "unexpected length %u\n", uc.dwUrlPathLength );
 }
 
 START_TEST(url)
index fb7bf89..7ed8a52 100644 (file)
@@ -33,6 +33,7 @@
 #include <httprequestid.h>
 
 #include "wine/test.h"
+#include "wine/heap.h"
 
 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
@@ -42,6 +43,22 @@ static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q',
 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 WCHAR *a2w(const char *str)
+{
+    int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+    WCHAR *ret = heap_alloc(len * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+    return ret;
+}
+
+static int strcmp_wa(const WCHAR *str1, const char *stra)
+{
+    WCHAR *str2 = a2w(stra);
+    int r = lstrcmpW(str1, str2);
+    heap_free(str2);
+    return r;
+}
+
 static BOOL proxy_active(void)
 {
     WINHTTP_PROXY_INFO proxy_info;
@@ -64,7 +81,7 @@ static BOOL proxy_active(void)
     return active;
 }
 
-static void test_QueryOption(void)
+static void test_WinHttpQueryOption(void)
 {
     BOOL ret;
     HINTERNET session, request, connection;
@@ -201,6 +218,42 @@ static void test_QueryOption(void)
     ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
 
+    feature = 0xdeadbeef;
+    size = sizeof(feature);
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, &size);
+    ok(!ret, "should fail to query enabled features for a request\n");
+    ok(feature == 0xdeadbeef, "expect feature 0xdeadbeef, got %u\n", feature);
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    feature = WINHTTP_ENABLE_SSL_REVOCATION;
+    SetLastError(0xdeadbeef);
+    ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, 0, sizeof(feature));
+    ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, 0);
+    ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
+    ok(ret, "failed to set feature\n");
+    ok(GetLastError() == NO_ERROR || broken(GetLastError() == 0xdeadbeef), /* Doesn't set error code on Vista or older */
+       "expected NO_ERROR, got %u\n", GetLastError());
+
+    feature = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature));
+    ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    feature = 6;
+    size = sizeof(feature);
+    ret = WinHttpSetOption(request, WINHTTP_OPTION_CONNECT_RETRIES, &feature, sizeof(feature));
+    ok(ret, "failed to set WINHTTP_OPTION_CONNECT_RETRIES %u\n", GetLastError());
+
     SetLastError(0xdeadbeef);
     ret = WinHttpCloseHandle(request);
     ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
@@ -214,7 +267,7 @@ done:
     ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
 }
 
-static void test_OpenRequest (void)
+static void test_WinHttpOpenRequest (void)
 {
     BOOL ret;
     HINTERNET session, request, connection;
@@ -309,20 +362,21 @@ static void test_empty_headers_param(void)
     WinHttpCloseHandle(ses);
 }
 
-static void test_SendRequest (void)
+static void test_WinHttpSendRequest (void)
 {
     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[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
-    static const WCHAR test_verb[] = {'P','O','S','T',0};
+    static const WCHAR postW[] = {'P','O','S','T',0};
     static CHAR post_data[] = "mode=Test";
     static const char test_post[] = "mode => Test\0\n";
     HINTERNET session, request, connection;
-    DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable;
+    DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable, len;
     DWORD_PTR context;
     BOOL ret;
     CHAR buffer[256];
+    WCHAR method[8];
     int i;
 
     header_len = -1L;
@@ -336,7 +390,7 @@ static void test_SendRequest (void)
     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,
+    request = WinHttpOpenRequest(connection, postW, test_file, NULL, WINHTTP_NO_REFERER,
         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
     {
@@ -346,6 +400,13 @@ static void test_SendRequest (void)
     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
     if (!request) goto done;
 
+    method[0] = 0;
+    len = sizeof(method);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_REQUEST_METHOD, NULL, method, &len, NULL);
+    ok(ret, "got %u\n", GetLastError());
+    ok(len == lstrlenW(postW) * sizeof(WCHAR), "got %u\n", len);
+    ok(!lstrcmpW(method, postW), "got %s\n", wine_dbgstr_w(method));
+
     context = 0xdeadbeef;
     ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
     ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
@@ -395,6 +456,14 @@ static void test_SendRequest (void)
        "Expected ERROR_SUCCESS got %u.\n", GetLastError());
     ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
 
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_ORIG_URI, NULL, NULL, &len, NULL);
+    ok(!ret && GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_MAX + 1, NULL, NULL, &len, NULL);
+    ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
+
     bytes_rw = -1;
     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
     ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
@@ -980,7 +1049,7 @@ static void test_secure_connection(void)
 {
     static const char data_start[] = "<!DOCTYPE html PUBLIC";
     HINTERNET ses, con, req;
-    DWORD size, status, policy, bitness, read_size, err, available_size, protocols;
+    DWORD size, status, policy, bitness, read_size, err, available_size, protocols, flags;
     BOOL ret;
     CERT_CONTEXT *cert;
     WINHTTP_CERTIFICATE_INFO info;
@@ -1034,6 +1103,33 @@ static void test_secure_connection(void)
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
+    flags = 0xdeadbeef;
+    size = sizeof(flags);
+    ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, &size);
+    ok(ret, "failed to query security flags %u\n", GetLastError());
+    ok(!flags, "got %08x\n", flags);
+
+    flags = SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+    ok(ret, "failed to set security flags %u\n", GetLastError());
+
+    flags = SECURITY_FLAG_SECURE;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+    ok(!ret, "success\n");
+
+    flags = SECURITY_FLAG_STRENGTH_STRONG;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+    ok(!ret, "success\n");
+
+    flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+            SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+    ok(ret, "failed to set security flags %u\n", GetLastError());
+
+    flags = 0;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+    ok(ret, "failed to set security flags %u\n", GetLastError());
+
     ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
     err = GetLastError();
     ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
@@ -1043,7 +1139,7 @@ static void test_secure_connection(void)
     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
     err = GetLastError();
     if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
-                 err == ERROR_WINHTTP_TIMEOUT))
+                 err == ERROR_WINHTTP_TIMEOUT || err == SEC_E_ILLEGAL_MESSAGE))
     {
         skip("secure connection failed, skipping remaining secure tests\n");
         goto cleanup;
@@ -1076,6 +1172,11 @@ static void test_secure_connection(void)
     }
 
     ret = WinHttpReceiveResponse(req, NULL);
+    if (!ret && GetLastError() == ERROR_WINHTTP_CONNECTION_ERROR)
+    {
+        skip("connection error, skipping remaining secure tests\n");
+        goto cleanup;
+    }
     ok(ret, "failed to receive response %u\n", GetLastError());
 
     available_size = 0;
@@ -1107,6 +1208,11 @@ static void test_secure_connection(void)
     }
     ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
 
+    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);
+
 cleanup:
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
@@ -1140,11 +1246,6 @@ static void test_request_parameter_defaults(void)
     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;
@@ -1342,7 +1443,7 @@ static void test_set_default_proxy_config(void)
     set_default_proxy_reg_value( saved_proxy_settings, len, type );
 }
 
-static void test_Timeouts (void)
+static void test_timeouts(void)
 {
     BOOL ret;
     DWORD value, size;
@@ -1931,6 +2032,70 @@ static void test_Timeouts (void)
     ok(ret, "%u\n", GetLastError());
     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
 
+    /* response timeout */
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 30000;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    todo_wine ok(value == 0xbeefdead, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 30000;
+    ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(!ret, "expected failure\n");
+    ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 48878;
+    ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    todo_wine ok(value == 48879, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 48880;
+    ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == 48880, "got %u\n", value);
+
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -1969,6 +2134,11 @@ static void test_resolve_timeout(void)
         ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
            "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
 
+        ret = WinHttpReceiveResponse( req, NULL );
+        ok( !ret && (GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE ||
+                     GetLastError() == ERROR_WINHTTP_OPERATION_CANCELLED /* < win7 */),
+            "got %u\n", GetLastError() );
+
         WinHttpCloseHandle(req);
         WinHttpCloseHandle(con);
         WinHttpCloseHandle(ses);
@@ -2079,6 +2249,13 @@ static const char largeauth[] =
 "Content-Type: text/plain\r\n"
 "\r\n";
 
+static const char passportauth[] =
+"HTTP/1.1 302 Found\r\n"
+"Content-Length: 0\r\n"
+"Location: /\r\n"
+"WWW-Authenticate: Passport1.4\r\n"
+"\r\n";
+
 static const char unauthorized[] = "Unauthorized";
 static const char hello_world[] = "Hello World";
 static const char auth_unseen[] = "Auth Unseen";
@@ -2243,6 +2420,30 @@ static DWORD CALLBACK server_thread(LPVOID param)
             if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
             else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
         }
+        else if (strstr(buffer, "GET /escape"))
+        {
+            static const char res[] = "%0D%0A%1F%7F%3C%20%one?%1F%7F%20!%22%23$%&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
+                                      "%5E_%60%7B%7C%7D~%0D%0A ";
+            static const char res2[] = "%0D%0A%1F%7F%3C%20%25two?%1F%7F%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D"
+                                       "%5E_%60%7B%7C%7D~%0D%0A ";
+            static const char res3[] = "\x1f\x7f<%20%three?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
+            static const char res4[] = "%0D%0A%1F%7F%3C%20%four?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
+            static const char res5[] = "&text=one%C2%80%7F~";
+            static const char res6[] = "&text=two%C2%80\x7f~";
+            static const char res7[] = "&text=%E5%90%9B%E3%81%AE%E5%90%8D%E3%81%AF";
+
+            if (strstr(buffer + 11, res) || strstr(buffer + 11, res2) || strstr(buffer + 11, res3) ||
+                strstr(buffer + 11, res4) || strstr(buffer + 11, res5) || strstr(buffer + 11, res6) ||
+                strstr(buffer + 11, res7))
+            {
+                send(c, okmsg, sizeof(okmsg) - 1, 0);
+            }
+            else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+        }
+        else if (strstr(buffer, "GET /passport"))
+        {
+            send(c, passportauth, sizeof(passportauth) - 1, 0);
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -2319,7 +2520,7 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
     error = GetLastError();
     ok(!ret, "unexpected success\n");
-    todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
+    ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
     ok(supported == 0xdeadbeef, "got %x\n", supported);
     ok(first == 0xdeadbeef, "got %x\n", first);
     ok(target == 0xdeadbeef, "got %x\n", target);
@@ -2406,7 +2607,7 @@ static void test_basic_authentication(int port)
     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
     error = GetLastError();
     ok(!ret, "expected failure\n");
-    todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
+    ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
     ok(supported == 0xdeadbeef, "got %x\n", supported);
     ok(first == 0xdeadbeef, "got %x\n", first);
     ok(target == 0xdeadbeef, "got %x\n", target);
@@ -2631,9 +2832,12 @@ static void test_basic_authentication(int port)
 static void test_multi_authentication(int port)
 {
     static const WCHAR multiauthW[] = {'/','m','u','l','t','i','a','u','t','h',0};
+    static const WCHAR www_authenticateW[] =
+        {'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',0};
     static const WCHAR getW[] = {'G','E','T',0};
     HINTERNET ses, con, req;
-    DWORD supported, first, target;
+    DWORD supported, first, target, size, index;
+    WCHAR buf[512];
     BOOL ret;
 
     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
@@ -2659,6 +2863,22 @@ static void test_multi_authentication(int port)
     ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
     ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
 
+    index = 0;
+    size = sizeof(buf);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, www_authenticateW, buf, &size, &index);
+    ok(ret, "expected success\n");
+    ok(!strcmp_wa(buf, "Bearer"), "buf = %s\n", wine_dbgstr_w(buf));
+    ok(size == lstrlenW(buf) * sizeof(WCHAR), "size = %u\n", size);
+    ok(index == 1, "index = %u\n", index);
+
+    index = 0;
+    size = 0xdeadbeef;
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, www_authenticateW, NULL, &size, &index);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "WinHttpQueryHeaders returned %x(%u)\n", ret, GetLastError());
+    ok(size == (lstrlenW(buf) + 1) * sizeof(WCHAR), "size = %u\n", size);
+    ok(index == 0, "index = %u\n", index);
+
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -2907,7 +3127,7 @@ static void test_not_modified(int port)
 
     memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
     GetSystemTime(&st);
-    WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
+    WinHttpTimeFromSystemTime(&st, &today[ARRAY_SIZE(ifmodifiedW)]);
 
     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
@@ -2982,6 +3202,7 @@ static void test_bad_header( int port )
                                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) );
+    ok( index == 1, "index = %u\n", index );
 
     WinHttpCloseHandle( req );
     WinHttpCloseHandle( con );
@@ -3022,6 +3243,7 @@ static void test_multiple_reads(int port)
             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
 
             ret = WinHttpReadData( req, buf, len, &bytes_read );
+            ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
             ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
 
             HeapFree( GetProcessHeap(), 0, buf );
@@ -3198,6 +3420,74 @@ static void test_cookies( int port )
     WinHttpCloseHandle( ses );
 }
 
+static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags )
+{
+    HINTERNET req;
+    DWORD status, size;
+    BOOL ret;
+
+    req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags );
+    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 || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
+        "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status );
+    WinHttpCloseHandle( req );
+}
+
+static void test_request_path_escapes( int port )
+{
+    static const WCHAR objW[] =
+        {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#',
+         '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
+         '{','|','}','~','\r','\n',0};
+    static const WCHAR obj2W[] =
+        {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#',
+         '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
+         '{','|','}','~','\r','\n',0};
+    static const WCHAR obj3W[] =
+        {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!',
+         '"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^',
+         '_','`','{','|','}','~','\r','\n',0};
+    static const WCHAR obj4W[] =
+        {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"',
+         '#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_',
+         '`','{','|','}','~','\r','\n',0};
+    static const WCHAR obj5W[] =
+        {'/','e','s','c','a','p','e','&','t','e','x','t','=','o','n','e',0x80,0x7f,0x7e,0};
+    static const WCHAR obj6W[] =
+        {'/','e','s','c','a','p','e','&','t','e','x','t','=','t','w','o',0x80,0x7f,0x7e,0};
+    static const WCHAR obj7W[] =
+        {'/','e','s','c','a','p','e','&','t','e','x','t','=',0x541b,0x306e,0x540d,0x306f,0};
+    HINTERNET ses, con;
+
+    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() );
+
+    do_request( con, objW, 0 );
+    do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT );
+    do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE );
+    do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY );
+    do_request( con, obj5W, 0 );
+    do_request( con, obj6W, WINHTTP_FLAG_ESCAPE_DISABLE );
+    do_request( con, obj7W, WINHTTP_FLAG_ESCAPE_DISABLE );
+
+    WinHttpCloseHandle( con );
+    WinHttpCloseHandle( ses );
+}
+
 static void test_connection_info( int port )
 {
     static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
@@ -3257,6 +3547,77 @@ static void test_connection_info( int port )
     WinHttpCloseHandle( ses );
 }
 
+static void test_passport_auth( int port )
+{
+    static const WCHAR passportW[] =
+        {'/','p','a','s','s','p','o','r','t',0};
+    static const WCHAR foundW[] =
+        {'F','o','u','n','d',0};
+    static const WCHAR unauthorizedW[] =
+        {'U','n','a','u','t','h','o','r','i','z','e','d',0};
+    static const WCHAR headersW[] =
+        {'H','T','T','P','/','1','.','1',' ','4','0','1',' ','F','o','u','n','d','\r','\n',
+         'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','0','\r','\n',
+         'L','o','c','a','t','i','o','n',':',' ','/','\r','\n',
+         'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',':',' ',
+         'P','a','s','s','p','o','r','t','1','.','4','\r','\n','\r','\n',0};
+    HINTERNET ses, con, req;
+    DWORD status, size, option;
+    WCHAR buf[128];
+    BOOL ret;
+
+    ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
+    ok( ses != NULL, "got %u\n", GetLastError() );
+
+    option = WINHTTP_ENABLE_PASSPORT_AUTH;
+    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
+    ok( ret, "got %u\n", GetLastError() );
+
+    con = WinHttpConnect( ses, localhostW, port, 0 );
+    ok( con != NULL, "got %u\n", GetLastError() );
+
+    req = WinHttpOpenRequest( con, NULL, passportW, NULL, NULL, NULL, 0 );
+    ok( req != NULL, "got %u\n", GetLastError() );
+
+    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
+    ok( ret, "got %u\n", GetLastError() );
+
+    ret = WinHttpReceiveResponse( req, NULL );
+    ok( ret || broken(!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) /* winxp */, "got %u\n", GetLastError() );
+    if (!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE)
+    {
+        win_skip("no support for Passport redirects\n");
+        goto cleanup;
+    }
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+    ok( ret, "got %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
+
+    buf[0] = 0;
+    size = sizeof(buf);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
+    ok( ret, "got %u\n", GetLastError() );
+    ok( !lstrcmpW(foundW, buf) || broken(!lstrcmpW(unauthorizedW, buf)) /* < win7 */, "got %s\n", wine_dbgstr_w(buf) );
+
+    buf[0] = 0;
+    size = sizeof(buf);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
+    ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
+    if (ret)
+    {
+        ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
+        ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
+    }
+
+cleanup:
+    WinHttpCloseHandle( req );
+    WinHttpCloseHandle( con );
+    WinHttpCloseHandle( ses );
+}
+
 static void test_credentials(void)
 {
     static WCHAR userW[] = {'u','s','e','r',0};
@@ -3277,13 +3638,13 @@ static void test_credentials(void)
     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
     ok(req != NULL, "failed to open a request %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
     ok(ret, "failed to query proxy username %u\n", GetLastError());
     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
     ok(!size, "expected 0, got %u\n", size);
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
     ok(ret, "failed to query proxy password %u\n", GetLastError());
     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
@@ -3292,19 +3653,19 @@ static void test_credentials(void)
     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
     ok(ret, "failed to set username %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
     ok(ret, "failed to query proxy username %u\n", GetLastError());
     ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
     ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
     ok(ret, "failed to query username %u\n", GetLastError());
     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
     ok(!size, "expected 0, got %u\n", size);
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
     ok(ret, "failed to query password %u\n", GetLastError());
     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
@@ -3313,7 +3674,7 @@ static void test_credentials(void)
     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
     ok(ret, "failed to set proxy password %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
     ok(ret, "failed to query proxy password %u\n", GetLastError());
     ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
@@ -3322,7 +3683,7 @@ static void test_credentials(void)
     ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
     ok(ret, "failed to set username %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
     ok(ret, "failed to query username %u\n", GetLastError());
     ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
@@ -3331,7 +3692,7 @@ static void test_credentials(void)
     ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
     ok(ret, "failed to set password %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
     ok(ret, "failed to query password %u\n", GetLastError());
     ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
@@ -3357,7 +3718,7 @@ static void test_credentials(void)
     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
     ok(ret, "failed to set credentials %u\n", GetLastError());
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
     ok(ret, "failed to query username %u\n", GetLastError());
     todo_wine {
@@ -3365,7 +3726,7 @@ static void test_credentials(void)
     ok(!size, "expected 0, got %u\n", size);
     }
 
-    size = sizeof(buffer)/sizeof(WCHAR);
+    size = ARRAY_SIZE(buffer);
     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
     ok(ret, "failed to query password %u\n", GetLastError());
     todo_wine {
@@ -3435,9 +3796,9 @@ static void test_IWinHttpRequest(int port)
     V_VT( &data ) = VT_BSTR;
     V_BSTR( &data ) = SysAllocString( test_dataW );
     hr = IWinHttpRequest_Send( req, data );
-    ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
-        "got %08x\n", hr );
+    ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %08x\n", hr );
     SysFreeString( V_BSTR( &data ) );
+    if (hr != S_OK) goto done;
 
     hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
@@ -3905,14 +4266,14 @@ static void test_IWinHttpRequest(int port)
     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 );
-    }
+    ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ) ||
+        hr == SEC_E_ILLEGAL_MESSAGE /* winxp */, "got %08x\n", hr );
+    if (hr != S_OK) goto done;
+
+    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 );
 
@@ -3920,7 +4281,7 @@ static void test_IWinHttpRequest(int port)
     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]) );
+    MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, ARRAY_SIZE( bufW ));
     url = SysAllocString( bufW );
     method = SysAllocString( method3W );
     V_VT( &async ) = VT_BOOL;
@@ -3949,8 +4310,8 @@ static void test_IWinHttpRequest(int port)
     ok( hr == S_OK, "got %08x\n", hr );
     ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
 
+done:
     IWinHttpRequest_Release( req );
-
     CoUninitialize();
 }
 
@@ -4195,14 +4556,12 @@ static void test_WinHttpDetectAutoProxyConfigUrl(void)
     WCHAR *url;
     DWORD error;
 
-if (0) /* crashes on some win2k systems */
-{
     SetLastError(0xdeadbeef);
     ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
     error = GetLastError();
     ok( !ret, "expected failure\n" );
     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
-}
+
     url = NULL;
     SetLastError(0xdeadbeef);
     ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
@@ -4210,14 +4569,12 @@ if (0) /* crashes on some win2k systems */
     ok( !ret, "expected failure\n" );
     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
 
-if (0) /* crashes on some win2k systems */
-{
     SetLastError(0xdeadbeef);
     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
     error = GetLastError();
     ok( !ret, "expected failure\n" );
     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
-}
+
     url = (WCHAR *)0xdeadbeef;
     SetLastError(0xdeadbeef);
     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
@@ -4388,7 +4745,7 @@ static void test_WinHttpGetProxyForUrl(void)
 
 static void test_chunked_read(void)
 {
-    static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
+    static const WCHAR verb[] = {'/','t','e','s','t','s','/','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, err;
@@ -4417,9 +4774,11 @@ static void test_chunked_read(void)
         goto done;
     }
     ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
+    if (!ret) goto done;
 
     ret = WinHttpReceiveResponse( req, NULL );
     ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
+    if (!ret) goto done;
 
     header[0] = 0;
     len = sizeof(header);
@@ -4449,6 +4808,7 @@ static void test_chunked_read(void)
             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
 
             ret = WinHttpReadData( req, buf, len, &bytes_read );
+            ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
 
             buf[bytes_read] = 0;
             trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
@@ -4476,17 +4836,17 @@ START_TEST (winhttp)
     HANDLE thread;
     DWORD ret;
 
-    test_OpenRequest();
-    test_SendRequest();
+    test_WinHttpOpenRequest();
+    test_WinHttpSendRequest();
     test_WinHttpTimeFromSystemTime();
     test_WinHttpTimeToSystemTime();
     test_WinHttpAddHeaders();
     test_secure_connection();
     test_request_parameter_defaults();
-    test_QueryOption();
+    test_WinHttpQueryOption();
     test_set_default_proxy_config();
     test_empty_headers_param();
-    test_Timeouts();
+    test_timeouts();
     test_resolve_timeout();
     test_credentials();
     test_IWinHttpRequest_Invoke();
@@ -4498,7 +4858,7 @@ START_TEST (winhttp)
     si.event = CreateEventW(NULL, 0, 0, NULL);
     si.port = 7532;
 
-    thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
+    thread = CreateThread(NULL, 0, server_thread, &si, 0, NULL);
     ok(thread != NULL, "failed to create thread %u\n", GetLastError());
 
     ret = WaitForSingleObject(si.event, 10000);
@@ -4522,6 +4882,8 @@ START_TEST (winhttp)
     test_bad_header(si.port);
     test_multiple_reads(si.port);
     test_cookies(si.port);
+    test_request_path_escapes(si.port);
+    test_passport_auth(si.port);
 
     /* send the basic request again to shutdown the server thread */
     test_basic_request(si.port, NULL, quitW);