From 4aeec1b88de11b171fe8746e2a34f20dc9ac4211 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Thu, 21 Jul 2011 11:50:45 +0200 Subject: [PATCH] winhttp: Implement IWinHttpRequest::Open. --- dlls/winhttp/request.c | 88 ++++++++++++++++++++++++++++++++-- dlls/winhttp/winhttp_private.h | 31 ++++++++++++ 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index c936fdd7fd..260811910b 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2137,10 +2137,25 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write return ret; } +enum request_state +{ + REQUEST_STATE_INVALID, + REQUEST_STATE_OPEN, + REQUEST_STATE_SENT, + REQUEST_STATE_RESPONSE_RECEIVED, + REQUEST_STATE_BODY_RECEIVED +}; + struct winhttp_request { IWinHttpRequest IWinHttpRequest_iface; LONG refs; + enum request_state state; + HINTERNET hsession; + HINTERNET hconnect; + HINTERNET hrequest; + HANDLE wait; + HANDLE cancel; }; static inline struct winhttp_request *impl_from_IWinHttpRequest( IWinHttpRequest *iface ) @@ -2163,6 +2178,11 @@ static ULONG WINAPI winhttp_request_Release( if (!refs) { TRACE("destroying %p\n", request); + WinHttpCloseHandle( request->hrequest ); + WinHttpCloseHandle( request->hconnect ); + WinHttpCloseHandle( request->hsession ); + CloseHandle( request->wait ); + CloseHandle( request->cancel ); heap_free( request ); } return refs; @@ -2342,8 +2362,70 @@ static HRESULT WINAPI winhttp_request_Open( BSTR url, VARIANT async ) { - FIXME("\n"); - return E_NOTIMPL; + struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); + HINTERNET hsession = NULL, hconnect = NULL, hrequest; + URL_COMPONENTS uc; + WCHAR *hostname, *path; + DWORD err, flags = 0; + + TRACE("%p, %s, %s, %s\n", request, debugstr_w(method), debugstr_w(url), + debugstr_variant(&async)); + + if (!method) return E_INVALIDARG; + + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.dwHostNameLength = ~0u; + uc.dwUrlPathLength = ~0u; + if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( GetLastError() ); + + if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; + memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) ); + hostname[uc.dwHostNameLength] = 0; + if (!(path = heap_alloc( (uc.dwUrlPathLength + 1) * sizeof(WCHAR) ))) + { + heap_free( hostname ); + return E_OUTOFMEMORY; + } + memcpy( path, uc.lpszUrlPath, uc.dwUrlPathLength * sizeof(WCHAR) ); + path[uc.dwUrlPathLength] = 0; + + if (V_BOOL( &async ) == VARIANT_TRUE) flags |= WINHTTP_FLAG_ASYNC; + if (!(hsession = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, flags ))) + { + err = GetLastError(); + goto error; + } + if (!(hconnect = WinHttpConnect( hsession, hostname, uc.nPort, 0 ))) + { + err = GetLastError(); + goto error; + } + if (!(hrequest = WinHttpOpenRequest( hconnect, method, path, NULL, NULL, NULL, 0 ))) + { + err = GetLastError(); + goto error; + } + if (flags & WINHTTP_FLAG_ASYNC) + { + request->wait = CreateEventW( NULL, FALSE, FALSE, NULL ); + request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL ); + WinHttpSetOption( hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request, sizeof(request) ); + } + request->state = REQUEST_STATE_OPEN; + request->hsession = hsession; + request->hconnect = hconnect; + request->hrequest = hrequest; + heap_free( hostname ); + heap_free( path ); + return S_OK; + +error: + WinHttpCloseHandle( hconnect ); + WinHttpCloseHandle( hsession ); + heap_free( hostname ); + heap_free( path ); + return HRESULT_FROM_WIN32( err ); } static HRESULT WINAPI winhttp_request_SetRequestHeader( @@ -2517,7 +2599,7 @@ HRESULT WinHttpRequest_create( IUnknown *unknown, void **obj ) TRACE("%p, %p\n", unknown, obj); - if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY; + if (!(request = heap_alloc_zero( sizeof(*request) ))) return E_OUTOFMEMORY; request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl; request->refs = 1; diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 760717478f..4bac24f148 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -240,6 +240,37 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT extern HRESULT WinHttpRequest_create( IUnknown *, void ** ) DECLSPEC_HIDDEN; +static inline const char *debugstr_variant( const VARIANT *v ) +{ + if (!v) return "(null)"; + switch (V_VT(v)) + { + case VT_EMPTY: + return "{VT_EMPTY}"; + case VT_NULL: + return "{VT_NULL}"; + case VT_I4: + return wine_dbg_sprintf( "{VT_I4: %d}", V_I4(v) ); + case VT_R8: + return wine_dbg_sprintf( "{VT_R8: %lf}", V_R8(v) ); + case VT_BSTR: + return wine_dbg_sprintf( "{VT_BSTR: %s}", debugstr_w(V_BSTR(v)) ); + case VT_DISPATCH: + return wine_dbg_sprintf( "{VT_DISPATCH: %p}", V_DISPATCH(v) ); + case VT_BOOL: + return wine_dbg_sprintf( "{VT_BOOL: %x}", V_BOOL(v) ); + case VT_UNKNOWN: + return wine_dbg_sprintf( "{VT_UNKNOWN: %p}", V_UNKNOWN(v) ); + case VT_UINT: + return wine_dbg_sprintf( "{VT_UINT: %u}", V_UINT(v) ); + case VT_BSTR|VT_BYREF: + return wine_dbg_sprintf( "{VT_BSTR|VT_BYREF: ptr %p, data %s}", + V_BSTRREF(v), V_BSTRREF(v) ? debugstr_w( *V_BSTRREF(v) ) : NULL ); + default: + return wine_dbg_sprintf( "{vt %d}", V_VT(v) ); + } +} + static inline void *heap_alloc( SIZE_T size ) { return HeapAlloc( GetProcessHeap(), 0, size );