X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=modules%2Frostests%2Fwinetests%2Fwinhttp%2Fwinhttp.c;h=7ed8a527fca8043a0e6b4eee7fa6c0726e057134;hp=fb7bf8907b83f1aa111739c86c63f39b13075247;hb=412bce85f2833c30750d7bf0129185ffbfd40f84;hpb=5bd6580fc63bb886686b62caf26f3ea99a173922 diff --git a/modules/rostests/winetests/winhttp/winhttp.c b/modules/rostests/winetests/winhttp/winhttp.c index fb7bf8907b8..7ed8a527fca 100644 --- a/modules/rostests/winetests/winhttp/winhttp.c +++ b/modules/rostests/winetests/winhttp/winhttp.c @@ -33,6 +33,7 @@ #include #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[] = "= 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);