static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
static const WCHAR g_szHttp1_1[] = {'H','T','T','P','/','1','.','1',0};
+static const WCHAR szOK[] = {'O','K',0};
+static const WCHAR szDefaultHeader[] = {'H','T','T','P','/','1','.','0',' ','2','0','0',' ','O','K',0};
static const WCHAR hostW[] = { 'H','o','s','t',0 };
static const WCHAR szAuthorization[] = { 'A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
static const WCHAR szProxy_Authorization[] = { 'P','r','o','x','y','-','A','u','t','h','o','r','i','z','a','t','i','o','n',0 };
BOOL end_of_data;
};
-static BOOL HTTP_OpenConnection(http_request_t *req);
+typedef struct _basicAuthorizationData
+{
+ struct list entry;
+
+ LPWSTR lpszwHost;
+ LPWSTR lpszwRealm;
+ LPSTR lpszAuthorization;
+ UINT AuthorizationLen;
+} basicAuthorizationData;
+
+typedef struct _authorizationData
+{
+ struct list entry;
+
+ LPWSTR host;
+ LPWSTR scheme;
+ LPWSTR domain;
+ UINT domain_len;
+ LPWSTR user;
+ UINT user_len;
+ LPWSTR password;
+ UINT password_len;
+} authorizationData;
+
+static struct list basicAuthorizationCache = LIST_INIT(basicAuthorizationCache);
+static struct list authorizationCache = LIST_INIT(authorizationCache);
+
+static CRITICAL_SECTION authcache_cs;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &authcache_cs,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": authcache_cs") }
+};
+static CRITICAL_SECTION authcache_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static DWORD HTTP_OpenConnection(http_request_t *req);
static BOOL HTTP_GetResponseHeaders(http_request_t *req, BOOL clear);
-static BOOL HTTP_ProcessHeader(http_request_t *req, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
+static DWORD HTTP_ProcessHeader(http_request_t *req, LPCWSTR field, LPCWSTR value, DWORD dwModifier);
static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer);
-static BOOL HTTP_InsertCustomHeader(http_request_t *req, LPHTTPHEADERW lpHdr);
+static DWORD HTTP_InsertCustomHeader(http_request_t *req, LPHTTPHEADERW lpHdr);
static INT HTTP_GetCustomHeaderIndex(http_request_t *req, LPCWSTR lpszField, INT index, BOOL Request);
static BOOL HTTP_DeleteCustomHeader(http_request_t *req, DWORD index);
static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
-static BOOL HTTP_HttpQueryInfoW(http_request_t*, DWORD, LPVOID, LPDWORD, LPDWORD);
+static DWORD HTTP_HttpQueryInfoW(http_request_t*, DWORD, LPVOID, LPDWORD, LPDWORD);
static LPWSTR HTTP_GetRedirectURL(http_request_t *req, LPCWSTR lpszUrl);
-static BOOL HTTP_HandleRedirect(http_request_t *req, LPCWSTR lpszUrl);
static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin);
static BOOL HTTP_VerifyValidHeader(http_request_t *req, LPCWSTR field);
static void HTTP_DrainContent(http_request_t *req);
DWORD size;
size = sizeof(lpwhr->dwContentLength);
- if (!HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
- &lpwhr->dwContentLength, &size, NULL))
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
+ &lpwhr->dwContentLength, &size, NULL) != ERROR_SUCCESS)
lpwhr->dwContentLength = ~0u;
size = sizeof(encoding);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &size, NULL) &&
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_TRANSFER_ENCODING, encoding, &size, NULL) == ERROR_SUCCESS &&
!strcmpiW(encoding, szChunked))
{
lpwhr->dwContentLength = ~0u;
HeapFree(GetProcessHeap(), 0, token_array);
}
-/* **********************************************************************
- *
- * Helper functions for the HttpSendRequest(Ex) functions
- *
- */
-static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
-{
- struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
- http_request_t *lpwhr = (http_request_t*) workRequest->hdr;
-
- TRACE("%p\n", lpwhr);
-
- HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
- req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
- req->dwContentLength, req->bEndRequest);
-
- HeapFree(GetProcessHeap(), 0, req->lpszHeader);
-}
-
static void HTTP_FixURL(http_request_t *lpwhr)
{
static const WCHAR szSlash[] = { '/',0 };
}
}
-static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
+static void strip_spaces(LPWSTR start)
+{
+ LPWSTR str = start;
+ LPWSTR end;
+
+ while (*str == ' ' && *str != '\0')
+ str++;
+
+ if (str != start)
+ memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
+
+ end = start + strlenW(start) - 1;
+ while (end >= start && *end == ' ')
+ {
+ *end = '\0';
+ end--;
+ }
+}
+
+static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue, LPWSTR *pszRealm )
{
static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
- return !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
+ static const WCHAR szRealm[] = {'r','e','a','l','m'}; /* Note: not nul-terminated */
+ BOOL is_basic;
+ is_basic = !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
+ if (is_basic && pszRealm)
+ {
+ LPCWSTR token;
+ LPCWSTR ptr = &pszAuthValue[ARRAYSIZE(szBasic)];
+ LPCWSTR realm;
+ ptr++;
+ *pszRealm=NULL;
+ token = strchrW(ptr,'=');
+ if (!token)
+ return TRUE;
+ realm = ptr;
+ while (*realm == ' ' && *realm != '\0')
+ realm++;
+ if(!strncmpiW(realm, szRealm, ARRAYSIZE(szRealm)) &&
+ (realm[ARRAYSIZE(szRealm)] == ' ' || realm[ARRAYSIZE(szRealm)] == '='))
+ {
+ token++;
+ while (*token == ' ' && *token != '\0')
+ token++;
+ if (*token == '\0')
+ return TRUE;
+ *pszRealm = heap_strdupW(token);
+ strip_spaces(*pszRealm);
+ }
+ }
+
+ return is_basic;
}
static void destroy_authinfo( struct HttpAuthInfo *authinfo )
HeapFree(GetProcessHeap(), 0, authinfo);
}
+static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data)
+{
+ basicAuthorizationData *ad;
+ UINT rc = 0;
+
+ TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, basicAuthorizationData, entry)
+ {
+ if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm))
+ {
+ TRACE("Authorization found in cache\n");
+ *auth_data = HeapAlloc(GetProcessHeap(),0,ad->AuthorizationLen);
+ memcpy(*auth_data,ad->lpszAuthorization,ad->AuthorizationLen);
+ rc = ad->AuthorizationLen;
+ break;
+ }
+ }
+ LeaveCriticalSection(&authcache_cs);
+ return rc;
+}
+
+static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
+{
+ struct list *cursor;
+ basicAuthorizationData* ad = NULL;
+
+ TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH(cursor, &basicAuthorizationCache)
+ {
+ basicAuthorizationData *check = LIST_ENTRY(cursor,basicAuthorizationData,entry);
+ if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm))
+ {
+ ad = check;
+ break;
+ }
+ }
+
+ if (ad)
+ {
+ TRACE("Found match in cache, replacing\n");
+ HeapFree(GetProcessHeap(),0,ad->lpszAuthorization);
+ ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
+ memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
+ ad->AuthorizationLen = auth_data_len;
+ }
+ else
+ {
+ ad = HeapAlloc(GetProcessHeap(),0,sizeof(basicAuthorizationData));
+ ad->lpszwHost = heap_strdupW(host);
+ ad->lpszwRealm = heap_strdupW(realm);
+ ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
+ memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
+ ad->AuthorizationLen = auth_data_len;
+ list_add_head(&basicAuthorizationCache,&ad->entry);
+ TRACE("authorization cached\n");
+ }
+ LeaveCriticalSection(&authcache_cs);
+}
+
+static BOOL retrieve_cached_authorization(LPWSTR host, LPWSTR scheme,
+ SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
+{
+ authorizationData *ad;
+
+ TRACE("Looking for authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry) {
+ if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) {
+ TRACE("Authorization found in cache\n");
+
+ nt_auth_identity->User = heap_strdupW(ad->user);
+ nt_auth_identity->Password = heap_strdupW(ad->password);
+ nt_auth_identity->Domain = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*ad->domain_len);
+ if(!nt_auth_identity->User || !nt_auth_identity->Password ||
+ (!nt_auth_identity->Domain && ad->domain_len)) {
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity->User);
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity->Password);
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity->Domain);
+ break;
+ }
+
+ nt_auth_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ nt_auth_identity->UserLength = ad->user_len;
+ nt_auth_identity->PasswordLength = ad->password_len;
+ memcpy(nt_auth_identity->Domain, ad->domain, sizeof(WCHAR)*ad->domain_len);
+ nt_auth_identity->DomainLength = ad->domain_len;
+ LeaveCriticalSection(&authcache_cs);
+ return TRUE;
+ }
+ }
+ LeaveCriticalSection(&authcache_cs);
+
+ return FALSE;
+}
+
+static void cache_authorization(LPWSTR host, LPWSTR scheme,
+ SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity)
+{
+ authorizationData *ad;
+ BOOL found = FALSE;
+
+ TRACE("Caching authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme));
+
+ EnterCriticalSection(&authcache_cs);
+ LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry)
+ if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) {
+ found = TRUE;
+ break;
+ }
+
+ if(found) {
+ HeapFree(GetProcessHeap(), 0, ad->user);
+ HeapFree(GetProcessHeap(), 0, ad->password);
+ HeapFree(GetProcessHeap(), 0, ad->domain);
+ } else {
+ ad = HeapAlloc(GetProcessHeap(), 0, sizeof(authorizationData));
+ if(!ad) {
+ LeaveCriticalSection(&authcache_cs);
+ return;
+ }
+
+ ad->host = heap_strdupW(host);
+ ad->scheme = heap_strdupW(scheme);
+ list_add_head(&authorizationCache, &ad->entry);
+ }
+
+ ad->user = heap_strndupW(nt_auth_identity->User, nt_auth_identity->UserLength);
+ ad->password = heap_strndupW(nt_auth_identity->Password, nt_auth_identity->PasswordLength);
+ ad->domain = heap_strndupW(nt_auth_identity->Domain, nt_auth_identity->DomainLength);
+ ad->user_len = nt_auth_identity->UserLength;
+ ad->password_len = nt_auth_identity->PasswordLength;
+ ad->domain_len = nt_auth_identity->DomainLength;
+
+ if(!ad->host || !ad->scheme || !ad->user || !ad->password
+ || (nt_auth_identity->Domain && !ad->domain)) {
+ HeapFree(GetProcessHeap(), 0, ad->host);
+ HeapFree(GetProcessHeap(), 0, ad->scheme);
+ HeapFree(GetProcessHeap(), 0, ad->user);
+ HeapFree(GetProcessHeap(), 0, ad->password);
+ HeapFree(GetProcessHeap(), 0, ad->domain);
+ list_remove(&ad->entry);
+ HeapFree(GetProcessHeap(), 0, ad);
+ }
+
+ LeaveCriticalSection(&authcache_cs);
+}
+
static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
struct HttpAuthInfo **ppAuthInfo,
- LPWSTR domain_and_username, LPWSTR password )
+ LPWSTR domain_and_username, LPWSTR password,
+ LPWSTR host )
{
SECURITY_STATUS sec_status;
struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
BOOL first = FALSE;
+ LPWSTR szRealm = NULL;
TRACE("%s\n", debugstr_w(pszAuthValue));
pAuthInfo->auth_data_len = 0;
pAuthInfo->finished = FALSE;
- if (is_basic_auth_value(pszAuthValue))
+ if (is_basic_auth_value(pszAuthValue,NULL))
{
static const WCHAR szBasic[] = {'B','a','s','i','c',0};
pAuthInfo->scheme = heap_strdupW(szBasic);
nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0;
nt_auth_identity.Password = password;
nt_auth_identity.PasswordLength = strlenW(nt_auth_identity.Password);
+
+ cache_authorization(host, pAuthInfo->scheme, &nt_auth_identity);
}
+ else if(retrieve_cached_authorization(host, pAuthInfo->scheme, &nt_auth_identity))
+ pAuthData = &nt_auth_identity;
else
/* use default credentials */
pAuthData = NULL;
pAuthData, NULL,
NULL, &pAuthInfo->cred,
&exp);
+
+ if(pAuthData && !domain_and_username) {
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity.User);
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity.Domain);
+ HeapFree(GetProcessHeap(), 0, nt_auth_identity.Password);
+ }
+
if (sec_status == SEC_E_OK)
{
PSecPkgInfoW sec_pkg_info;
return FALSE;
}
- if (is_basic_auth_value(pszAuthValue))
+ if (is_basic_auth_value(pszAuthValue,&szRealm))
{
int userlen;
int passlen;
- char *auth_data;
+ char *auth_data = NULL;
+ UINT auth_data_len = 0;
- TRACE("basic authentication\n");
+ TRACE("basic authentication realm %s\n",debugstr_w(szRealm));
- /* we don't cache credentials for basic authentication, so we can't
- * retrieve them if the application didn't pass us any credentials */
- if (!domain_and_username) return FALSE;
-
- userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
- passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
+ if (!domain_and_username)
+ {
+ if (host && szRealm)
+ auth_data_len = retrieve_cached_basic_authorization(host, szRealm,&auth_data);
+ if (auth_data_len == 0)
+ {
+ HeapFree(GetProcessHeap(),0,szRealm);
+ return FALSE;
+ }
+ }
+ else
+ {
+ userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
+ passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
- /* length includes a nul terminator, which will be re-used for the ':' */
- auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
- if (!auth_data)
- return FALSE;
+ /* length includes a nul terminator, which will be re-used for the ':' */
+ auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
+ if (!auth_data)
+ {
+ HeapFree(GetProcessHeap(),0,szRealm);
+ return FALSE;
+ }
- WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
- auth_data[userlen] = ':';
- WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
+ WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
+ auth_data[userlen] = ':';
+ WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
+ auth_data_len = userlen + 1 + passlen;
+ if (host && szRealm)
+ cache_basic_authorization(host, szRealm, auth_data, auth_data_len);
+ }
pAuthInfo->auth_data = auth_data;
- pAuthInfo->auth_data_len = userlen + 1 + passlen;
+ pAuthInfo->auth_data_len = auth_data_len;
pAuthInfo->finished = TRUE;
+ HeapFree(GetProcessHeap(),0,szRealm);
return TRUE;
}
/***********************************************************************
* HTTP_HttpAddRequestHeadersW (internal)
*/
-static BOOL HTTP_HttpAddRequestHeadersW(http_request_t *lpwhr,
+static DWORD HTTP_HttpAddRequestHeadersW(http_request_t *lpwhr,
LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
{
LPWSTR lpszStart;
LPWSTR lpszEnd;
LPWSTR buffer;
- BOOL bSuccess = FALSE;
- DWORD len;
+ DWORD len, res = ERROR_HTTP_INVALID_HEADER;
TRACE("copying header: %s\n", debugstr_wn(lpszHeader, dwHeaderLength));
{
/* Skip 0-length headers */
lpszStart = lpszEnd;
- bSuccess = TRUE;
+ res = ERROR_SUCCESS;
continue;
}
pFieldAndValue = HTTP_InterpretHttpHeader(lpszStart);
if (pFieldAndValue)
{
- bSuccess = HTTP_VerifyValidHeader(lpwhr, pFieldAndValue[0]);
- if (bSuccess)
- bSuccess = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0],
+ res = HTTP_VerifyValidHeader(lpwhr, pFieldAndValue[0]);
+ if (res == ERROR_SUCCESS)
+ res = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0],
pFieldAndValue[1], dwModifier | HTTP_ADDHDR_FLAG_REQ);
HTTP_FreeTokens(pFieldAndValue);
}
lpszStart = lpszEnd;
- } while (bSuccess);
+ } while (res == ERROR_SUCCESS);
HeapFree(GetProcessHeap(), 0, buffer);
- return bSuccess;
+ return res;
}
/***********************************************************************
BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest,
LPCWSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier)
{
- BOOL bSuccess = FALSE;
http_request_t *lpwhr;
+ DWORD res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_wn(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier);
return TRUE;
lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
- bSuccess = HTTP_HttpAddRequestHeadersW( lpwhr, lpszHeader, dwHeaderLength, dwModifier );
-lend:
+ if (lpwhr && lpwhr->hdr.htype == WH_HHTTPREQ)
+ res = HTTP_HttpAddRequestHeadersW( lpwhr, lpszHeader, dwHeaderLength, dwModifier );
if( lpwhr )
WININET_Release( &lpwhr->hdr );
- return bSuccess;
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
/***********************************************************************
}
/***********************************************************************
- * HttpEndRequestA (WININET.@)
+ * HttpOpenRequestA (WININET.@)
*
- * Ends an HTTP request that was started by HttpSendRequestEx
+ * Open a HTTP request handle
*
* RETURNS
- * TRUE if successful
- * FALSE on failure
+ * HINTERNET a HTTP request handle on success
+ * NULL on failure
*
*/
-BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
- LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
+HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
+ LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
+ LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
+ DWORD dwFlags, DWORD_PTR dwContext)
{
- TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+ LPWSTR szVerb = NULL, szObjectName = NULL;
+ LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
+ INT acceptTypesCount;
+ HINTERNET rc = FALSE;
+ LPCSTR *types;
- if (lpBuffersOut)
+ TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
+ debugstr_a(lpszVerb), debugstr_a(lpszObjectName),
+ debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes,
+ dwFlags, dwContext);
+
+ if (lpszVerb)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
+ szVerb = heap_strdupAtoW(lpszVerb);
+ if ( !szVerb )
+ goto end;
}
- return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
-}
-
-static BOOL HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
-{
- BOOL rc = FALSE;
- INT responseLen;
- DWORD dwBufferSize;
- INTERNET_ASYNC_RESULT iar;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
-
- responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- rc = TRUE;
-
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
+ if (lpszObjectName)
+ {
+ szObjectName = heap_strdupAtoW(lpszObjectName);
+ if ( !szObjectName )
+ goto end;
+ }
- /* process cookies here. Is this right? */
- HTTP_ProcessCookies(lpwhr);
+ if (lpszVersion)
+ {
+ szVersion = heap_strdupAtoW(lpszVersion);
+ if ( !szVersion )
+ goto end;
+ }
- if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
+ if (lpszReferrer)
+ {
+ szReferrer = heap_strdupAtoW(lpszReferrer);
+ if ( !szReferrer )
+ goto end;
+ }
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+ if (lpszAcceptTypes)
{
- 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))
+ acceptTypesCount = 0;
+ types = lpszAcceptTypes;
+ while (*types)
{
- WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
- dwBufferSize=sizeof(szNewLocation);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
+ __TRY
{
- if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
- {
- HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
- lpwhr->lpszVerb = heap_strdupW(szGET);
- }
- HTTP_DrainContent(lpwhr);
- if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
+ /* find out how many there are */
+ if (*types && **types)
{
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
- new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
- rc = HTTP_HandleRedirect(lpwhr, new_url);
- if (rc)
- rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
- HeapFree( GetProcessHeap(), 0, new_url );
+ TRACE("accept type: %s\n", debugstr_a(*types));
+ acceptTypesCount++;
}
}
+ __EXCEPT_PAGE_FAULT
+ {
+ WARN("invalid accept type pointer\n");
+ }
+ __ENDTRY;
+ types++;
}
- }
+ szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
+ if (!szAcceptTypes) goto end;
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = rc ? 0 : INTERNET_GetLastError();
+ acceptTypesCount = 0;
+ types = lpszAcceptTypes;
+ while (*types)
+ {
+ __TRY
+ {
+ if (*types && **types)
+ szAcceptTypes[acceptTypesCount++] = heap_strdupAtoW(*types);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ /* ignore invalid pointer */
+ }
+ __ENDTRY;
+ types++;
+ }
+ szAcceptTypes[acceptTypesCount] = NULL;
+ }
- 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;
- http_request_t *lpwhr = (http_request_t*)work->hdr;
-
- TRACE("%p\n", lpwhr);
-
- HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
-}
-
-/***********************************************************************
- * HttpEndRequestW (WININET.@)
- *
- * Ends an HTTP request that was started by HttpSendRequestEx
- *
- * RETURNS
- * TRUE if successful
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
- LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
-{
- BOOL rc = FALSE;
- http_request_t *lpwhr;
-
- TRACE("-->\n");
-
- if (lpBuffersOut)
- {
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- lpwhr = (http_request_t*) WININET_GetObject( hRequest );
-
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- if (lpwhr)
- WININET_Release( &lpwhr->hdr );
- return FALSE;
- }
- lpwhr->hdr.dwFlags |= dwFlags;
-
- if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST work;
- struct WORKREQ_HTTPENDREQUESTW *request;
-
- work.asyncproc = AsyncHttpEndRequestProc;
- work.hdr = WININET_AddRef( &lpwhr->hdr );
-
- request = &work.u.HttpEndRequestW;
- request->dwFlags = dwFlags;
- request->dwContext = dwContext;
-
- INTERNET_AsyncCall(&work);
- INTERNET_SetLastError(ERROR_IO_PENDING);
- }
- else
- rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
-
- WININET_Release( &lpwhr->hdr );
- TRACE("%i <--\n",rc);
- return rc;
-}
-
-/***********************************************************************
- * HttpOpenRequestW (WININET.@)
- *
- * Open a HTTP request handle
- *
- * RETURNS
- * HINTERNET a HTTP request handle on success
- * NULL on failure
- *
- */
-HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
- LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
- LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
- DWORD dwFlags, DWORD_PTR dwContext)
-{
- http_session_t *lpwhs;
- HINTERNET handle = NULL;
-
- TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
- debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
- debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
- dwFlags, dwContext);
- if(lpszAcceptTypes!=NULL)
- {
- int i;
- for(i=0;lpszAcceptTypes[i]!=NULL;i++)
- TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
- }
-
- lpwhs = (http_session_t*) WININET_GetObject( hHttpSession );
- if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
-
- /*
- * My tests seem to show that the windows version does not
- * become asynchronous until after this point. And anyhow
- * if this call was asynchronous then how would you get the
- * necessary HINTERNET pointer returned by this function.
- *
- */
- handle = HTTP_HttpOpenRequestW(lpwhs, lpszVerb, lpszObjectName,
- lpszVersion, lpszReferrer, lpszAcceptTypes,
- dwFlags, dwContext);
-lend:
- if( lpwhs )
- WININET_Release( &lpwhs->hdr );
- TRACE("returning %p\n", handle);
- return handle;
-}
-
-
-/***********************************************************************
- * HttpOpenRequestA (WININET.@)
- *
- * Open a HTTP request handle
- *
- * RETURNS
- * HINTERNET a HTTP request handle on success
- * NULL on failure
- *
- */
-HINTERNET WINAPI HttpOpenRequestA(HINTERNET hHttpSession,
- LPCSTR lpszVerb, LPCSTR lpszObjectName, LPCSTR lpszVersion,
- LPCSTR lpszReferrer , LPCSTR *lpszAcceptTypes,
- DWORD dwFlags, DWORD_PTR dwContext)
-{
- LPWSTR szVerb = NULL, szObjectName = NULL;
- LPWSTR szVersion = NULL, szReferrer = NULL, *szAcceptTypes = NULL;
- INT acceptTypesCount;
- HINTERNET rc = FALSE;
- LPCSTR *types;
-
- TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
- debugstr_a(lpszVerb), debugstr_a(lpszObjectName),
- debugstr_a(lpszVersion), debugstr_a(lpszReferrer), lpszAcceptTypes,
- dwFlags, dwContext);
-
- if (lpszVerb)
- {
- szVerb = heap_strdupAtoW(lpszVerb);
- if ( !szVerb )
- goto end;
- }
-
- if (lpszObjectName)
- {
- szObjectName = heap_strdupAtoW(lpszObjectName);
- if ( !szObjectName )
- goto end;
- }
-
- if (lpszVersion)
- {
- szVersion = heap_strdupAtoW(lpszVersion);
- if ( !szVersion )
- goto end;
- }
-
- if (lpszReferrer)
- {
- szReferrer = heap_strdupAtoW(lpszReferrer);
- if ( !szReferrer )
- goto end;
- }
-
- if (lpszAcceptTypes)
- {
- acceptTypesCount = 0;
- types = lpszAcceptTypes;
- while (*types)
- {
- __TRY
- {
- /* find out how many there are */
- if (*types && **types)
- {
- TRACE("accept type: %s\n", debugstr_a(*types));
- acceptTypesCount++;
- }
- }
- __EXCEPT_PAGE_FAULT
- {
- WARN("invalid accept type pointer\n");
- }
- __ENDTRY;
- types++;
- }
- szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
- if (!szAcceptTypes) goto end;
-
- acceptTypesCount = 0;
- types = lpszAcceptTypes;
- while (*types)
- {
- __TRY
- {
- if (*types && **types)
- szAcceptTypes[acceptTypesCount++] = heap_strdupAtoW(*types);
- }
- __EXCEPT_PAGE_FAULT
- {
- /* ignore invalid pointer */
- }
- __ENDTRY;
- types++;
- }
- szAcceptTypes[acceptTypesCount] = NULL;
- }
-
- rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName,
- szVersion, szReferrer,
- (LPCWSTR*)szAcceptTypes, dwFlags, dwContext);
+ rc = HttpOpenRequestW(hHttpSession, szVerb, szObjectName,
+ szVersion, szReferrer,
+ (LPCWSTR*)szAcceptTypes, dwFlags, dwContext);
end:
if (szAcceptTypes)
DWORD size;
size = sizeof(new_location);
- if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_LOCATION, new_location, &size, NULL))
+ if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_LOCATION, new_location, &size, NULL) == ERROR_SUCCESS)
{
if (!(url = HeapAlloc( GetProcessHeap(), 0, size + sizeof(WCHAR) ))) return NULL;
strcpyW( url, new_location );
static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *lpwhs, http_request_t *lpwhr)
{
WCHAR buf[MAXHOSTNAME];
+ WCHAR protoProxy[MAXHOSTNAME + 15];
+ DWORD protoProxyLen = sizeof(protoProxy) / sizeof(protoProxy[0]);
WCHAR proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */
static WCHAR szNul[] = { 0 };
URL_COMPONENTSW UrlComponents;
+ static const WCHAR protoHttp[] = { 'h','t','t','p',0 };
static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 };
static const WCHAR szFormat[] = { 'h','t','t','p',':','/','/','%','s',0 };
UrlComponents.lpszHostName = buf;
UrlComponents.dwHostNameLength = MAXHOSTNAME;
+ if (!INTERNET_FindProxyForProtocol(hIC->lpszProxy, protoHttp, protoProxy, &protoProxyLen))
+ return FALSE;
if( CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
- hIC->lpszProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) )
- sprintfW(proxy, szFormat, hIC->lpszProxy);
+ protoProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) )
+ sprintfW(proxy, szFormat, protoProxy);
else
- strcpyW(proxy, hIC->lpszProxy);
+ strcpyW(proxy, protoProxy);
if( !InternetCrackUrlW(proxy, 0, 0, &UrlComponents) )
return FALSE;
if( UrlComponents.dwHostNameLength == 0 )
#define INET6_ADDRSTRLEN 46
#endif
-static BOOL HTTP_ResolveName(http_request_t *lpwhr)
+static DWORD HTTP_ResolveName(http_request_t *lpwhr)
{
char szaddr[INET6_ADDRSTRLEN];
http_session_t *lpwhs = lpwhr->lpHttpSession;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESOLVING_NAME,
lpwhs->lpszServerName,
- strlenW(lpwhs->lpszServerName)+1);
+ (strlenW(lpwhs->lpszServerName)+1) * sizeof(WCHAR));
lpwhs->sa_len = sizeof(lpwhs->socketAddress);
if (!GetAddress(lpwhs->lpszServerName, lpwhs->nServerPort,
(struct sockaddr *)&lpwhs->socketAddress, &lpwhs->sa_len))
- {
- INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
- return FALSE;
- }
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
switch (lpwhs->socketAddress.ss_family)
{
break;
default:
WARN("unsupported family %d\n", lpwhs->socketAddress.ss_family);
- INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
- return FALSE;
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
}
inet_ntop(lpwhs->socketAddress.ss_family, addr, szaddr, sizeof(szaddr));
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
szaddr, strlen(szaddr)+1);
TRACE("resolved %s to %s\n", debugstr_w(lpwhs->lpszServerName), szaddr);
+ return ERROR_SUCCESS;
+}
+
+static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
+{
+ LPHTTPHEADERW host_header;
+
+ static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
+
+ host_header = HTTP_GetHeader(req, hostW);
+ if(!host_header)
+ return FALSE;
+
+ sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
return TRUE;
}
TRACE("\n");
- if(lpwhr->hCacheFile)
+ if(lpwhr->hCacheFile) {
+ WCHAR url[INTERNET_MAX_URL_LENGTH];
+ FILETIME ft;
+
CloseHandle(lpwhr->hCacheFile);
+ memset(&ft, 0, sizeof(FILETIME));
+ if(HTTP_GetRequestURL(lpwhr, url)) {
+ CommitUrlCacheEntryW(url, lpwhr->lpszCacheFile, ft, ft,
+ NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
+ }
+ }
+
HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
DeleteCriticalSection( &lpwhr->read_section );
INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
}
-static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
-{
- LPHTTPHEADERW host_header;
-
- static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
-
- host_header = HTTP_GetHeader(req, hostW);
- if(!host_header)
- return FALSE;
-
- sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
- return TRUE;
-}
-
static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
{
WCHAR szVersion[10];
/* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
* the connection is keep-alive by default */
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion,
- &dwBufferSize, NULL) &&
- !strcmpiW(szVersion, g_szHttp1_1))
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion, &dwBufferSize, NULL) == ERROR_SUCCESS
+ && !strcmpiW(szVersion, g_szHttp1_1))
{
keepalive = TRUE;
}
dwBufferSize = sizeof(szConnectionResponse);
- if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) ||
- HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL))
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) == ERROR_SUCCESS
+ || HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) == ERROR_SUCCESS)
{
keepalive = !strcmpiW(szConnectionResponse, szKeepAlive);
}
case INTERNET_OPTION_SECURITY_FLAGS:
{
- http_session_t *lpwhs;
- lpwhs = req->lpHttpSession;
+ DWORD flags;
+ int bits;
if (*size < sizeof(ULONG))
return ERROR_INSUFFICIENT_BUFFER;
*size = sizeof(DWORD);
- if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
- *(DWORD*)buffer = SECURITY_FLAG_SECURE;
+ flags = 0;
+ if (req->hdr.dwFlags & INTERNET_FLAG_SECURE)
+ flags |= SECURITY_FLAG_SECURE;
+ flags |= req->netConnection.security_flags;
+ bits = NETCON_GetCipherStrength(&req->netConnection);
+ if (bits >= 128)
+ flags |= SECURITY_FLAG_STRENGTH_STRONG;
+ else if (bits >= 56)
+ flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
else
- *(DWORD*)buffer = 0;
- FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
+ flags |= SECURITY_FLAG_STRENGTH_WEAK;
+ *(DWORD *)buffer = flags;
return ERROR_SUCCESS;
}
case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: {
PCCERT_CONTEXT context;
- if(*size < sizeof(INTERNET_CERTIFICATE_INFOW)) {
- *size = sizeof(INTERNET_CERTIFICATE_INFOW);
+ if(*size < sizeof(INTERNET_CERTIFICATE_INFOA)) {
+ *size = sizeof(INTERNET_CERTIFICATE_INFOA);
return ERROR_INSUFFICIENT_BUFFER;
}
context = (PCCERT_CONTEXT)NETCON_GetCert(&(req->netConnection));
if(context) {
- INTERNET_CERTIFICATE_INFOW *info = (INTERNET_CERTIFICATE_INFOW*)buffer;
+ INTERNET_CERTIFICATE_INFOA *info = (INTERNET_CERTIFICATE_INFOA*)buffer;
DWORD len;
memset(info, 0, sizeof(INTERNET_CERTIFICATE_INFOW));
info->ftExpiry = context->pCertInfo->NotAfter;
info->ftStart = context->pCertInfo->NotBefore;
- if(unicode) {
- len = CertNameToStrW(context->dwCertEncodingType,
- &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
- info->lpszSubjectInfo = LocalAlloc(0, len*sizeof(WCHAR));
- if(info->lpszSubjectInfo)
- CertNameToStrW(context->dwCertEncodingType,
- &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
- info->lpszSubjectInfo, len);
- len = CertNameToStrW(context->dwCertEncodingType,
- &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
- info->lpszIssuerInfo = LocalAlloc(0, len*sizeof(WCHAR));
- if (info->lpszIssuerInfo)
- CertNameToStrW(context->dwCertEncodingType,
- &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
- info->lpszIssuerInfo, len);
- }else {
- INTERNET_CERTIFICATE_INFOA *infoA = (INTERNET_CERTIFICATE_INFOA*)info;
-
- len = CertNameToStrA(context->dwCertEncodingType,
- &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
- infoA->lpszSubjectInfo = LocalAlloc(0, len);
- if(infoA->lpszSubjectInfo)
- CertNameToStrA(context->dwCertEncodingType,
- &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
- infoA->lpszSubjectInfo, len);
- len = CertNameToStrA(context->dwCertEncodingType,
- &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
- infoA->lpszIssuerInfo = LocalAlloc(0, len);
- if(infoA->lpszIssuerInfo)
- CertNameToStrA(context->dwCertEncodingType,
- &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
- infoA->lpszIssuerInfo, len);
- }
-
- /*
- * Contrary to MSDN, these do not appear to be set.
- * lpszProtocolName
- * lpszSignatureAlgName
- * lpszEncryptionAlgName
- * dwKeySize
- */
+ len = CertNameToStrA(context->dwCertEncodingType,
+ &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
+ info->lpszSubjectInfo = LocalAlloc(0, len);
+ if(info->lpszSubjectInfo)
+ CertNameToStrA(context->dwCertEncodingType,
+ &context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
+ info->lpszSubjectInfo, len);
+ len = CertNameToStrA(context->dwCertEncodingType,
+ &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
+ info->lpszIssuerInfo = LocalAlloc(0, len);
+ if(info->lpszIssuerInfo)
+ CertNameToStrA(context->dwCertEncodingType,
+ &context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
+ info->lpszIssuerInfo, len);
+ info->dwKeySize = NETCON_GetCipherStrength(&req->netConnection);
CertFreeCertificateContext(context);
return ERROR_SUCCESS;
}
}
}
- return INET_QueryOption(option, buffer, size, unicode);
+ return INET_QueryOption(hdr, option, buffer, size, unicode);
}
static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
http_request_t *req = (http_request_t*)hdr;
switch(option) {
- case INTERNET_OPTION_SEND_TIMEOUT:
- case INTERNET_OPTION_RECEIVE_TIMEOUT:
- TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n");
+ case INTERNET_OPTION_SECURITY_FLAGS:
+ {
+ DWORD flags;
+
+ if (!buffer || size != sizeof(DWORD))
+ return ERROR_INVALID_PARAMETER;
+ flags = *(DWORD *)buffer;
+ TRACE("%08x\n", flags);
+ req->netConnection.security_flags = flags;
+ return ERROR_SUCCESS;
+ }
+ case INTERNET_OPTION_SEND_TIMEOUT:
+ case INTERNET_OPTION_RECEIVE_TIMEOUT:
+ TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n");
if (size != sizeof(DWORD))
return ERROR_INVALID_PARAMETER;
}
/* read some more data into the read buffer (the read section must be held) */
-static BOOL read_more_data( http_request_t *req, int maxlen )
+static DWORD read_more_data( http_request_t *req, int maxlen )
{
+ DWORD res;
int len;
if (req->read_pos)
if (maxlen == -1) maxlen = sizeof(req->read_buf);
- if(!NETCON_recv( &req->netConnection, req->read_buf + req->read_size,
- maxlen - req->read_size, 0, &len ))
- return FALSE;
+ res = NETCON_recv( &req->netConnection, req->read_buf + req->read_size,
+ maxlen - req->read_size, 0, &len );
+ if(res == ERROR_SUCCESS)
+ req->read_size += len;
- req->read_size += len;
- return TRUE;
+ return res;
}
/* remove some amount of data from the read buffer (the read section must be held) */
static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
{
int count, bytes_read, pos = 0;
+ DWORD res;
EnterCriticalSection( &req->read_section );
for (;;)
remove_data( req, bytes_read );
if (eol) break;
- if (!read_more_data( req, -1 ) || !req->read_size)
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS || !req->read_size)
{
*len = 0;
TRACE( "returning empty string\n" );
LeaveCriticalSection( &req->read_section );
+ INTERNET_SetLastError(res);
return FALSE;
}
}
}
/* discard data contents until we reach end of line (the read section must be held) */
-static BOOL discard_eol( http_request_t *req )
+static DWORD discard_eol( http_request_t *req )
{
+ DWORD res;
+
do
{
BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
break;
}
req->read_pos = req->read_size = 0; /* discard everything */
- if (!read_more_data( req, -1 )) return FALSE;
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS) return res;
} while (req->read_size);
- return TRUE;
+ return ERROR_SUCCESS;
}
/* read the size of the next chunk (the read section must be held) */
-static BOOL start_next_chunk( http_request_t *req )
+static DWORD start_next_chunk( http_request_t *req )
{
- DWORD chunk_size = 0;
+ DWORD chunk_size = 0, res;
- if (!req->dwContentLength) return TRUE;
+ if (!req->dwContentLength) return ERROR_SUCCESS;
if (req->dwContentLength == req->dwContentRead)
{
/* read terminator for the previous chunk */
- if (!discard_eol( req )) return FALSE;
+ if ((res = discard_eol( req )) != ERROR_SUCCESS) return res;
req->dwContentLength = ~0u;
req->dwContentRead = 0;
}
TRACE( "reading %u byte chunk\n", chunk_size );
req->dwContentLength = chunk_size;
req->dwContentRead = 0;
- if (!discard_eol( req )) return FALSE;
- return TRUE;
+ return discard_eol( req );
}
remove_data( req, 1 );
}
- if (!read_more_data( req, -1 )) return FALSE;
+ if ((res = read_more_data( req, -1 )) != ERROR_SUCCESS) return res;
if (!req->read_size)
{
req->dwContentLength = req->dwContentRead = 0;
- return TRUE;
+ return ERROR_SUCCESS;
}
}
}
}
/* fetch some more data into the read buffer (the read section must be held) */
-static BOOL refill_buffer( http_request_t *req )
+static DWORD refill_buffer( http_request_t *req )
{
int len = sizeof(req->read_buf);
+ DWORD res;
if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
{
- if (!start_next_chunk( req )) return FALSE;
+ if ((res = start_next_chunk( req )) != ERROR_SUCCESS) return res;
}
if (req->dwContentLength != ~0u) len = min( len, req->dwContentLength - req->dwContentRead );
- if (len <= req->read_size) return TRUE;
+ if (len <= req->read_size) return ERROR_SUCCESS;
- if (!read_more_data( req, len )) return FALSE;
+ if ((res = read_more_data( req, len )) != ERROR_SUCCESS) return res;
if (!req->read_size) req->dwContentLength = req->dwContentRead = 0;
- return TRUE;
+ return ERROR_SUCCESS;
}
static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync, int *read_ret)
#ifdef HAVE_ZLIB
z_stream *zstream = &req->gzip_stream->zstream;
+ DWORD buf_avail;
int zres;
while(read < size && !req->gzip_stream->end_of_data) {
if(!req->read_size) {
- if(!sync || !refill_buffer(req))
+ if(!sync || refill_buffer(req) != ERROR_SUCCESS)
break;
}
+ if(req->dwContentRead == req->dwContentLength)
+ break;
+
+ buf_avail = req->dwContentLength == ~0 ? req->read_size : min(req->read_size, req->dwContentLength-req->dwContentRead);
+
zstream->next_in = req->read_buf+req->read_pos;
- zstream->avail_in = req->read_size;
+ zstream->avail_in = buf_avail;
zstream->next_out = buf+read;
zstream->avail_out = size-read;
zres = inflate(zstream, Z_FULL_FLUSH);
read = size - zstream->avail_out;
- remove_data(req, req->read_size-zstream->avail_in);
+ req->dwContentRead += buf_avail-zstream->avail_in;
+ remove_data(req, buf_avail-zstream->avail_in);
if(zres == Z_STREAM_END) {
TRACE("end of data\n");
req->gzip_stream->end_of_data = TRUE;
static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif)
{
INTERNET_ASYNC_RESULT iar;
+ DWORD res;
TRACE("%p\n", req);
EnterCriticalSection( &req->read_section );
- if (refill_buffer( req )) {
+ if ((res = refill_buffer( req )) == ERROR_SUCCESS) {
iar.dwResult = (DWORD_PTR)req->hdr.hInternet;
iar.dwError = first_notif ? 0 : get_avail_data(req);
}else {
iar.dwResult = 0;
- iar.dwError = INTERNET_GetLastError();
+ iar.dwError = res;
}
LeaveCriticalSection( &req->read_section );
if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
{
- if (!start_next_chunk( req )) goto done;
+ if (start_next_chunk( req ) != ERROR_SUCCESS) goto done;
}
if(req->gzip_stream) {
if (size > bytes_read && (!bytes_read || sync)) {
if (NETCON_recv( &req->netConnection, (char *)buffer + bytes_read, size - bytes_read,
- sync ? MSG_WAITALL : 0, &len))
+ sync ? MSG_WAITALL : 0, &len) == ERROR_SUCCESS)
bytes_read += len;
/* always return success, even if the network layer returns an error */
}
finished_reading = !bytes_read && req->dwContentRead == req->dwContentLength;
+ req->dwContentRead += bytes_read;
}
done:
- req->dwContentRead += bytes_read;
*read = bytes_read;
TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, req->dwContentRead, req->dwContentLength );
static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
{
http_request_t *req = (http_request_t*)hdr;
- return HTTPREQ_Read(req, buffer, size, read, TRUE);
+ DWORD res;
+
+ EnterCriticalSection( &req->read_section );
+ if(hdr->dwError == INTERNET_HANDLE_IN_USE)
+ hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
+
+ res = HTTPREQ_Read(req, buffer, size, read, TRUE);
+ if(res == ERROR_SUCCESS)
+ res = hdr->dwError;
+ LeaveCriticalSection( &req->read_section );
+
+ return res;
}
static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest)
DWORD flags, DWORD_PTR context)
{
http_request_t *req = (http_request_t*)hdr;
- DWORD res;
+ DWORD res, size, read, error = ERROR_SUCCESS;
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);
- if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
+ if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
{
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
&buffers->dwBufferLength, FALSE);
+ size = buffers->dwBufferLength;
LeaveCriticalSection( &req->read_section );
goto done;
}
return ERROR_IO_PENDING;
}
- res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
- !(flags & IRF_NO_WAIT));
+ read = 0;
+ size = buffers->dwBufferLength;
+
+ 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*)buffers->lpvBuffer+read, size-read,
+ &buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
+ if(res == ERROR_SUCCESS)
+ read += buffers->dwBufferLength;
+ else
+ break;
+
+ if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
+ || !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
+ break;
+ LeaveCriticalSection( &req->read_section );
+
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
+ &buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ EnterCriticalSection( &req->read_section );
+ }
+
+ if(hdr->dwError == INTERNET_HANDLE_IN_USE)
+ hdr->dwError = ERROR_SUCCESS;
+ else
+ error = hdr->dwError;
+
+ LeaveCriticalSection( &req->read_section );
+ size = buffers->dwBufferLength;
+ buffers->dwBufferLength = read;
done:
if (res == ERROR_SUCCESS) {
- DWORD size = buffers->dwBufferLength;
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&size, sizeof(size));
}
- return res;
+ return res==ERROR_SUCCESS ? error : res;
}
static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
{
http_request_t *req = (http_request_t*)hdr;
- DWORD res;
+ DWORD res, size, read, error = ERROR_SUCCESS;
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
{
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
&buffers->dwBufferLength, FALSE);
+ size = buffers->dwBufferLength;
LeaveCriticalSection( &req->read_section );
goto done;
}
return ERROR_IO_PENDING;
}
- res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
- !(flags & IRF_NO_WAIT));
+ read = 0;
+ size = buffers->dwBufferLength;
+
+ 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*)buffers->lpvBuffer+read, size-read,
+ &buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
+ if(res == ERROR_SUCCESS)
+ read += buffers->dwBufferLength;
+ else
+ break;
+
+ if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
+ || !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
+ break;
+ LeaveCriticalSection( &req->read_section );
+
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
+ &buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
+ INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ EnterCriticalSection( &req->read_section );
+ }
+
+ if(hdr->dwError == INTERNET_HANDLE_IN_USE)
+ hdr->dwError = ERROR_SUCCESS;
+ else
+ error = hdr->dwError;
+
+ LeaveCriticalSection( &req->read_section );
+ size = buffers->dwBufferLength;
+ buffers->dwBufferLength = read;
done:
if (res == ERROR_SUCCESS) {
- DWORD size = buffers->dwBufferLength;
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
&size, sizeof(size));
}
- return res;
+ return res==ERROR_SUCCESS ? error : res;
}
-static BOOL HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
+static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
{
- BOOL ret;
+ DWORD res;
http_request_t *lpwhr = (http_request_t*)hdr;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
*written = 0;
- if ((ret = NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written)))
+ res = NETCON_send(&lpwhr->netConnection, buffer, size, 0, (LPINT)written);
+ if (res == ERROR_SUCCESS)
lpwhr->dwBytesWritten += *written;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, written, sizeof(DWORD));
- return ret;
+ return res;
}
static void HTTPREQ_AsyncQueryDataAvailableProc(WORKREQUEST *workRequest)
* NULL on failure
*
*/
-HINTERNET WINAPI HTTP_HttpOpenRequestW(http_session_t *lpwhs,
- LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
- LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
- DWORD dwFlags, DWORD_PTR dwContext)
+static DWORD HTTP_HttpOpenRequestW(http_session_t *lpwhs,
+ LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
+ LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
+ DWORD dwFlags, DWORD_PTR dwContext, HINTERNET *ret)
{
appinfo_t *hIC = NULL;
http_request_t *lpwhr;
LPWSTR lpszHostName = NULL;
HINTERNET handle = NULL;
static const WCHAR szHostForm[] = {'%','s',':','%','u',0};
- DWORD len;
+ DWORD len, res;
TRACE("-->\n");
lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(http_request_t));
if (NULL == lpwhr)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
lpwhr->hdr.htype = WH_HHTTPREQ;
(strlenW(lpwhs->lpszHostName) + 7 /* length of ":65535" + 1 */));
if (NULL == lpszHostName)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
handle = WININET_AllocHandle( &lpwhr->hdr );
if (NULL == handle)
{
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
goto lend;
}
- if (!NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE))
+ if ((res = NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE)) != ERROR_SUCCESS)
{
InternetCloseHandle( handle );
handle = NULL;
WININET_Release( &lpwhr->hdr );
TRACE("<-- %p (%p)\n", handle, lpwhr);
+ *ret = handle;
+ return res;
+}
+
+/***********************************************************************
+ * HttpOpenRequestW (WININET.@)
+ *
+ * Open a HTTP request handle
+ *
+ * RETURNS
+ * HINTERNET a HTTP request handle on success
+ * NULL on failure
+ *
+ */
+HINTERNET WINAPI HttpOpenRequestW(HINTERNET hHttpSession,
+ LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
+ LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_session_t *lpwhs;
+ HINTERNET handle = NULL;
+ DWORD res;
+
+ TRACE("(%p, %s, %s, %s, %s, %p, %08x, %08lx)\n", hHttpSession,
+ debugstr_w(lpszVerb), debugstr_w(lpszObjectName),
+ debugstr_w(lpszVersion), debugstr_w(lpszReferrer), lpszAcceptTypes,
+ dwFlags, dwContext);
+ if(lpszAcceptTypes!=NULL)
+ {
+ int i;
+ for(i=0;lpszAcceptTypes[i]!=NULL;i++)
+ TRACE("\taccept type: %s\n",debugstr_w(lpszAcceptTypes[i]));
+ }
+
+ lpwhs = (http_session_t*) WININET_GetObject( hHttpSession );
+ if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ /*
+ * My tests seem to show that the windows version does not
+ * become asynchronous until after this point. And anyhow
+ * if this call was asynchronous then how would you get the
+ * necessary HINTERNET pointer returned by this function.
+ *
+ */
+ res = HTTP_HttpOpenRequestW(lpwhs, lpszVerb, lpszObjectName,
+ lpszVersion, lpszReferrer, lpszAcceptTypes,
+ dwFlags, dwContext, &handle);
+lend:
+ if( lpwhs )
+ WININET_Release( &lpwhs->hdr );
+ TRACE("returning %p\n", handle);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
return handle;
}
/***********************************************************************
* HTTP_HttpQueryInfoW (internal)
*/
-static BOOL HTTP_HttpQueryInfoW(http_request_t *lpwhr, DWORD dwInfoLevel,
- LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+static DWORD HTTP_HttpQueryInfoW(http_request_t *lpwhr, DWORD dwInfoLevel,
+ LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
{
LPHTTPHEADERW lphttpHdr = NULL;
- BOOL bSuccess = FALSE;
BOOL request_only = dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS;
INT requested_index = lpdwIndex ? *lpdwIndex : 0;
DWORD level = (dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK);
switch (level)
{
case HTTP_QUERY_CUSTOM:
- if (!lpBuffer) return FALSE;
+ if (!lpBuffer) return ERROR_INVALID_PARAMETER;
index = HTTP_GetCustomHeaderIndex(lpwhr, lpBuffer, requested_index, request_only);
break;
case HTTP_QUERY_RAW_HEADERS_CRLF:
{
LPWSTR headers;
DWORD len = 0;
- BOOL ret = FALSE;
+ DWORD res = ERROR_INVALID_PARAMETER;
if (request_only)
headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion);
if (len + sizeof(WCHAR) > *lpdwBufferLength)
{
len += sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- ret = FALSE;
+ res = ERROR_INSUFFICIENT_BUFFER;
}
else if (lpBuffer)
{
memcpy(lpBuffer, szCrLf, sizeof(szCrLf));
}
TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR)));
- ret = TRUE;
+ res = ERROR_SUCCESS;
}
*lpdwBufferLength = len;
if (request_only)
HeapFree(GetProcessHeap(), 0, headers);
- return ret;
+ return res;
}
case HTTP_QUERY_RAW_HEADERS:
{
{
HTTP_FreeTokens(ppszRawHeaderLines);
*lpdwBufferLength = (size + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
}
if (pszString)
{
*lpdwBufferLength = size * sizeof(WCHAR);
HTTP_FreeTokens(ppszRawHeaderLines);
- return TRUE;
+ return ERROR_SUCCESS;
}
case HTTP_QUERY_STATUS_TEXT:
if (lpwhr->lpszStatusText)
if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
}
if (lpBuffer)
{
TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
}
*lpdwBufferLength = len * sizeof(WCHAR);
- return TRUE;
+ return ERROR_SUCCESS;
}
break;
case HTTP_QUERY_VERSION:
if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ return ERROR_INSUFFICIENT_BUFFER;
}
if (lpBuffer)
{
TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len));
}
*lpdwBufferLength = len * sizeof(WCHAR);
- return TRUE;
+ return ERROR_SUCCESS;
}
break;
case HTTP_QUERY_CONTENT_ENCODING:
((dwInfoLevel & HTTP_QUERY_FLAG_REQUEST_HEADERS) &&
(~lphttpHdr->wFlags & HDR_ISREQUEST)))
{
- INTERNET_SetLastError(ERROR_HTTP_HEADER_NOT_FOUND);
- return bSuccess;
+ return ERROR_HTTP_HEADER_NOT_FOUND;
}
if (lpdwIndex && level != HTTP_QUERY_STATUS_CODE) (*lpdwIndex)++;
{
*(int *)lpBuffer = atoiW(lphttpHdr->lpszValue);
TRACE(" returning number: %d\n", *(int *)lpBuffer);
- bSuccess = TRUE;
- }
+ }
else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
{
time_t tmpTime;
STHook->wMonth = tmpTM.tm_mon + 1;
STHook->wSecond = tmpTM.tm_sec;
STHook->wYear = tmpTM.tm_year;
- bSuccess = TRUE;
-
+
TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
if (len > *lpdwBufferLength)
{
*lpdwBufferLength = len;
- INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return bSuccess;
+ return ERROR_INSUFFICIENT_BUFFER;
}
if (lpBuffer)
{
memcpy(lpBuffer, lphttpHdr->lpszValue, len);
- TRACE(" returning string: %s\n", debugstr_w(lpBuffer));
+ TRACE("! returning string: %s\n", debugstr_w(lpBuffer));
}
*lpdwBufferLength = len - sizeof(WCHAR);
- bSuccess = TRUE;
}
- return bSuccess;
+ return ERROR_SUCCESS;
}
/***********************************************************************
*
*/
BOOL WINAPI HttpQueryInfoW(HINTERNET hHttpRequest, DWORD dwInfoLevel,
- LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
+ LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex)
{
- BOOL bSuccess = FALSE;
http_request_t *lpwhr;
+ DWORD res;
if (TRACE_ON(wininet)) {
#define FE(x) { x, #x }
DWORD info = dwInfoLevel & HTTP_QUERY_HEADER_MASK;
DWORD i;
- TRACE("(%p, 0x%08x)--> %d\n", hHttpRequest, dwInfoLevel, dwInfoLevel);
+ TRACE("(%p, 0x%08x)--> %d\n", hHttpRequest, dwInfoLevel, info);
TRACE(" Attribute:");
for (i = 0; i < (sizeof(query_flags) / sizeof(query_flags[0])); i++) {
if (query_flags[i].val == info) {
lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
}
if (lpBuffer == NULL)
*lpdwBufferLength = 0;
- bSuccess = HTTP_HttpQueryInfoW( lpwhr, dwInfoLevel,
- lpBuffer, lpdwBufferLength, lpdwIndex);
+ res = HTTP_HttpQueryInfoW( lpwhr, dwInfoLevel,
+ lpBuffer, lpdwBufferLength, lpdwIndex);
lend:
if( lpwhr )
WININET_Release( &lpwhr->hdr );
- TRACE("%d <--\n", bSuccess);
- return bSuccess;
+ TRACE("%u <--\n", res);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
}
/***********************************************************************
}
/***********************************************************************
- * HttpSendRequestExA (WININET.@)
- *
- * Sends the specified request to the HTTP server and allows chunked
- * transfers.
- *
- * RETURNS
- * Success: TRUE
- * Failure: FALSE, call GetLastError() for more information.
+ * HTTP_GetRedirectURL (internal)
*/
-BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
- LPINTERNET_BUFFERSA lpBuffersIn,
- LPINTERNET_BUFFERSA lpBuffersOut,
- DWORD dwFlags, DWORD_PTR dwContext)
+static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
- INTERNET_BUFFERSW BuffersInW;
- BOOL rc = FALSE;
- DWORD headerlen;
- LPWSTR header = NULL;
+ static WCHAR szHttp[] = {'h','t','t','p',0};
+ static WCHAR szHttps[] = {'h','t','t','p','s',0};
+ http_session_t *lpwhs = lpwhr->lpHttpSession;
+ URL_COMPONENTSW urlComponents;
+ DWORD url_length = 0;
+ LPWSTR orig_url;
+ LPWSTR combined_url;
- TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
- lpBuffersOut, dwFlags, dwContext);
+ urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
+ urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
+ urlComponents.dwSchemeLength = 0;
+ urlComponents.lpszHostName = lpwhs->lpszHostName;
+ urlComponents.dwHostNameLength = 0;
+ urlComponents.nPort = lpwhs->nHostPort;
+ urlComponents.lpszUserName = lpwhs->lpszUserName;
+ urlComponents.dwUserNameLength = 0;
+ urlComponents.lpszPassword = NULL;
+ urlComponents.dwPasswordLength = 0;
+ urlComponents.lpszUrlPath = lpwhr->lpszPath;
+ urlComponents.dwUrlPathLength = 0;
+ urlComponents.lpszExtraInfo = NULL;
+ urlComponents.dwExtraInfoLength = 0;
- if (lpBuffersIn)
+ if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ return NULL;
+
+ orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
+
+ /* convert from bytes to characters */
+ url_length = url_length / sizeof(WCHAR) - 1;
+ if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
{
- BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
- if (lpBuffersIn->lpcszHeader)
- {
- headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
- lpBuffersIn->dwHeadersLength,0,0);
- header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
- if (!(BuffersInW.lpcszHeader = header))
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- return FALSE;
- }
- BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
- lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
- header, headerlen);
- }
- else
- BuffersInW.lpcszHeader = NULL;
- BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
- BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
- BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
- BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
- BuffersInW.Next = NULL;
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return NULL;
}
- rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
-
- HeapFree(GetProcessHeap(),0,header);
+ url_length = 0;
+ if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return NULL;
+ }
+ combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
- return rc;
+ if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
+ {
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ HeapFree(GetProcessHeap(), 0, combined_url);
+ return NULL;
+ }
+ HeapFree(GetProcessHeap(), 0, orig_url);
+ return combined_url;
}
+
/***********************************************************************
- * HttpSendRequestExW (WININET.@)
- *
- * Sends the specified request to the HTTP server and allows chunked
- * transfers
- *
- * RETURNS
- * Success: TRUE
- * Failure: FALSE, call GetLastError() for more information.
+ * HTTP_HandleRedirect (internal)
*/
-BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
- LPINTERNET_BUFFERSW lpBuffersIn,
- LPINTERNET_BUFFERSW lpBuffersOut,
- DWORD dwFlags, DWORD_PTR dwContext)
-{
- BOOL ret = FALSE;
- http_request_t *lpwhr;
- http_session_t *lpwhs;
- appinfo_t *hIC;
-
- TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
- lpBuffersOut, dwFlags, dwContext);
-
- lpwhr = (http_request_t*) WININET_GetObject( hRequest );
-
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- goto lend;
- }
-
- lpwhs = lpwhr->lpHttpSession;
- assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
- hIC = lpwhs->lpAppInfo;
- assert(hIC->hdr.htype == WH_HINIT);
-
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST workRequest;
- struct WORKREQ_HTTPSENDREQUESTW *req;
-
- workRequest.asyncproc = AsyncHttpSendRequestProc;
- workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
- req = &workRequest.u.HttpSendRequestW;
- if (lpBuffersIn)
- {
- /* FIXME: this should use dwHeadersLength or may not be necessary at all */
- req->lpszHeader = heap_strdupW(lpBuffersIn->lpcszHeader);
- req->dwHeaderLength = lpBuffersIn->dwHeadersLength;
- req->lpOptional = lpBuffersIn->lpvBuffer;
- req->dwOptionalLength = lpBuffersIn->dwBufferLength;
- req->dwContentLength = lpBuffersIn->dwBufferTotal;
- }
- else
- {
- req->lpszHeader = NULL;
- req->dwHeaderLength = 0;
- req->lpOptional = NULL;
- req->dwOptionalLength = 0;
- req->dwContentLength = 0;
- }
-
- req->bEndRequest = FALSE;
-
- INTERNET_AsyncCall(&workRequest);
- /*
- * This is from windows.
- */
- INTERNET_SetLastError(ERROR_IO_PENDING);
- }
- else
- {
- if (lpBuffersIn)
- ret = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
- lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
- lpBuffersIn->dwBufferTotal, FALSE);
- else
- ret = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
- }
-
-lend:
- if ( lpwhr )
- WININET_Release( &lpwhr->hdr );
-
- TRACE("<---\n");
- return ret;
-}
-
-/***********************************************************************
- * HttpSendRequestW (WININET.@)
- *
- * Sends the specified request to the HTTP server
- *
- * RETURNS
- * TRUE on success
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
- DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
-{
- http_request_t *lpwhr;
- http_session_t *lpwhs = NULL;
- appinfo_t *hIC = NULL;
- BOOL r;
-
- TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
- debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
-
- lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
- if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- lpwhs = lpwhr->lpHttpSession;
- if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- hIC = lpwhs->lpAppInfo;
- if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
- {
- INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
- r = FALSE;
- goto lend;
- }
-
- if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
- {
- WORKREQUEST workRequest;
- struct WORKREQ_HTTPSENDREQUESTW *req;
-
- workRequest.asyncproc = AsyncHttpSendRequestProc;
- workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
- req = &workRequest.u.HttpSendRequestW;
- if (lpszHeaders)
- {
- DWORD size;
-
- if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR);
- else size = dwHeaderLength * sizeof(WCHAR);
-
- req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size);
- memcpy(req->lpszHeader, lpszHeaders, size);
- }
- else
- req->lpszHeader = 0;
- req->dwHeaderLength = dwHeaderLength;
- req->lpOptional = lpOptional;
- req->dwOptionalLength = dwOptionalLength;
- req->dwContentLength = dwOptionalLength;
- req->bEndRequest = TRUE;
-
- INTERNET_AsyncCall(&workRequest);
- /*
- * This is from windows.
- */
- INTERNET_SetLastError(ERROR_IO_PENDING);
- r = FALSE;
- }
- else
- {
- r = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
- dwHeaderLength, lpOptional, dwOptionalLength,
- dwOptionalLength, TRUE);
- }
-lend:
- if( lpwhr )
- WININET_Release( &lpwhr->hdr );
- return r;
-}
-
-/***********************************************************************
- * HttpSendRequestA (WININET.@)
- *
- * Sends the specified request to the HTTP server
- *
- * RETURNS
- * TRUE on success
- * FALSE on failure
- *
- */
-BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
- DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
-{
- BOOL result;
- LPWSTR szHeaders=NULL;
- DWORD nLen=dwHeaderLength;
- if(lpszHeaders!=NULL)
- {
- nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
- szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
- }
- result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
- HeapFree(GetProcessHeap(),0,szHeaders);
- return result;
-}
-
-/***********************************************************************
- * HTTP_GetRedirectURL (internal)
- */
-static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
-{
- static WCHAR szHttp[] = {'h','t','t','p',0};
- static WCHAR szHttps[] = {'h','t','t','p','s',0};
- http_session_t *lpwhs = lpwhr->lpHttpSession;
- URL_COMPONENTSW urlComponents;
- DWORD url_length = 0;
- LPWSTR orig_url;
- LPWSTR combined_url;
-
- urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
- urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
- urlComponents.dwSchemeLength = 0;
- urlComponents.lpszHostName = lpwhs->lpszHostName;
- urlComponents.dwHostNameLength = 0;
- urlComponents.nPort = lpwhs->nHostPort;
- urlComponents.lpszUserName = lpwhs->lpszUserName;
- urlComponents.dwUserNameLength = 0;
- urlComponents.lpszPassword = NULL;
- urlComponents.dwPasswordLength = 0;
- urlComponents.lpszUrlPath = lpwhr->lpszPath;
- urlComponents.dwUrlPathLength = 0;
- urlComponents.lpszExtraInfo = NULL;
- urlComponents.dwExtraInfoLength = 0;
-
- if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
- return NULL;
-
- orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
-
- /* convert from bytes to characters */
- url_length = url_length / sizeof(WCHAR) - 1;
- if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- return NULL;
- }
-
- url_length = 0;
- if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
- (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- return NULL;
- }
- combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
-
- if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
- {
- HeapFree(GetProcessHeap(), 0, orig_url);
- HeapFree(GetProcessHeap(), 0, combined_url);
- return NULL;
- }
- HeapFree(GetProcessHeap(), 0, orig_url);
- return combined_url;
-}
-
-
-/***********************************************************************
- * HTTP_HandleRedirect (internal)
- */
-static BOOL HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
+static DWORD HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
http_session_t *lpwhs = lpwhr->lpHttpSession;
appinfo_t *hIC = lpwhs->lpAppInfo;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
- return FALSE;
+ return INTERNET_GetLastError();
if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) &&
(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
{
if (strcmpiW(lpwhs->lpszServerName, hostName) || lpwhs->nServerPort != urlComponents.nPort)
{
+ DWORD res;
+
HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
lpwhs->lpszServerName = heap_strdupW(hostName);
lpwhs->nServerPort = urlComponents.nPort;
NETCON_close(&lpwhr->netConnection);
- if (!HTTP_ResolveName(lpwhr)) return FALSE;
- if (!NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)) return FALSE;
+ if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS)
+ return res;
+
+ res = NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE);
+ if (res != ERROR_SUCCESS)
+ return res;
+
lpwhr->read_pos = lpwhr->read_size = 0;
lpwhr->read_chunked = FALSE;
}
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
- return TRUE;
+ return ERROR_SUCCESS;
}
/***********************************************************************
return str;
}
-static BOOL HTTP_SecureProxyConnect(http_request_t *lpwhr)
+static DWORD HTTP_SecureProxyConnect(http_request_t *lpwhr)
{
LPWSTR lpszPath;
LPWSTR requestString;
INT cnt;
INT responseLen;
char *ascii_req;
- BOOL ret;
+ DWORD res;
static const WCHAR szConnect[] = {'C','O','N','N','E','C','T',0};
static const WCHAR szFormat[] = {'%','s',':','%','d',0};
http_session_t *lpwhs = lpwhr->lpHttpSession;
TRACE("full request -> %s\n", debugstr_an( ascii_req, len ) );
- ret = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
+ res = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
HeapFree( GetProcessHeap(), 0, ascii_req );
- if (!ret || cnt < 0)
- return FALSE;
+ if (res != ERROR_SUCCESS)
+ return res;
responseLen = HTTP_GetResponseHeaders( lpwhr, TRUE );
if (!responseLen)
- return FALSE;
+ return ERROR_HTTP_INVALID_HEADER;
- return TRUE;
+ return ERROR_SUCCESS;
}
static void HTTP_InsertCookies(http_request_t *lpwhr)
* FALSE on failure
*
*/
-BOOL WINAPI HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
+static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest)
{
INT cnt;
- BOOL bSuccess = FALSE, redirected = FALSE;
+ BOOL redirected = FALSE;
LPWSTR requestString = NULL;
INT responseLen;
BOOL loop_next;
static const WCHAR szContentLength[] =
{ 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
+ DWORD res;
TRACE("--> %p\n", lpwhr);
do
{
DWORD len;
+ BOOL reusing_connection;
char *ascii_req;
loop_next = FALSE;
* for all the data */
HTTP_DrainContent(lpwhr);
lpwhr->dwContentRead = 0;
+ if(redirected) {
+ lpwhr->dwContentLength = ~0u;
+ lpwhr->dwBytesToWrite = 0;
+ }
if (TRACE_ON(wininet))
{
TRACE("Request header -> %s\n", debugstr_w(requestString) );
/* Send the request and store the results */
- if (!HTTP_OpenConnection(lpwhr))
+ if(NETCON_connected(&lpwhr->netConnection))
+ reusing_connection = TRUE;
+ else
+ reusing_connection = FALSE;
+
+ if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS)
goto lend;
/* send the request as ASCII, tack on the optional data */
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
- NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
+ res = NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
HeapFree( GetProcessHeap(), 0, ascii_req );
lpwhr->dwBytesWritten = dwOptionalLength;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
- if (cnt < 0)
+ if (res != ERROR_SUCCESS)
goto lend;
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
- if (responseLen)
- bSuccess = TRUE;
+ /* FIXME: We should know that connection is closed before sending
+ * headers. Otherwise wrong callbacks are executed */
+ if(!responseLen && reusing_connection) {
+ TRACE("Connection closed by server, reconnecting\n");
+ loop_next = TRUE;
+ continue;
+ }
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
dwBufferSize = sizeof(dwStatusCode);
- if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
- &dwStatusCode,&dwBufferSize,NULL))
+ if (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
+ &dwStatusCode,&dwBufferSize,NULL) != ERROR_SUCCESS)
dwStatusCode = 0;
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && responseLen)
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
- if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
- HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
+ if ((dwStatusCode == HTTP_STATUS_REDIRECT ||
+ dwStatusCode == HTTP_STATUS_MOVED ||
+ dwStatusCode == HTTP_STATUS_REDIRECT_METHOD) &&
+ HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL) == ERROR_SUCCESS)
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
{
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
- bSuccess = HTTP_HandleRedirect(lpwhr, new_url);
- if (bSuccess)
+ res = HTTP_HandleRedirect(lpwhr, new_url);
+ if (res == ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, requestString);
loop_next = TRUE;
redirected = TRUE;
}
}
- if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
+ if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && res == ERROR_SUCCESS)
{
WCHAR szAuthValue[2048];
dwBufferSize=2048;
if (dwStatusCode == HTTP_STATUS_DENIED)
{
+ LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
DWORD dwIndex = 0;
- while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
+ while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pAuthInfo,
lpwhr->lpHttpSession->lpszUserName,
- lpwhr->lpHttpSession->lpszPassword))
+ lpwhr->lpHttpSession->lpszPassword,
+ Host->lpszValue))
{
+ HeapFree(GetProcessHeap(), 0, requestString);
loop_next = TRUE;
break;
}
}
+
+ if(!loop_next) {
+ TRACE("Cleaning wrong authorization data\n");
+ destroy_authinfo(lpwhr->pAuthInfo);
+ lpwhr->pAuthInfo = NULL;
+ }
}
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
DWORD dwIndex = 0;
- while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
+ while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex) == ERROR_SUCCESS)
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pProxyAuthInfo,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyUsername,
- lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword))
+ lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword,
+ NULL))
{
loop_next = TRUE;
break;
}
}
+
+ if(!loop_next) {
+ TRACE("Cleaning wrong proxy authorization data\n");
+ destroy_authinfo(lpwhr->pProxyAuthInfo);
+ lpwhr->pProxyAuthInfo = NULL;
+ }
}
}
}
else
- bSuccess = TRUE;
+ res = ERROR_SUCCESS;
}
while (loop_next);
- if(bSuccess) {
- WCHAR url[INTERNET_MAX_URL_LENGTH];
- WCHAR cacheFileName[MAX_PATH+1];
- BOOL b;
+ if(res == ERROR_SUCCESS) {
+ WCHAR url[INTERNET_MAX_URL_LENGTH];
+ WCHAR cacheFileName[MAX_PATH+1];
+ BOOL b;
+
+ b = HTTP_GetRequestURL(lpwhr, url);
+ if(!b) {
+ WARN("Could not get URL\n");
+ goto lend;
+ }
+
+ b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0);
+ if(b) {
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+ CloseHandle(lpwhr->hCacheFile);
+
+ lpwhr->lpszCacheFile = heap_strdupW(cacheFileName);
+ lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) {
+ WARN("Could not create file: %u\n", GetLastError());
+ lpwhr->hCacheFile = NULL;
+ }
+ }else {
+ WARN("Could not create cache entry: %08x\n", GetLastError());
+ }
+ }
+
+lend:
+
+ HeapFree(GetProcessHeap(), 0, requestString);
+
+ /* TODO: send notification for P3P header */
+
+ if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ if (res == ERROR_SUCCESS && lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite)
+ HTTP_ReceiveRequestData(lpwhr, TRUE);
+ else
+ {
+ iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
+ iar.dwError = res;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+ }
+ }
+
+ TRACE("<--\n");
+ return res;
+}
+
+/***********************************************************************
+ *
+ * Helper functions for the HttpSendRequest(Ex) functions
+ *
+ */
+static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
+{
+ struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
+ http_request_t *lpwhr = (http_request_t*) workRequest->hdr;
+
+ TRACE("%p\n", lpwhr);
+
+ HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
+ req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
+ req->dwContentLength, req->bEndRequest);
+
+ HeapFree(GetProcessHeap(), 0, req->lpszHeader);
+}
+
+
+static DWORD HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ INT responseLen;
+ DWORD dwBufferSize;
+ INTERNET_ASYNC_RESULT iar;
+ DWORD res = ERROR_SUCCESS;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+
+ responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
+ if (!responseLen)
+ res = ERROR_HTTP_HEADER_NOT_FOUND;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
+
+ /* process cookies here. Is this right? */
+ HTTP_ProcessCookies(lpwhr);
+
+ if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
+
+ 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) == ERROR_SUCCESS
+ && (dwCode == 302 || dwCode == 301 || dwCode == 303))
+ {
+ WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
+ dwBufferSize=sizeof(szNewLocation);
+ if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL) == ERROR_SUCCESS)
+ {
+ if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
+ {
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
+ lpwhr->lpszVerb = heap_strdupW(szGET);
+ }
+ HTTP_DrainContent(lpwhr);
+ if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
+ {
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
+ new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
+ res = HTTP_HandleRedirect(lpwhr, new_url);
+ if (res == ERROR_SUCCESS)
+ res = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
+ HeapFree( GetProcessHeap(), 0, new_url );
+ }
+ }
+ }
+ }
+
+ iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
+ iar.dwError = res;
+
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_REQUEST_COMPLETE, &iar,
+ sizeof(INTERNET_ASYNC_RESULT));
+ return res;
+}
+
+/***********************************************************************
+ * HttpEndRequestA (WININET.@)
+ *
+ * Ends an HTTP request that was started by HttpSendRequestEx
+ *
+ * RETURNS
+ * TRUE if successful
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
+ LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+
+ if (lpBuffersOut)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
+}
+
+static void AsyncHttpEndRequestProc(WORKREQUEST *work)
+{
+ struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW;
+ http_request_t *lpwhr = (http_request_t*)work->hdr;
+
+ TRACE("%p\n", lpwhr);
+
+ HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
+}
+
+/***********************************************************************
+ * HttpEndRequestW (WININET.@)
+ *
+ * Ends an HTTP request that was started by HttpSendRequestEx
+ *
+ * RETURNS
+ * TRUE if successful
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
+ LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_request_t *lpwhr;
+ DWORD res;
+
+ TRACE("-->\n");
+
+ if (lpBuffersOut)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+ if (lpwhr)
+ WININET_Release( &lpwhr->hdr );
+ return FALSE;
+ }
+ lpwhr->hdr.dwFlags |= dwFlags;
+
+ if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST work;
+ struct WORKREQ_HTTPENDREQUESTW *request;
+
+ work.asyncproc = AsyncHttpEndRequestProc;
+ work.hdr = WININET_AddRef( &lpwhr->hdr );
+
+ request = &work.u.HttpEndRequestW;
+ request->dwFlags = dwFlags;
+ request->dwContext = dwContext;
+
+ INTERNET_AsyncCall(&work);
+ res = ERROR_IO_PENDING;
+ }
+ else
+ res = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
+
+ WININET_Release( &lpwhr->hdr );
+ TRACE("%u <--\n", res);
+ if(res != ERROR_SUCCESS)
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * HttpSendRequestExA (WININET.@)
+ *
+ * Sends the specified request to the HTTP server and allows chunked
+ * transfers.
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE, call GetLastError() for more information.
+ */
+BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
+ LPINTERNET_BUFFERSA lpBuffersIn,
+ LPINTERNET_BUFFERSA lpBuffersOut,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ INTERNET_BUFFERSW BuffersInW;
+ BOOL rc = FALSE;
+ DWORD headerlen;
+ LPWSTR header = NULL;
+
+ TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
+ lpBuffersOut, dwFlags, dwContext);
+
+ if (lpBuffersIn)
+ {
+ BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
+ if (lpBuffersIn->lpcszHeader)
+ {
+ headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
+ lpBuffersIn->dwHeadersLength,0,0);
+ header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
+ if (!(BuffersInW.lpcszHeader = header))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
+ lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
+ header, headerlen);
+ }
+ else
+ BuffersInW.lpcszHeader = NULL;
+ BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
+ BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
+ BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
+ BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
+ BuffersInW.Next = NULL;
+ }
+
+ rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
+
+ HeapFree(GetProcessHeap(),0,header);
+
+ return rc;
+}
+
+/***********************************************************************
+ * HttpSendRequestExW (WININET.@)
+ *
+ * Sends the specified request to the HTTP server and allows chunked
+ * transfers
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE, call GetLastError() for more information.
+ */
+BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
+ LPINTERNET_BUFFERSW lpBuffersIn,
+ LPINTERNET_BUFFERSW lpBuffersOut,
+ DWORD dwFlags, DWORD_PTR dwContext)
+{
+ http_request_t *lpwhr;
+ http_session_t *lpwhs;
+ appinfo_t *hIC;
+ DWORD res;
+
+ TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
+ lpBuffersOut, dwFlags, dwContext);
+
+ lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ lpwhs = lpwhr->lpHttpSession;
+ assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
+ hIC = lpwhs->lpAppInfo;
+ assert(hIC->hdr.htype == WH_HINIT);
+
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ {
+ WORKREQUEST workRequest;
+ struct WORKREQ_HTTPSENDREQUESTW *req;
+
+ workRequest.asyncproc = AsyncHttpSendRequestProc;
+ workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
+ req = &workRequest.u.HttpSendRequestW;
+ if (lpBuffersIn)
+ {
+ DWORD size = 0;
- b = HTTP_GetRequestURL(lpwhr, url);
- if(!b) {
- WARN("Could not get URL\n");
- goto lend;
- }
+ if (lpBuffersIn->lpcszHeader)
+ {
+ if (lpBuffersIn->dwHeadersLength == ~0u)
+ size = (strlenW( lpBuffersIn->lpcszHeader ) + 1) * sizeof(WCHAR);
+ else
+ size = lpBuffersIn->dwHeadersLength * sizeof(WCHAR);
- b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0);
- if(b) {
- lpwhr->lpszCacheFile = heap_strdupW(cacheFileName);
- lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) {
- WARN("Could not create file: %u\n", GetLastError());
- lpwhr->hCacheFile = NULL;
+ req->lpszHeader = HeapAlloc( GetProcessHeap(), 0, size );
+ memcpy( req->lpszHeader, lpBuffersIn->lpcszHeader, size );
}
- }else {
- WARN("Could not create cache entry: %08x\n", GetLastError());
+ else req->lpszHeader = NULL;
+
+ req->dwHeaderLength = size / sizeof(WCHAR);
+ req->lpOptional = lpBuffersIn->lpvBuffer;
+ req->dwOptionalLength = lpBuffersIn->dwBufferLength;
+ req->dwContentLength = lpBuffersIn->dwBufferTotal;
}
+ else
+ {
+ req->lpszHeader = NULL;
+ req->dwHeaderLength = 0;
+ req->lpOptional = NULL;
+ req->dwOptionalLength = 0;
+ req->dwContentLength = 0;
+ }
+
+ req->bEndRequest = FALSE;
+
+ INTERNET_AsyncCall(&workRequest);
+ /*
+ * This is from windows.
+ */
+ res = ERROR_IO_PENDING;
+ }
+ else
+ {
+ if (lpBuffersIn)
+ res = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
+ lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
+ lpBuffersIn->dwBufferTotal, FALSE);
+ else
+ res = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
}
lend:
+ if ( lpwhr )
+ WININET_Release( &lpwhr->hdr );
- HeapFree(GetProcessHeap(), 0, requestString);
+ TRACE("<---\n");
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
- /* TODO: send notification for P3P header */
+/***********************************************************************
+ * HttpSendRequestW (WININET.@)
+ *
+ * Sends the specified request to the HTTP server
+ *
+ * RETURNS
+ * TRUE on success
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
+ DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+{
+ http_request_t *lpwhr;
+ http_session_t *lpwhs = NULL;
+ appinfo_t *hIC = NULL;
+ DWORD res = ERROR_SUCCESS;
- if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+ TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
+ debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
+
+ lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
+ if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ lpwhs = lpwhr->lpHttpSession;
+ if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ hIC = lpwhs->lpAppInfo;
+ if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
+ {
+ res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
+ goto lend;
+ }
+
+ if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
- if (bSuccess)
+ WORKREQUEST workRequest;
+ struct WORKREQ_HTTPSENDREQUESTW *req;
+
+ workRequest.asyncproc = AsyncHttpSendRequestProc;
+ workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
+ req = &workRequest.u.HttpSendRequestW;
+ if (lpszHeaders)
{
- if (lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite) HTTP_ReceiveRequestData(lpwhr, TRUE);
- else
- {
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = 0;
+ DWORD size;
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
- }
+ if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR);
+ else size = dwHeaderLength * sizeof(WCHAR);
+
+ req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size);
+ memcpy(req->lpszHeader, lpszHeaders, size);
}
else
- {
- iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
- iar.dwError = INTERNET_GetLastError();
+ req->lpszHeader = 0;
+ req->dwHeaderLength = dwHeaderLength;
+ req->lpOptional = lpOptional;
+ req->dwOptionalLength = dwOptionalLength;
+ req->dwContentLength = dwOptionalLength;
+ req->bEndRequest = TRUE;
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_REQUEST_COMPLETE, &iar,
- sizeof(INTERNET_ASYNC_RESULT));
- }
+ INTERNET_AsyncCall(&workRequest);
+ /*
+ * This is from windows.
+ */
+ res = ERROR_IO_PENDING;
+ }
+ else
+ {
+ res = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
+ dwHeaderLength, lpOptional, dwOptionalLength,
+ dwOptionalLength, TRUE);
}
+lend:
+ if( lpwhr )
+ WININET_Release( &lpwhr->hdr );
- TRACE("<--\n");
- if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS);
- return bSuccess;
+ SetLastError(res);
+ return res == ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * HttpSendRequestA (WININET.@)
+ *
+ * Sends the specified request to the HTTP server
+ *
+ * RETURNS
+ * TRUE on success
+ * FALSE on failure
+ *
+ */
+BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
+ DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
+{
+ BOOL result;
+ LPWSTR szHeaders=NULL;
+ DWORD nLen=dwHeaderLength;
+ if(lpszHeaders!=NULL)
+ {
+ nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
+ szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
+ }
+ result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
+ HeapFree(GetProcessHeap(),0,szHeaders);
+ return result;
}
/***********************************************************************
return ERROR_SUCCESS;
}
- return INET_QueryOption(option, buffer, size, unicode);
+ return INET_QueryOption(hdr, option, buffer, size, unicode);
}
static DWORD HTTPSESSION_SetOption(object_header_t *hdr, DWORD option, void *buffer, DWORD size)
* NULL on failure
*
*/
-HINTERNET HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
- INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
- LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
- DWORD dwInternalFlags)
+DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
+ INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
+ LPCWSTR lpszPassword, DWORD dwFlags, DWORD_PTR dwContext,
+ DWORD dwInternalFlags, HINTERNET *ret)
{
http_session_t *lpwhs = NULL;
HINTERNET handle = NULL;
+ DWORD res = ERROR_SUCCESS;
TRACE("-->\n");
if (!lpszServerName || !lpszServerName[0])
- {
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
- goto lerror;
- }
+ return ERROR_INVALID_PARAMETER;
assert( hIC->hdr.htype == WH_HINIT );
lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(http_session_t));
- if (NULL == lpwhs)
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- goto lerror;
- }
+ if (!lpwhs)
+ return ERROR_OUTOFMEMORY;
/*
* According to my tests. The name is not resolved until a request is sent
if (NULL == handle)
{
ERR("Failed to alloc handle\n");
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- goto lerror;
+ res = ERROR_OUTOFMEMORY;
+ goto lerror;
}
if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
- if(strchrW(hIC->lpszProxy, ' '))
- FIXME("Several proxies not implemented.\n");
if(hIC->lpszProxyBypass)
FIXME("Proxy bypass is ignored.\n");
}
- if (lpszServerName && lpszServerName[0])
- {
- lpwhs->lpszServerName = heap_strdupW(lpszServerName);
- lpwhs->lpszHostName = heap_strdupW(lpszServerName);
- }
+ lpwhs->lpszServerName = heap_strdupW(lpszServerName);
+ lpwhs->lpszHostName = heap_strdupW(lpszServerName);
if (lpszUserName && lpszUserName[0])
lpwhs->lpszUserName = heap_strdupW(lpszUserName);
if (lpszPassword && lpszPassword[0])
*/
TRACE("%p --> %p (%p)\n", hIC, handle, lpwhs);
- return handle;
+
+ if(res == ERROR_SUCCESS)
+ *ret = handle;
+ return res;
}
* TRUE on success
* FALSE on failure
*/
-static BOOL HTTP_OpenConnection(http_request_t *lpwhr)
+static DWORD HTTP_OpenConnection(http_request_t *lpwhr)
{
- BOOL bSuccess = FALSE;
http_session_t *lpwhs;
appinfo_t *hIC = NULL;
char szaddr[INET6_ADDRSTRLEN];
const void *addr;
+ DWORD res = ERROR_SUCCESS;
TRACE("-->\n");
if (lpwhr->hdr.htype != WH_HHTTPREQ)
{
- INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+ res = ERROR_INVALID_PARAMETER;
goto lend;
}
if (NETCON_connected(&lpwhr->netConnection))
- {
- bSuccess = TRUE;
goto lend;
- }
- if (!HTTP_ResolveName(lpwhr)) goto lend;
+ if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS) goto lend;
lpwhs = lpwhr->lpHttpSession;
break;
default:
WARN("unsupported family %d\n", lpwhs->socketAddress.ss_family);
- INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
- return FALSE;
+ return ERROR_INTERNET_NAME_NOT_RESOLVED;
}
inet_ntop(lpwhs->socketAddress.ss_family, addr, szaddr, sizeof(szaddr));
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
szaddr,
strlen(szaddr)+1);
- if (!NETCON_create(&lpwhr->netConnection, lpwhs->socketAddress.ss_family,
- SOCK_STREAM, 0))
+ res = NETCON_create(&lpwhr->netConnection, lpwhs->socketAddress.ss_family, SOCK_STREAM, 0);
+ if (res != ERROR_SUCCESS)
{
- WARN("Socket creation failed: %u\n", INTERNET_GetLastError());
+ WARN("Socket creation failed: %u\n", res);
goto lend;
}
- if (!NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
- lpwhs->sa_len))
+ res = NETCON_connect(&lpwhr->netConnection, (struct sockaddr *)&lpwhs->socketAddress,
+ lpwhs->sa_len);
+ if(res != ERROR_SUCCESS)
goto lend;
+ INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+ INTERNET_STATUS_CONNECTED_TO_SERVER,
+ szaddr, strlen(szaddr)+1);
+
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE)
{
/* Note: we differ from Microsoft's WinINet here. they seem to have
* behaviour to be more correct and to not cause any incompatibilities
* because using a secure connection through a proxy server is a rare
* case that would be hard for anyone to depend on */
- if (hIC->lpszProxy && !HTTP_SecureProxyConnect(lpwhr))
+ if (hIC->lpszProxy && (res = HTTP_SecureProxyConnect(lpwhr)) != ERROR_SUCCESS) {
+ HTTPREQ_CloseConnection(&lpwhr->hdr);
goto lend;
+ }
- if (!NETCON_secure_connect(&lpwhr->netConnection, lpwhs->lpszHostName))
+ res = NETCON_secure_connect(&lpwhr->netConnection, lpwhs->lpszHostName);
+ if(res != ERROR_SUCCESS)
{
WARN("Couldn't connect securely to host\n");
+
+ if((lpwhr->hdr.ErrorMask&INTERNET_ERROR_MASK_COMBINED_SEC_CERT) && (
+ res == ERROR_INTERNET_SEC_CERT_DATE_INVALID
+ || res == ERROR_INTERNET_INVALID_CA
+ || res == ERROR_INTERNET_SEC_CERT_NO_REV
+ || res == ERROR_INTERNET_SEC_CERT_REV_FAILED
+ || res == ERROR_INTERNET_SEC_CERT_REVOKED
+ || res == ERROR_INTERNET_SEC_INVALID_CERT
+ || res == ERROR_INTERNET_SEC_CERT_CN_INVALID))
+ res = ERROR_INTERNET_SEC_CERT_ERRORS;
+
+ HTTPREQ_CloseConnection(&lpwhr->hdr);
goto lend;
}
}
- INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
- INTERNET_STATUS_CONNECTED_TO_SERVER,
- szaddr, strlen(szaddr)+1);
-
- bSuccess = TRUE;
lend:
lpwhr->read_pos = lpwhr->read_size = 0;
lpwhr->read_chunked = FALSE;
- TRACE("%d <--\n", bSuccess);
- return bSuccess;
+ TRACE("%d <--\n", res);
+ return res;
}
char bufferA[MAX_REPLY_LEN];
LPWSTR status_code = NULL, status_text = NULL;
DWORD cchMaxRawHeaders = 1024;
- LPWSTR lpszRawHeaders = HeapAlloc(GetProcessHeap(), 0, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+ LPWSTR lpszRawHeaders = NULL;
LPWSTR temp;
DWORD cchRawHeaders = 0;
BOOL codeHundred = FALSE;
TRACE("-->\n");
- /* clear old response headers (eg. from a redirect response) */
- if (clear) HTTP_clear_response_headers( lpwhr );
-
if (!NETCON_connected(&lpwhr->netConnection))
goto lend;
buflen = MAX_REPLY_LEN;
if (!read_line(lpwhr, bufferA, &buflen))
goto lend;
+
+ /* clear old response headers (eg. from a redirect response) */
+ if (clear) {
+ HTTP_clear_response_headers( lpwhr );
+ clear = FALSE;
+ }
+
rc += buflen;
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
/* check is this a status code line? */
}
else if (!codeHundred)
{
- FIXME("Non status line at head of response (%s)\n",debugstr_w(buffer));
+ WARN("No status line at head of response (%s)\n", debugstr_w(buffer));
+
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszVersion);
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszStatusText);
+
+ lpwhr->lpszVersion = heap_strdupW(g_szHttp1_0);
+ lpwhr->lpszStatusText = heap_strdupW(szOK);
+
+ HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
+ lpwhr->lpszRawHeaders = heap_strdupW(szDefaultHeader);
+
+ bSuccess = TRUE;
goto lend;
}
} while (codeHundred);
*(status_text-1) = ' ';
/* regenerate raw headers */
+ lpszRawHeaders = HeapAlloc(GetProcessHeap(), 0, (cchMaxRawHeaders + 1) * sizeof(WCHAR));
+ if (!lpszRawHeaders) goto lend;
+
while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
cchMaxRawHeaders *= 2;
temp = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
}
}
-
-static void strip_spaces(LPWSTR start)
-{
- LPWSTR str = start;
- LPWSTR end;
-
- while (*str == ' ' && *str != '\0')
- str++;
-
- if (str != start)
- memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
-
- end = start + strlenW(start) - 1;
- while (end >= start && *end == ' ')
- {
- *end = '\0';
- end--;
- }
-}
-
-
/***********************************************************************
* HTTP_InterpretHttpHeader (internal)
*
#define COALESCEFLAGS (HTTP_ADDHDR_FLAG_COALESCE|HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA|HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
-static BOOL HTTP_ProcessHeader(http_request_t *lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
+static DWORD HTTP_ProcessHeader(http_request_t *lpwhr, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
{
LPHTTPHEADERW lphttpHdr = NULL;
- BOOL bSuccess = FALSE;
INT index = -1;
BOOL request_only = dwModifier & HTTP_ADDHDR_FLAG_REQ;
+ DWORD res = ERROR_HTTP_INVALID_HEADER;
TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), dwModifier);
if (index >= 0)
{
if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
- {
- return FALSE;
- }
+ return ERROR_HTTP_INVALID_HEADER;
lphttpHdr = &lpwhr->pCustHeaders[index];
}
else if (value)
return HTTP_InsertCustomHeader(lpwhr, &hdr);
}
/* no value to delete */
- else return TRUE;
+ else return ERROR_SUCCESS;
if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
lphttpHdr->wFlags |= HDR_ISREQUEST;
return HTTP_InsertCustomHeader(lpwhr, &hdr);
}
- return TRUE;
+ return ERROR_SUCCESS;
}
else if (dwModifier & COALESCEFLAGS)
{
memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
lphttpHdr->lpszValue[len] = '\0';
- bSuccess = TRUE;
+ res = ERROR_SUCCESS;
}
else
{
WARN("HeapReAlloc (%d bytes) failed\n",len+1);
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+ res = ERROR_OUTOFMEMORY;
}
}
- TRACE("<-- %d\n",bSuccess);
- return bSuccess;
+ TRACE("<-- %d\n", res);
+ return res;
}
{
DWORD index;
- TRACE("%s\n", debugstr_w(lpszField));
+ TRACE("%s, %d, %d\n", debugstr_w(lpszField), requested_index, request_only);
for (index = 0; index < lpwhr->nCustHeaders; index++)
{
* Insert header into array
*
*/
-static BOOL HTTP_InsertCustomHeader(http_request_t *lpwhr, LPHTTPHEADERW lpHdr)
+static DWORD HTTP_InsertCustomHeader(http_request_t *lpwhr, LPHTTPHEADERW lpHdr)
{
INT count;
LPHTTPHEADERW lph = NULL;
- BOOL r = FALSE;
TRACE("--> %s: %s\n", debugstr_w(lpHdr->lpszField), debugstr_w(lpHdr->lpszValue));
count = lpwhr->nCustHeaders + 1;
else
lph = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HTTPHEADERW) * count);
- if (NULL != lph)
- {
- lpwhr->pCustHeaders = lph;
- lpwhr->pCustHeaders[count-1].lpszField = heap_strdupW(lpHdr->lpszField);
- lpwhr->pCustHeaders[count-1].lpszValue = heap_strdupW(lpHdr->lpszValue);
- lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
- lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
- lpwhr->nCustHeaders++;
- r = TRUE;
- }
- else
- {
- INTERNET_SetLastError(ERROR_OUTOFMEMORY);
- }
+ if (!lph)
+ return ERROR_OUTOFMEMORY;
- return r;
+ lpwhr->pCustHeaders = lph;
+ lpwhr->pCustHeaders[count-1].lpszField = heap_strdupW(lpHdr->lpszField);
+ lpwhr->pCustHeaders[count-1].lpszValue = heap_strdupW(lpHdr->lpszValue);
+ lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags;
+ lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount;
+ lpwhr->nCustHeaders++;
+
+ return ERROR_SUCCESS;
}
{
/* Accept-Encoding is stripped from HTTP/1.0 requests. It is invalid */
if (!strcmpW(lpwhr->lpszVersion, g_szHttp1_0) && !strcmpiW(field, szAccept_Encoding))
- return FALSE;
+ return ERROR_HTTP_INVALID_HEADER;
- return TRUE;
+ return ERROR_SUCCESS;
}
/***********************************************************************
FIXME("STUB: flags=%d host=%s length=%d\n",flags,szHost,length);
return FALSE;
}
+
+/***********************************************************************
+ * InternetShowSecurityInfoByURLA (@)
+ */
+BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
+{
+ FIXME("stub: %s %p\n", url, window);
+ return FALSE;
+}
+
+/***********************************************************************
+ * InternetShowSecurityInfoByURLW (@)
+ */
+BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
+{
+ FIXME("stub: %s %p\n", debugstr_w(url), window);
+ return FALSE;
+}