Module: wine Branch: master Commit: 728bf77c83e331d821272131aaf8eb71600c2a77 URL: http://source.winehq.org/git/wine.git/?a=commit;h=728bf77c83e331d821272131aa...
Author: Hans Leidekker hans@codeweavers.com Date: Tue Aug 26 11:04:43 2008 +0200
winhttp: Implement WinHttpReadData.
---
dlls/winhttp/main.c | 12 ---- dlls/winhttp/request.c | 133 ++++++++++++++++++++++++++++++++++++++++++ dlls/winhttp/tests/winhttp.c | 8 +-- 3 files changed, 136 insertions(+), 17 deletions(-)
diff --git a/dlls/winhttp/main.c b/dlls/winhttp/main.c index 82f0a61..220cc51 100644 --- a/dlls/winhttp/main.c +++ b/dlls/winhttp/main.c @@ -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, diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 14b57cc..21e59c7 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -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; +} diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index a247938..fa0249d 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -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);