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

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-03-09 18:19:50 +01:00 committed by Alexandre Julliard
parent 98bcd00e21
commit 08808747b2
2 changed files with 47 additions and 61 deletions

View File

@ -3166,77 +3166,73 @@ 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,
DWORD flags, DWORD_PTR context)
{
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);
if (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(allow_blocking || TryEnterCriticalSection(&req->read_section)) {
if(allow_blocking)
EnterCriticalSection(&req->read_section);
if(hdr->dwError == ERROR_SUCCESS)
hdr->dwError = INTERNET_HANDLE_IN_USE;
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
if(req->read_size) {
read = min(size, req->read_size);
memcpy(buf, req->read_buf + req->read_pos, read);
req->read_size -= read;
req->read_pos += read;
}
if(flags & IRF_NO_WAIT)
return async_read(req, NULL, 0, 0, 0);
return async_read(req, buf, size, 0, ret_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;
read = 0;
while(read < size) {
res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread,
allow_blocking ? BLOCKING_ALLOW : BLOCKING_DISALLOW);
read += cread;
if (res != ERROR_SUCCESS || !cread)
break;
}
}
EnterCriticalSection( &req->read_section );
if(hdr->dwError == ERROR_SUCCESS)
hdr->dwError = INTERNET_HANDLE_IN_USE;
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
while(1) {
res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, BLOCKING_ALLOW);
if(res != ERROR_SUCCESS)
break;
read += cread;
if(read == size || end_of_read_data(req))
break;
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_SUCCESS;
else
error = hdr->dwError;
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 );
}else {
res = WSAEWOULDBLOCK;
}
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
hdr->dwError = ERROR_SUCCESS;
else
error = hdr->dwError;
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;
}
LeaveCriticalSection( &req->read_section );
done:
*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,
&read, sizeof(read));
}
return res==ERROR_SUCCESS ? error : res;
return error;
}
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)

View File

@ -1111,16 +1111,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),
@ -1167,10 +1160,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
{
@ -4463,7 +4454,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 );