X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=modules%2Frostests%2Fwinetests%2Fwininet%2Fhttp.c;h=de34a37cd6ba0e7cc6f83b78a5148e09ab72fb7e;hp=1c5cbfe834b2ec02081975fde7f646f5cdc96457;hb=a4f791d9206d3b1c67fba2793f80234ad8a2411f;hpb=56601978c4dfeba5add6e5a4abb853de72c8bb34 diff --git a/modules/rostests/winetests/wininet/http.c b/modules/rostests/winetests/wininet/http.c index 1c5cbfe834b..de34a37cd6b 100644 --- a/modules/rostests/winetests/wininet/http.c +++ b/modules/rostests/winetests/wininet/http.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "windef.h" #include "winbase.h" @@ -172,7 +173,7 @@ static BOOL (WINAPI *pInternetGetSecurityInfoByURLA)(LPSTR,PCCERT_CHAIN_CONTEXT* static int strcmp_wa(LPCWSTR strw, const char *stra) { WCHAR buf[512]; - MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf)); return lstrcmpW(strw, buf); } @@ -723,8 +724,11 @@ static void InternetReadFile_test(int flags, const test_data_t *test) length = sizeof(buffer)-2; memset(buffer, 0x77, sizeof(buffer)); + SetLastError(0xdeadbeef); res = HttpQueryInfoA(hor,HTTP_QUERY_RAW_HEADERS,buffer,&length,0x0); ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError()); + ok(GetLastError() == 0 || + broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError()); /* show that the function writes data past the length returned */ ok(buffer[length-2], "Expected any header character, got 0x00\n"); ok(!buffer[length-1], "Expected 0x00, got %02X\n", buffer[length-1]); @@ -985,7 +989,10 @@ static void InternetReadFile_chunked_test(void) { char *buffer = HeapAlloc(GetProcessHeap(),0,length+1); + SetLastError(0xdeadbeef); res = InternetReadFile(hor,buffer,length,&got); + ok(GetLastError() == 0 || + broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError()); buffer[got]=0; trace("ReadFile -> %i %i\n",res,got); @@ -998,8 +1005,11 @@ static void InternetReadFile_chunked_test(void) if (length == 0) { got = 0xdeadbeef; + SetLastError(0xdeadbeef); res = InternetReadFile( hor, buffer, 1, &got ); ok( res, "InternetReadFile failed: %u\n", GetLastError() ); + ok(GetLastError() == 0 || + broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError()); ok( !got, "got %u\n", got ); break; } @@ -2044,6 +2054,11 @@ static const char okmsg[] = "Server: winetest\r\n" "\r\n"; +static const char okmsg201[] = +"HTTP/1.1 201 OK\r\n" +"Server: winetest\r\n" +"\r\n"; + static const char okmsg2[] = "HTTP/1.1 200 OK\r\n" "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n" @@ -2053,6 +2068,12 @@ static const char okmsg2[] = "Set-Cookie: two\r\n" "\r\n"; +static DWORD64 content_length; +static const char largemsg[] = +"HTTP/1.1 200 OK\r\n" +"Content-Length: %I64u\r\n" +"\r\n"; + static const char okmsg_cookie_path[] = "HTTP/1.1 200 OK\r\n" "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n" @@ -2432,6 +2453,22 @@ static DWORD CALLBACK server_thread(LPVOID param) else send(c, notokmsg, sizeof notokmsg-1, 0); } + if (strstr(buffer, "HEAD /upload3.txt")) + { + if (strstr(buffer, "Authorization: Basic dXNlcjE6cHdkMQ==")) + send(c, okmsg, sizeof okmsg-1, 0); + else + send(c, noauthmsg, sizeof noauthmsg-1, 0); + } + if (strstr(buffer, "HEAD /upload4.txt")) + { + if (strstr(buffer, "Authorization: Bearer dXNlcjE6cHdkMQ==")) + send(c, okmsg, sizeof okmsg-1, 0); + else if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q=")) + send(c, okmsg201, sizeof okmsg-1, 0); + else + send(c, noauthmsg, sizeof noauthmsg-1, 0); + } if (strstr(buffer, "/test_cookie_path1")) { if (strstr(buffer, "subcookie=data")) @@ -2508,6 +2545,13 @@ static DWORD CALLBACK server_thread(LPVOID param) { send(c, okmsg, sizeof(okmsg)-1, 0); } + + if (strstr(buffer, "HEAD /test_large_content")) + { + char msg[sizeof(largemsg) + 16]; + sprintf(msg, largemsg, content_length); + send(c, msg, strlen(msg), 0); + } if (strstr(buffer, "HEAD /test_auth_host1")) { if (strstr(buffer, "Authorization: Basic dGVzdDE6cGFzcw==")) @@ -4245,7 +4289,7 @@ static void test_head_request(int port) len = sizeof(content_length); content_length = -1; ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, &content_length, &len, 0); - ok(ret, "HttpQueryInfo dailed: %u\n", GetLastError()); + ok(ret, "HttpQueryInfo failed: %u\n", GetLastError()); ok(len == sizeof(DWORD), "len = %u\n", len); ok(content_length == 100, "content_length = %u\n", content_length); @@ -4544,7 +4588,7 @@ static void test_http_status(int port) DWORD i, size; BOOL res; - for(i=0; i < sizeof(http_status_tests)/sizeof(*http_status_tests); i++) { + for(i = 0; i < ARRAY_SIZE(http_status_tests); i++) { send_buffer = http_status_tests[i].response_text; open_simple_request(&req, "localhost", port, NULL, "/send_from_buffer"); @@ -4681,6 +4725,7 @@ static void test_basic_auth_credentials_reuse(int port) HINTERNET ses, con, req; DWORD status, size; BOOL ret; + char buffer[0x40]; ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); ok( ses != NULL, "InternetOpenA failed\n" ); @@ -4695,6 +4740,20 @@ static void test_basic_auth_credentials_reuse(int port) ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "user"), "got %s\n", buffer); + ok(size == 4, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "pwd"), "got %s\n", buffer); + ok(size == 3, "got %u\n", size); + status = 0xdeadbeef; size = sizeof(status); ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); @@ -4718,6 +4777,316 @@ static void test_basic_auth_credentials_reuse(int port) ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "user"), "got %s\n", buffer); + ok(size == 4, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "pwd"), "got %s\n", buffer); + ok(size == 3, "got %u\n", size); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 200, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); +} + +static void test_basic_auth_credentials_end_session(int port) +{ + HINTERNET ses, con, req; + DWORD status, size; + BOOL ret; + char buffer[0x40]; + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, "user", "pwd", + INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "user"), "got %s\n", buffer); + ok(size == 4, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "pwd"), "got %s\n", buffer); + ok(size == 3, "got %u\n", size); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == HTTP_STATUS_OK, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + /* Clear the cached credentials */ + ret = InternetSetOptionA(ses, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0); + ok(ret, "unexpected failure %u\n", GetLastError()); + + con = InternetConnectA( ses, "localhost", port, NULL, NULL, + INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "PUT", "/upload2.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, ""), "got %s\n", buffer); + ok(size == 0, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, ""), "got %s\n", buffer); + ok(size == 0, "got %u\n", size); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); +} + +static void test_basic_auth_credentials_different(int port) +{ + HINTERNET ses, con, req; + DWORD status, size; + BOOL ret; + char buffer[0x40]; + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, "user", "pwd", + INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "user"), "got %s\n", buffer); + ok(size == 4, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "pwd"), "got %s\n", buffer); + ok(size == 3, "got %u\n", size); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 200, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, "user1", "pwd1", + INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload3.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "user1"), "got %s\n", buffer); + ok(size == 5, "got %u\n", size); + + size = sizeof(buffer); + SetLastError(0xdeadbeef); + ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size); + ok(ret, "unexpected failure %u\n", GetLastError()); + ok(!strcmp(buffer, "pwd1"), "got %s\n", buffer); + ok(size == 4, "got %u\n", size); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 200, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); +} + +/* + * Manually set the Authorization for both calls. + */ +static void test_basic_auth_credentials_manual(int port) +{ + HINTERNET ses, con, req; + DWORD status, size; + BOOL ret; + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + /* Clear the cached credentials */ + ret = InternetSetOptionA(ses, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0); + ok(ret, "unexpected failure %u\n", GetLastError()); + + con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + /* Set Authorization Header */ + ret = HttpAddRequestHeadersA(req, "Authorization: Basic dXNlcjpwd2Q=\r\n", ~0u, + HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); + ok(ret, "HttpAddRequestHeaders Failed\n"); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 200, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); + + /* Show manual headers are cached. */ + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 401, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload4.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + /* Set Authorization Header */ + ret = HttpAddRequestHeadersA(req, "Authorization: Bearer dXNlcjE6cHdkMQ==\r\n", ~0u, + HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); + ok(ret, "HttpAddRequestHeaders Failed\n"); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 200, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); +} + +/* + * Manually set the Authorization for the bearer call, which shows the cached is used. + */ +static void test_basic_auth_credentials_cached_manual(int port) +{ + HINTERNET ses, con, req; + DWORD status, size; + BOOL ret; + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + /* Clear the cached credentials */ + ret = InternetSetOptionA(ses, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0); + ok(ret, "unexpected failure %u\n", GetLastError()); + + con = InternetConnectA( ses, "localhost", port, "user", "pwd", + INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + status = 0xdeadbeef; size = sizeof(status); ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); @@ -4727,6 +5096,33 @@ static void test_basic_auth_credentials_reuse(int port) InternetCloseHandle( req ); InternetCloseHandle( con ); InternetCloseHandle( ses ); + + ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); + ok( ses != NULL, "InternetOpenA failed\n" ); + + con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ); + ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() ); + + req = HttpOpenRequestA( con, "HEAD", "/upload4.txt", NULL, NULL, NULL, 0, 0 ); + ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() ); + + /* Setting an Authorization Header doesn't override the cached one. */ + ret = HttpAddRequestHeadersA(req, "Authorization: Bearer dXNlcjE6cHdkMQ==\r\n", ~0u, + HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); + ok(ret, "HttpAddRequestHeaders Failed\n"); + + ret = HttpSendRequestA( req, NULL, 0, NULL, 0 ); + ok( ret, "HttpSendRequestA failed %u\n", GetLastError() ); + + status = 0xdeadbeef; + size = sizeof(status); + ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); + ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() ); + ok( status == 201, "got %u\n", status ); + + InternetCloseHandle( req ); + InternetCloseHandle( con ); + InternetCloseHandle( ses ); } static void test_async_read(int port) @@ -5792,6 +6188,94 @@ static void test_remove_dot_segments(int port) close_request(&req); } +struct large_test +{ + DWORD64 content_length; + BOOL ret; +}; + +static void test_large_content(int port) +{ + struct large_test tests[] = { + { 0, TRUE }, + { UINT_MAX-1, TRUE }, + { UINT_MAX, TRUE }, + { (DWORD64)UINT_MAX+1, FALSE }, + { ~0, FALSE }, + }; + test_request_t req; + DWORD sizelen, len; + DWORD read_size; + DWORD64 len64; + char buf[16]; + BOOL ret; + size_t i; + + open_simple_request(&req, "localhost", port, "HEAD", "/test_large_content"); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + content_length = tests[i].content_length; + ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0); + ok(ret, "HttpSendRequest failed: %u\n", GetLastError()); + + len = ~0; + sizelen = sizeof(len); + SetLastError(0xdeadbeef); + ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &len, &sizelen, 0); + if (tests[i].ret) + { + ok(ret, "HttpQueryInfo should have succeeded\n"); + ok(GetLastError() == ERROR_SUCCESS || + broken(GetLastError() == 0xdeadbeef), /* xp, 2k8, vista */ + "expected ERROR_SUCCESS, got %x\n", GetLastError()); + ok(len == (DWORD)tests[i].content_length, "expected %u, got %u\n", + (DWORD)tests[i].content_length, len); + } + else + { + ok(!ret, "HttpQueryInfo should have failed\n"); + ok(GetLastError() == ERROR_HTTP_INVALID_HEADER, + "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError()); + ok(len == ~0, "expected ~0, got %u\n", len); + } + ok(sizelen == sizeof(DWORD), "sizelen %u\n", sizelen); + } + + /* test argument size */ + len64 = ~0; + sizelen = sizeof(len64); + SetLastError(0xdeadbeef); + ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, + &len64, &len, 0); + ok(!ret, "HttpQueryInfo should have failed\n"); + ok(GetLastError() == ERROR_HTTP_INVALID_HEADER, + "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError()); + ok(sizelen == sizeof(DWORD64), "sizelen %u\n", sizelen); + ok(len64 == ~0, "len64 %x%08x\n", (DWORD)(len64 >> 32), (DWORD)len64); + + close_request(&req); + + /* test internal use of HttpQueryInfo on large size */ + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "Content-Length: 4294967296\r\n" + "\r\n" + "xx"); + read_expect_async(req.request, buf, 4, &read_size, "xx"); + send_response_and_wait("yy1234567890", FALSE, buf, &read_size, "xxyy", 4, 0, 2); + read_expect_sync_data(req.request, buf, 10, "1234567890"); + + SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION); + SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED); + close_async_handle(req.session, 2); + CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + close_connection(); +} + static void test_http_connection(void) { struct server_info si; @@ -5801,7 +6285,7 @@ static void test_http_connection(void) si.hEvent = CreateEventW(NULL, 0, 0, NULL); si.port = 7531; - hThread = CreateThread(NULL, 0, server_thread, (LPVOID) &si, 0, &id); + hThread = CreateThread(NULL, 0, server_thread, &si, 0, &id); ok( hThread != NULL, "create thread failed\n"); r = WaitForSingleObject(si.hEvent, 10000); @@ -5843,6 +6327,10 @@ static void test_http_connection(void) test_request_content_length(si.port); test_accept_encoding(si.port); test_basic_auth_credentials_reuse(si.port); + test_basic_auth_credentials_end_session(si.port); + test_basic_auth_credentials_different(si.port); + test_basic_auth_credentials_manual(si.port); + test_basic_auth_credentials_cached_manual(si.port); test_async_read(si.port); test_http_read(si.port); test_connection_break(si.port); @@ -5861,6 +6349,7 @@ else } #endif test_remove_dot_segments(si.port); + test_large_content(si.port); /* send the basic request again to shutdown the server thread */ test_basic_request(si.port, "GET", "/quit"); @@ -5908,12 +6397,15 @@ static const cert_struct_test_t test_winehq_com_cert = { "Minnesota\r\n" "Saint Paul\r\n" "WineHQ\r\n" + "IT\r\n" "test.winehq.com\r\n" "webmaster@winehq.org", "US\r\n" "Minnesota\r\n" + "Saint Paul\r\n" "WineHQ\r\n" + "IT\r\n" "test.winehq.com\r\n" "webmaster@winehq.org" }; @@ -5928,6 +6420,12 @@ static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test) size = sizeof(info); res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size); + if (!res) + { + win_skip("Querying INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT failed, skipping tests\n"); + return; + } + ok(res, "InternetQueryOption failed: %u\n", GetLastError()); ok(size == sizeof(info), "size = %u\n", size); @@ -6142,7 +6640,7 @@ static void test_security_flags(void) ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError()); WaitForSingleObject(complete_event, INFINITE); - ok(req_error == ERROR_INTERNET_SEC_CERT_REV_FAILED || broken(req_error == ERROR_INTERNET_SEC_CERT_ERRORS), + ok(req_error == ERROR_INTERNET_SEC_CERT_ERRORS, "req_error = %d\n", req_error); size = 0; @@ -6166,6 +6664,9 @@ static void test_security_flags(void) ok(!cert->lpszEncryptionAlgName, "unexpected encryption algorithm name\n"); ok(!cert->lpszProtocolName, "unexpected protocol name\n"); ok(cert->dwKeySize != 0xdeadbeef, "unexpected key size\n"); + + LocalFree(cert->lpszSubjectInfo); + LocalFree(cert->lpszIssuerInfo); } HeapFree(GetProcessHeap(), 0, cert); @@ -6178,7 +6679,7 @@ static void test_security_flags(void) CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT); CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY); - if(req_error != ERROR_INTERNET_SEC_CERT_REV_FAILED) { + if(req_error != ERROR_INTERNET_SEC_CERT_ERRORS) { win_skip("Unexpected cert errors %u, skipping security flags tests\n", req_error); close_async_handle(ses, 3); @@ -6192,10 +6693,10 @@ static void test_security_flags(void) test_request_flags(req, 8); /* IE11 finds both rev failure and invalid CA. Previous versions required rev failure to be ignored before invalid CA was reported. */ - test_secflags_option(req, _SECURITY_FLAG_CERT_REV_FAILED, _SECURITY_FLAG_CERT_INVALID_CA); + test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA, _SECURITY_FLAG_CERT_REV_FAILED); set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_REVOCATION); - test_secflags_option(req, _SECURITY_FLAG_CERT_REV_FAILED|SECURITY_FLAG_IGNORE_REVOCATION, _SECURITY_FLAG_CERT_INVALID_CA); + test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA|SECURITY_FLAG_IGNORE_REVOCATION, _SECURITY_FLAG_CERT_REV_FAILED); SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER); SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER); @@ -6209,7 +6710,7 @@ static void test_security_flags(void) ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError()); WaitForSingleObject(complete_event, INFINITE); - ok(req_error == ERROR_INTERNET_SEC_CERT_ERRORS, "req_error = %d\n", req_error); + ok(req_error == ERROR_INTERNET_INVALID_CA || req_error == ERROR_INTERNET_SEC_CERT_ERRORS, "req_error = %d\n", req_error); CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER); CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); @@ -6220,11 +6721,11 @@ static void test_security_flags(void) CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY); test_request_flags(req, INTERNET_REQFLAG_NO_HEADERS); - test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_REV_FAILED|_SECURITY_FLAG_CERT_INVALID_CA, 0); + test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0); test_security_info("https://test.winehq.com/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0); set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_UNKNOWN_CA); - test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA|_SECURITY_FLAG_CERT_REV_FAILED + test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA |SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_UNKNOWN_CA, 0); test_http_version(req); @@ -6262,11 +6763,11 @@ static void test_security_flags(void) test_request_flags(req, 0); test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_IGNORE_REVOCATION - |SECURITY_FLAG_STRENGTH_STRONG|_SECURITY_FLAG_CERT_REV_FAILED|_SECURITY_FLAG_CERT_INVALID_CA, 0); + |SECURITY_FLAG_STRENGTH_STRONG|_SECURITY_FLAG_CERT_INVALID_CA, 0); test_cert_struct(req, &test_winehq_com_cert); test_security_info("https://test.winehq.com/data/some_file.html?q", 0, - _SECURITY_FLAG_CERT_INVALID_CA|_SECURITY_FLAG_CERT_REV_FAILED); + _SECURITY_FLAG_CERT_INVALID_CA); res = InternetReadFile(req, buf, sizeof(buf), &size); ok(res, "InternetReadFile failed: %u\n", GetLastError()); @@ -6299,7 +6800,7 @@ static void test_security_flags(void) CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG - |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_REV_FAILED|_SECURITY_FLAG_CERT_INVALID_CA, 0); + |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0); test_http_version(req); SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER); @@ -6334,7 +6835,7 @@ static void test_security_flags(void) test_request_flags(req, 0); test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG - |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_REV_FAILED|_SECURITY_FLAG_CERT_INVALID_CA, 0); + |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0); res = InternetReadFile(req, buf, sizeof(buf), &size); ok(res, "InternetReadFile failed: %u\n", GetLastError()); @@ -6903,14 +7404,14 @@ static const struct notification async_send_request_ex_chunked_test[] = static const struct notification_data notification_data[] = { { async_send_request_ex_chunked_test, - sizeof(async_send_request_ex_chunked_test)/sizeof(async_send_request_ex_chunked_test[0]), + ARRAY_SIZE(async_send_request_ex_chunked_test), "GET", "test.winehq.org", "tests/data.php" }, { async_send_request_ex_test, - sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]), + ARRAY_SIZE(async_send_request_ex_test), "POST", "test.winehq.org", "tests/post.php", @@ -6918,14 +7419,14 @@ static const struct notification_data notification_data[] = { }, { async_send_request_ex_test2, - sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]), + ARRAY_SIZE(async_send_request_ex_test2), "POST", "test.winehq.org", "tests/post.php" }, { async_send_request_ex_resolve_failure_test, - sizeof(async_send_request_ex_resolve_failure_test)/sizeof(async_send_request_ex_resolve_failure_test[0]), + ARRAY_SIZE(async_send_request_ex_resolve_failure_test), "GET", "brokenhost", "index.html",