Commit 728bf77c authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

winhttp: Implement WinHttpReadData.

parent d7f54676
......@@ -106,18 +106,6 @@ BOOL WINAPI WinHttpSetOption (HINTERNET hInternet, DWORD dwOption, LPVOID lpBuff
}
/***********************************************************************
* WinHttpReadData (winhttp.@)
*/
BOOL WINAPI WinHttpReadData (HINTERNET hInternet, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead,
LPDWORD lpdwNumberOfBytesRead)
{
FIXME("(%d): stub\n", dwNumberOfBytesToRead);
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
/***********************************************************************
* WinHttpWriteData (winhttp.@)
*/
BOOL WINAPI WinHttpWriteData (HINTERNET hRequest, LPCVOID lpBuffer,
......
......@@ -976,3 +976,136 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
release_object( &request->hdr );
return ret;
}
static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
{
DWORD to_read;
int bytes_read;
to_read = min( size, request->content_length - request->content_read );
if (!netconn_recv( &request->netconn, buffer, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
{
if (bytes_read != to_read)
{
ERR("not all data received %d/%d\n", bytes_read, to_read);
}
/* always return success, even if the network layer returns an error */
*read = 0;
return TRUE;
}
request->content_read += bytes_read;
*read = bytes_read;
return TRUE;
}
static DWORD get_chunk_size( const char *buffer )
{
const char *p;
DWORD size = 0;
for (p = buffer; *p; p++)
{
if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
else if (*p == ';') break;
}
return size;
}
static BOOL read_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async )
{
char reply[MAX_REPLY_LEN], *p = buffer;
DWORD buflen, to_read, to_write = size;
int bytes_read;
*read = 0;
for (;;)
{
if (*read == size) break;
if (request->content_length == ~0UL) /* new chunk */
{
buflen = sizeof(reply);
if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break;
if (!(request->content_length = get_chunk_size( reply )))
{
/* zero sized chunk marks end of transfer; read any trailing headers and return */
receive_response( request, FALSE );
break;
}
}
to_read = min( to_write, request->content_length - request->content_read );
if (!netconn_recv( &request->netconn, p, to_read, async ? 0 : MSG_WAITALL, &bytes_read ))
{
if (bytes_read != to_read)
{
ERR("Not all data received %d/%d\n", bytes_read, to_read);
}
/* always return success, even if the network layer returns an error */
*read = 0;
break;
}
if (!bytes_read) break;
request->content_read += bytes_read;
to_write -= bytes_read;
*read += bytes_read;
p += bytes_read;
if (request->content_read == request->content_length) /* chunk complete */
{
request->content_read = 0;
request->content_length = ~0UL;
buflen = sizeof(reply);
if (!netconn_get_next_line( &request->netconn, reply, &buflen ))
{
ERR("Malformed chunk\n");
*read = 0;
break;
}
}
}
return TRUE;
}
/***********************************************************************
* WinHttpReadData (winhttp.@)
*/
BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read )
{
static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
BOOL ret;
request_t *request;
WCHAR encoding[20];
DWORD buflen = sizeof(encoding);
TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
if (!(request = (request_t *)grab_object( hrequest )))
{
set_last_error( ERROR_INVALID_HANDLE );
return FALSE;
}
if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST)
{
release_object( &request->hdr );
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
return FALSE;
}
if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
!strcmpiW( encoding, chunked ))
{
ret = read_data_chunked( request, buffer, to_read, read, request->hdr.flags & WINHTTP_FLAG_ASYNC );
}
else
ret = read_data( request, buffer, to_read, read, request->hdr.flags & WINHTTP_FLAG_ASYNC );
release_object( &request->hdr );
return ret;
}
......@@ -126,12 +126,10 @@ static void test_SendRequest (void)
bytes_rw = -1;
ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
todo_wine ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
todo_wine ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n",
bytes_rw, lstrlen(test_post));
todo_wine ok(strncmp(buffer, test_post, bytes_rw) == 0,
"Data read did not match, got '%s'.\n", buffer);
ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", bytes_rw, lstrlen(test_post));
ok(strncmp(buffer, test_post, bytes_rw) == 0, "Data read did not match, got '%s'.\n", buffer);
ret = WinHttpCloseHandle(request);
ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
......
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