[WININET_WINETEST] Sync with Wine Staging 2.9. CORE-13362
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 4 Jun 2017 01:49:09 +0000 (01:49 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 4 Jun 2017 01:49:09 +0000 (01:49 +0000)
svn path=/trunk/; revision=74868

rostests/winetests/wininet/http.c
rostests/winetests/wininet/internet.c

index 8c63c80..e42a878 100644 (file)
@@ -1116,16 +1116,9 @@ static void InternetReadFileExA_test(int flags)
     inetbuffers.lpvBuffer = NULL;
     inetbuffers.dwOffsetHigh = 1234;
     inetbuffers.dwOffsetLow = 5678;
-    SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
-    SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
     rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe);
     ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError());
     trace("read %i bytes\n", inetbuffers.dwBufferLength);
-    todo_wine
-    {
-        CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
-        CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
-    }
 
     rc = InternetReadFileExA(NULL, &inetbuffers, 0, 0xdeadcafe);
     ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE),
@@ -1172,10 +1165,8 @@ static void InternetReadFileExA_test(int flags)
             CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
             if (inetbuffers.dwBufferLength)
             {
-                todo_wine {
                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
-                }
             }
             else
             {
@@ -2076,6 +2067,12 @@ static const char ok_with_length2[] =
 "Content-Length: 19\r\n\r\n"
 "HTTP/1.1 211 OK\r\n\r\n";
 
+static const char redir_no_host[] =
+"HTTP/1.1 302 Found\r\n"
+"Location: http:///test1\r\n"
+"Server: winetest\r\n"
+"\r\n";
+
 struct server_info {
     HANDLE hEvent;
     int port;
@@ -2486,6 +2483,10 @@ static DWORD CALLBACK server_thread(LPVOID param)
             else
                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
         }
+        if (strstr(buffer, "GET /test_redirect_no_host"))
+        {
+            send(c, redir_no_host, sizeof redir_no_host-1, 0);
+        }
         shutdown(c, 2);
         closesocket(c);
         c = -1;
@@ -3890,6 +3891,68 @@ static void test_cache_read_gzipped(int port)
     InternetCloseHandle(con);
     InternetCloseHandle(ses);
 
+    /* Decompression doesn't work while reading from cache */
+    test_cache_gzip = 0;
+    sprintf(cache_url, cache_url_fmt, port, get_gzip);
+    DeleteUrlCacheEntryA(cache_url);
+
+    ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+    ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
+
+    ret = TRUE;
+    ret = InternetSetOptionA(ses, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
+    ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
+
+    con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+    ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
+
+    req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
+    ok(req != NULL, "HttpOpenRequest failed\n");
+
+    ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
+    ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
+    size = 0;
+    while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
+        size += read;
+    ok(size == 10, "read %d bytes of data\n", size);
+    buf[size] = 0;
+    ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
+    InternetCloseHandle(req);
+
+    InternetCloseHandle(con);
+    InternetCloseHandle(ses);
+
+    /* Decompression doesn't work while reading from cache */
+    test_cache_gzip = 0;
+    sprintf(cache_url, cache_url_fmt, port, get_gzip);
+    DeleteUrlCacheEntryA(cache_url);
+
+    ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+    ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
+
+    con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+    ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
+
+    ret = TRUE;
+    ret = InternetSetOptionA(con, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
+    ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
+
+    req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
+    ok(req != NULL, "HttpOpenRequest failed\n");
+
+    ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
+    ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
+    size = 0;
+    while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
+        size += read;
+    ok(size == 10, "read %d bytes of data\n", size);
+    buf[size] = 0;
+    ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
+    InternetCloseHandle(req);
+
+    InternetCloseHandle(con);
+    InternetCloseHandle(ses);
+
     DeleteUrlCacheEntryA(cache_url);
 }
 
@@ -4745,7 +4808,6 @@ static void test_async_read(int port)
         if (!ib.dwBufferLength) break;
     }
 
-    todo_wine
     ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads );
     ok( !strcmp(buffer, page1), "unexpected buffer content\n" );
     close_async_handle( ses, hCompleteEvent, 2 );
@@ -4812,7 +4874,6 @@ static void test_async_read(int port)
         {
             ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
             ok( bytes == 0, "expected 0, got %u\n", bytes );
-            todo_wine
             CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
             SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE );
             if (!pending_reads++)
@@ -4835,7 +4896,6 @@ static void test_async_read(int port)
         if (!bytes) break;
     }
 
-    todo_wine
     ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads );
     ok( !strcmp(buffer, page1), "unexpected buffer content\n" );
     close_async_handle( ses, hCompleteEvent, 2 );
@@ -4849,11 +4909,20 @@ static void server_send_string(const char *msg)
     send(server_socket, msg, strlen(msg), 0);
 }
 
+static BOOL skip_receive_notification_tests;
+static DWORD received_response_size;
+
 static void WINAPI readex_callback(HINTERNET handle, DWORD_PTR context, DWORD status, void *info, DWORD info_size)
 {
     switch(status) {
     case INTERNET_STATUS_RECEIVING_RESPONSE:
+        if(!skip_receive_notification_tests)
+            callback(handle, context, status, info, info_size);
+        break;
     case INTERNET_STATUS_RESPONSE_RECEIVED:
+        if(!skip_receive_notification_tests)
+            callback(handle, context, status, info, info_size);
+        received_response_size = *(DWORD*)info;
         break;
     default:
         callback(handle, context, status, info, info_size);
@@ -4884,12 +4953,13 @@ static void open_read_test_request(int port, test_request_t *req, const char *re
     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
+    if(!skip_receive_notification_tests)
+        SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
 
     SetLastError(0xdeadbeef);
     ret = HttpSendRequestA(req->request, NULL, 0, NULL, 0);
     ok(!ret, "HttpSendRequestA unexpectedly succeeded\n");
     ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError());
-    ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
 
     WaitForSingleObject(server_req_rec_event, INFINITE);
 
@@ -4899,22 +4969,37 @@ static void open_read_test_request(int port, test_request_t *req, const char *re
     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
 
+    if(!skip_receive_notification_tests) {
+        SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
+        received_response_size = 0xdeadbeef;
+    }
     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
 
     server_send_string(response);
     WaitForSingleObject(hCompleteEvent, INFINITE);
 
+    if(!skip_receive_notification_tests) {
+        CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
+        CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
+        todo_wine
+        ok(received_response_size == strlen(response), "received_response_size = %u\n", received_response_size);
+    }
     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
+    ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
 }
 
-#define readex_expect_sync_data_len(a,b,c,d,e,f) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f)
+#define readex_expect_sync_data_len(a,b,c,d,e,f,g) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f,g)
 static void _readex_expect_sync_data_len(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
-        DWORD buf_size, const char *exdata, DWORD len)
+                                         DWORD buf_size, const char *exdata, DWORD len, BOOL expect_receive)
 {
     BOOL ret;
 
-    SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
+    if(!skip_receive_notification_tests && expect_receive) {
+        SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
+        SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
+        received_response_size = 0xdeadbeef;
+    }
 
     memset(buf->lpvBuffer, 0xff, buf_size);
     buf->dwBufferLength = buf_size;
@@ -4924,38 +5009,102 @@ static void _readex_expect_sync_data_len(unsigned line, HINTERNET req, DWORD fla
     if(len && exdata)
         ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "Unexpected data\n");
 
-    CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
+    if(!skip_receive_notification_tests && expect_receive) {
+        CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
+        CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
+        ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size);
+    }
 }
 
-#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e)
+#define readex_expect_sync_data(a,b,c,d,e,f) _readex_expect_sync_data(__LINE__,a,b,c,d,e,f)
 static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
+                                     DWORD buf_size, const char *exdata, DWORD expect_receive)
+{
+    _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata), expect_receive);
+}
+
+#define read_expect_sync_data_len(a,b,c,d,e) _read_expect_sync_data_len(__LINE__,a,b,c,d,e)
+static void _read_expect_sync_data_len(unsigned line, HINTERNET req, void *buf, DWORD buf_size,
+        const char *exdata, DWORD len)
+{
+    DWORD ret_size = 0xdeadbeef;
+    BOOL ret;
+
+    SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
+    SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
+    SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
+    received_response_size = 0xdeadbeef;
+
+    memset(buf, 0xff, buf_size);
+    ret = InternetReadFile(req, buf, buf_size, &ret_size);
+    ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError());
+    ok_(__FILE__,line)(ret_size == len, "dwBufferLength = %u, expected %u\n", ret_size, len);
+    if(len && exdata)
+        ok_(__FILE__,line)(!memcmp(buf, exdata, len), "Unexpected data\n");
+
+    CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
+    CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
+    CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
+    ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size);
+    ok_(__FILE__,line)(!req_error, "req_error = %u\n", req_error);
+}
+
+#define read_expect_sync_data(a,b,c,d) _read_expect_sync_data(__LINE__,a,b,c,d)
+static void _read_expect_sync_data(unsigned line, HINTERNET req, void *buf,
         DWORD buf_size, const char *exdata)
 {
-    _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata));
+    _read_expect_sync_data_len(line, req, buf, buf_size, exdata, strlen(exdata));
 }
 
-static void send_response_and_wait(const char *response, BOOL close_connection, INTERNET_BUFFERSW *buf)
+static void close_connection(void)
 {
-    DWORD orig_size = buf->dwBufferLength;
+    char c;
+    SetEvent(conn_wait_event);
+    recv(server_socket, &c, 1, 0);
+}
 
+#define send_response_and_wait(a,b,c,d,e,f,g,h) _send_response_and_wait(__LINE__,a,b,c,d,e,f,g,h)
+static void _send_response_and_wait(unsigned line, const char *response, BOOL do_close_connection,
+                                    void *buf, DWORD *ret_size, const char *exdata,
+                                    DWORD expected_size, DWORD expected_req_error, DWORD expected_receive_size)
+{
+    if(!skip_receive_notification_tests)
+        SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
 
     if(response)
         server_send_string(response);
 
-    if(close_connection) {
-        char c;
-        SetEvent(conn_wait_event);
-        recv(server_socket, &c, 1, 0);
-    }
+    if(do_close_connection)
+        close_connection();
 
     WaitForSingleObject(hCompleteEvent, INFINITE);
 
+    if(!skip_receive_notification_tests)
+        CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
+    if(!skip_receive_notification_tests && expected_receive_size != -1)
+        todo_wine_if(received_response_size != expected_receive_size) /* FIXME! remove when wine is fixed */
+        ok_(__FILE__,line)(received_response_size == expected_receive_size,
+                           "received_response_size = %u\n", received_response_size);
+    ok_(__FILE__,line)(req_error == expected_req_error, "req_error = %u, expected %u\n", req_error, expected_req_error);
 
     /* If IRF_NO_WAIT is used, buffer is not changed. */
-    ok(buf->dwBufferLength == orig_size, "dwBufferLength = %u\n", buf->dwBufferLength);
-    ok(!*(int*)buf->lpvBuffer, "buffer data changed\n");
+    ok_(__FILE__,line)(*ret_size == expected_size, "dwBufferLength = %u\n", *ret_size);
+    if(exdata)
+        ok_(__FILE__,line)(!memcmp(buf, exdata, strlen(exdata)), "unexpected buffer data\n");
+    else if(buf)
+        ok_(__FILE__,line)(!*(DWORD*)buf, "buffer data changed\n");
+}
+
+#define send_response_ex_and_wait(a,b,c,d,e,f) _send_response_ex_and_wait(__LINE__,a,b,c,d,e,f)
+static void _send_response_ex_and_wait(unsigned line, const char *response, BOOL close_connection,
+                                       INTERNET_BUFFERSW *buf, const char *exdata, DWORD expected_req_error,
+                                       DWORD expected_receive_size)
+{
+    _send_response_and_wait(line, response, close_connection, buf->lpvBuffer, &buf->dwBufferLength,
+                            exdata, exdata ? strlen(exdata) : buf->dwBufferLength, expected_req_error,
+                            expected_receive_size);
 }
 
 static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTERNET_BUFFERSW *buf)
@@ -4965,20 +5114,59 @@ static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTE
     response = HeapAlloc(GetProcessHeap(), 0, len+1);
     memset(response, 'x', len);
     response[len] = 0;
-    send_response_and_wait(response, close_connection, buf);
+    send_response_ex_and_wait(response, close_connection, buf, NULL, 0, -1);
     HeapFree(GetProcessHeap(), 0, response);
 }
 
-static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, DWORD buf_size)
+#define readex_expect_async(a,b,c,d,e) _readex_expect_async(__LINE__,a,b,c,d,e)
+static void _readex_expect_async(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
+        DWORD buf_size, const char *exdata)
 {
+    unsigned len = 0;
     BOOL ret;
 
+    if(!skip_receive_notification_tests)
+        SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
+
     memset(buf->lpvBuffer, 0, buf_size);
     buf->dwBufferLength = buf_size;
     ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef);
+    ok_(__FILE__,line)(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError());
+    ok_(__FILE__,line)(buf->dwBufferLength == buf_size, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, buf_size);
+    if(exdata) {
+        len = strlen(exdata);
+        ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "unexpected buffer data\n");
+    }else {
+        ok_(__FILE__,line)(!*(DWORD*)buf->lpvBuffer, "buffer data changed\n");
+    }
+
+    if(!skip_receive_notification_tests)
+        CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
+}
+
+static void read_expect_async(HINTERNET req, void *buf, DWORD buf_size, DWORD *ret_size, const char *exdata)
+{
+    unsigned len = 0;
+    const char *p;
+    BOOL ret;
+
+    SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
+
+    *ret_size = 0xdeadbeef;
+    memset(buf, 0, buf_size);
+    ret = InternetReadFile(req, buf, buf_size, ret_size);
     ok(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError());
-    ok(buf->dwBufferLength == buf_size, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, buf_size);
-    ok(!*(int*)buf->lpvBuffer, "buffer data changed\n");
+    ok(*ret_size == 0, "dwBufferLength = %u\n", *ret_size);
+    if(exdata) {
+        len = strlen(exdata);
+        ok(!memcmp(buf, exdata, len), "unexpected buffer data\n");
+    }
+    for(p = (const char*)buf + len; p < (const char*)buf + buf_size; p++) {
+        if(*p)
+            ok(0, "buffer data changed\n");
+    }
+
+    CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
 }
 
 #define expect_data_available(a,b) _expect_data_available(__LINE__,a,b)
@@ -4995,12 +5183,31 @@ static DWORD _expect_data_available(unsigned line, HINTERNET req, int exsize)
     return size;
 }
 
+#define async_query_data_available(a,b) _async_query_data_available(__LINE__,a,b)
+static void _async_query_data_available(unsigned line, HINTERNET req, DWORD *size)
+{
+    BOOL res;
+
+    if(!skip_receive_notification_tests)
+        SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
+
+    *size = 0xdeadbeef;
+    res = InternetQueryDataAvailable(req, size, 0, 0);
+    ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING,
+                       "InternetQueryDataAvailable returned: %x(%u)\n", res, GetLastError());
+    ok_(__FILE__,line)(!*size, "size = %u\n", *size);
+
+    if(!skip_receive_notification_tests)
+        CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
+}
+
 static void test_http_read(int port)
 {
     INTERNET_BUFFERSW ib;
     test_request_t req;
+    DWORD read_size;
     char buf[24000];
-    DWORD avail;
+    DWORD avail, i;
 
     if(!is_ie7plus)
         return;
@@ -5009,6 +5216,67 @@ static void test_http_read(int port)
     conn_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     server_req_rec_event = CreateEventW(NULL, FALSE, FALSE, NULL);
 
+    memset(&ib, 0, sizeof(ib));
+    ib.dwStructSize = sizeof(ib);
+    ib.lpvBuffer = buf;
+
+    trace("Testing InternetReadFileExW with IRF_ASYNC flag...\n");
+
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "\r\n"
+                           "xx");
+
+    readex_expect_async(req.request, IRF_ASYNC, &ib, 4, "xx");
+
+    send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2);
+    readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 4, "1234", 4);
+    readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 5, "56789", 5);
+
+    readex_expect_async(req.request, IRF_ASYNC, &ib, sizeof(buf), "0");
+    send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4);
+
+    close_async_handle(req.session, hCompleteEvent, 2);
+
+    trace("Testing InternetReadFileExW with no flags...\n");
+
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "\r\n"
+                           "xx");
+
+    readex_expect_async(req.request, 0, &ib, 4, "xx");
+
+    send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2);
+    readex_expect_sync_data(req.request, 0, &ib, 4, "1234", 4);
+    readex_expect_sync_data(req.request, 0, &ib, 5, "56789", 5);
+
+    readex_expect_async(req.request, 0, &ib, sizeof(buf), "0");
+    send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4);
+
+    close_async_handle(req.session, hCompleteEvent, 2);
+
+    trace("Testing InternetReadFile...\n");
+
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\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, 4, "1234");
+    read_expect_sync_data(req.request, buf, 5, "56789");
+
+    read_expect_async(req.request, buf, sizeof(buf), &read_size, "0");
+    send_response_and_wait("123", TRUE, buf, &read_size, "0123", 4, 0, 4);
+
+    close_async_handle(req.session, hCompleteEvent, 2);
+
     trace("Testing InternetReadFileExW with IRF_NO_WAIT flag...\n");
 
     open_read_test_request(port, &req,
@@ -5017,22 +5285,26 @@ static void test_http_read(int port)
                            "\r\n"
                            "xx");
 
-    memset(&ib, 0, sizeof(ib));
-    ib.dwStructSize = sizeof(ib);
-    ib.lpvBuffer = buf;
+    SET_OPTIONAL(INTERNET_STATUS_RECEIVING_RESPONSE);
+
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "xx", 0);
 
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "xx");
+    if(notified[INTERNET_STATUS_RECEIVING_RESPONSE]) {
+        win_skip("Skipping receive notification tests on too old Windows.\n");
+        skip_receive_notification_tests = TRUE;
+    }
+    CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
 
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
-    send_response_and_wait("1234567890", FALSE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 5, "12345");
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "67890");
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
+    send_response_ex_and_wait("1234567890", FALSE, &ib, NULL, 0, 10);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 5, "12345", 0);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "67890", 0);
 
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
-    send_response_and_wait("12345", TRUE, &ib);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
+    send_response_ex_and_wait("12345", TRUE, &ib, NULL, 0, 5);
 
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "12345");
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "");
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "12345", 0);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", TRUE);
 
     close_async_handle(req.session, hCompleteEvent, 2);
 
@@ -5042,24 +5314,24 @@ static void test_http_read(int port)
                            "Transfer-Encoding: chunked\r\n"
                            "\r\n"
                            "9\r\n123456789");
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123456789");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123456789", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
-    send_response_and_wait("\r\n1\r\na\r\n1\r\nb\r", FALSE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    send_response_ex_and_wait("\r\n1\r\na\r\n1\r\nb\r", FALSE, &ib, NULL, 0, 13);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
-    send_response_and_wait("\n3\r\nab", FALSE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    send_response_ex_and_wait("\n3\r\nab", FALSE, &ib, NULL, 0, 6);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
-    send_response_and_wait("c", FALSE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "c");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    send_response_ex_and_wait("c", FALSE, &ib, NULL, 0, 1);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "c", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
-    send_response_and_wait("\r\n1\r\nx\r\n0\r\n\r\n", TRUE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "x");
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "");
+    send_response_ex_and_wait("\r\n1\r\nx\r\n0\r\n\r\n", TRUE, &ib, NULL, 0, 13);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "x", 0);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0);
 
     close_async_handle(req.session, hCompleteEvent, 2);
 
@@ -5069,14 +5341,29 @@ static void test_http_read(int port)
                            "Transfer-Encoding: chunked\r\n"
                            "\r\n"
                            "3\r\n123\r\n");
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
-    send_response_and_wait("0\r\n\r\n", TRUE, &ib);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "");
+    send_response_ex_and_wait("0\r\n\r\n", TRUE, &ib, NULL, 0, 5);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0);
 
     close_async_handle(req.session, hCompleteEvent, 2);
 
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "Connection: close\r\n"
+                           "\r\n");
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
+    send_response_ex_and_wait("123", TRUE, &ib, NULL, 0, 3);
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
+
+    SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
+    SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
+    close_async_handle(req.session, hCompleteEvent, 2);
+    CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
+    CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
+
     trace("Testing InternetQueryDataAvailable...\n");
 
     open_read_test_request(port, &req,
@@ -5085,8 +5372,8 @@ static void test_http_read(int port)
                            "\r\n"
                            "123");
     expect_data_available(req.request, 3);
-    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123");
-    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf));
+    readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
+    readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
 
     send_response_len_and_wait(20000, TRUE, &ib);
     avail = expect_data_available(req.request, -1);
@@ -5098,9 +5385,82 @@ static void test_http_read(int port)
     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
 
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "Connection: close\r\n"
+                           "\r\n"
+                           "123");
+
+    expect_data_available(req.request, 3);
+    readex_expect_sync_data(req.request, 0, &ib, 3, "123", 0);
+
+    async_query_data_available(req.request, &read_size);
+    send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10);
+
+    readex_expect_sync_data(req.request, 0, &ib, 9, "123456789", 0);
+    expect_data_available(req.request, 1);
+    readex_expect_sync_data(req.request, 0, &ib, 1, "0", 0);
+
+    async_query_data_available(req.request, &read_size);
+    send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10);
+    expect_data_available(req.request, 10);
+    for(i = 0; i < 10; i++)
+        server_send_string("x");
+    expect_data_available(req.request, 10);
+
+    readex_expect_async(req.request, IRF_ASYNC, &ib, 21, "1234567890");
+    send_response_ex_and_wait("X", FALSE, &ib, "1234567890xxxxxxxxxxX", 0, 11);
+    async_query_data_available(req.request, &read_size);
+
+    SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
+    SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
+    send_response_and_wait(NULL, TRUE, NULL, &read_size, NULL, 0, 0, 0);
+    CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
+    CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
+
+    close_async_handle(req.session, hCompleteEvent, 2);
+
     CloseHandle(hCompleteEvent);
     CloseHandle(conn_wait_event);
     CloseHandle(server_req_rec_event);
+
+    skip_receive_notification_tests = FALSE;
+}
+
+static void test_connection_break(int port)
+{
+    INTERNET_BUFFERSW ib;
+    test_request_t req;
+    char buf[24000];
+
+    if(!is_ie7plus)
+        return;
+
+    hCompleteEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    conn_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    server_req_rec_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+    memset(&ib, 0, sizeof(ib));
+    ib.dwStructSize = sizeof(ib);
+    ib.lpvBuffer = buf;
+
+    trace("Testing InternetReadFileExW on broken connection...\n");
+
+    open_read_test_request(port, &req,
+                           "HTTP/1.1 200 OK\r\n"
+                           "Server: winetest\r\n"
+                           "Content-Length: 10000\r\n"
+                           "\r\n"
+                           "xx");
+
+    /* close connection and make sure that it's closed on handle release. */
+    close_connection();
+    SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
+    SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
+    close_async_handle(req.session, hCompleteEvent, 2);
+    CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
+    CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
 }
 
 static void test_long_url(int port)
@@ -5151,6 +5511,27 @@ static void test_remove_dot_segments(int port)
     close_request(&req);
 }
 
+static void test_redirect(int port)
+{
+    test_request_t req;
+    BOOL ret;
+
+    open_simple_request(&req, "localhost", port, NULL, "/test_redirect_no_host");
+    ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
+    if (ret)
+    {
+        trace("Succeeded with status code 302\n");
+        test_status_code(req.request, 302);
+    }
+    else
+    {
+        trace("Failed with error ERROR_INTERNET_INVALID_URL\n");
+        ok(GetLastError() == ERROR_INTERNET_INVALID_URL,
+           "Expected error ERROR_INTERNET_INVALID_URL, got %u\n", GetLastError());
+    }
+    close_request(&req);
+}
+
 static void test_http_connection(void)
 {
     struct server_info si;
@@ -5201,8 +5582,10 @@ static void test_http_connection(void)
     test_basic_auth_credentials_reuse(si.port);
     test_async_read(si.port);
     test_http_read(si.port);
+    test_connection_break(si.port);
     test_long_url(si.port);
     test_remove_dot_segments(si.port);
+    test_redirect(si.port);
 
     /* send the basic request again to shutdown the server thread */
     test_basic_request(si.port, "GET", "/quit");
index 8a06be8..dd7b897 100644 (file)
@@ -1610,12 +1610,16 @@ static void test_InternetGetConnectedStateExA(void)
         return;
     }
 
+    flags = 0;
+    buffer[0] = 0;
     res = pInternetGetConnectedStateExA(&flags, buffer, sizeof(buffer), 0);
+    trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, buffer);
+todo_wine
+    ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n");
     if(!res) {
         win_skip("InternetGetConnectedStateExA tests require a valid connection\n");
         return;
     }
-    trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, buffer);
 
     res = pInternetGetConnectedStateExA(NULL, NULL, 0, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
@@ -1623,7 +1627,16 @@ static void test_InternetGetConnectedStateExA(void)
     flags = 0;
     res = pInternetGetConnectedStateExA(&flags, NULL, 0, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
-    ok(flags, "Expected at least one flag set\n");
+    if (flags & INTERNET_CONNECTION_CONFIGURED)
+    {
+        ok(flags & INTERNET_CONNECTION_MODEM, "Modem connection flag missing\n");
+        ok(flags & ~INTERNET_CONNECTION_LAN, "Mixed Modem and LAN flags\n");
+    }
+    else
+    {
+        ok(flags & INTERNET_CONNECTION_LAN, "LAN connection flag missing\n");
+        ok(flags & ~INTERNET_CONNECTION_MODEM, "Mixed Modem and LAN flags\n");
+    }
 
     buffer[0] = 0;
     flags = 0;
@@ -1699,12 +1712,16 @@ static void test_InternetGetConnectedStateExW(void)
         return;
     }
 
+    flags = 0;
+    buffer[0] = 0;
     res = pInternetGetConnectedStateExW(&flags, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
+    trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer));
+todo_wine
+    ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n");
     if(!res) {
         win_skip("InternetGetConnectedStateExW tests require a valid connection\n");
         return;
     }
-    trace("Internet Connection: Flags 0x%02x - Name '%s'\n", flags, wine_dbgstr_w(buffer));
 
     res = pInternetGetConnectedStateExW(NULL, NULL, 0, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
@@ -1712,7 +1729,16 @@ static void test_InternetGetConnectedStateExW(void)
     flags = 0;
     res = pInternetGetConnectedStateExW(&flags, NULL, 0, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
-    ok(flags, "Expected at least one flag set\n");
+    if (flags & INTERNET_CONNECTION_CONFIGURED)
+    {
+        ok(flags & INTERNET_CONNECTION_MODEM, "Modem connection flag missing\n");
+        ok(flags & ~INTERNET_CONNECTION_LAN, "Mixed Modem and LAN flags\n");
+    }
+    else
+    {
+        ok(flags & INTERNET_CONNECTION_LAN, "LAN connection flag missing\n");
+        ok(flags & ~INTERNET_CONNECTION_MODEM, "Mixed Modem and LAN flags\n");
+    }
 
     buffer[0] = 0;
     flags = 0;
@@ -1746,14 +1772,20 @@ static void test_InternetGetConnectedStateExW(void)
     res = pInternetGetConnectedStateExW(&flags, buffer, sz, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
     ok(flags, "Expected at least one flag set\n");
-    ok(sz - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz - 1, lstrlenW(buffer));
+    if (flags & INTERNET_CONNECTION_MODEM)
+        ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer));
+    else
+        ok(sz - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz - 1, lstrlenW(buffer));
 
     buffer[0] = 0;
     flags = 0;
     res = pInternetGetConnectedStateExW(&flags, buffer, sz / 2, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
     ok(flags, "Expected at least one flag set\n");
-    ok(sz / 2 - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz / 2 - 1, lstrlenW(buffer));
+    if (flags & INTERNET_CONNECTION_MODEM)
+        ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer));
+    else
+        ok(sz / 2 - 1 == lstrlenW(buffer), "Expected %u bytes, got %u\n", sz / 2 - 1, lstrlenW(buffer));
 
     buffer[0] = 0;
     flags = 0;
@@ -1767,7 +1799,10 @@ static void test_InternetGetConnectedStateExW(void)
     res = pInternetGetConnectedStateExW(&flags, buffer, 2, 0);
     ok(res == TRUE, "Expected TRUE, got %d\n", res);
     ok(flags, "Expected at least one flag set\n");
-    ok(lstrlenW(buffer) == 1, "Expected 1 byte, got %u\n", lstrlenW(buffer));
+    if (flags & INTERNET_CONNECTION_MODEM)
+        ok(!buffer[0], "Expected 0 bytes, got %u\n", lstrlenW(buffer));
+    else
+        ok(lstrlenW(buffer) == 1, "Expected 1 byte, got %u\n", lstrlenW(buffer));
 
     buffer[0] = 0xDEAD;
     flags = 0;