[4/5] wininet: Support asynchronous HttpEndRequest.
Hans Leidekker
hans at meelstraat.net
Wed Apr 8 08:22:44 CDT 2009
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 3777d4c..8d03b61 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -714,57 +714,87 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
- LPINTERNET_BUFFERSA ptr;
- LPINTERNET_BUFFERSW lpBuffersOutW,ptrW;
+ TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+
+ if (lpBuffersOut)
+ {
+ INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
+}
+
+static BOOL HTTP_HttpEndRequestW(LPWININETHTTPREQW lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
+{
BOOL rc = FALSE;
+ INT responseLen;
+ DWORD dwBufferSize;
+ INTERNET_ASYNC_RESULT iar;
- TRACE("(%p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags,
- dwContext);
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
- ptr = lpBuffersOut;
- if (ptr)
- lpBuffersOutW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(INTERNET_BUFFERSW));
- else
- lpBuffersOutW = NULL;
+ responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
+ if (responseLen)
+ rc = TRUE;
- ptrW = lpBuffersOutW;
- while (ptr)
- {
- if (ptr->lpvBuffer && ptr->dwBufferLength)
- ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength);
- ptrW->dwBufferLength = ptr->dwBufferLength;
- ptrW->dwBufferTotal= ptr->dwBufferTotal;
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
- if (ptr->Next)
- ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
- sizeof(INTERNET_BUFFERSW));
+ /* process cookies here. Is this right? */
+ HTTP_ProcessCookies(lpwhr);
- ptr = ptr->Next;
- ptrW = ptrW->Next;
- }
+ dwBufferSize = sizeof(lpwhr->dwContentLength);
+ if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
+ &lpwhr->dwContentLength, &dwBufferSize, NULL))
+ lpwhr->dwContentLength = -1;
- rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext);
+ if (lpwhr->dwContentLength == 0)
+ HTTP_FinishedReading(lpwhr);
- if (lpBuffersOutW)
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
{
- ptrW = lpBuffersOutW;
- while (ptrW)
+ DWORD dwCode,dwCodeLength = sizeof(DWORD);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) &&
+ (dwCode == 302 || dwCode == 301 || dwCode == 303))
{
- LPINTERNET_BUFFERSW ptrW2;
-
- FIXME("Do we need to translate info out of these buffer?\n");
-
- HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer);
- ptrW2 = ptrW->Next;
- HeapFree(GetProcessHeap(),0,ptrW);
- ptrW = ptrW2;
+ WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
+ dwBufferSize=sizeof(szNewLocation);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
+ {
+ /* redirects are always GETs */
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
+ lpwhr->lpszVerb = WININET_strdupW(szGET);
+ HTTP_DrainContent(lpwhr);
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REDIRECT, szNewLocation, dwBufferSize);
+ rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
+ if (rc)
+ rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
+ }
}
}
+ iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
+ iar.dwError = rc ? 0 : INTERNET_GetLastError();
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
return rc;
}
+static void AsyncHttpEndRequestProc(WORKREQUEST *work)
+{
+ struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW;
+ LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)work->hdr;
+
+ TRACE("%p\n", lpwhr);
+
+ HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
+}
+
/***********************************************************************
* HttpEndRequestW (WININET.@)
*
@@ -780,10 +810,15 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
{
BOOL rc = FALSE;
LPWININETHTTPREQW lpwhr;
- INT responseLen;
- DWORD dwBufferSize;
TRACE("-->\n");
+
+ if (lpBuffersOut)
+ {
+ INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
@@ -791,58 +826,27 @@ BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
if (lpwhr)
WININET_Release( &lpwhr->hdr );
- return FALSE;
+ return FALSE;
}
-
lpwhr->hdr.dwFlags |= dwFlags;
- lpwhr->hdr.dwContext = dwContext;
- /* We appear to do nothing with lpBuffersOut.. is that correct? */
-
- SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
-
- responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- rc = TRUE;
-
- SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
-
- /* process cookies here. Is this right? */
- HTTP_ProcessCookies(lpwhr);
+ if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST work;
+ struct WORKREQ_HTTPENDREQUESTW *request;
- dwBufferSize = sizeof(lpwhr->dwContentLength);
- if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
- &lpwhr->dwContentLength,&dwBufferSize,NULL))
- lpwhr->dwContentLength = -1;
+ work.asyncproc = AsyncHttpEndRequestProc;
+ work.hdr = WININET_AddRef( &lpwhr->hdr );
- if (lpwhr->dwContentLength == 0)
- HTTP_FinishedReading(lpwhr);
+ request = &work.u.HttpEndRequestW;
+ request->dwFlags = dwFlags;
+ request->dwContext = dwContext;
- if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
- {
- DWORD dwCode,dwCodeLength=sizeof(DWORD);
- if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
- (dwCode==302 || dwCode==301 || dwCode==303))
- {
- WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
- dwBufferSize=sizeof(szNewLocation);
- if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
- {
- /* redirects are always GETs */
- HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb);
- lpwhr->lpszVerb = WININET_strdupW(szGET);
- HTTP_DrainContent(lpwhr);
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REDIRECT, szNewLocation,
- dwBufferSize);
- rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
- if (rc)
- rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
- }
- }
+ INTERNET_AsyncCall(&work);
+ INTERNET_SetLastError(ERROR_IO_PENDING);
}
+ else
+ rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
WININET_Release( &lpwhr->hdr );
TRACE("%i <--\n",rc);
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 8e92788..f69c424 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -291,6 +291,12 @@ struct WORKREQ_HTTPSENDREQUESTW
BOOL bEndRequest;
};
+struct WORKREQ_HTTPENDREQUESTW
+{
+ DWORD dwFlags;
+ DWORD_PTR dwContext;
+};
+
struct WORKREQ_SENDCALLBACK
{
DWORD_PTR dwContext;
@@ -337,6 +343,7 @@ typedef struct WORKREQ
struct WORKREQ_FTPRENAMEFILEW FtpRenameFileW;
struct WORKREQ_FTPFINDNEXTW FtpFindNextW;
struct WORKREQ_HTTPSENDREQUESTW HttpSendRequestW;
+ struct WORKREQ_HTTPENDREQUESTW HttpEndRequestW;
struct WORKREQ_SENDCALLBACK SendCallback;
struct WORKREQ_INTERNETOPENURLW InternetOpenUrlW;
struct WORKREQ_INTERNETREADFILEEXA InternetReadFileExA;
More information about the wine-patches
mailing list