diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index ac794048ff1..b51c6c9fda8 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -2621,7 +2621,16 @@ static DWORD refill_read_buffer(http_request_t *req, blocking_mode_t blocking_mo /* return the size of data available to be read immediately (the read section must be held) */ static DWORD get_avail_data( http_request_t *req ) { - return req->read_size + req->data_stream->vtbl->get_avail_data(req->data_stream, req); + DWORD avail = req->read_size; + + /* + * Different Windows versions have different limits of returned data, but all + * of them return no more than centrain amount. We use READ_BUFFER_SIZE as a limit. + */ + if(avail < READ_BUFFER_SIZE) + avail += req->data_stream->vtbl->get_avail_data(req->data_stream, req); + + return min(avail, READ_BUFFER_SIZE); } static DWORD netconn_get_avail_data(data_stream_t *stream, http_request_t *req) diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index bf3f6903fe0..fc68fe17ef2 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -4622,11 +4622,10 @@ static void open_read_test_request(int port, test_request_t *req, const char *re CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); } -#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e) -static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, - DWORD buf_size, const char *exdata) +#define readex_expect_sync_data_len(a,b,c,d,e,f) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f) +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 len = strlen(exdata); BOOL ret; SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); @@ -4636,12 +4635,19 @@ static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef); ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError()); ok_(__FILE__,line)(buf->dwBufferLength == len, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, len); - if(len) + if(len && exdata) ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "Unexpected data\n"); CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); } +#define readex_expect_sync_data(a,b,c,d,e) _readex_expect_sync_data(__LINE__,a,b,c,d,e) +static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, + DWORD buf_size, const char *exdata) +{ + _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata)); +} + static void send_response_and_wait(const char *response, BOOL close_connection, INTERNET_BUFFERSW *buf) { DWORD orig_size = buf->dwBufferLength; @@ -4666,6 +4672,17 @@ static void send_response_and_wait(const char *response, BOOL close_connection, ok(!*(int*)buf->lpvBuffer, "buffer data changed\n"); } +static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTERNET_BUFFERSW *buf) +{ + char *response; + + response = HeapAlloc(GetProcessHeap(), 0, len+1); + memset(response, 'x', len); + response[len] = 0; + send_response_and_wait(response, close_connection, buf); + HeapFree(GetProcessHeap(), 0, response); +} + static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf, DWORD buf_size) { BOOL ret; @@ -4678,11 +4695,26 @@ static void readex_expect_async(HINTERNET req, DWORD flags, INTERNET_BUFFERSW *b ok(!*(int*)buf->lpvBuffer, "buffer data changed\n"); } +#define expect_data_available(a,b) _expect_data_available(__LINE__,a,b) +static DWORD _expect_data_available(unsigned line, HINTERNET req, int exsize) +{ + DWORD size = 0; + BOOL res; + + res = InternetQueryDataAvailable(req, &size, 0, 0); + ok_(__FILE__,line)(res, "InternetQueryDataAvailable failed: %u\n", GetLastError()); + if(exsize != -1) + ok_(__FILE__,line)(size == exsize, "size = %u, expected %u\n", size, exsize); + + return size; +} + static void test_http_read(int port) { INTERNET_BUFFERSW ib; test_request_t req; - char buf[4096]; + char buf[24000]; + DWORD avail; if(!is_ie7plus) return; @@ -4759,6 +4791,27 @@ static void test_http_read(int port) close_async_handle(req.session, hCompleteEvent, 2); + trace("Testing InternetQueryDataAvailable...\n"); + + open_read_test_request(port, &req, + "HTTP/1.1 200 OK\r\n" + "Server: winetest\r\n" + "\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)); + + send_response_len_and_wait(20000, TRUE, &ib); + avail = expect_data_available(req.request, -1); + ok(avail < 17000, "avail = %u\n", avail); + + SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION); + SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED); + close_async_handle(req.session, hCompleteEvent, 2); + todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + CloseHandle(hCompleteEvent); CloseHandle(conn_wait_event); CloseHandle(server_req_rec_event);