Commit 08808747 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

wininet: Rewrite InternetReadFileEx for http protocol to make use of non-blocking reads.

parent 98bcd00e
...@@ -3166,60 +3166,45 @@ static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_p ...@@ -3166,60 +3166,45 @@ static DWORD async_read(http_request_t *req, void *buf, DWORD size, DWORD read_p
static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read, static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWORD *ret_read,
DWORD flags, DWORD_PTR context) DWORD flags, DWORD_PTR context)
{ {
http_request_t *req = (http_request_t*)hdr; http_request_t *req = (http_request_t*)hdr;
DWORD res, read, cread, error = ERROR_SUCCESS; DWORD res = ERROR_SUCCESS, read = 0, cread, error = ERROR_SUCCESS;
BOOL allow_blocking, notify_received = FALSE;
TRACE("(%p %p %u %x)\n", req, buf, size, flags); TRACE("(%p %p %u %x)\n", req, buf, size, flags);
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT)); FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); allow_blocking = !(req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC);
if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
if (TryEnterCriticalSection( &req->read_section ))
{
if (get_avail_data(req) || end_of_read_data(req))
{
res = HTTPREQ_Read(req, buf, size, &read, BLOCKING_DISALLOW);
LeaveCriticalSection( &req->read_section );
goto done;
}
LeaveCriticalSection( &req->read_section );
}
if(flags & IRF_NO_WAIT) if(allow_blocking || TryEnterCriticalSection(&req->read_section)) {
return async_read(req, NULL, 0, 0, 0); if(allow_blocking)
return async_read(req, buf, size, 0, ret_read); EnterCriticalSection(&req->read_section);
}
read = 0;
EnterCriticalSection( &req->read_section );
if(hdr->dwError == ERROR_SUCCESS) if(hdr->dwError == ERROR_SUCCESS)
hdr->dwError = INTERNET_HANDLE_IN_USE; hdr->dwError = INTERNET_HANDLE_IN_USE;
else if(hdr->dwError == INTERNET_HANDLE_IN_USE) else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
while(1) { if(req->read_size) {
res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, BLOCKING_ALLOW); read = min(size, req->read_size);
if(res != ERROR_SUCCESS) memcpy(buf, req->read_buf + req->read_pos, read);
break; req->read_size -= read;
req->read_pos += read;
}
if(read < size && (!read || !(flags & IRF_NO_WAIT)) && !end_of_read_data(req)) {
LeaveCriticalSection(&req->read_section);
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
EnterCriticalSection( &req->read_section );
notify_received = TRUE;
while(read < size) {
res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread,
allow_blocking ? BLOCKING_ALLOW : BLOCKING_DISALLOW);
read += cread; read += cread;
if(read == size || end_of_read_data(req)) if (res != ERROR_SUCCESS || !cread)
break; break;
}
LeaveCriticalSection( &req->read_section );
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&cread, sizeof(cread));
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
EnterCriticalSection( &req->read_section );
} }
if(hdr->dwError == INTERNET_HANDLE_IN_USE) if(hdr->dwError == INTERNET_HANDLE_IN_USE)
...@@ -3228,15 +3213,26 @@ static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWO ...@@ -3228,15 +3213,26 @@ static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWO
error = hdr->dwError; error = hdr->dwError;
LeaveCriticalSection( &req->read_section ); LeaveCriticalSection( &req->read_section );
}else {
res = WSAEWOULDBLOCK;
}
if(res == WSAEWOULDBLOCK) {
if(!(flags & IRF_NO_WAIT))
return async_read(req, buf, size, read, ret_read);
if(!read)
return async_read(req, NULL, 0, 0, NULL);
res = ERROR_SUCCESS;
}
done:
*ret_read = read; *ret_read = read;
if (res == ERROR_SUCCESS) { if (res != ERROR_SUCCESS)
return res;
if(notify_received)
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&read, sizeof(read)); &read, sizeof(read));
} return error;
return res==ERROR_SUCCESS ? error : res;
} }
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written) static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
......
...@@ -1111,16 +1111,9 @@ static void InternetReadFileExA_test(int flags) ...@@ -1111,16 +1111,9 @@ static void InternetReadFileExA_test(int flags)
inetbuffers.lpvBuffer = NULL; inetbuffers.lpvBuffer = NULL;
inetbuffers.dwOffsetHigh = 1234; inetbuffers.dwOffsetHigh = 1234;
inetbuffers.dwOffsetLow = 5678; inetbuffers.dwOffsetLow = 5678;
SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe); rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe);
ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError()); ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError());
trace("read %i bytes\n", inetbuffers.dwBufferLength); 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); rc = InternetReadFileExA(NULL, &inetbuffers, 0, 0xdeadcafe);
ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE), ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE),
...@@ -1167,11 +1160,9 @@ static void InternetReadFileExA_test(int flags) ...@@ -1167,11 +1160,9 @@ static void InternetReadFileExA_test(int flags)
CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
if (inetbuffers.dwBufferLength) if (inetbuffers.dwBufferLength)
{ {
todo_wine {
CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
} }
}
else else
{ {
/* Win98 still sends these when 0 bytes are read, WinXP does not */ /* Win98 still sends these when 0 bytes are read, WinXP does not */
...@@ -4463,7 +4454,6 @@ static void test_async_read(int port) ...@@ -4463,7 +4454,6 @@ static void test_async_read(int port)
if (!ib.dwBufferLength) break; if (!ib.dwBufferLength) break;
} }
todo_wine
ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads ); ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads );
ok( !strcmp(buffer, page1), "unexpected buffer content\n" ); ok( !strcmp(buffer, page1), "unexpected buffer content\n" );
close_async_handle( ses, hCompleteEvent, 2 ); close_async_handle( ses, hCompleteEvent, 2 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment