winhttp: Protect access to the request object with a critical section.

This commit is contained in:
Hans Leidekker 2011-08-02 09:22:58 +02:00 committed by Alexandre Julliard
parent 3dc6226519
commit 916e3c1cc4
1 changed files with 201 additions and 81 deletions

View File

@ -2158,6 +2158,7 @@ struct winhttp_request
{ {
IWinHttpRequest IWinHttpRequest_iface; IWinHttpRequest IWinHttpRequest_iface;
LONG refs; LONG refs;
CRITICAL_SECTION cs;
enum request_state state; enum request_state state;
HINTERNET hsession; HINTERNET hsession;
HINTERNET hconnect; HINTERNET hconnect;
@ -2200,6 +2201,7 @@ static ULONG WINAPI winhttp_request_Release(
WinHttpCloseHandle( request->hrequest ); WinHttpCloseHandle( request->hrequest );
WinHttpCloseHandle( request->hconnect ); WinHttpCloseHandle( request->hconnect );
WinHttpCloseHandle( request->hsession ); WinHttpCloseHandle( request->hsession );
DeleteCriticalSection( &request->cs );
CloseHandle( request->wait ); CloseHandle( request->wait );
CloseHandle( request->cancel ); CloseHandle( request->cancel );
heap_free( (WCHAR *)request->proxy.lpszProxy ); heap_free( (WCHAR *)request->proxy.lpszProxy );
@ -2366,10 +2368,12 @@ static HRESULT WINAPI winhttp_request_SetProxy(
VARIANT bypass_list ) VARIANT bypass_list )
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD err = ERROR_SUCCESS;
TRACE("%p, %u, %s, %s\n", request, proxy_setting, debugstr_variant(&proxy_server), TRACE("%p, %u, %s, %s\n", request, proxy_setting, debugstr_variant(&proxy_server),
debugstr_variant(&bypass_list)); debugstr_variant(&bypass_list));
EnterCriticalSection( &request->cs );
switch (proxy_setting) switch (proxy_setting)
{ {
case HTTPREQUEST_PROXYSETTING_DEFAULT: case HTTPREQUEST_PROXYSETTING_DEFAULT:
@ -2390,9 +2394,12 @@ static HRESULT WINAPI winhttp_request_SetProxy(
request->proxy.lpszProxyBypass = strdupW( V_BSTR( &bypass_list ) ); request->proxy.lpszProxyBypass = strdupW( V_BSTR( &bypass_list ) );
break; break;
default: return E_INVALIDARG; default:
err = ERROR_INVALID_PARAMETER;
break;
} }
return S_OK; LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_SetCredentials( static HRESULT WINAPI winhttp_request_SetCredentials(
@ -2403,12 +2410,15 @@ static HRESULT WINAPI winhttp_request_SetCredentials(
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD target, scheme = WINHTTP_AUTH_SCHEME_BASIC; /* FIXME: query supported schemes */ DWORD target, scheme = WINHTTP_AUTH_SCHEME_BASIC; /* FIXME: query supported schemes */
DWORD err = ERROR_SUCCESS;
TRACE("%p, %s, %p\n", request, debugstr_w(username), password); TRACE("%p, %s, %p\n", request, debugstr_w(username), password);
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_OPEN) if (request->state < REQUEST_STATE_OPEN)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN;
goto done;
} }
switch (flags) switch (flags)
{ {
@ -2419,10 +2429,16 @@ static HRESULT WINAPI winhttp_request_SetCredentials(
target = WINHTTP_AUTH_TARGET_PROXY; target = WINHTTP_AUTH_TARGET_PROXY;
break; break;
default: default:
return E_INVALIDARG; err = ERROR_INVALID_PARAMETER;
goto done;
} }
if (WinHttpSetCredentials( request->hrequest, target, scheme, username, password, NULL )) return S_OK; if (!WinHttpSetCredentials( request->hrequest, target, scheme, username, password, NULL ))
return HRESULT_FROM_WIN32( get_last_error() ); {
err = get_last_error();
}
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_Open( static HRESULT WINAPI winhttp_request_Open(
@ -2456,14 +2472,20 @@ static HRESULT WINAPI winhttp_request_Open(
uc.dwUrlPathLength = ~0u; uc.dwUrlPathLength = ~0u;
uc.dwExtraInfoLength = ~0u; uc.dwExtraInfoLength = ~0u;
if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( get_last_error() ); if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( get_last_error() );
if (!(request->verb = strdupW( method ))) return E_OUTOFMEMORY;
EnterCriticalSection( &request->cs );
if (!(request->verb = strdupW( method )))
{
LeaveCriticalSection( &request->cs );
return E_OUTOFMEMORY;
}
if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) ); memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
hostname[uc.dwHostNameLength] = 0; hostname[uc.dwHostNameLength] = 0;
if (!(path = heap_alloc( (uc.dwUrlPathLength + uc.dwExtraInfoLength + 1) * sizeof(WCHAR) ))) if (!(path = heap_alloc( (uc.dwUrlPathLength + uc.dwExtraInfoLength + 1) * sizeof(WCHAR) )))
{ {
heap_free( hostname ); heap_free( hostname );
LeaveCriticalSection( &request->cs );
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
memcpy( path, uc.lpszUrlPath, (uc.dwUrlPathLength + uc.dwExtraInfoLength) * sizeof(WCHAR) ); memcpy( path, uc.lpszUrlPath, (uc.dwUrlPathLength + uc.dwExtraInfoLength) * sizeof(WCHAR) );
@ -2508,6 +2530,7 @@ static HRESULT WINAPI winhttp_request_Open(
request->hrequest = hrequest; request->hrequest = hrequest;
heap_free( hostname ); heap_free( hostname );
heap_free( path ); heap_free( path );
LeaveCriticalSection( &request->cs );
return S_OK; return S_OK;
error: error:
@ -2515,6 +2538,7 @@ error:
WinHttpCloseHandle( hsession ); WinHttpCloseHandle( hsession );
heap_free( hostname ); heap_free( hostname );
heap_free( path ); heap_free( path );
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err ); return HRESULT_FROM_WIN32( err );
} }
@ -2526,30 +2550,41 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
static const WCHAR fmtW[] = {'%','s',':',' ','%','s','\r','\n',0}; static const WCHAR fmtW[] = {'%','s',':',' ','%','s','\r','\n',0};
static const WCHAR emptyW[] = {0}; static const WCHAR emptyW[] = {0};
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD len; DWORD len, err = ERROR_SUCCESS;
WCHAR *str; WCHAR *str;
BOOL ret;
TRACE("%p, %s, %s\n", request, debugstr_w(header), debugstr_w(value)); TRACE("%p, %s, %s\n", request, debugstr_w(header), debugstr_w(value));
if (!header) return E_INVALIDARG; if (!header) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_OPEN) if (request->state < REQUEST_STATE_OPEN)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN;
goto done;
} }
if (request->state >= REQUEST_STATE_SENT) if (request->state >= REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND;
goto done;
} }
len = strlenW( header ) + 4; len = strlenW( header ) + 4;
if (value) len += strlenW( value ); if (value) len += strlenW( value );
if (!(str = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; if (!(str = heap_alloc( (len + 1) * sizeof(WCHAR) )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
sprintfW( str, fmtW, header, value ? value : emptyW ); sprintfW( str, fmtW, header, value ? value : emptyW );
ret = WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_REPLACE ); if (!WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_REPLACE ))
{
err = get_last_error();
}
heap_free( str ); heap_free( str );
if (ret) return S_OK;
return HRESULT_FROM_WIN32( get_last_error() ); done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static DWORD wait_for_completion( struct winhttp_request *request, DWORD timeout ) static DWORD wait_for_completion( struct winhttp_request *request, DWORD timeout )
@ -2628,29 +2663,44 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader(
BSTR *value ) BSTR *value )
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD err, size; DWORD size, err = ERROR_SUCCESS;
TRACE("%p, %p\n", request, header); TRACE("%p, %p\n", request, header);
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT) if (request->state < REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
} }
if (!header || !value) return E_INVALIDARG; if (!header || !value)
if ((err = request_wait_for_response( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); {
err = ERROR_INVALID_PARAMETER;
goto done;
}
if ((err = request_wait_for_response( request, INFINITE ))) goto done;
request->state = REQUEST_STATE_RESPONSE_RECEIVED; request->state = REQUEST_STATE_RESPONSE_RECEIVED;
size = 0; size = 0;
WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, NULL, &size, NULL ); if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, NULL, &size, NULL ))
err = get_last_error(); {
if (err != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32( err ); err = get_last_error();
if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) ))) return E_OUTOFMEMORY; if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, *value, &size, NULL )) if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, *value, &size, NULL ))
{ {
err = get_last_error();
SysFreeString( *value ); SysFreeString( *value );
return HRESULT_FROM_WIN32( get_last_error() );
} }
return S_OK; done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_GetAllResponseHeaders( static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
@ -2658,29 +2708,41 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders(
BSTR *headers ) BSTR *headers )
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD err, size; DWORD size, err = ERROR_SUCCESS;
TRACE("%p, %p\n", request, headers); TRACE("%p, %p\n", request, headers);
if (!headers) return E_INVALIDARG; if (!headers) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT) if (request->state < REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
} }
if ((err = request_wait_for_response( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); if ((err = request_wait_for_response( request, INFINITE ))) goto done;
request->state = REQUEST_STATE_RESPONSE_RECEIVED; request->state = REQUEST_STATE_RESPONSE_RECEIVED;
size = 0; size = 0;
WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL ); if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL ))
err = get_last_error(); {
if (err != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32( err ); err = get_last_error();
if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) ))) return E_OUTOFMEMORY; if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, *headers, &size, NULL )) if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, *headers, &size, NULL ))
{ {
err = get_last_error();
SysFreeString( *headers ); SysFreeString( *headers );
return HRESULT_FROM_WIN32( get_last_error() );
} }
return S_OK; done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_Send( static HRESULT WINAPI winhttp_request_Send(
@ -2694,45 +2756,57 @@ static HRESULT WINAPI winhttp_request_Send(
LONG size = 0; LONG size = 0;
HRESULT hr; HRESULT hr;
BOOL ret; BOOL ret;
DWORD err; DWORD err = ERROR_SUCCESS;
TRACE("%p, %s\n", request, debugstr_variant(&body)); TRACE("%p, %s\n", request, debugstr_variant(&body));
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_OPEN) if (request->state < REQUEST_STATE_OPEN)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN;
goto done;
} }
if (request->state >= REQUEST_STATE_SENT) return ERROR_SUCCESS; if (request->state >= REQUEST_STATE_SENT) goto done;
if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY, &request->proxy, sizeof(request->proxy) )) if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY, &request->proxy, sizeof(request->proxy) ))
{ {
return HRESULT_FROM_WIN32( get_last_error() ); err = get_last_error();
goto done;
} }
if (!WinHttpSetTimeouts( request->hrequest, if (!WinHttpSetTimeouts( request->hrequest, request->resolve_timeout, request->connect_timeout,
request->resolve_timeout, request->send_timeout, request->receive_timeout ))
request->connect_timeout,
request->send_timeout,
request->receive_timeout ))
{ {
return HRESULT_FROM_WIN32( get_last_error() ); err = get_last_error();
goto done;
} }
VariantInit( &array ); VariantInit( &array );
if (strcmpW( request->verb, getW ) && VariantChangeType( &array, &body, 0, VT_ARRAY|VT_UI1 ) == S_OK) if (strcmpW( request->verb, getW ) && VariantChangeType( &array, &body, 0, VT_ARRAY|VT_UI1 ) == S_OK)
{ {
SAFEARRAY *sa = V_ARRAY( &array ); SAFEARRAY *sa = V_ARRAY( &array );
if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) return hr; if (((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) ||
if ((hr = SafeArrayGetUBound( sa, 1, &size ) != S_OK)) return hr; (hr = SafeArrayGetUBound( sa, 1, &size ) != S_OK))
{
LeaveCriticalSection( &request->cs );
return hr;
}
size++; size++;
} }
wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT ); wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT );
ret = WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 ); ret = WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 );
err = get_last_error(); err = get_last_error();
if (sa && (hr = SafeArrayUnaccessData( sa )) != S_OK) return hr; if (sa && (hr = SafeArrayUnaccessData( sa )) != S_OK)
if (!ret) return HRESULT_FROM_WIN32( err ); {
LeaveCriticalSection( &request->cs );
if ((err = wait_for_completion( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); return hr;
request->state = REQUEST_STATE_SENT; }
return S_OK; if (!ret) goto done;
if (!(err = wait_for_completion( request, INFINITE )))
{
request->state = REQUEST_STATE_SENT;
}
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_get_Status( static HRESULT WINAPI winhttp_request_get_Status(
@ -2740,25 +2814,31 @@ static HRESULT WINAPI winhttp_request_get_Status(
LONG *status ) LONG *status )
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD err, flags, status_code, len = sizeof(status_code), index = 0; DWORD err = ERROR_SUCCESS, flags, status_code, len = sizeof(status_code), index = 0;
TRACE("%p, %p\n", request, status); TRACE("%p, %p\n", request, status);
if (!status) return E_INVALIDARG; if (!status) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT) if (request->state < REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
} }
if ((err = request_wait_for_response( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); if ((err = request_wait_for_response( request, INFINITE ))) goto done;
request->state = REQUEST_STATE_RESPONSE_RECEIVED; request->state = REQUEST_STATE_RESPONSE_RECEIVED;
flags = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; flags = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code, &len, &index )) if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code, &len, &index ))
{ {
return HRESULT_FROM_WIN32( get_last_error() ); err = get_last_error();
} }
*status = status_code; *status = status_code;
return S_OK;
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_get_StatusText( static HRESULT WINAPI winhttp_request_get_StatusText(
@ -2766,29 +2846,41 @@ static HRESULT WINAPI winhttp_request_get_StatusText(
BSTR *status ) BSTR *status )
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
DWORD err, len = 0, index = 0; DWORD err = ERROR_SUCCESS, len = 0, index = 0;
TRACE("%p, %p\n", request, status); TRACE("%p, %p\n", request, status);
if (!status) return E_INVALIDARG; if (!status) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT) if (request->state < REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
} }
if ((err = request_wait_for_response( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); if ((err = request_wait_for_response( request, INFINITE ))) goto done;
request->state = REQUEST_STATE_RESPONSE_RECEIVED; request->state = REQUEST_STATE_RESPONSE_RECEIVED;
WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, NULL, &len, &index ); if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, NULL, &len, &index ))
err = get_last_error(); {
if (err != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32( err ); err = get_last_error();
if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) ))) return E_OUTOFMEMORY; if (err != ERROR_INSUFFICIENT_BUFFER) goto done;
}
if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
index = 0; index = 0;
err = ERROR_SUCCESS;
if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, *status, &len, &index )) if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, *status, &len, &index ))
{ {
err = get_last_error();
SysFreeString( *status ); SysFreeString( *status );
return HRESULT_FROM_WIN32( get_last_error() );
} }
return S_OK; done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static DWORD request_read_body( struct winhttp_request *request, DWORD timeout ) static DWORD request_read_body( struct winhttp_request *request, DWORD timeout )
@ -2883,24 +2975,34 @@ static HRESULT WINAPI winhttp_request_get_ResponseText(
{ {
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
UINT codepage; UINT codepage;
DWORD err; DWORD err = ERROR_SUCCESS;
int len; int len;
TRACE("%p, %p\n", request, body); TRACE("%p, %p\n", request, body);
if (!body) return E_INVALIDARG; if (!body) return E_INVALIDARG;
EnterCriticalSection( &request->cs );
if (request->state < REQUEST_STATE_SENT) if (request->state < REQUEST_STATE_SENT)
{ {
return HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ); err = ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND;
goto done;
} }
if ((err = request_read_body( request, INFINITE ))) return HRESULT_FROM_WIN32( err ); if ((err = request_read_body( request, INFINITE ))) goto done;
if ((err = request_get_codepage( request, &codepage ))) return HRESULT_FROM_WIN32( err ); if ((err = request_get_codepage( request, &codepage ))) goto done;
len = MultiByteToWideChar( codepage, 0, request->buffer, request->offset, NULL, 0 ); len = MultiByteToWideChar( codepage, 0, request->buffer, request->offset, NULL, 0 );
if (!(*body = SysAllocStringLen( NULL, len ))) return E_OUTOFMEMORY; if (!(*body = SysAllocStringLen( NULL, len )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
MultiByteToWideChar( codepage, 0, request->buffer, request->offset, *body, len ); MultiByteToWideChar( codepage, 0, request->buffer, request->offset, *body, len );
(*body)[len] = 0; (*body)[len] = 0;
return S_OK;
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_get_ResponseBody( static HRESULT WINAPI winhttp_request_get_ResponseBody(
@ -2910,29 +3012,40 @@ static HRESULT WINAPI winhttp_request_get_ResponseBody(
struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); struct winhttp_request *request = impl_from_IWinHttpRequest( iface );
SAFEARRAY *sa; SAFEARRAY *sa;
HRESULT hr; HRESULT hr;
DWORD err; DWORD err = ERROR_SUCCESS;
char *ptr; char *ptr;
TRACE("%p, %p\n", request, body); TRACE("%p, %p\n", request, body);
if (!body) return E_INVALIDARG; if (!body) return E_INVALIDARG;
if ((err = request_read_body( request, INFINITE ))) return HRESULT_FROM_WIN32( err );
if (!(sa = SafeArrayCreateVector( VT_UI1, 0, request->offset ))) return E_OUTOFMEMORY; EnterCriticalSection( &request->cs );
if ((err = request_read_body( request, INFINITE ))) goto done;
if (!(sa = SafeArrayCreateVector( VT_UI1, 0, request->offset )))
{
err = ERROR_OUTOFMEMORY;
goto done;
}
if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK)
{ {
SafeArrayDestroy( sa ); SafeArrayDestroy( sa );
LeaveCriticalSection( &request->cs );
return hr; return hr;
} }
memcpy( ptr, request->buffer, request->offset ); memcpy( ptr, request->buffer, request->offset );
if ((hr = SafeArrayUnaccessData( sa )) != S_OK) if ((hr = SafeArrayUnaccessData( sa )) != S_OK)
{ {
SafeArrayDestroy( sa ); SafeArrayDestroy( sa );
LeaveCriticalSection( &request->cs );
return hr; return hr;
} }
V_VT( body ) = VT_ARRAY|VT_UI1; V_VT( body ) = VT_ARRAY|VT_UI1;
V_ARRAY( body ) = sa; V_ARRAY( body ) = sa;
return S_OK;
done:
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static HRESULT WINAPI winhttp_request_get_ResponseStream( static HRESULT WINAPI winhttp_request_get_ResponseStream(
@ -2971,20 +3084,22 @@ static HRESULT WINAPI winhttp_request_WaitForResponse(
TRACE("%p, %s, %p\n", request, debugstr_variant(&timeout), succeeded); TRACE("%p, %s, %p\n", request, debugstr_variant(&timeout), succeeded);
EnterCriticalSection( &request->cs );
switch ((err = request_wait_for_response( request, msecs ))) switch ((err = request_wait_for_response( request, msecs )))
{ {
case ERROR_TIMEOUT: case ERROR_TIMEOUT:
if (succeeded) *succeeded = VARIANT_FALSE; if (succeeded) *succeeded = VARIANT_FALSE;
return S_OK; break;
case ERROR_SUCCESS: case ERROR_SUCCESS:
if (succeeded) *succeeded = VARIANT_TRUE; if (succeeded) *succeeded = VARIANT_TRUE;
request->state = REQUEST_STATE_RESPONSE_RECEIVED; request->state = REQUEST_STATE_RESPONSE_RECEIVED;
return S_OK; break;
default: default: break;
return HRESULT_FROM_WIN32( err );
} }
LeaveCriticalSection( &request->cs );
return HRESULT_FROM_WIN32( err );
} }
static void initialize_request( struct winhttp_request *request ) static void initialize_request( struct winhttp_request *request )
@ -3018,6 +3133,7 @@ static HRESULT WINAPI winhttp_request_Abort(
TRACE("%p\n", request); TRACE("%p\n", request);
SetEvent( request->cancel ); SetEvent( request->cancel );
EnterCriticalSection( &request->cs );
WinHttpCloseHandle( request->hrequest ); WinHttpCloseHandle( request->hrequest );
WinHttpCloseHandle( request->hconnect ); WinHttpCloseHandle( request->hconnect );
WinHttpCloseHandle( request->hsession ); WinHttpCloseHandle( request->hsession );
@ -3028,6 +3144,7 @@ static HRESULT WINAPI winhttp_request_Abort(
heap_free( request->buffer ); heap_free( request->buffer );
heap_free( request->verb ); heap_free( request->verb );
initialize_request( request ); initialize_request( request );
LeaveCriticalSection( &request->cs );
return S_OK; return S_OK;
} }
@ -3042,10 +3159,12 @@ static HRESULT WINAPI winhttp_request_SetTimeouts(
TRACE("%p, %d, %d, %d, %d\n", request, resolve_timeout, connect_timeout, send_timeout, receive_timeout); TRACE("%p, %d, %d, %d, %d\n", request, resolve_timeout, connect_timeout, send_timeout, receive_timeout);
EnterCriticalSection( &request->cs );
request->resolve_timeout = resolve_timeout; request->resolve_timeout = resolve_timeout;
request->connect_timeout = connect_timeout; request->connect_timeout = connect_timeout;
request->send_timeout = send_timeout; request->send_timeout = send_timeout;
request->receive_timeout = receive_timeout; request->receive_timeout = receive_timeout;
LeaveCriticalSection( &request->cs );
return S_OK; return S_OK;
} }
@ -3104,6 +3223,7 @@ HRESULT WinHttpRequest_create( IUnknown *unknown, void **obj )
if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY; if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY;
request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl; request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl;
request->refs = 1; request->refs = 1;
InitializeCriticalSection( &request->cs );
initialize_request( request ); initialize_request( request );
*obj = &request->IWinHttpRequest_iface; *obj = &request->IWinHttpRequest_iface;