Hans Leidekker : winhttp: Implement WinHttpReadData.
Alexandre Julliard
julliard at winehq.org
Tue Aug 26 07:07:43 CDT 2008
Module: wine
Branch: master
Commit: 728bf77c83e331d821272131aaf8eb71600c2a77
URL: http://source.winehq.org/git/wine.git/?a=commit;h=728bf77c83e331d821272131aaf8eb71600c2a77
Author: Hans Leidekker <hans at 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);
More information about the wine-cvs
mailing list