diff --git a/reactos/dll/win32/wininet/cookie.c b/reactos/dll/win32/wininet/cookie.c index 75cf049308b..7dfd2a82a8d 100644 --- a/reactos/dll/win32/wininet/cookie.c +++ b/reactos/dll/win32/wininet/cookie.c @@ -431,7 +431,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST value = data = heap_strdupW(cookie_data); if (!data) { - ERR("could not allocate %zu bytes for the cookie data buffer\n", (strlenW(cookie_data) + 1) * sizeof(WCHAR)); + ERR("could not allocate the cookie data buffer\n"); return FALSE; } @@ -457,7 +457,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST if (value == NULL) { HeapFree(GetProcessHeap(), 0, data); - ERR("could not allocate %zu bytes for the cookie value buffer\n", (ptr - data) * sizeof(WCHAR)); + ERR("could not allocate the cookie value buffer\n"); return FALSE; } strcpyW(value, data); diff --git a/reactos/dll/win32/wininet/http.c b/reactos/dll/win32/wininet/http.c index d14a52281e7..324f6c5f535 100644 --- a/reactos/dll/win32/wininet/http.c +++ b/reactos/dll/win32/wininet/http.c @@ -181,7 +181,7 @@ struct gzip_stream_t { BOOL end_of_data; }; -typedef struct _authorizationData +typedef struct _basicAuthorizationData { struct list entry; @@ -189,9 +189,24 @@ typedef struct _authorizationData 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 = @@ -572,13 +587,13 @@ static void destroy_authinfo( struct HttpAuthInfo *authinfo ) static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data) { - authorizationData *ad; + 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, authorizationData, entry) + LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, basicAuthorizationData, entry) { if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm)) { @@ -596,14 +611,14 @@ static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len) { struct list *cursor; - authorizationData* ad = NULL; + 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) { - authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry); + basicAuthorizationData *check = LIST_ENTRY(cursor,basicAuthorizationData,entry); if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm)) { ad = check; @@ -621,7 +636,7 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data } else { - ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData)); + ad = HeapAlloc(GetProcessHeap(),0,sizeof(basicAuthorizationData)); ad->lpszwHost = heap_strdupW(host); ad->lpszwRealm = heap_strdupW(realm); ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len); @@ -633,6 +648,95 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data 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, @@ -707,7 +811,11 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue, 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; @@ -717,6 +825,13 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue, 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; @@ -1426,6 +1541,20 @@ static DWORD HTTP_ResolveName(http_request_t *lpwhr) 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; +} + /*********************************************************************** * HTTPREQ_Destroy (internal) @@ -1440,9 +1569,19 @@ static void HTTPREQ_Destroy(object_header_t *hdr) 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 ); @@ -1493,20 +1632,6 @@ static void HTTPREQ_CloseConnection(object_header_t *hdr) 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]; @@ -1567,18 +1692,25 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe 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; } @@ -1696,60 +1828,34 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe 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; } @@ -1764,6 +1870,17 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer, http_request_t *req = (http_request_t*)hdr; switch(option) { + 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"); @@ -1970,6 +2087,9 @@ static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync, 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; @@ -2125,7 +2245,18 @@ done: 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) @@ -2152,7 +2283,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer 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)); @@ -2162,7 +2293,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer 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; @@ -2172,6 +2303,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer { res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength, FALSE); + size = buffers->dwBufferLength; LeaveCriticalSection( &req->read_section ); goto done; } @@ -2187,17 +2319,52 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer 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) @@ -2225,7 +2392,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer { 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)); @@ -2245,6 +2412,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer { res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength, FALSE); + size = buffers->dwBufferLength; LeaveCriticalSection( &req->read_section ); goto done; } @@ -2260,17 +2428,52 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer 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 DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written) @@ -3456,6 +3659,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, do { DWORD len; + BOOL reusing_connection; char *ascii_req; loop_next = FALSE; @@ -3506,6 +3710,11 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, TRACE("Request header -> %s\n", debugstr_w(requestString) ); /* Send the request and store the results */ + if(NETCON_connected(&lpwhr->netConnection)) + reusing_connection = TRUE; + else + reusing_connection = FALSE; + if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS) goto lend; @@ -3547,6 +3756,13 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, goto lend; responseLen = HTTP_GetResponseHeaders(lpwhr, 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, @@ -3565,7 +3781,9 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, { WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH]; dwBufferSize=sizeof(szNewLocation); - if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) && + 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)) @@ -3610,6 +3828,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, break; } } + + if(!loop_next) { + TRACE("Cleaning wrong authorization data\n"); + destroy_authinfo(lpwhr->pAuthInfo); + lpwhr->pAuthInfo = NULL; + } } if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ) { @@ -3626,6 +3850,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders, break; } } + + if(!loop_next) { + TRACE("Cleaning wrong proxy authorization data\n"); + destroy_authinfo(lpwhr->pProxyAuthInfo); + lpwhr->pProxyAuthInfo = NULL; + } } } } @@ -3674,7 +3904,7 @@ lend: HTTP_ReceiveRequestData(lpwhr, TRUE); else { - iar.dwResult = 0; + iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0); iar.dwError = res; INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, @@ -3758,7 +3988,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PT } } - iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet; + iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0); iar.dwError = res; INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, @@ -4459,9 +4689,6 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear) 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; @@ -4473,6 +4700,13 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear) 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? */ diff --git a/reactos/dll/win32/wininet/internet.c b/reactos/dll/win32/wininet/internet.c index 001736001a4..89337ac6d1a 100644 --- a/reactos/dll/win32/wininet/internet.c +++ b/reactos/dll/win32/wininet/internet.c @@ -3569,8 +3569,8 @@ LPSTR INTERNET_GetResponseBuffer(void) LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) { - struct timeval tv; fd_set infd; + struct timeval tv; BOOL bSuccess = FALSE; INT nRecv = 0; LPSTR lpszBuffer = INTERNET_GetResponseBuffer(); @@ -3578,13 +3578,13 @@ LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) TRACE("\n"); FD_ZERO(&infd); - FD_SET(nSocket, &infd); - tv.tv_sec=RESPONSE_TIMEOUT; - tv.tv_usec=0; + FD_SET(nSocket,&infd); + tv.tv_sec = RESPONSE_TIMEOUT; + tv.tv_usec = 0; while (nRecv < MAX_REPLY_LEN) { - if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0) + if (select(0, &infd, NULL, NULL, &tv) > 0) { if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0) { diff --git a/reactos/dll/win32/wininet/internet.h b/reactos/dll/win32/wininet/internet.h index d675f0fd3ba..1b9aff25547 100644 --- a/reactos/dll/win32/wininet/internet.h +++ b/reactos/dll/win32/wininet/internet.h @@ -53,6 +53,7 @@ typedef struct BOOL useSSL; int socketFD; void *ssl_s; + DWORD security_flags; } WININET_NETCONNECTION; static inline LPWSTR heap_strdupW(LPCWSTR str) @@ -71,6 +72,27 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) return ret; } +static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len) +{ + LPWSTR ret; + UINT len; + + if(!str) + return NULL; + + for(len=0; len +# include #undef FAR #undef DSA #endif @@ -113,10 +114,15 @@ static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 }; static void *OpenSSL_ssl_handle; static void *OpenSSL_crypto_handle; +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER> 0x1000000) +static const SSL_METHOD *meth; +#else static SSL_METHOD *meth; +#endif static SSL_CTX *ctx; static int hostname_idx; static int error_idx; +static int conn_idx; #define MAKE_FUNCPTR(f) static typeof(f) * p##f @@ -139,12 +145,13 @@ MAKE_FUNCPTR(SSL_get_ex_new_index); MAKE_FUNCPTR(SSL_get_ex_data); MAKE_FUNCPTR(SSL_set_ex_data); MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx); -MAKE_FUNCPTR(SSL_get_verify_result); MAKE_FUNCPTR(SSL_get_peer_certificate); MAKE_FUNCPTR(SSL_CTX_get_timeout); MAKE_FUNCPTR(SSL_CTX_set_timeout); MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths); MAKE_FUNCPTR(SSL_CTX_set_verify); +MAKE_FUNCPTR(SSL_get_current_cipher); +MAKE_FUNCPTR(SSL_CIPHER_get_bits); MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data); /* OpenSSL's libcrypto functions that we use */ @@ -214,7 +221,7 @@ static PCCERT_CONTEXT X509_to_cert_context(X509 *cert) } static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store, - WCHAR *server) + WCHAR *server, DWORD security_flags) { BOOL ret; CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } }; @@ -231,38 +238,58 @@ static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store, { if (chain->TrustStatus.dwErrorStatus) { + static const DWORD supportedErrors = + CERT_TRUST_IS_NOT_TIME_VALID | + CERT_TRUST_IS_UNTRUSTED_ROOT | + CERT_TRUST_IS_OFFLINE_REVOCATION | + CERT_TRUST_REVOCATION_STATUS_UNKNOWN | + CERT_TRUST_IS_REVOKED | + CERT_TRUST_IS_NOT_VALID_FOR_USAGE; + if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID) err = ERROR_INTERNET_SEC_CERT_DATE_INVALID; else if (chain->TrustStatus.dwErrorStatus & - CERT_TRUST_IS_UNTRUSTED_ROOT) + CERT_TRUST_IS_UNTRUSTED_ROOT && + !(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) err = ERROR_INTERNET_INVALID_CA; - else if ((chain->TrustStatus.dwErrorStatus & + else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) && + ((chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_OFFLINE_REVOCATION) || - (chain->TrustStatus.dwErrorStatus & - CERT_TRUST_REVOCATION_STATUS_UNKNOWN)) + (chain->TrustStatus.dwErrorStatus & + CERT_TRUST_REVOCATION_STATUS_UNKNOWN))) err = ERROR_INTERNET_SEC_CERT_NO_REV; - else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED) + else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) && + (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)) err = ERROR_INTERNET_SEC_CERT_REVOKED; - else if (chain->TrustStatus.dwErrorStatus & - CERT_TRUST_IS_NOT_VALID_FOR_USAGE) + else if (!(security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE) && + (chain->TrustStatus.dwErrorStatus & + CERT_TRUST_IS_NOT_VALID_FOR_USAGE)) err = ERROR_INTERNET_SEC_INVALID_CERT; - else + else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) err = ERROR_INTERNET_SEC_INVALID_CERT; } - else + if (!err) { CERT_CHAIN_POLICY_PARA policyPara; SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara; CERT_CHAIN_POLICY_STATUS policyStatus; + CERT_CHAIN_CONTEXT chainCopy; + /* Clear chain->TrustStatus.dwErrorStatus so + * CertVerifyCertificateChainPolicy will verify additional checks + * rather than stopping with an existing, ignored error. + */ + memcpy(&chainCopy, chain, sizeof(chainCopy)); + chainCopy.TrustStatus.dwErrorStatus = 0; sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara); sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER; sslExtraPolicyPara.pwszServerName = server; + sslExtraPolicyPara.fdwChecks = security_flags; policyPara.cbSize = sizeof(policyPara); policyPara.dwFlags = 0; policyPara.pvExtraPolicyPara = &sslExtraPolicyPara; ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, - chain, &policyPara, &policyStatus); + &chainCopy, &policyPara, &policyStatus); /* Any error in the policy status indicates that the * policy couldn't be verified. */ @@ -285,55 +312,52 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx) SSL *ssl; WCHAR *server; BOOL ret = FALSE; + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + WININET_NETCONNECTION *conn; ssl = pX509_STORE_CTX_get_ex_data(ctx, pSSL_get_ex_data_X509_STORE_CTX_idx()); server = pSSL_get_ex_data(ssl, hostname_idx); - if (preverify_ok) + conn = pSSL_get_ex_data(ssl, conn_idx); + if (store) { - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, - CERT_STORE_CREATE_NEW_FLAG, NULL); + X509 *cert; + int i; + PCCERT_CONTEXT endCert = NULL; - if (store) + ret = TRUE; + for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++) { - X509 *cert; - int i; - PCCERT_CONTEXT endCert = NULL; + PCCERT_CONTEXT context; - ret = TRUE; - for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++) + cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i); + if ((context = X509_to_cert_context(cert))) { - PCCERT_CONTEXT context; - - cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i); - if ((context = X509_to_cert_context(cert))) - { - if (i == 0) - ret = CertAddCertificateContextToStore(store, context, - CERT_STORE_ADD_ALWAYS, &endCert); - else - ret = CertAddCertificateContextToStore(store, context, - CERT_STORE_ADD_ALWAYS, NULL); - CertFreeCertificateContext(context); - } + if (i == 0) + ret = CertAddCertificateContextToStore(store, context, + CERT_STORE_ADD_ALWAYS, &endCert); + else + ret = CertAddCertificateContextToStore(store, context, + CERT_STORE_ADD_ALWAYS, NULL); + CertFreeCertificateContext(context); } - if (!endCert) ret = FALSE; - if (ret) - { - DWORD_PTR err = netconn_verify_cert(endCert, store, server); - - if (err) - { - pSSL_set_ex_data(ssl, error_idx, (void *)err); - ret = FALSE; - } - } - CertFreeCertificateContext(endCert); - CertCloseStore(store, 0); } - } else - pSSL_set_ex_data(ssl, error_idx, (void *)ERROR_INTERNET_SEC_CERT_ERRORS); + if (!endCert) ret = FALSE; + if (ret) + { + DWORD_PTR err = netconn_verify_cert(endCert, store, server, + conn->security_flags); + if (err) + { + pSSL_set_ex_data(ssl, error_idx, (void *)err); + ret = FALSE; + } + } + CertFreeCertificateContext(endCert); + CertCloseStore(store, 0); + } return ret; } @@ -400,12 +424,13 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) DYNSSL(SSL_get_ex_data); DYNSSL(SSL_set_ex_data); DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx); - DYNSSL(SSL_get_verify_result); DYNSSL(SSL_get_peer_certificate); DYNSSL(SSL_CTX_get_timeout); DYNSSL(SSL_CTX_set_timeout); DYNSSL(SSL_CTX_set_default_verify_paths); DYNSSL(SSL_CTX_set_verify); + DYNSSL(SSL_get_current_cipher); + DYNSSL(SSL_CIPHER_get_bits); DYNSSL(X509_STORE_CTX_get_ex_data); #undef DYNSSL @@ -460,6 +485,15 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) LeaveCriticalSection(&init_ssl_cs); return ERROR_OUTOFMEMORY; } + conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index", + NULL, NULL, NULL); + if (conn_idx == -1) + { + ERR("SSL_get_ex_new_index failed; %s\n", + pERR_error_string(pERR_get_error(), 0)); + LeaveCriticalSection(&init_ssl_cs); + return ERROR_OUTOFMEMORY; + } pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify); pCRYPTO_set_id_callback(ssl_thread_id); @@ -637,10 +671,8 @@ DWORD NETCON_close(WININET_NETCONNECTION *connection) DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname) { DWORD res = ERROR_NOT_SUPPORTED; -#ifdef SONAME_LIBSSL - long verify_res; - X509 *cert; +#ifdef SONAME_LIBSSL /* can't connect if we are already connected */ if (connection->useSSL) { @@ -665,6 +697,20 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname) goto fail; } + if (!pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname)) + { + ERR("SSL_set_ex_data failed: %s\n", + pERR_error_string(pERR_get_error(), 0)); + res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; + goto fail; + } + if (!pSSL_set_ex_data(connection->ssl_s, conn_idx, connection)) + { + ERR("SSL_set_ex_data failed: %s\n", + pERR_error_string(pERR_get_error(), 0)); + res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; + goto fail; + } if (pSSL_connect(connection->ssl_s) <= 0) { res = (DWORD_PTR)pSSL_get_ex_data(connection->ssl_s, error_idx); @@ -673,22 +719,6 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname) ERR("SSL_connect failed: %d\n", res); goto fail; } - pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname); - cert = pSSL_get_peer_certificate(connection->ssl_s); - if (!cert) - { - ERR("no certificate for server %s\n", debugstr_w(hostname)); - /* FIXME: is this the best error? */ - res = ERROR_INTERNET_INVALID_CA; - goto fail; - } - verify_res = pSSL_get_verify_result(connection->ssl_s); - if (verify_res != X509_V_OK) - { - ERR("couldn't verify the security of the connection, %ld\n", verify_res); - /* FIXME: we should set an error and return, but we only warn at - * the moment */ - } connection->useSSL = TRUE; return ERROR_SUCCESS; @@ -772,6 +802,8 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int if (!connection->useSSL) { *recvd = recv(connection->socketFD, buf, len, flags); + if(!*recvd) + NETCON_close(connection); return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS; } else @@ -781,8 +813,10 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int /* Check if EOF was received */ if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN - || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) + || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) { + NETCON_close(connection); return ERROR_SUCCESS; + } return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED; #else @@ -840,6 +874,24 @@ LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection) #endif } +int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection) +{ +#ifdef SONAME_LIBSSL + SSL_CIPHER *cipher; + int bits = 0; + + if (!connection->useSSL) + return 0; + cipher = pSSL_get_current_cipher(connection->ssl_s); + if (!cipher) + return 0; + pSSL_CIPHER_get_bits(cipher, &bits); + return bits; +#else + return 0; +#endif +} + DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value) { int result; diff --git a/reactos/dll/win32/wininet/urlcache.c b/reactos/dll/win32/wininet/urlcache.c index c617a93299f..2129f42e734 100644 --- a/reactos/dll/win32/wininet/urlcache.c +++ b/reactos/dll/win32/wininet/urlcache.c @@ -2184,14 +2184,17 @@ BOOL WINAPI CreateUrlCacheEntryA( ) { WCHAR *url_name; - WCHAR *file_extension; + WCHAR *file_extension = NULL; WCHAR file_name[MAX_PATH]; BOOL bSuccess = FALSE; DWORD dwError = 0; + TRACE("(%s %d %s %p %d)\n", debugstr_a(lpszUrlName), dwExpectedFileSize, + debugstr_a(lpszFileExtension), lpszFileName, dwReserved); + if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName))) { - if (lpszFileExtension && (file_extension = heap_strdupAtoW(lpszFileExtension))) + if (!lpszFileExtension || (file_extension = heap_strdupAtoW(lpszFileExtension))) { if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved)) { @@ -2268,6 +2271,12 @@ BOOL WINAPI CreateUrlCacheEntryW( if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\')) lpszUrlEnd--; + lpszUrlPart = memchrW(lpszUrlName, '?', lpszUrlEnd - lpszUrlName); + if (!lpszUrlPart) + lpszUrlPart = memchrW(lpszUrlName, '#', lpszUrlEnd - lpszUrlName); + if (lpszUrlPart) + lpszUrlEnd = lpszUrlPart; + for (lpszUrlPart = lpszUrlEnd; (lpszUrlPart >= lpszUrlName); lpszUrlPart--) @@ -2278,10 +2287,6 @@ BOOL WINAPI CreateUrlCacheEntryW( lpszUrlPart++; break; } - else if(*lpszUrlPart == '?' || *lpszUrlPart == '#') - { - lpszUrlEnd = lpszUrlPart; - } } if (!lstrcmpW(lpszUrlPart, szWWW)) { @@ -2327,7 +2332,13 @@ BOOL WINAPI CreateUrlCacheEntryW( CacheDir = (BYTE)(rand() % pHeader->DirectoryCount); lBufferSize = MAX_PATH * sizeof(WCHAR); - URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize); + if (!URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize)) + { + WARN("Failed to get full path for filename %s, needed %u bytes.\n", + debugstr_a(szFile), lBufferSize); + URLCacheContainer_UnlockIndex(pContainer, pHeader); + return FALSE; + } URLCacheContainer_UnlockIndex(pContainer, pHeader); diff --git a/reactos/dll/win32/wininet/wininet_ros.diff b/reactos/dll/win32/wininet/wininet_ros.diff index 097bf72d8ae..9fce1d677c5 100644 --- a/reactos/dll/win32/wininet/wininet_ros.diff +++ b/reactos/dll/win32/wininet/wininet_ros.diff @@ -1,7 +1,18 @@ ---- D:/Wine-CVS/wine/dlls/wininet/http.c Wed May 28 14:33:28 2008 -+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/http.c Sun Jun 15 18:16:06 2008 -@@ -61,6 +61,8 @@ - #include "wine/debug.h" +--- wine-1.3.4/dlls/wininet/internet.h 2010-10-01 14:46:44.000000000 -0400 ++++ dll/win32/wininet/internet.h 2010-10-09 15:34:13.000000000 -0400 +@@ -462,7 +462,7 @@ + LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection); + int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection); + DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value); +-int sock_get_error(int); ++#define sock_get_error(x) WSAGetLastError() + + extern void URLCacheContainers_CreateDefaults(void); + extern void URLCacheContainers_DeleteAll(void); +--- wine-1.3.4/dlls/wininet/http.c 2010-10-01 14:46:44.000000000 -0400 ++++ dll/win32/wininet/http.c 2010-10-09 15:28:29.000000000 -0400 +@@ -69,6 +69,8 @@ + #include "wine/exception.h" #include "wine/unicode.h" +#include "inet_ntop.c" @@ -9,95 +20,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0}; ---- D:/Wine-CVS/wine/dlls/wininet/internet.c Wed May 28 14:33:28 2008 -+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.c Fri May 30 18:04:29 2008 -@@ -3101,19 +3101,22 @@ - - LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen) - { -- struct pollfd pfd; -+ struct timeval tv; -+ fd_set infd; - BOOL bSuccess = FALSE; - INT nRecv = 0; - LPSTR lpszBuffer = INTERNET_GetResponseBuffer(); - - TRACE("\n"); - -- pfd.fd = nSocket; -- pfd.events = POLLIN; -+ FD_ZERO(&infd); -+ FD_SET(nSocket, &infd); -+ tv.tv_sec=RESPONSE_TIMEOUT; -+ tv.tv_usec=0; - - while (nRecv < MAX_REPLY_LEN) - { -- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0) -+ if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0) - { - if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0) - { ---- D:/Wine-CVS/wine/dlls/wininet/internet.h Fri Mar 28 20:13:36 2008 -+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.h Thu May 29 19:01:31 2008 -@@ -23,6 +23,9 @@ - #ifndef _WINE_INTERNET_H_ - #define _WINE_INTERNET_H_ - -+/* ReactOS-specific definitions */ -+#define CP_UNIXCP CP_THREAD_ACP -+ - #ifndef __WINE_CONFIG_H - # error You must include config.h to use this header - #endif ---- D:/Wine-CVS/wine/dlls/wininet/netconnection.c Sat May 17 12:09:49 2008 -+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/netconnection.c Sat May 31 12:01:55 2008 -@@ -64,7 +64,7 @@ - #include "winsock2.h" - - #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ -- -+#define sock_get_error(x) WSAGetLastError() - - WINE_DEFAULT_DEBUG_CHANNEL(wininet); - -@@ -206,6 +206,7 @@ +--- wine-1.3.4/dlls/wininet/netconnection.c 2010-10-01 14:46:44.000000000 -0400 ++++ dll/win32/wininet/netconnection.c 2010-10-09 15:33:53.000000000 -0400 +@@ -547,6 +547,7 @@ return TRUE; } +#if 0 /* translate a unix error code into a winsock one */ - static int sock_get_error( int err ) + int sock_get_error( int err ) { -@@ -272,6 +273,7 @@ +@@ -613,6 +614,7 @@ #endif return err; } +#endif /****************************************************************************** - * NETCON_create -@@ -616,16 +618,19 @@ - - if (!connection->useSSL) - { -- struct pollfd pfd; -+ struct timeval tv; -+ fd_set infd; - BOOL bSuccess = FALSE; - DWORD nRecv = 0; - -- pfd.fd = connection->socketFD; -- pfd.events = POLLIN; -+ FD_ZERO(&infd); -+ FD_SET(connection->socketFD, &infd); -+ tv.tv_sec=RESPONSE_TIMEOUT; -+ tv.tv_usec=0; - - while (nRecv < *dwBuffer) - { -- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0) -+ if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0) - { - if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0) - { + * NETCON_create \ No newline at end of file