1c2c66affSColin Finck /* 2c2c66affSColin Finck * Copyright 2008 Hans Leidekker for CodeWeavers 3c2c66affSColin Finck * 4c2c66affSColin Finck * This library is free software; you can redistribute it and/or 5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 6c2c66affSColin Finck * License as published by the Free Software Foundation; either 7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 8c2c66affSColin Finck * 9c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12c2c66affSColin Finck * Lesser General Public License for more details. 13c2c66affSColin Finck * 14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 15c2c66affSColin Finck * License along with this library; if not, write to the Free Software 16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17c2c66affSColin Finck */ 18c2c66affSColin Finck 19c2c66affSColin Finck #include "winhttp_private.h" 20c2c66affSColin Finck 21c2c66affSColin Finck #include <wincrypt.h> 22c2c66affSColin Finck #include <winreg.h> 23c2c66affSColin Finck #include <dispex.h> 24c2c66affSColin Finck #include <activscp.h> 25c2c66affSColin Finck 26c2c66affSColin Finck #define DEFAULT_RESOLVE_TIMEOUT 0 27c2c66affSColin Finck #define DEFAULT_CONNECT_TIMEOUT 20000 28c2c66affSColin Finck #define DEFAULT_SEND_TIMEOUT 30000 29c2c66affSColin Finck #define DEFAULT_RECEIVE_TIMEOUT 30000 30c2c66affSColin Finck 31c2c66affSColin Finck void set_last_error( DWORD error ) 32c2c66affSColin Finck { 33c2c66affSColin Finck /* FIXME */ 34c2c66affSColin Finck SetLastError( error ); 35c2c66affSColin Finck } 36c2c66affSColin Finck 37c2c66affSColin Finck DWORD get_last_error( void ) 38c2c66affSColin Finck { 39c2c66affSColin Finck /* FIXME */ 40c2c66affSColin Finck return GetLastError(); 41c2c66affSColin Finck } 42c2c66affSColin Finck 43c2c66affSColin Finck void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen ) 44c2c66affSColin Finck { 45c2c66affSColin Finck if (hdr->callback && (hdr->notify_mask & status)) 46c2c66affSColin Finck { 47c2c66affSColin Finck TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen); 48c2c66affSColin Finck hdr->callback( hdr->handle, hdr->context, status, info, buflen ); 49c2c66affSColin Finck TRACE("returning from 0x%08x callback\n", status); 50c2c66affSColin Finck } 51c2c66affSColin Finck } 52c2c66affSColin Finck 53c2c66affSColin Finck /*********************************************************************** 54c2c66affSColin Finck * WinHttpCheckPlatform (winhttp.@) 55c2c66affSColin Finck */ 56c2c66affSColin Finck BOOL WINAPI WinHttpCheckPlatform( void ) 57c2c66affSColin Finck { 58c2c66affSColin Finck TRACE("\n"); 59c2c66affSColin Finck return TRUE; 60c2c66affSColin Finck } 61c2c66affSColin Finck 62c2c66affSColin Finck /*********************************************************************** 63c2c66affSColin Finck * session_destroy (internal) 64c2c66affSColin Finck */ 65c2c66affSColin Finck static void session_destroy( object_header_t *hdr ) 66c2c66affSColin Finck { 67c2c66affSColin Finck session_t *session = (session_t *)hdr; 68c2c66affSColin Finck struct list *item, *next; 69c2c66affSColin Finck domain_t *domain; 70c2c66affSColin Finck 71c2c66affSColin Finck TRACE("%p\n", session); 72c2c66affSColin Finck 73c2c66affSColin Finck if (session->unload_event) SetEvent( session->unload_event ); 74*9048bdf9SAmine Khaldi if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle ); 75c2c66affSColin Finck 76c2c66affSColin Finck LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) 77c2c66affSColin Finck { 78c2c66affSColin Finck domain = LIST_ENTRY( item, domain_t, entry ); 79c2c66affSColin Finck delete_domain( domain ); 80c2c66affSColin Finck } 81c2c66affSColin Finck heap_free( session->agent ); 82c2c66affSColin Finck heap_free( session->proxy_server ); 83c2c66affSColin Finck heap_free( session->proxy_bypass ); 84c2c66affSColin Finck heap_free( session->proxy_username ); 85c2c66affSColin Finck heap_free( session->proxy_password ); 86c2c66affSColin Finck heap_free( session ); 87c2c66affSColin Finck } 88c2c66affSColin Finck 89c2c66affSColin Finck static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) 90c2c66affSColin Finck { 91c2c66affSColin Finck session_t *session = (session_t *)hdr; 92c2c66affSColin Finck 93c2c66affSColin Finck switch (option) 94c2c66affSColin Finck { 95c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY: 96c2c66affSColin Finck { 97c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD)) 98c2c66affSColin Finck { 99c2c66affSColin Finck *buflen = sizeof(DWORD); 100c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 101c2c66affSColin Finck return FALSE; 102c2c66affSColin Finck } 103c2c66affSColin Finck 104c2c66affSColin Finck *(DWORD *)buffer = hdr->redirect_policy; 105c2c66affSColin Finck *buflen = sizeof(DWORD); 106c2c66affSColin Finck return TRUE; 107c2c66affSColin Finck } 108c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT: 109c2c66affSColin Finck *(DWORD *)buffer = session->resolve_timeout; 110c2c66affSColin Finck *buflen = sizeof(DWORD); 111c2c66affSColin Finck return TRUE; 112c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT: 113c2c66affSColin Finck *(DWORD *)buffer = session->connect_timeout; 114c2c66affSColin Finck *buflen = sizeof(DWORD); 115c2c66affSColin Finck return TRUE; 116c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT: 117c2c66affSColin Finck *(DWORD *)buffer = session->send_timeout; 118c2c66affSColin Finck *buflen = sizeof(DWORD); 119c2c66affSColin Finck return TRUE; 120c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT: 121c2c66affSColin Finck *(DWORD *)buffer = session->recv_timeout; 122c2c66affSColin Finck *buflen = sizeof(DWORD); 123c2c66affSColin Finck return TRUE; 124c2c66affSColin Finck default: 125c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 126c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 127c2c66affSColin Finck return FALSE; 128c2c66affSColin Finck } 129c2c66affSColin Finck } 130c2c66affSColin Finck 131c2c66affSColin Finck static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) 132c2c66affSColin Finck { 133c2c66affSColin Finck session_t *session = (session_t *)hdr; 134c2c66affSColin Finck 135c2c66affSColin Finck switch (option) 136c2c66affSColin Finck { 137c2c66affSColin Finck case WINHTTP_OPTION_PROXY: 138c2c66affSColin Finck { 139c2c66affSColin Finck WINHTTP_PROXY_INFO *pi = buffer; 140c2c66affSColin Finck 141c2c66affSColin Finck FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass)); 142c2c66affSColin Finck return TRUE; 143c2c66affSColin Finck } 144c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY: 145c2c66affSColin Finck { 146c2c66affSColin Finck DWORD policy; 147c2c66affSColin Finck 148c2c66affSColin Finck if (buflen != sizeof(policy)) 149c2c66affSColin Finck { 150c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 151c2c66affSColin Finck return FALSE; 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck policy = *(DWORD *)buffer; 155c2c66affSColin Finck TRACE("0x%x\n", policy); 156c2c66affSColin Finck hdr->redirect_policy = policy; 157c2c66affSColin Finck return TRUE; 158c2c66affSColin Finck } 159*9048bdf9SAmine Khaldi case WINHTTP_OPTION_SECURE_PROTOCOLS: 160*9048bdf9SAmine Khaldi { 161*9048bdf9SAmine Khaldi if (buflen != sizeof(session->secure_protocols)) 162*9048bdf9SAmine Khaldi { 163*9048bdf9SAmine Khaldi set_last_error( ERROR_INSUFFICIENT_BUFFER ); 164*9048bdf9SAmine Khaldi return FALSE; 165*9048bdf9SAmine Khaldi } 166*9048bdf9SAmine Khaldi session->secure_protocols = *(DWORD *)buffer; 167*9048bdf9SAmine Khaldi TRACE("0x%x\n", session->secure_protocols); 168*9048bdf9SAmine Khaldi return TRUE; 169*9048bdf9SAmine Khaldi } 170c2c66affSColin Finck case WINHTTP_OPTION_DISABLE_FEATURE: 171c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 172c2c66affSColin Finck return FALSE; 173c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT: 174c2c66affSColin Finck session->resolve_timeout = *(DWORD *)buffer; 175c2c66affSColin Finck return TRUE; 176c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT: 177c2c66affSColin Finck session->connect_timeout = *(DWORD *)buffer; 178c2c66affSColin Finck return TRUE; 179c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT: 180c2c66affSColin Finck session->send_timeout = *(DWORD *)buffer; 181c2c66affSColin Finck return TRUE; 182c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT: 183c2c66affSColin Finck session->recv_timeout = *(DWORD *)buffer; 184c2c66affSColin Finck return TRUE; 185c2c66affSColin Finck case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 186c2c66affSColin Finck FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer); 187c2c66affSColin Finck return TRUE; 188c2c66affSColin Finck case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: 189c2c66affSColin Finck TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer); 190c2c66affSColin Finck session->unload_event = *(HANDLE *)buffer; 191c2c66affSColin Finck return TRUE; 192c2c66affSColin Finck case WINHTTP_OPTION_MAX_CONNS_PER_SERVER: 193c2c66affSColin Finck FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer); 194c2c66affSColin Finck return TRUE; 195c2c66affSColin Finck case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: 196c2c66affSColin Finck FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer); 197c2c66affSColin Finck return TRUE; 198c2c66affSColin Finck default: 199c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 200c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 201c2c66affSColin Finck return FALSE; 202c2c66affSColin Finck } 203c2c66affSColin Finck } 204c2c66affSColin Finck 205c2c66affSColin Finck static const object_vtbl_t session_vtbl = 206c2c66affSColin Finck { 207c2c66affSColin Finck session_destroy, 208c2c66affSColin Finck session_query_option, 209c2c66affSColin Finck session_set_option 210c2c66affSColin Finck }; 211c2c66affSColin Finck 212c2c66affSColin Finck #ifdef __REACTOS__ 213c2c66affSColin Finck BOOL netconn_init_winsock(); 214c2c66affSColin Finck #endif /* __REACTOS__ */ 215c2c66affSColin Finck /*********************************************************************** 216c2c66affSColin Finck * WinHttpOpen (winhttp.@) 217c2c66affSColin Finck */ 218c2c66affSColin Finck HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags ) 219c2c66affSColin Finck { 220c2c66affSColin Finck session_t *session; 221c2c66affSColin Finck HINTERNET handle = NULL; 222c2c66affSColin Finck #ifdef __REACTOS__ 223c2c66affSColin Finck if (!netconn_init_winsock()) return NULL; 224c2c66affSColin Finck #endif 225c2c66affSColin Finck 226c2c66affSColin Finck TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags); 227c2c66affSColin Finck 228c2c66affSColin Finck if (!(session = heap_alloc_zero( sizeof(session_t) ))) return NULL; 229c2c66affSColin Finck 230c2c66affSColin Finck session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION; 231c2c66affSColin Finck session->hdr.vtbl = &session_vtbl; 232c2c66affSColin Finck session->hdr.flags = flags; 233c2c66affSColin Finck session->hdr.refs = 1; 234c2c66affSColin Finck session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP; 235c2c66affSColin Finck list_init( &session->hdr.children ); 236c2c66affSColin Finck session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT; 237c2c66affSColin Finck session->connect_timeout = DEFAULT_CONNECT_TIMEOUT; 238c2c66affSColin Finck session->send_timeout = DEFAULT_SEND_TIMEOUT; 239c2c66affSColin Finck session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT; 240c2c66affSColin Finck list_init( &session->cookie_cache ); 241c2c66affSColin Finck 242c2c66affSColin Finck if (agent && !(session->agent = strdupW( agent ))) goto end; 243c2c66affSColin Finck if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY) 244c2c66affSColin Finck { 245c2c66affSColin Finck WINHTTP_PROXY_INFO info; 246c2c66affSColin Finck 247c2c66affSColin Finck WinHttpGetDefaultProxyConfiguration( &info ); 248c2c66affSColin Finck session->access = info.dwAccessType; 249c2c66affSColin Finck if (info.lpszProxy && !(session->proxy_server = strdupW( info.lpszProxy ))) 250c2c66affSColin Finck { 251c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxy ); 252c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxyBypass ); 253c2c66affSColin Finck goto end; 254c2c66affSColin Finck } 255c2c66affSColin Finck if (info.lpszProxyBypass && !(session->proxy_bypass = strdupW( info.lpszProxyBypass ))) 256c2c66affSColin Finck { 257c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxy ); 258c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxyBypass ); 259c2c66affSColin Finck goto end; 260c2c66affSColin Finck } 261c2c66affSColin Finck } 262c2c66affSColin Finck else if (access == WINHTTP_ACCESS_TYPE_NAMED_PROXY) 263c2c66affSColin Finck { 264c2c66affSColin Finck session->access = access; 265c2c66affSColin Finck if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end; 266c2c66affSColin Finck if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end; 267c2c66affSColin Finck } 268c2c66affSColin Finck 269c2c66affSColin Finck if (!(handle = alloc_handle( &session->hdr ))) goto end; 270c2c66affSColin Finck session->hdr.handle = handle; 271c2c66affSColin Finck 272c2c66affSColin Finck end: 273c2c66affSColin Finck release_object( &session->hdr ); 274c2c66affSColin Finck TRACE("returning %p\n", handle); 275c2c66affSColin Finck if (handle) set_last_error( ERROR_SUCCESS ); 276c2c66affSColin Finck return handle; 277c2c66affSColin Finck } 278c2c66affSColin Finck 279c2c66affSColin Finck /*********************************************************************** 280c2c66affSColin Finck * connect_destroy (internal) 281c2c66affSColin Finck */ 282c2c66affSColin Finck static void connect_destroy( object_header_t *hdr ) 283c2c66affSColin Finck { 284c2c66affSColin Finck connect_t *connect = (connect_t *)hdr; 285c2c66affSColin Finck 286c2c66affSColin Finck TRACE("%p\n", connect); 287c2c66affSColin Finck 288c2c66affSColin Finck release_object( &connect->session->hdr ); 289c2c66affSColin Finck 290c2c66affSColin Finck heap_free( connect->hostname ); 291c2c66affSColin Finck heap_free( connect->servername ); 292c2c66affSColin Finck heap_free( connect->username ); 293c2c66affSColin Finck heap_free( connect->password ); 294c2c66affSColin Finck heap_free( connect ); 295c2c66affSColin Finck } 296c2c66affSColin Finck 297c2c66affSColin Finck static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) 298c2c66affSColin Finck { 299c2c66affSColin Finck connect_t *connect = (connect_t *)hdr; 300c2c66affSColin Finck 301c2c66affSColin Finck switch (option) 302c2c66affSColin Finck { 303c2c66affSColin Finck case WINHTTP_OPTION_PARENT_HANDLE: 304c2c66affSColin Finck { 305c2c66affSColin Finck if (!buffer || *buflen < sizeof(HINTERNET)) 306c2c66affSColin Finck { 307c2c66affSColin Finck *buflen = sizeof(HINTERNET); 308c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 309c2c66affSColin Finck return FALSE; 310c2c66affSColin Finck } 311c2c66affSColin Finck 312c2c66affSColin Finck *(HINTERNET *)buffer = ((object_header_t *)connect->session)->handle; 313c2c66affSColin Finck *buflen = sizeof(HINTERNET); 314c2c66affSColin Finck return TRUE; 315c2c66affSColin Finck } 316c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT: 317c2c66affSColin Finck *(DWORD *)buffer = connect->session->resolve_timeout; 318c2c66affSColin Finck *buflen = sizeof(DWORD); 319c2c66affSColin Finck return TRUE; 320c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT: 321c2c66affSColin Finck *(DWORD *)buffer = connect->session->connect_timeout; 322c2c66affSColin Finck *buflen = sizeof(DWORD); 323c2c66affSColin Finck return TRUE; 324c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT: 325c2c66affSColin Finck *(DWORD *)buffer = connect->session->send_timeout; 326c2c66affSColin Finck *buflen = sizeof(DWORD); 327c2c66affSColin Finck return TRUE; 328c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT: 329c2c66affSColin Finck *(DWORD *)buffer = connect->session->recv_timeout; 330c2c66affSColin Finck *buflen = sizeof(DWORD); 331c2c66affSColin Finck return TRUE; 332c2c66affSColin Finck default: 333c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 334c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 335c2c66affSColin Finck return FALSE; 336c2c66affSColin Finck } 337c2c66affSColin Finck } 338c2c66affSColin Finck 339c2c66affSColin Finck static const object_vtbl_t connect_vtbl = 340c2c66affSColin Finck { 341c2c66affSColin Finck connect_destroy, 342c2c66affSColin Finck connect_query_option, 343c2c66affSColin Finck NULL 344c2c66affSColin Finck }; 345c2c66affSColin Finck 346c2c66affSColin Finck static BOOL domain_matches(LPCWSTR server, LPCWSTR domain) 347c2c66affSColin Finck { 348c2c66affSColin Finck static const WCHAR localW[] = { '<','l','o','c','a','l','>',0 }; 349c2c66affSColin Finck BOOL ret = FALSE; 350c2c66affSColin Finck 351c2c66affSColin Finck if (!strcmpiW( domain, localW ) && !strchrW( server, '.' )) 352c2c66affSColin Finck ret = TRUE; 353c2c66affSColin Finck else if (*domain == '*') 354c2c66affSColin Finck { 355c2c66affSColin Finck if (domain[1] == '.') 356c2c66affSColin Finck { 357c2c66affSColin Finck LPCWSTR dot; 358c2c66affSColin Finck 359c2c66affSColin Finck /* For a hostname to match a wildcard, the last domain must match 360c2c66affSColin Finck * the wildcard exactly. E.g. if the wildcard is *.a.b, and the 361c2c66affSColin Finck * hostname is www.foo.a.b, it matches, but a.b does not. 362c2c66affSColin Finck */ 363c2c66affSColin Finck dot = strchrW( server, '.' ); 364c2c66affSColin Finck if (dot) 365c2c66affSColin Finck { 366c2c66affSColin Finck int len = strlenW( dot + 1 ); 367c2c66affSColin Finck 368c2c66affSColin Finck if (len > strlenW( domain + 2 )) 369c2c66affSColin Finck { 370c2c66affSColin Finck LPCWSTR ptr; 371c2c66affSColin Finck 372c2c66affSColin Finck /* The server's domain is longer than the wildcard, so it 373c2c66affSColin Finck * could be a subdomain. Compare the last portion of the 374c2c66affSColin Finck * server's domain. 375c2c66affSColin Finck */ 376c2c66affSColin Finck ptr = dot + len + 1 - strlenW( domain + 2 ); 377c2c66affSColin Finck if (!strcmpiW( ptr, domain + 2 )) 378c2c66affSColin Finck { 379c2c66affSColin Finck /* This is only a match if the preceding character is 380c2c66affSColin Finck * a '.', i.e. that it is a matching domain. E.g. 381c2c66affSColin Finck * if domain is '*.b.c' and server is 'www.ab.c' they 382c2c66affSColin Finck * do not match. 383c2c66affSColin Finck */ 384c2c66affSColin Finck ret = *(ptr - 1) == '.'; 385c2c66affSColin Finck } 386c2c66affSColin Finck } 387c2c66affSColin Finck else 388c2c66affSColin Finck ret = !strcmpiW( dot + 1, domain + 2 ); 389c2c66affSColin Finck } 390c2c66affSColin Finck } 391c2c66affSColin Finck } 392c2c66affSColin Finck else 393c2c66affSColin Finck ret = !strcmpiW( server, domain ); 394c2c66affSColin Finck return ret; 395c2c66affSColin Finck } 396c2c66affSColin Finck 397c2c66affSColin Finck /* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */ 398c2c66affSColin Finck #define MAX_HOST_NAME_LENGTH 256 399c2c66affSColin Finck 400c2c66affSColin Finck static BOOL should_bypass_proxy(session_t *session, LPCWSTR server) 401c2c66affSColin Finck { 402c2c66affSColin Finck LPCWSTR ptr; 403c2c66affSColin Finck BOOL ret = FALSE; 404c2c66affSColin Finck 405c2c66affSColin Finck if (!session->proxy_bypass) return FALSE; 406c2c66affSColin Finck ptr = session->proxy_bypass; 407c2c66affSColin Finck do { 408c2c66affSColin Finck LPCWSTR tmp = ptr; 409c2c66affSColin Finck 410c2c66affSColin Finck ptr = strchrW( ptr, ';' ); 411c2c66affSColin Finck if (!ptr) 412c2c66affSColin Finck ptr = strchrW( tmp, ' ' ); 413c2c66affSColin Finck if (ptr) 414c2c66affSColin Finck { 415c2c66affSColin Finck if (ptr - tmp < MAX_HOST_NAME_LENGTH) 416c2c66affSColin Finck { 417c2c66affSColin Finck WCHAR domain[MAX_HOST_NAME_LENGTH]; 418c2c66affSColin Finck 419c2c66affSColin Finck memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) ); 420c2c66affSColin Finck domain[ptr - tmp] = 0; 421c2c66affSColin Finck ret = domain_matches( server, domain ); 422c2c66affSColin Finck } 423c2c66affSColin Finck ptr += 1; 424c2c66affSColin Finck } 425c2c66affSColin Finck else if (*tmp) 426c2c66affSColin Finck ret = domain_matches( server, tmp ); 427c2c66affSColin Finck } while (ptr && !ret); 428c2c66affSColin Finck return ret; 429c2c66affSColin Finck } 430c2c66affSColin Finck 431c2c66affSColin Finck BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port ) 432c2c66affSColin Finck { 433c2c66affSColin Finck session_t *session = connect->session; 434c2c66affSColin Finck BOOL ret = TRUE; 435c2c66affSColin Finck 436c2c66affSColin Finck if (session->proxy_server && !should_bypass_proxy(session, server)) 437c2c66affSColin Finck { 438c2c66affSColin Finck LPCWSTR colon; 439c2c66affSColin Finck 440c2c66affSColin Finck if ((colon = strchrW( session->proxy_server, ':' ))) 441c2c66affSColin Finck { 442c2c66affSColin Finck if (!connect->servername || strncmpiW( connect->servername, 443c2c66affSColin Finck session->proxy_server, colon - session->proxy_server - 1 )) 444c2c66affSColin Finck { 445c2c66affSColin Finck heap_free( connect->servername ); 446c2c66affSColin Finck connect->resolved = FALSE; 447c2c66affSColin Finck if (!(connect->servername = heap_alloc( 448c2c66affSColin Finck (colon - session->proxy_server + 1) * sizeof(WCHAR) ))) 449c2c66affSColin Finck { 450c2c66affSColin Finck ret = FALSE; 451c2c66affSColin Finck goto end; 452c2c66affSColin Finck } 453c2c66affSColin Finck memcpy( connect->servername, session->proxy_server, 454c2c66affSColin Finck (colon - session->proxy_server) * sizeof(WCHAR) ); 455c2c66affSColin Finck connect->servername[colon - session->proxy_server] = 0; 456c2c66affSColin Finck if (*(colon + 1)) 457c2c66affSColin Finck connect->serverport = atoiW( colon + 1 ); 458c2c66affSColin Finck else 459c2c66affSColin Finck connect->serverport = INTERNET_DEFAULT_PORT; 460c2c66affSColin Finck } 461c2c66affSColin Finck } 462c2c66affSColin Finck else 463c2c66affSColin Finck { 464c2c66affSColin Finck if (!connect->servername || strcmpiW( connect->servername, 465c2c66affSColin Finck session->proxy_server )) 466c2c66affSColin Finck { 467c2c66affSColin Finck heap_free( connect->servername ); 468c2c66affSColin Finck connect->resolved = FALSE; 469c2c66affSColin Finck if (!(connect->servername = strdupW( session->proxy_server ))) 470c2c66affSColin Finck { 471c2c66affSColin Finck ret = FALSE; 472c2c66affSColin Finck goto end; 473c2c66affSColin Finck } 474c2c66affSColin Finck connect->serverport = INTERNET_DEFAULT_PORT; 475c2c66affSColin Finck } 476c2c66affSColin Finck } 477c2c66affSColin Finck } 478c2c66affSColin Finck else if (server) 479c2c66affSColin Finck { 480c2c66affSColin Finck heap_free( connect->servername ); 481c2c66affSColin Finck connect->resolved = FALSE; 482c2c66affSColin Finck if (!(connect->servername = strdupW( server ))) 483c2c66affSColin Finck { 484c2c66affSColin Finck ret = FALSE; 485c2c66affSColin Finck goto end; 486c2c66affSColin Finck } 487c2c66affSColin Finck connect->serverport = port; 488c2c66affSColin Finck } 489c2c66affSColin Finck end: 490c2c66affSColin Finck return ret; 491c2c66affSColin Finck } 492c2c66affSColin Finck 493c2c66affSColin Finck /*********************************************************************** 494c2c66affSColin Finck * WinHttpConnect (winhttp.@) 495c2c66affSColin Finck */ 496c2c66affSColin Finck HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved ) 497c2c66affSColin Finck { 498c2c66affSColin Finck connect_t *connect; 499c2c66affSColin Finck session_t *session; 500c2c66affSColin Finck HINTERNET hconnect = NULL; 501c2c66affSColin Finck 502c2c66affSColin Finck TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved); 503c2c66affSColin Finck 504c2c66affSColin Finck if (!server) 505c2c66affSColin Finck { 506c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 507c2c66affSColin Finck return NULL; 508c2c66affSColin Finck } 509c2c66affSColin Finck if (!(session = (session_t *)grab_object( hsession ))) 510c2c66affSColin Finck { 511c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 512c2c66affSColin Finck return NULL; 513c2c66affSColin Finck } 514c2c66affSColin Finck if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION) 515c2c66affSColin Finck { 516c2c66affSColin Finck release_object( &session->hdr ); 517c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 518c2c66affSColin Finck return NULL; 519c2c66affSColin Finck } 520c2c66affSColin Finck if (!(connect = heap_alloc_zero( sizeof(connect_t) ))) 521c2c66affSColin Finck { 522c2c66affSColin Finck release_object( &session->hdr ); 523c2c66affSColin Finck return NULL; 524c2c66affSColin Finck } 525c2c66affSColin Finck connect->hdr.type = WINHTTP_HANDLE_TYPE_CONNECT; 526c2c66affSColin Finck connect->hdr.vtbl = &connect_vtbl; 527c2c66affSColin Finck connect->hdr.refs = 1; 528c2c66affSColin Finck connect->hdr.flags = session->hdr.flags; 529c2c66affSColin Finck connect->hdr.callback = session->hdr.callback; 530c2c66affSColin Finck connect->hdr.notify_mask = session->hdr.notify_mask; 531c2c66affSColin Finck connect->hdr.context = session->hdr.context; 532c2c66affSColin Finck connect->hdr.redirect_policy = session->hdr.redirect_policy; 533c2c66affSColin Finck list_init( &connect->hdr.children ); 534c2c66affSColin Finck 535c2c66affSColin Finck addref_object( &session->hdr ); 536c2c66affSColin Finck connect->session = session; 537c2c66affSColin Finck list_add_head( &session->hdr.children, &connect->hdr.entry ); 538c2c66affSColin Finck 539c2c66affSColin Finck if (!(connect->hostname = strdupW( server ))) goto end; 540c2c66affSColin Finck connect->hostport = port; 541c2c66affSColin Finck if (!set_server_for_hostname( connect, server, port )) goto end; 542c2c66affSColin Finck 543c2c66affSColin Finck if (!(hconnect = alloc_handle( &connect->hdr ))) goto end; 544c2c66affSColin Finck connect->hdr.handle = hconnect; 545c2c66affSColin Finck 546c2c66affSColin Finck send_callback( &session->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hconnect, sizeof(hconnect) ); 547c2c66affSColin Finck 548c2c66affSColin Finck end: 549c2c66affSColin Finck release_object( &connect->hdr ); 550c2c66affSColin Finck release_object( &session->hdr ); 551c2c66affSColin Finck TRACE("returning %p\n", hconnect); 552c2c66affSColin Finck if (hconnect) set_last_error( ERROR_SUCCESS ); 553c2c66affSColin Finck return hconnect; 554c2c66affSColin Finck } 555c2c66affSColin Finck 556c2c66affSColin Finck /*********************************************************************** 557c2c66affSColin Finck * request_destroy (internal) 558c2c66affSColin Finck */ 559c2c66affSColin Finck static void request_destroy( object_header_t *hdr ) 560c2c66affSColin Finck { 561c2c66affSColin Finck request_t *request = (request_t *)hdr; 562c2c66affSColin Finck unsigned int i, j; 563c2c66affSColin Finck 564c2c66affSColin Finck TRACE("%p\n", request); 565c2c66affSColin Finck 566c2c66affSColin Finck if (request->task_thread) 567c2c66affSColin Finck { 568c2c66affSColin Finck /* Signal to the task proc to quit. It will call 569c2c66affSColin Finck this again when it does. */ 570c2c66affSColin Finck HANDLE thread = request->task_thread; 571c2c66affSColin Finck request->task_thread = 0; 572c2c66affSColin Finck SetEvent( request->task_cancel ); 573c2c66affSColin Finck CloseHandle( thread ); 574c2c66affSColin Finck return; 575c2c66affSColin Finck } 576c2c66affSColin Finck release_object( &request->connect->hdr ); 577c2c66affSColin Finck 578c2c66affSColin Finck destroy_authinfo( request->authinfo ); 579c2c66affSColin Finck destroy_authinfo( request->proxy_authinfo ); 580c2c66affSColin Finck 581c2c66affSColin Finck heap_free( request->verb ); 582c2c66affSColin Finck heap_free( request->path ); 583c2c66affSColin Finck heap_free( request->version ); 584c2c66affSColin Finck heap_free( request->raw_headers ); 585c2c66affSColin Finck heap_free( request->status_text ); 586c2c66affSColin Finck for (i = 0; i < request->num_headers; i++) 587c2c66affSColin Finck { 588c2c66affSColin Finck heap_free( request->headers[i].field ); 589c2c66affSColin Finck heap_free( request->headers[i].value ); 590c2c66affSColin Finck } 591c2c66affSColin Finck heap_free( request->headers ); 592*9048bdf9SAmine Khaldi for (i = 0; i < request->num_accept_types; i++) heap_free( request->accept_types[i] ); 593*9048bdf9SAmine Khaldi heap_free( request->accept_types ); 594c2c66affSColin Finck for (i = 0; i < TARGET_MAX; i++) 595c2c66affSColin Finck { 596c2c66affSColin Finck for (j = 0; j < SCHEME_MAX; j++) 597c2c66affSColin Finck { 598c2c66affSColin Finck heap_free( request->creds[i][j].username ); 599c2c66affSColin Finck heap_free( request->creds[i][j].password ); 600c2c66affSColin Finck } 601c2c66affSColin Finck } 602c2c66affSColin Finck heap_free( request ); 603c2c66affSColin Finck } 604c2c66affSColin Finck 605c2c66affSColin Finck static void str_to_buffer( WCHAR *buffer, const WCHAR *str, LPDWORD buflen ) 606c2c66affSColin Finck { 607c2c66affSColin Finck int len = 0; 608c2c66affSColin Finck if (str) len = strlenW( str ); 609c2c66affSColin Finck if (buffer && *buflen > len) 610c2c66affSColin Finck { 611c2c66affSColin Finck if (str) memcpy( buffer, str, len * sizeof(WCHAR) ); 612c2c66affSColin Finck buffer[len] = 0; 613c2c66affSColin Finck } 614c2c66affSColin Finck *buflen = len * sizeof(WCHAR); 615c2c66affSColin Finck } 616c2c66affSColin Finck 617c2c66affSColin Finck static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob ) 618c2c66affSColin Finck { 619c2c66affSColin Finck WCHAR *ret; 620c2c66affSColin Finck DWORD size, format = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG; 621c2c66affSColin Finck 622c2c66affSColin Finck size = CertNameToStrW( encoding, blob, format, NULL, 0 ); 623c2c66affSColin Finck if ((ret = LocalAlloc( 0, size * sizeof(WCHAR) ))) 624c2c66affSColin Finck CertNameToStrW( encoding, blob, format, ret, size ); 625c2c66affSColin Finck 626c2c66affSColin Finck return ret; 627c2c66affSColin Finck } 628c2c66affSColin Finck 629c2c66affSColin Finck static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage ) 630c2c66affSColin Finck { 631c2c66affSColin Finck #if !defined(__MINGW32__) && !defined(_MSC_VER) 632c2c66affSColin Finck switch (addr->sa_family) 633c2c66affSColin Finck { 634c2c66affSColin Finck case AF_INET: 635c2c66affSColin Finck { 636c2c66affSColin Finck const struct sockaddr_in *addr_unix = (const struct sockaddr_in *)addr; 637c2c66affSColin Finck struct WS_sockaddr_in *addr_win = (struct WS_sockaddr_in *)addr_storage; 638c2c66affSColin Finck char *p; 639c2c66affSColin Finck 640c2c66affSColin Finck addr_win->sin_family = WS_AF_INET; 641c2c66affSColin Finck addr_win->sin_port = addr_unix->sin_port; 642c2c66affSColin Finck memcpy( &addr_win->sin_addr, &addr_unix->sin_addr, 4 ); 643c2c66affSColin Finck p = (char *)&addr_win->sin_addr + 4; 644c2c66affSColin Finck memset( p, 0, sizeof(*addr_storage) - (p - (char *)addr_win) ); 645c2c66affSColin Finck return TRUE; 646c2c66affSColin Finck } 647c2c66affSColin Finck case AF_INET6: 648c2c66affSColin Finck { 649c2c66affSColin Finck const struct sockaddr_in6 *addr_unix = (const struct sockaddr_in6 *)addr; 650c2c66affSColin Finck struct WS_sockaddr_in6 *addr_win = (struct WS_sockaddr_in6 *)addr_storage; 651c2c66affSColin Finck 652c2c66affSColin Finck addr_win->sin6_family = WS_AF_INET6; 653c2c66affSColin Finck addr_win->sin6_port = addr_unix->sin6_port; 654c2c66affSColin Finck addr_win->sin6_flowinfo = addr_unix->sin6_flowinfo; 655c2c66affSColin Finck memcpy( &addr_win->sin6_addr, &addr_unix->sin6_addr, 16 ); 656c2c66affSColin Finck #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 657c2c66affSColin Finck addr_win->sin6_scope_id = addr_unix->sin6_scope_id; 658c2c66affSColin Finck #else 659c2c66affSColin Finck addr_win->sin6_scope_id = 0; 660c2c66affSColin Finck #endif 661c2c66affSColin Finck memset( addr_win + 1, 0, sizeof(*addr_storage) - sizeof(*addr_win) ); 662c2c66affSColin Finck return TRUE; 663c2c66affSColin Finck } 664c2c66affSColin Finck default: 665c2c66affSColin Finck ERR("unhandled family %u\n", addr->sa_family); 666c2c66affSColin Finck return FALSE; 667c2c66affSColin Finck } 668c2c66affSColin Finck #else 669c2c66affSColin Finck switch (addr->sa_family) 670c2c66affSColin Finck { 671c2c66affSColin Finck case AF_INET: 672c2c66affSColin Finck { 673c2c66affSColin Finck struct sockaddr_in *addr_in = (struct sockaddr_in *)addr_storage; 674c2c66affSColin Finck 675c2c66affSColin Finck memcpy( addr_in, addr, sizeof(*addr_in) ); 676c2c66affSColin Finck memset( addr_in + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in) ); 677c2c66affSColin Finck return TRUE; 678c2c66affSColin Finck } 679c2c66affSColin Finck case AF_INET6: 680c2c66affSColin Finck { 681c2c66affSColin Finck struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr_storage; 682c2c66affSColin Finck 683c2c66affSColin Finck memcpy( addr_in6, addr, sizeof(*addr_in6) ); 684c2c66affSColin Finck memset( addr_in6 + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in6) ); 685c2c66affSColin Finck return TRUE; 686c2c66affSColin Finck } 687c2c66affSColin Finck default: 688c2c66affSColin Finck ERR("unhandled family %u\n", addr->sa_family); 689c2c66affSColin Finck return FALSE; 690c2c66affSColin Finck } 691c2c66affSColin Finck #endif 692c2c66affSColin Finck } 693c2c66affSColin Finck 694c2c66affSColin Finck static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) 695c2c66affSColin Finck { 696c2c66affSColin Finck request_t *request = (request_t *)hdr; 697c2c66affSColin Finck 698c2c66affSColin Finck switch (option) 699c2c66affSColin Finck { 700c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_FLAGS: 701c2c66affSColin Finck { 702c2c66affSColin Finck DWORD flags = 0; 703c2c66affSColin Finck int bits; 704c2c66affSColin Finck 705c2c66affSColin Finck if (!buffer || *buflen < sizeof(flags)) 706c2c66affSColin Finck { 707c2c66affSColin Finck *buflen = sizeof(flags); 708c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 709c2c66affSColin Finck return FALSE; 710c2c66affSColin Finck } 711c2c66affSColin Finck 712c2c66affSColin Finck flags = 0; 713c2c66affSColin Finck if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE; 714c2c66affSColin Finck flags |= request->security_flags; 715c2c66affSColin Finck if (request->netconn) 716c2c66affSColin Finck { 717c2c66affSColin Finck bits = netconn_get_cipher_strength( request->netconn ); 718c2c66affSColin Finck if (bits >= 128) 719c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_STRONG; 720c2c66affSColin Finck else if (bits >= 56) 721c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_MEDIUM; 722c2c66affSColin Finck else 723c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_WEAK; 724c2c66affSColin Finck } 725c2c66affSColin Finck *(DWORD *)buffer = flags; 726c2c66affSColin Finck *buflen = sizeof(flags); 727c2c66affSColin Finck return TRUE; 728c2c66affSColin Finck } 729c2c66affSColin Finck case WINHTTP_OPTION_SERVER_CERT_CONTEXT: 730c2c66affSColin Finck { 731c2c66affSColin Finck const CERT_CONTEXT *cert; 732c2c66affSColin Finck 733c2c66affSColin Finck if (!buffer || *buflen < sizeof(cert)) 734c2c66affSColin Finck { 735c2c66affSColin Finck *buflen = sizeof(cert); 736c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 737c2c66affSColin Finck return FALSE; 738c2c66affSColin Finck } 739c2c66affSColin Finck 740c2c66affSColin Finck if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; 741c2c66affSColin Finck *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert; 742c2c66affSColin Finck *buflen = sizeof(cert); 743c2c66affSColin Finck return TRUE; 744c2c66affSColin Finck } 745c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT: 746c2c66affSColin Finck { 747c2c66affSColin Finck const CERT_CONTEXT *cert; 748c2c66affSColin Finck const CRYPT_OID_INFO *oidInfo; 749c2c66affSColin Finck WINHTTP_CERTIFICATE_INFO *ci = buffer; 750c2c66affSColin Finck 751c2c66affSColin Finck FIXME("partial stub\n"); 752c2c66affSColin Finck 753c2c66affSColin Finck if (!buffer || *buflen < sizeof(*ci)) 754c2c66affSColin Finck { 755c2c66affSColin Finck *buflen = sizeof(*ci); 756c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 757c2c66affSColin Finck return FALSE; 758c2c66affSColin Finck } 759c2c66affSColin Finck if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; 760c2c66affSColin Finck 761c2c66affSColin Finck ci->ftExpiry = cert->pCertInfo->NotAfter; 762c2c66affSColin Finck ci->ftStart = cert->pCertInfo->NotBefore; 763c2c66affSColin Finck ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject ); 764c2c66affSColin Finck ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer ); 765c2c66affSColin Finck ci->lpszProtocolName = NULL; 766c2c66affSColin Finck oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, 767c2c66affSColin Finck cert->pCertInfo->SignatureAlgorithm.pszObjId, 768c2c66affSColin Finck 0 ); 769c2c66affSColin Finck if (oidInfo) 770c2c66affSColin Finck ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName; 771c2c66affSColin Finck else 772c2c66affSColin Finck ci->lpszSignatureAlgName = NULL; 773c2c66affSColin Finck ci->lpszEncryptionAlgName = NULL; 774c2c66affSColin Finck ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0; 775c2c66affSColin Finck 776c2c66affSColin Finck CertFreeCertificateContext( cert ); 777c2c66affSColin Finck *buflen = sizeof(*ci); 778c2c66affSColin Finck return TRUE; 779c2c66affSColin Finck } 780c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_KEY_BITNESS: 781c2c66affSColin Finck { 782c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD)) 783c2c66affSColin Finck { 784c2c66affSColin Finck *buflen = sizeof(DWORD); 785c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 786c2c66affSColin Finck return FALSE; 787c2c66affSColin Finck } 788c2c66affSColin Finck 789c2c66affSColin Finck *(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0; 790c2c66affSColin Finck *buflen = sizeof(DWORD); 791c2c66affSColin Finck return TRUE; 792c2c66affSColin Finck } 793c2c66affSColin Finck case WINHTTP_OPTION_CONNECTION_INFO: 794c2c66affSColin Finck { 795c2c66affSColin Finck WINHTTP_CONNECTION_INFO *info = buffer; 796c2c66affSColin Finck struct sockaddr local; 797c2c66affSColin Finck socklen_t len = sizeof(local); 798c2c66affSColin Finck const struct sockaddr *remote = (const struct sockaddr *)&request->connect->sockaddr; 799c2c66affSColin Finck 800c2c66affSColin Finck if (!buffer || *buflen < sizeof(*info)) 801c2c66affSColin Finck { 802c2c66affSColin Finck *buflen = sizeof(*info); 803c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 804c2c66affSColin Finck return FALSE; 805c2c66affSColin Finck } 806c2c66affSColin Finck if (!request->netconn) 807c2c66affSColin Finck { 808c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); 809c2c66affSColin Finck return FALSE; 810c2c66affSColin Finck } 811c2c66affSColin Finck if (getsockname( request->netconn->socket, &local, &len )) return FALSE; 812c2c66affSColin Finck if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE; 813c2c66affSColin Finck if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE; 814c2c66affSColin Finck info->cbSize = sizeof(*info); 815c2c66affSColin Finck return TRUE; 816c2c66affSColin Finck } 817c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT: 818c2c66affSColin Finck *(DWORD *)buffer = request->resolve_timeout; 819c2c66affSColin Finck *buflen = sizeof(DWORD); 820c2c66affSColin Finck return TRUE; 821c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT: 822c2c66affSColin Finck *(DWORD *)buffer = request->connect_timeout; 823c2c66affSColin Finck *buflen = sizeof(DWORD); 824c2c66affSColin Finck return TRUE; 825c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT: 826c2c66affSColin Finck *(DWORD *)buffer = request->send_timeout; 827c2c66affSColin Finck *buflen = sizeof(DWORD); 828c2c66affSColin Finck return TRUE; 829c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT: 830c2c66affSColin Finck *(DWORD *)buffer = request->recv_timeout; 831c2c66affSColin Finck *buflen = sizeof(DWORD); 832c2c66affSColin Finck return TRUE; 833c2c66affSColin Finck 834c2c66affSColin Finck case WINHTTP_OPTION_USERNAME: 835c2c66affSColin Finck str_to_buffer( buffer, request->connect->username, buflen ); 836c2c66affSColin Finck return TRUE; 837c2c66affSColin Finck 838c2c66affSColin Finck case WINHTTP_OPTION_PASSWORD: 839c2c66affSColin Finck str_to_buffer( buffer, request->connect->password, buflen ); 840c2c66affSColin Finck return TRUE; 841c2c66affSColin Finck 842c2c66affSColin Finck case WINHTTP_OPTION_PROXY_USERNAME: 843c2c66affSColin Finck str_to_buffer( buffer, request->connect->session->proxy_username, buflen ); 844c2c66affSColin Finck return TRUE; 845c2c66affSColin Finck 846c2c66affSColin Finck case WINHTTP_OPTION_PROXY_PASSWORD: 847c2c66affSColin Finck str_to_buffer( buffer, request->connect->session->proxy_password, buflen ); 848c2c66affSColin Finck return TRUE; 849c2c66affSColin Finck 850c2c66affSColin Finck default: 851c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 852c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 853c2c66affSColin Finck return FALSE; 854c2c66affSColin Finck } 855c2c66affSColin Finck } 856c2c66affSColin Finck 857c2c66affSColin Finck static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen ) 858c2c66affSColin Finck { 859c2c66affSColin Finck WCHAR *ret; 860c2c66affSColin Finck if ((ret = heap_alloc( (buflen + 1) * sizeof(WCHAR)))) 861c2c66affSColin Finck { 862c2c66affSColin Finck memcpy( ret, buffer, buflen * sizeof(WCHAR) ); 863c2c66affSColin Finck ret[buflen] = 0; 864c2c66affSColin Finck return ret; 865c2c66affSColin Finck } 866c2c66affSColin Finck set_last_error( ERROR_OUTOFMEMORY ); 867c2c66affSColin Finck return NULL; 868c2c66affSColin Finck } 869c2c66affSColin Finck 870c2c66affSColin Finck static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) 871c2c66affSColin Finck { 872c2c66affSColin Finck request_t *request = (request_t *)hdr; 873c2c66affSColin Finck 874c2c66affSColin Finck switch (option) 875c2c66affSColin Finck { 876c2c66affSColin Finck case WINHTTP_OPTION_PROXY: 877c2c66affSColin Finck { 878c2c66affSColin Finck WINHTTP_PROXY_INFO *pi = buffer; 879c2c66affSColin Finck 880c2c66affSColin Finck FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass)); 881c2c66affSColin Finck return TRUE; 882c2c66affSColin Finck } 883c2c66affSColin Finck case WINHTTP_OPTION_DISABLE_FEATURE: 884c2c66affSColin Finck { 885c2c66affSColin Finck DWORD disable; 886c2c66affSColin Finck 887c2c66affSColin Finck if (buflen != sizeof(DWORD)) 888c2c66affSColin Finck { 889c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 890c2c66affSColin Finck return FALSE; 891c2c66affSColin Finck } 892c2c66affSColin Finck 893c2c66affSColin Finck disable = *(DWORD *)buffer; 894c2c66affSColin Finck TRACE("0x%x\n", disable); 895c2c66affSColin Finck hdr->disable_flags |= disable; 896c2c66affSColin Finck return TRUE; 897c2c66affSColin Finck } 898c2c66affSColin Finck case WINHTTP_OPTION_AUTOLOGON_POLICY: 899c2c66affSColin Finck { 900c2c66affSColin Finck DWORD policy; 901c2c66affSColin Finck 902c2c66affSColin Finck if (buflen != sizeof(DWORD)) 903c2c66affSColin Finck { 904c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 905c2c66affSColin Finck return FALSE; 906c2c66affSColin Finck } 907c2c66affSColin Finck 908c2c66affSColin Finck policy = *(DWORD *)buffer; 909c2c66affSColin Finck TRACE("0x%x\n", policy); 910c2c66affSColin Finck hdr->logon_policy = policy; 911c2c66affSColin Finck return TRUE; 912c2c66affSColin Finck } 913c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY: 914c2c66affSColin Finck { 915c2c66affSColin Finck DWORD policy; 916c2c66affSColin Finck 917c2c66affSColin Finck if (buflen != sizeof(DWORD)) 918c2c66affSColin Finck { 919c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 920c2c66affSColin Finck return FALSE; 921c2c66affSColin Finck } 922c2c66affSColin Finck 923c2c66affSColin Finck policy = *(DWORD *)buffer; 924c2c66affSColin Finck TRACE("0x%x\n", policy); 925c2c66affSColin Finck hdr->redirect_policy = policy; 926c2c66affSColin Finck return TRUE; 927c2c66affSColin Finck } 928c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_FLAGS: 929c2c66affSColin Finck { 930c2c66affSColin Finck DWORD flags; 931c2c66affSColin Finck 932c2c66affSColin Finck if (buflen < sizeof(DWORD)) 933c2c66affSColin Finck { 934c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 935c2c66affSColin Finck return FALSE; 936c2c66affSColin Finck } 937c2c66affSColin Finck flags = *(DWORD *)buffer; 938c2c66affSColin Finck TRACE("0x%x\n", flags); 939c2c66affSColin Finck if (!(flags & (SECURITY_FLAG_IGNORE_CERT_CN_INVALID | 940c2c66affSColin Finck SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | 941c2c66affSColin Finck SECURITY_FLAG_IGNORE_UNKNOWN_CA | 942c2c66affSColin Finck SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE))) 943c2c66affSColin Finck { 944c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 945c2c66affSColin Finck return FALSE; 946c2c66affSColin Finck } 947c2c66affSColin Finck request->security_flags = flags; 948c2c66affSColin Finck return TRUE; 949c2c66affSColin Finck } 950c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT: 951c2c66affSColin Finck request->resolve_timeout = *(DWORD *)buffer; 952c2c66affSColin Finck return TRUE; 953c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT: 954c2c66affSColin Finck request->connect_timeout = *(DWORD *)buffer; 955c2c66affSColin Finck return TRUE; 956c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT: 957c2c66affSColin Finck request->send_timeout = *(DWORD *)buffer; 958c2c66affSColin Finck return TRUE; 959c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT: 960c2c66affSColin Finck request->recv_timeout = *(DWORD *)buffer; 961c2c66affSColin Finck return TRUE; 962c2c66affSColin Finck 963c2c66affSColin Finck case WINHTTP_OPTION_USERNAME: 964c2c66affSColin Finck { 965c2c66affSColin Finck connect_t *connect = request->connect; 966c2c66affSColin Finck 967c2c66affSColin Finck heap_free( connect->username ); 968c2c66affSColin Finck if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE; 969c2c66affSColin Finck return TRUE; 970c2c66affSColin Finck } 971c2c66affSColin Finck case WINHTTP_OPTION_PASSWORD: 972c2c66affSColin Finck { 973c2c66affSColin Finck connect_t *connect = request->connect; 974c2c66affSColin Finck 975c2c66affSColin Finck heap_free( connect->password ); 976c2c66affSColin Finck if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE; 977c2c66affSColin Finck return TRUE; 978c2c66affSColin Finck } 979c2c66affSColin Finck case WINHTTP_OPTION_PROXY_USERNAME: 980c2c66affSColin Finck { 981c2c66affSColin Finck session_t *session = request->connect->session; 982c2c66affSColin Finck 983c2c66affSColin Finck heap_free( session->proxy_username ); 984c2c66affSColin Finck if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE; 985c2c66affSColin Finck return TRUE; 986c2c66affSColin Finck } 987c2c66affSColin Finck case WINHTTP_OPTION_PROXY_PASSWORD: 988c2c66affSColin Finck { 989c2c66affSColin Finck session_t *session = request->connect->session; 990c2c66affSColin Finck 991c2c66affSColin Finck heap_free( session->proxy_password ); 992c2c66affSColin Finck if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE; 993c2c66affSColin Finck return TRUE; 994c2c66affSColin Finck } 995c2c66affSColin Finck case WINHTTP_OPTION_CLIENT_CERT_CONTEXT: 996c2c66affSColin Finck if (!(hdr->flags & WINHTTP_FLAG_SECURE)) 997c2c66affSColin Finck { 998c2c66affSColin Finck SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); 999c2c66affSColin Finck return FALSE; 1000c2c66affSColin Finck } 1001c2c66affSColin Finck FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n"); 1002c2c66affSColin Finck return TRUE; 1003c2c66affSColin Finck default: 1004c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 1005c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1006c2c66affSColin Finck return TRUE; 1007c2c66affSColin Finck } 1008c2c66affSColin Finck } 1009c2c66affSColin Finck 1010c2c66affSColin Finck static const object_vtbl_t request_vtbl = 1011c2c66affSColin Finck { 1012c2c66affSColin Finck request_destroy, 1013c2c66affSColin Finck request_query_option, 1014c2c66affSColin Finck request_set_option 1015c2c66affSColin Finck }; 1016c2c66affSColin Finck 1017c2c66affSColin Finck static BOOL store_accept_types( request_t *request, const WCHAR **accept_types ) 1018c2c66affSColin Finck { 1019c2c66affSColin Finck const WCHAR **types = accept_types; 1020*9048bdf9SAmine Khaldi DWORD i; 1021c2c66affSColin Finck 1022c2c66affSColin Finck if (!types) return TRUE; 1023c2c66affSColin Finck while (*types) 1024c2c66affSColin Finck { 1025*9048bdf9SAmine Khaldi request->num_accept_types++; 1026*9048bdf9SAmine Khaldi types++; 1027*9048bdf9SAmine Khaldi } 1028*9048bdf9SAmine Khaldi if (!request->num_accept_types) return TRUE; 1029*9048bdf9SAmine Khaldi if (!(request->accept_types = heap_alloc( request->num_accept_types * sizeof(WCHAR *)))) 1030*9048bdf9SAmine Khaldi { 1031*9048bdf9SAmine Khaldi request->num_accept_types = 0; 1032*9048bdf9SAmine Khaldi return FALSE; 1033*9048bdf9SAmine Khaldi } 1034*9048bdf9SAmine Khaldi types = accept_types; 1035*9048bdf9SAmine Khaldi for (i = 0; i < request->num_accept_types; i++) 1036*9048bdf9SAmine Khaldi { 1037*9048bdf9SAmine Khaldi if (!(request->accept_types[i] = strdupW( *types ))) 1038*9048bdf9SAmine Khaldi { 1039*9048bdf9SAmine Khaldi for ( ; i > 0; --i) heap_free( request->accept_types[i - 1] ); 1040*9048bdf9SAmine Khaldi heap_free( request->accept_types ); 1041*9048bdf9SAmine Khaldi request->accept_types = NULL; 1042*9048bdf9SAmine Khaldi request->num_accept_types = 0; 1043*9048bdf9SAmine Khaldi return FALSE; 1044*9048bdf9SAmine Khaldi } 1045c2c66affSColin Finck types++; 1046c2c66affSColin Finck } 1047c2c66affSColin Finck return TRUE; 1048c2c66affSColin Finck } 1049c2c66affSColin Finck 1050c2c66affSColin Finck /*********************************************************************** 1051c2c66affSColin Finck * WinHttpOpenRequest (winhttp.@) 1052c2c66affSColin Finck */ 1053c2c66affSColin Finck HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version, 1054c2c66affSColin Finck LPCWSTR referrer, LPCWSTR *types, DWORD flags ) 1055c2c66affSColin Finck { 1056c2c66affSColin Finck request_t *request; 1057c2c66affSColin Finck connect_t *connect; 1058c2c66affSColin Finck HINTERNET hrequest = NULL; 1059c2c66affSColin Finck 1060c2c66affSColin Finck TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object), 1061c2c66affSColin Finck debugstr_w(version), debugstr_w(referrer), types, flags); 1062c2c66affSColin Finck 1063c2c66affSColin Finck if(types && TRACE_ON(winhttp)) { 1064c2c66affSColin Finck const WCHAR **iter; 1065c2c66affSColin Finck 1066c2c66affSColin Finck TRACE("accept types:\n"); 1067c2c66affSColin Finck for(iter = types; *iter; iter++) 1068c2c66affSColin Finck TRACE(" %s\n", debugstr_w(*iter)); 1069c2c66affSColin Finck } 1070c2c66affSColin Finck 1071c2c66affSColin Finck if (!(connect = (connect_t *)grab_object( hconnect ))) 1072c2c66affSColin Finck { 1073c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 1074c2c66affSColin Finck return NULL; 1075c2c66affSColin Finck } 1076c2c66affSColin Finck if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT) 1077c2c66affSColin Finck { 1078c2c66affSColin Finck release_object( &connect->hdr ); 1079c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 1080c2c66affSColin Finck return NULL; 1081c2c66affSColin Finck } 1082c2c66affSColin Finck if (!(request = heap_alloc_zero( sizeof(request_t) ))) 1083c2c66affSColin Finck { 1084c2c66affSColin Finck release_object( &connect->hdr ); 1085c2c66affSColin Finck return NULL; 1086c2c66affSColin Finck } 1087c2c66affSColin Finck request->hdr.type = WINHTTP_HANDLE_TYPE_REQUEST; 1088c2c66affSColin Finck request->hdr.vtbl = &request_vtbl; 1089c2c66affSColin Finck request->hdr.refs = 1; 1090c2c66affSColin Finck request->hdr.flags = flags; 1091c2c66affSColin Finck request->hdr.callback = connect->hdr.callback; 1092c2c66affSColin Finck request->hdr.notify_mask = connect->hdr.notify_mask; 1093c2c66affSColin Finck request->hdr.context = connect->hdr.context; 1094c2c66affSColin Finck request->hdr.redirect_policy = connect->hdr.redirect_policy; 1095c2c66affSColin Finck list_init( &request->hdr.children ); 1096c2c66affSColin Finck list_init( &request->task_queue ); 1097c2c66affSColin Finck 1098c2c66affSColin Finck addref_object( &connect->hdr ); 1099c2c66affSColin Finck request->connect = connect; 1100c2c66affSColin Finck list_add_head( &connect->hdr.children, &request->hdr.entry ); 1101c2c66affSColin Finck 1102c2c66affSColin Finck request->resolve_timeout = connect->session->resolve_timeout; 1103c2c66affSColin Finck request->connect_timeout = connect->session->connect_timeout; 1104c2c66affSColin Finck request->send_timeout = connect->session->send_timeout; 1105c2c66affSColin Finck request->recv_timeout = connect->session->recv_timeout; 1106c2c66affSColin Finck 1107c2c66affSColin Finck if (!verb || !verb[0]) verb = getW; 1108c2c66affSColin Finck if (!(request->verb = strdupW( verb ))) goto end; 1109c2c66affSColin Finck 1110c2c66affSColin Finck if (object) 1111c2c66affSColin Finck { 1112c2c66affSColin Finck WCHAR *path, *p; 1113c2c66affSColin Finck unsigned int len; 1114c2c66affSColin Finck 1115c2c66affSColin Finck len = strlenW( object ) + 1; 1116c2c66affSColin Finck if (object[0] != '/') len++; 1117c2c66affSColin Finck if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end; 1118c2c66affSColin Finck 1119c2c66affSColin Finck if (object[0] != '/') *p++ = '/'; 1120c2c66affSColin Finck strcpyW( p, object ); 1121c2c66affSColin Finck request->path = path; 1122c2c66affSColin Finck } 1123c2c66affSColin Finck else if (!(request->path = strdupW( slashW ))) goto end; 1124c2c66affSColin Finck 1125c2c66affSColin Finck if (!version || !version[0]) version = http1_1; 1126c2c66affSColin Finck if (!(request->version = strdupW( version ))) goto end; 1127c2c66affSColin Finck if (!(store_accept_types( request, types ))) goto end; 1128c2c66affSColin Finck 1129c2c66affSColin Finck if (!(hrequest = alloc_handle( &request->hdr ))) goto end; 1130c2c66affSColin Finck request->hdr.handle = hrequest; 1131c2c66affSColin Finck 1132c2c66affSColin Finck send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hrequest, sizeof(hrequest) ); 1133c2c66affSColin Finck 1134c2c66affSColin Finck end: 1135c2c66affSColin Finck release_object( &request->hdr ); 1136c2c66affSColin Finck release_object( &connect->hdr ); 1137c2c66affSColin Finck TRACE("returning %p\n", hrequest); 1138c2c66affSColin Finck if (hrequest) set_last_error( ERROR_SUCCESS ); 1139c2c66affSColin Finck return hrequest; 1140c2c66affSColin Finck } 1141c2c66affSColin Finck 1142c2c66affSColin Finck /*********************************************************************** 1143c2c66affSColin Finck * WinHttpCloseHandle (winhttp.@) 1144c2c66affSColin Finck */ 1145c2c66affSColin Finck BOOL WINAPI WinHttpCloseHandle( HINTERNET handle ) 1146c2c66affSColin Finck { 1147c2c66affSColin Finck object_header_t *hdr; 1148c2c66affSColin Finck 1149c2c66affSColin Finck TRACE("%p\n", handle); 1150c2c66affSColin Finck 1151c2c66affSColin Finck if (!(hdr = grab_object( handle ))) 1152c2c66affSColin Finck { 1153c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 1154c2c66affSColin Finck return FALSE; 1155c2c66affSColin Finck } 1156c2c66affSColin Finck release_object( hdr ); 1157c2c66affSColin Finck free_handle( handle ); 1158c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 1159c2c66affSColin Finck return TRUE; 1160c2c66affSColin Finck } 1161c2c66affSColin Finck 1162c2c66affSColin Finck static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) 1163c2c66affSColin Finck { 1164c2c66affSColin Finck BOOL ret = FALSE; 1165c2c66affSColin Finck 1166c2c66affSColin Finck if (!buflen) 1167c2c66affSColin Finck { 1168c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1169c2c66affSColin Finck return FALSE; 1170c2c66affSColin Finck } 1171c2c66affSColin Finck 1172c2c66affSColin Finck switch (option) 1173c2c66affSColin Finck { 1174c2c66affSColin Finck case WINHTTP_OPTION_CONTEXT_VALUE: 1175c2c66affSColin Finck { 1176c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD_PTR)) 1177c2c66affSColin Finck { 1178c2c66affSColin Finck *buflen = sizeof(DWORD_PTR); 1179c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 1180c2c66affSColin Finck return FALSE; 1181c2c66affSColin Finck } 1182c2c66affSColin Finck 1183c2c66affSColin Finck *(DWORD_PTR *)buffer = hdr->context; 1184c2c66affSColin Finck *buflen = sizeof(DWORD_PTR); 1185c2c66affSColin Finck return TRUE; 1186c2c66affSColin Finck } 1187c2c66affSColin Finck default: 1188c2c66affSColin Finck if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen ); 1189c2c66affSColin Finck else 1190c2c66affSColin Finck { 1191c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 1192c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 1193c2c66affSColin Finck return FALSE; 1194c2c66affSColin Finck } 1195c2c66affSColin Finck break; 1196c2c66affSColin Finck } 1197c2c66affSColin Finck return ret; 1198c2c66affSColin Finck } 1199c2c66affSColin Finck 1200c2c66affSColin Finck /*********************************************************************** 1201c2c66affSColin Finck * WinHttpQueryOption (winhttp.@) 1202c2c66affSColin Finck */ 1203c2c66affSColin Finck BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen ) 1204c2c66affSColin Finck { 1205c2c66affSColin Finck BOOL ret = FALSE; 1206c2c66affSColin Finck object_header_t *hdr; 1207c2c66affSColin Finck 1208c2c66affSColin Finck TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen); 1209c2c66affSColin Finck 1210c2c66affSColin Finck if (!(hdr = grab_object( handle ))) 1211c2c66affSColin Finck { 1212c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 1213c2c66affSColin Finck return FALSE; 1214c2c66affSColin Finck } 1215c2c66affSColin Finck 1216c2c66affSColin Finck ret = query_option( hdr, option, buffer, buflen ); 1217c2c66affSColin Finck 1218c2c66affSColin Finck release_object( hdr ); 1219c2c66affSColin Finck if (ret) set_last_error( ERROR_SUCCESS ); 1220c2c66affSColin Finck return ret; 1221c2c66affSColin Finck } 1222c2c66affSColin Finck 1223c2c66affSColin Finck static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) 1224c2c66affSColin Finck { 1225c2c66affSColin Finck BOOL ret = TRUE; 1226c2c66affSColin Finck 1227c2c66affSColin Finck if (!buffer && buflen) 1228c2c66affSColin Finck { 1229c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1230c2c66affSColin Finck return FALSE; 1231c2c66affSColin Finck } 1232c2c66affSColin Finck 1233c2c66affSColin Finck switch (option) 1234c2c66affSColin Finck { 1235c2c66affSColin Finck case WINHTTP_OPTION_CONTEXT_VALUE: 1236c2c66affSColin Finck { 1237c2c66affSColin Finck if (buflen != sizeof(DWORD_PTR)) 1238c2c66affSColin Finck { 1239c2c66affSColin Finck set_last_error( ERROR_INSUFFICIENT_BUFFER ); 1240c2c66affSColin Finck return FALSE; 1241c2c66affSColin Finck } 1242c2c66affSColin Finck 1243c2c66affSColin Finck hdr->context = *(DWORD_PTR *)buffer; 1244c2c66affSColin Finck return TRUE; 1245c2c66affSColin Finck } 1246c2c66affSColin Finck default: 1247c2c66affSColin Finck if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen ); 1248c2c66affSColin Finck else 1249c2c66affSColin Finck { 1250c2c66affSColin Finck FIXME("unimplemented option %u\n", option); 1251c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 1252c2c66affSColin Finck return FALSE; 1253c2c66affSColin Finck } 1254c2c66affSColin Finck break; 1255c2c66affSColin Finck } 1256c2c66affSColin Finck return ret; 1257c2c66affSColin Finck } 1258c2c66affSColin Finck 1259c2c66affSColin Finck /*********************************************************************** 1260c2c66affSColin Finck * WinHttpSetOption (winhttp.@) 1261c2c66affSColin Finck */ 1262c2c66affSColin Finck BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen ) 1263c2c66affSColin Finck { 1264c2c66affSColin Finck BOOL ret = FALSE; 1265c2c66affSColin Finck object_header_t *hdr; 1266c2c66affSColin Finck 1267c2c66affSColin Finck TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen); 1268c2c66affSColin Finck 1269c2c66affSColin Finck if (!(hdr = grab_object( handle ))) 1270c2c66affSColin Finck { 1271c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 1272c2c66affSColin Finck return FALSE; 1273c2c66affSColin Finck } 1274c2c66affSColin Finck 1275c2c66affSColin Finck ret = set_option( hdr, option, buffer, buflen ); 1276c2c66affSColin Finck 1277c2c66affSColin Finck release_object( hdr ); 1278c2c66affSColin Finck if (ret) set_last_error( ERROR_SUCCESS ); 1279c2c66affSColin Finck return ret; 1280c2c66affSColin Finck } 1281c2c66affSColin Finck 1282c2c66affSColin Finck static char *get_computer_name( COMPUTER_NAME_FORMAT format ) 1283c2c66affSColin Finck { 1284c2c66affSColin Finck char *ret; 1285c2c66affSColin Finck DWORD size = 0; 1286c2c66affSColin Finck 1287c2c66affSColin Finck GetComputerNameExA( format, NULL, &size ); 1288c2c66affSColin Finck if (GetLastError() != ERROR_MORE_DATA) return NULL; 1289c2c66affSColin Finck if (!(ret = heap_alloc( size ))) return NULL; 1290c2c66affSColin Finck if (!GetComputerNameExA( format, ret, &size )) 1291c2c66affSColin Finck { 1292c2c66affSColin Finck heap_free( ret ); 1293c2c66affSColin Finck return NULL; 1294c2c66affSColin Finck } 1295c2c66affSColin Finck return ret; 1296c2c66affSColin Finck } 1297c2c66affSColin Finck 1298c2c66affSColin Finck static BOOL is_domain_suffix( const char *domain, const char *suffix ) 1299c2c66affSColin Finck { 1300c2c66affSColin Finck int len_domain = strlen( domain ), len_suffix = strlen( suffix ); 1301c2c66affSColin Finck 1302c2c66affSColin Finck if (len_suffix > len_domain) return FALSE; 1303c2c66affSColin Finck if (!strcasecmp( domain + len_domain - len_suffix, suffix )) return TRUE; 1304c2c66affSColin Finck return FALSE; 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len ) 1308c2c66affSColin Finck { 1309c2c66affSColin Finck int ret = -1; 1310c2c66affSColin Finck #ifdef HAVE_GETNAMEINFO 1311c2c66affSColin Finck ret = getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); 1312c2c66affSColin Finck #endif 1313c2c66affSColin Finck return ret; 1314c2c66affSColin Finck } 1315c2c66affSColin Finck 1316c2c66affSColin Finck static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai ) 1317c2c66affSColin Finck { 1318c2c66affSColin Finck static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0}; 1319c2c66affSColin Finck static const WCHAR wpadW[] = {'/','w','p','a','d','.','d','a','t',0}; 1320c2c66affSColin Finck char name[NI_MAXHOST]; 1321c2c66affSColin Finck WCHAR *ret, *p; 1322c2c66affSColin Finck int len; 1323c2c66affSColin Finck 1324c2c66affSColin Finck while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next; 1325c2c66affSColin Finck if (!ai) return NULL; 1326c2c66affSColin Finck 1327c2c66affSColin Finck if (!reverse_lookup( ai, name, sizeof(name) )) hostname = name; 1328c2c66affSColin Finck 1329c2c66affSColin Finck len = strlenW( httpW ) + strlen( hostname ) + strlenW( wpadW ); 1330c2c66affSColin Finck if (!(ret = p = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) return NULL; 1331c2c66affSColin Finck strcpyW( p, httpW ); 1332c2c66affSColin Finck p += strlenW( httpW ); 1333c2c66affSColin Finck while (*hostname) { *p++ = *hostname++; } 1334c2c66affSColin Finck strcpyW( p, wpadW ); 1335c2c66affSColin Finck return ret; 1336c2c66affSColin Finck } 1337c2c66affSColin Finck 1338c2c66affSColin Finck static BOOL get_system_proxy_autoconfig_url( char *buf, DWORD buflen ) 1339c2c66affSColin Finck { 1340c2c66affSColin Finck #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 1341c2c66affSColin Finck CFDictionaryRef settings = CFNetworkCopySystemProxySettings(); 1342c2c66affSColin Finck const void *ref; 1343c2c66affSColin Finck BOOL ret = FALSE; 1344c2c66affSColin Finck 1345c2c66affSColin Finck if (!settings) return FALSE; 1346c2c66affSColin Finck 1347c2c66affSColin Finck if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString ))) 1348c2c66affSColin Finck { 1349c2c66affSColin Finck CFRelease( settings ); 1350c2c66affSColin Finck return FALSE; 1351c2c66affSColin Finck } 1352c2c66affSColin Finck if (CFStringGetCString( ref, buf, buflen, kCFStringEncodingASCII )) 1353c2c66affSColin Finck { 1354c2c66affSColin Finck TRACE( "returning %s\n", debugstr_a(buf) ); 1355c2c66affSColin Finck ret = TRUE; 1356c2c66affSColin Finck } 1357c2c66affSColin Finck CFRelease( settings ); 1358c2c66affSColin Finck return ret; 1359c2c66affSColin Finck #else 1360c2c66affSColin Finck static BOOL first = TRUE; 1361c2c66affSColin Finck if (first) 1362c2c66affSColin Finck { 1363c2c66affSColin Finck FIXME( "no support on this platform\n" ); 1364c2c66affSColin Finck first = FALSE; 1365c2c66affSColin Finck } 1366c2c66affSColin Finck else 1367c2c66affSColin Finck TRACE( "no support on this platform\n" ); 1368c2c66affSColin Finck return FALSE; 1369c2c66affSColin Finck #endif 1370c2c66affSColin Finck } 1371c2c66affSColin Finck 1372c2c66affSColin Finck #define INTERNET_MAX_URL_LENGTH 2084 1373c2c66affSColin Finck 1374c2c66affSColin Finck /*********************************************************************** 1375c2c66affSColin Finck * WinHttpDetectAutoProxyConfigUrl (winhttp.@) 1376c2c66affSColin Finck */ 1377c2c66affSColin Finck BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url ) 1378c2c66affSColin Finck { 1379c2c66affSColin Finck BOOL ret = FALSE; 1380c2c66affSColin Finck char system_url[INTERNET_MAX_URL_LENGTH + 1]; 1381c2c66affSColin Finck 1382c2c66affSColin Finck TRACE("0x%08x, %p\n", flags, url); 1383c2c66affSColin Finck 1384c2c66affSColin Finck if (!flags || !url) 1385c2c66affSColin Finck { 1386c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1387c2c66affSColin Finck return FALSE; 1388c2c66affSColin Finck } 1389c2c66affSColin Finck if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) )) 1390c2c66affSColin Finck { 1391c2c66affSColin Finck WCHAR *urlW; 1392c2c66affSColin Finck 1393c2c66affSColin Finck if (!(urlW = strdupAW( system_url ))) return FALSE; 1394c2c66affSColin Finck *url = urlW; 1395c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 1396c2c66affSColin Finck return TRUE; 1397c2c66affSColin Finck } 1398c2c66affSColin Finck if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP) 1399c2c66affSColin Finck { 1400c2c66affSColin Finck static int fixme_shown; 1401c2c66affSColin Finck if (!fixme_shown++) FIXME("discovery via DHCP not supported\n"); 1402c2c66affSColin Finck } 1403c2c66affSColin Finck if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A) 1404c2c66affSColin Finck { 1405c2c66affSColin Finck #ifdef HAVE_GETADDRINFO 1406c2c66affSColin Finck char *fqdn, *domain, *p; 1407c2c66affSColin Finck 1408c2c66affSColin Finck if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return FALSE; 1409c2c66affSColin Finck if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain ))) 1410c2c66affSColin Finck { 1411c2c66affSColin Finck heap_free( fqdn ); 1412c2c66affSColin Finck return FALSE; 1413c2c66affSColin Finck } 1414c2c66affSColin Finck p = fqdn; 1415c2c66affSColin Finck while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain )) 1416c2c66affSColin Finck { 1417c2c66affSColin Finck struct addrinfo *ai; 1418c2c66affSColin Finck char *name; 1419c2c66affSColin Finck int res; 1420c2c66affSColin Finck 1421c2c66affSColin Finck if (!(name = heap_alloc( sizeof("wpad") + strlen(p) ))) 1422c2c66affSColin Finck { 1423c2c66affSColin Finck heap_free( fqdn ); 1424c2c66affSColin Finck heap_free( domain ); 1425c2c66affSColin Finck return FALSE; 1426c2c66affSColin Finck } 1427c2c66affSColin Finck strcpy( name, "wpad" ); 1428c2c66affSColin Finck strcat( name, p ); 1429c2c66affSColin Finck res = getaddrinfo( name, NULL, NULL, &ai ); 1430c2c66affSColin Finck if (!res) 1431c2c66affSColin Finck { 1432c2c66affSColin Finck *url = build_wpad_url( name, ai ); 1433c2c66affSColin Finck freeaddrinfo( ai ); 1434c2c66affSColin Finck if (*url) 1435c2c66affSColin Finck { 1436c2c66affSColin Finck TRACE("returning %s\n", debugstr_w(*url)); 1437c2c66affSColin Finck heap_free( name ); 1438c2c66affSColin Finck ret = TRUE; 1439c2c66affSColin Finck break; 1440c2c66affSColin Finck } 1441c2c66affSColin Finck } 1442c2c66affSColin Finck heap_free( name ); 1443c2c66affSColin Finck p++; 1444c2c66affSColin Finck } 1445c2c66affSColin Finck heap_free( domain ); 1446c2c66affSColin Finck heap_free( fqdn ); 1447c2c66affSColin Finck #else 1448c2c66affSColin Finck FIXME("getaddrinfo not found at build time\n"); 1449c2c66affSColin Finck #endif 1450c2c66affSColin Finck } 1451c2c66affSColin Finck if (!ret) 1452c2c66affSColin Finck { 1453c2c66affSColin Finck set_last_error( ERROR_WINHTTP_AUTODETECTION_FAILED ); 1454c2c66affSColin Finck *url = NULL; 1455c2c66affSColin Finck } 1456c2c66affSColin Finck else set_last_error( ERROR_SUCCESS ); 1457c2c66affSColin Finck return ret; 1458c2c66affSColin Finck } 1459c2c66affSColin Finck 1460c2c66affSColin Finck static const WCHAR Connections[] = { 1461c2c66affSColin Finck 'S','o','f','t','w','a','r','e','\\', 1462c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\', 1463c2c66affSColin Finck 'W','i','n','d','o','w','s','\\', 1464c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 1465c2c66affSColin Finck 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\', 1466c2c66affSColin Finck 'C','o','n','n','e','c','t','i','o','n','s',0 }; 1467c2c66affSColin Finck static const WCHAR WinHttpSettings[] = { 1468c2c66affSColin Finck 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 }; 1469c2c66affSColin Finck static const DWORD WINHTTP_SETTINGS_MAGIC = 0x18; 1470c2c66affSColin Finck static const DWORD WININET_SETTINGS_MAGIC = 0x46; 1471c2c66affSColin Finck static const DWORD PROXY_TYPE_DIRECT = 1; 1472c2c66affSColin Finck static const DWORD PROXY_TYPE_PROXY = 2; 1473c2c66affSColin Finck static const DWORD PROXY_USE_PAC_SCRIPT = 4; 1474c2c66affSColin Finck static const DWORD PROXY_AUTODETECT_SETTINGS = 8; 1475c2c66affSColin Finck 1476c2c66affSColin Finck struct connection_settings_header 1477c2c66affSColin Finck { 1478c2c66affSColin Finck DWORD magic; 1479c2c66affSColin Finck DWORD unknown; /* always zero? */ 1480c2c66affSColin Finck DWORD flags; /* one or more of PROXY_* */ 1481c2c66affSColin Finck }; 1482c2c66affSColin Finck 1483c2c66affSColin Finck static inline void copy_char_to_wchar_sz(const BYTE *src, DWORD len, WCHAR *dst) 1484c2c66affSColin Finck { 1485c2c66affSColin Finck const BYTE *begin; 1486c2c66affSColin Finck 1487c2c66affSColin Finck for (begin = src; src - begin < len; src++, dst++) 1488c2c66affSColin Finck *dst = *src; 1489c2c66affSColin Finck *dst = 0; 1490c2c66affSColin Finck } 1491c2c66affSColin Finck 1492c2c66affSColin Finck /*********************************************************************** 1493c2c66affSColin Finck * WinHttpGetDefaultProxyConfiguration (winhttp.@) 1494c2c66affSColin Finck */ 1495c2c66affSColin Finck BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) 1496c2c66affSColin Finck { 1497c2c66affSColin Finck LONG l; 1498c2c66affSColin Finck HKEY key; 1499c2c66affSColin Finck BOOL got_from_reg = FALSE, direct = TRUE; 1500c2c66affSColin Finck char *envproxy; 1501c2c66affSColin Finck 1502c2c66affSColin Finck TRACE("%p\n", info); 1503c2c66affSColin Finck 1504c2c66affSColin Finck l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key ); 1505c2c66affSColin Finck if (!l) 1506c2c66affSColin Finck { 1507c2c66affSColin Finck DWORD type, size = 0; 1508c2c66affSColin Finck 1509c2c66affSColin Finck l = RegQueryValueExW( key, WinHttpSettings, NULL, &type, NULL, &size ); 1510c2c66affSColin Finck if (!l && type == REG_BINARY && 1511c2c66affSColin Finck size >= sizeof(struct connection_settings_header) + 2 * sizeof(DWORD)) 1512c2c66affSColin Finck { 1513c2c66affSColin Finck BYTE *buf = heap_alloc( size ); 1514c2c66affSColin Finck 1515c2c66affSColin Finck if (buf) 1516c2c66affSColin Finck { 1517c2c66affSColin Finck struct connection_settings_header *hdr = 1518c2c66affSColin Finck (struct connection_settings_header *)buf; 1519c2c66affSColin Finck DWORD *len = (DWORD *)(hdr + 1); 1520c2c66affSColin Finck 1521c2c66affSColin Finck l = RegQueryValueExW( key, WinHttpSettings, NULL, NULL, buf, 1522c2c66affSColin Finck &size ); 1523c2c66affSColin Finck if (!l && hdr->magic == WINHTTP_SETTINGS_MAGIC && 1524c2c66affSColin Finck hdr->unknown == 0) 1525c2c66affSColin Finck { 1526c2c66affSColin Finck if (hdr->flags & PROXY_TYPE_PROXY) 1527c2c66affSColin Finck { 1528c2c66affSColin Finck BOOL sane = FALSE; 1529c2c66affSColin Finck LPWSTR proxy = NULL; 1530c2c66affSColin Finck LPWSTR proxy_bypass = NULL; 1531c2c66affSColin Finck 1532c2c66affSColin Finck /* Sanity-check length of proxy string */ 1533c2c66affSColin Finck if ((BYTE *)len - buf + *len <= size) 1534c2c66affSColin Finck { 1535c2c66affSColin Finck sane = TRUE; 1536c2c66affSColin Finck proxy = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) ); 1537c2c66affSColin Finck if (proxy) 1538c2c66affSColin Finck copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy ); 1539c2c66affSColin Finck len = (DWORD *)((BYTE *)(len + 1) + *len); 1540c2c66affSColin Finck } 1541c2c66affSColin Finck if (sane) 1542c2c66affSColin Finck { 1543c2c66affSColin Finck /* Sanity-check length of proxy bypass string */ 1544c2c66affSColin Finck if ((BYTE *)len - buf + *len <= size) 1545c2c66affSColin Finck { 1546c2c66affSColin Finck proxy_bypass = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) ); 1547c2c66affSColin Finck if (proxy_bypass) 1548c2c66affSColin Finck copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy_bypass ); 1549c2c66affSColin Finck } 1550c2c66affSColin Finck else 1551c2c66affSColin Finck { 1552c2c66affSColin Finck sane = FALSE; 1553c2c66affSColin Finck GlobalFree( proxy ); 1554c2c66affSColin Finck proxy = NULL; 1555c2c66affSColin Finck } 1556c2c66affSColin Finck } 1557c2c66affSColin Finck info->lpszProxy = proxy; 1558c2c66affSColin Finck info->lpszProxyBypass = proxy_bypass; 1559c2c66affSColin Finck if (sane) 1560c2c66affSColin Finck { 1561c2c66affSColin Finck got_from_reg = TRUE; 1562c2c66affSColin Finck direct = FALSE; 1563c2c66affSColin Finck info->dwAccessType = 1564c2c66affSColin Finck WINHTTP_ACCESS_TYPE_NAMED_PROXY; 1565c2c66affSColin Finck TRACE("http proxy (from registry) = %s, bypass = %s\n", 1566c2c66affSColin Finck debugstr_w(info->lpszProxy), 1567c2c66affSColin Finck debugstr_w(info->lpszProxyBypass)); 1568c2c66affSColin Finck } 1569c2c66affSColin Finck } 1570c2c66affSColin Finck } 1571c2c66affSColin Finck heap_free( buf ); 1572c2c66affSColin Finck } 1573c2c66affSColin Finck } 1574c2c66affSColin Finck RegCloseKey( key ); 1575c2c66affSColin Finck } 1576c2c66affSColin Finck if (!got_from_reg && (envproxy = getenv( "http_proxy" ))) 1577c2c66affSColin Finck { 1578c2c66affSColin Finck char *colon, *http_proxy; 1579c2c66affSColin Finck 1580c2c66affSColin Finck if ((colon = strchr( envproxy, ':' ))) 1581c2c66affSColin Finck { 1582c2c66affSColin Finck if (*(colon + 1) == '/' && *(colon + 2) == '/') 1583c2c66affSColin Finck { 1584c2c66affSColin Finck static const char http[] = "http://"; 1585c2c66affSColin Finck 1586c2c66affSColin Finck /* It's a scheme, check that it's http */ 1587c2c66affSColin Finck if (!strncmp( envproxy, http, strlen( http ) )) 1588c2c66affSColin Finck http_proxy = envproxy + strlen( http ); 1589c2c66affSColin Finck else 1590c2c66affSColin Finck { 1591c2c66affSColin Finck WARN("unsupported scheme in $http_proxy: %s\n", envproxy); 1592c2c66affSColin Finck http_proxy = NULL; 1593c2c66affSColin Finck } 1594c2c66affSColin Finck } 1595c2c66affSColin Finck else 1596c2c66affSColin Finck http_proxy = envproxy; 1597c2c66affSColin Finck } 1598c2c66affSColin Finck else 1599c2c66affSColin Finck http_proxy = envproxy; 1600c2c66affSColin Finck if (http_proxy) 1601c2c66affSColin Finck { 1602c2c66affSColin Finck WCHAR *http_proxyW; 1603c2c66affSColin Finck int len; 1604c2c66affSColin Finck 1605c2c66affSColin Finck len = MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, NULL, 0 ); 1606c2c66affSColin Finck if ((http_proxyW = GlobalAlloc( 0, len * sizeof(WCHAR)))) 1607c2c66affSColin Finck { 1608c2c66affSColin Finck MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, http_proxyW, len ); 1609c2c66affSColin Finck direct = FALSE; 1610c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 1611c2c66affSColin Finck info->lpszProxy = http_proxyW; 1612c2c66affSColin Finck info->lpszProxyBypass = NULL; 1613c2c66affSColin Finck TRACE("http proxy (from environment) = %s\n", 1614c2c66affSColin Finck debugstr_w(info->lpszProxy)); 1615c2c66affSColin Finck } 1616c2c66affSColin Finck } 1617c2c66affSColin Finck } 1618c2c66affSColin Finck if (direct) 1619c2c66affSColin Finck { 1620c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY; 1621c2c66affSColin Finck info->lpszProxy = NULL; 1622c2c66affSColin Finck info->lpszProxyBypass = NULL; 1623c2c66affSColin Finck } 1624c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 1625c2c66affSColin Finck return TRUE; 1626c2c66affSColin Finck } 1627c2c66affSColin Finck 1628c2c66affSColin Finck /*********************************************************************** 1629c2c66affSColin Finck * WinHttpGetIEProxyConfigForCurrentUser (winhttp.@) 1630c2c66affSColin Finck */ 1631c2c66affSColin Finck BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *config ) 1632c2c66affSColin Finck { 1633c2c66affSColin Finck static const WCHAR settingsW[] = 1634c2c66affSColin Finck {'D','e','f','a','u','l','t','C','o','n','n','e','c','t','i','o','n','S','e','t','t','i','n','g','s',0}; 1635c2c66affSColin Finck HKEY hkey = NULL; 1636c2c66affSColin Finck struct connection_settings_header *hdr = NULL; 1637c2c66affSColin Finck DWORD type, offset, len, size = 0; 1638c2c66affSColin Finck BOOL ret = FALSE; 1639c2c66affSColin Finck 1640c2c66affSColin Finck TRACE("%p\n", config); 1641c2c66affSColin Finck 1642c2c66affSColin Finck if (!config) 1643c2c66affSColin Finck { 1644c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1645c2c66affSColin Finck return FALSE; 1646c2c66affSColin Finck } 1647c2c66affSColin Finck memset( config, 0, sizeof(*config) ); 1648c2c66affSColin Finck config->fAutoDetect = TRUE; 1649c2c66affSColin Finck 1650c2c66affSColin Finck if (RegOpenKeyExW( HKEY_CURRENT_USER, Connections, 0, KEY_READ, &hkey ) || 1651c2c66affSColin Finck RegQueryValueExW( hkey, settingsW, NULL, &type, NULL, &size ) || 1652c2c66affSColin Finck type != REG_BINARY || size < sizeof(struct connection_settings_header)) 1653c2c66affSColin Finck { 1654c2c66affSColin Finck ret = TRUE; 1655c2c66affSColin Finck goto done; 1656c2c66affSColin Finck } 1657c2c66affSColin Finck if (!(hdr = heap_alloc( size ))) goto done; 1658c2c66affSColin Finck if (RegQueryValueExW( hkey, settingsW, NULL, &type, (BYTE *)hdr, &size ) || 1659c2c66affSColin Finck hdr->magic != WININET_SETTINGS_MAGIC) 1660c2c66affSColin Finck { 1661c2c66affSColin Finck ret = TRUE; 1662c2c66affSColin Finck goto done; 1663c2c66affSColin Finck } 1664c2c66affSColin Finck 1665c2c66affSColin Finck config->fAutoDetect = (hdr->flags & PROXY_AUTODETECT_SETTINGS) != 0; 1666c2c66affSColin Finck offset = sizeof(*hdr); 1667c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done; 1668c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset); 1669c2c66affSColin Finck offset += sizeof(DWORD); 1670c2c66affSColin Finck if (len && hdr->flags & PROXY_TYPE_PROXY) 1671c2c66affSColin Finck { 1672c2c66affSColin Finck if (!(config->lpszProxy = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done; 1673c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxy ); 1674c2c66affSColin Finck } 1675c2c66affSColin Finck offset += len; 1676c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done; 1677c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset); 1678c2c66affSColin Finck offset += sizeof(DWORD); 1679c2c66affSColin Finck if (len && (hdr->flags & PROXY_TYPE_PROXY)) 1680c2c66affSColin Finck { 1681c2c66affSColin Finck if (!(config->lpszProxyBypass = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done; 1682c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxyBypass ); 1683c2c66affSColin Finck } 1684c2c66affSColin Finck offset += len; 1685c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done; 1686c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset); 1687c2c66affSColin Finck offset += sizeof(DWORD); 1688c2c66affSColin Finck if (len && (hdr->flags & PROXY_USE_PAC_SCRIPT)) 1689c2c66affSColin Finck { 1690c2c66affSColin Finck if (!(config->lpszAutoConfigUrl = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done; 1691c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszAutoConfigUrl ); 1692c2c66affSColin Finck } 1693c2c66affSColin Finck ret = TRUE; 1694c2c66affSColin Finck 1695c2c66affSColin Finck done: 1696c2c66affSColin Finck RegCloseKey( hkey ); 1697c2c66affSColin Finck heap_free( hdr ); 1698c2c66affSColin Finck if (!ret) 1699c2c66affSColin Finck { 1700c2c66affSColin Finck GlobalFree( config->lpszAutoConfigUrl ); 1701c2c66affSColin Finck config->lpszAutoConfigUrl = NULL; 1702c2c66affSColin Finck GlobalFree( config->lpszProxy ); 1703c2c66affSColin Finck config->lpszProxy = NULL; 1704c2c66affSColin Finck GlobalFree( config->lpszProxyBypass ); 1705c2c66affSColin Finck config->lpszProxyBypass = NULL; 1706c2c66affSColin Finck } 1707c2c66affSColin Finck else set_last_error( ERROR_SUCCESS ); 1708c2c66affSColin Finck return ret; 1709c2c66affSColin Finck } 1710c2c66affSColin Finck 1711c2c66affSColin Finck static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info ) 1712c2c66affSColin Finck { 1713c2c66affSColin Finck const char *p; 1714c2c66affSColin Finck WCHAR *q; 1715c2c66affSColin Finck int len; 1716c2c66affSColin Finck 1717c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY; 1718c2c66affSColin Finck info->lpszProxy = NULL; 1719c2c66affSColin Finck info->lpszProxyBypass = NULL; 1720c2c66affSColin Finck 1721c2c66affSColin Finck TRACE("%s\n", debugstr_a( result )); 1722c2c66affSColin Finck 1723c2c66affSColin Finck p = result; 1724c2c66affSColin Finck while (*p == ' ') p++; 1725c2c66affSColin Finck len = strlen( p ); 1726c2c66affSColin Finck if (len >= 5 && !strncasecmp( p, "PROXY", sizeof("PROXY") - 1 )) 1727c2c66affSColin Finck { 1728c2c66affSColin Finck p += 5; 1729c2c66affSColin Finck while (*p == ' ') p++; 1730c2c66affSColin Finck if (!*p || *p == ';') return TRUE; 1731c2c66affSColin Finck if (!(info->lpszProxy = q = strdupAW( p ))) return FALSE; 1732c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 1733c2c66affSColin Finck for (; *q; q++) 1734c2c66affSColin Finck { 1735c2c66affSColin Finck if (*q == ' ' || *q == ';') 1736c2c66affSColin Finck { 1737c2c66affSColin Finck *q = 0; 1738c2c66affSColin Finck break; 1739c2c66affSColin Finck } 1740c2c66affSColin Finck } 1741c2c66affSColin Finck } 1742c2c66affSColin Finck return TRUE; 1743c2c66affSColin Finck } 1744c2c66affSColin Finck 1745c2c66affSColin Finck static char *download_script( const WCHAR *url, DWORD *out_size ) 1746c2c66affSColin Finck { 1747c2c66affSColin Finck static const WCHAR typeW[] = {'*','/','*',0}; 1748c2c66affSColin Finck static const WCHAR *acceptW[] = {typeW, NULL}; 1749c2c66affSColin Finck HINTERNET ses, con = NULL, req = NULL; 1750c2c66affSColin Finck WCHAR *hostname; 1751c2c66affSColin Finck URL_COMPONENTSW uc; 1752c2c66affSColin Finck DWORD status, size = sizeof(status), offset, to_read, bytes_read, flags = 0; 1753c2c66affSColin Finck char *tmp, *buffer = NULL; 1754c2c66affSColin Finck 1755c2c66affSColin Finck *out_size = 0; 1756c2c66affSColin Finck 1757c2c66affSColin Finck memset( &uc, 0, sizeof(uc) ); 1758c2c66affSColin Finck uc.dwStructSize = sizeof(uc); 1759c2c66affSColin Finck uc.dwHostNameLength = -1; 1760c2c66affSColin Finck uc.dwUrlPathLength = -1; 1761c2c66affSColin Finck if (!WinHttpCrackUrl( url, 0, 0, &uc )) return NULL; 1762c2c66affSColin Finck if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return NULL; 1763c2c66affSColin Finck memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) ); 1764c2c66affSColin Finck hostname[uc.dwHostNameLength] = 0; 1765c2c66affSColin Finck 1766c2c66affSColin Finck if (!(ses = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ))) goto done; 1767c2c66affSColin Finck if (!(con = WinHttpConnect( ses, hostname, uc.nPort, 0 ))) goto done; 1768c2c66affSColin Finck if (uc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE; 1769c2c66affSColin Finck if (!(req = WinHttpOpenRequest( con, NULL, uc.lpszUrlPath, NULL, NULL, acceptW, flags ))) goto done; 1770c2c66affSColin Finck if (!WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 )) goto done; 1771c2c66affSColin Finck 1772c2c66affSColin Finck if (!(WinHttpReceiveResponse( req, 0 ))) goto done; 1773c2c66affSColin Finck if (!WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, 1774c2c66affSColin Finck &size, NULL ) || status != HTTP_STATUS_OK) goto done; 1775c2c66affSColin Finck 1776c2c66affSColin Finck size = 4096; 1777c2c66affSColin Finck if (!(buffer = heap_alloc( size ))) goto done; 1778c2c66affSColin Finck to_read = size; 1779c2c66affSColin Finck offset = 0; 1780c2c66affSColin Finck for (;;) 1781c2c66affSColin Finck { 1782c2c66affSColin Finck if (!WinHttpReadData( req, buffer + offset, to_read, &bytes_read )) goto done; 1783c2c66affSColin Finck if (!bytes_read) break; 1784c2c66affSColin Finck to_read -= bytes_read; 1785c2c66affSColin Finck offset += bytes_read; 1786c2c66affSColin Finck *out_size += bytes_read; 1787c2c66affSColin Finck if (!to_read) 1788c2c66affSColin Finck { 1789c2c66affSColin Finck to_read = size; 1790c2c66affSColin Finck size *= 2; 1791c2c66affSColin Finck if (!(tmp = heap_realloc( buffer, size ))) goto done; 1792c2c66affSColin Finck buffer = tmp; 1793c2c66affSColin Finck } 1794c2c66affSColin Finck } 1795c2c66affSColin Finck 1796c2c66affSColin Finck done: 1797c2c66affSColin Finck WinHttpCloseHandle( req ); 1798c2c66affSColin Finck WinHttpCloseHandle( con ); 1799c2c66affSColin Finck WinHttpCloseHandle( ses ); 1800c2c66affSColin Finck heap_free( hostname ); 1801c2c66affSColin Finck if (!buffer) set_last_error( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); 1802c2c66affSColin Finck return buffer; 1803c2c66affSColin Finck } 1804c2c66affSColin Finck 1805c2c66affSColin Finck struct AUTO_PROXY_SCRIPT_BUFFER 1806c2c66affSColin Finck { 1807c2c66affSColin Finck DWORD dwStructSize; 1808c2c66affSColin Finck LPSTR lpszScriptBuffer; 1809c2c66affSColin Finck DWORD dwScriptBufferSize; 1810c2c66affSColin Finck }; 1811c2c66affSColin Finck 1812c2c66affSColin Finck BOOL WINAPI InternetDeInitializeAutoProxyDll(LPSTR, DWORD); 1813c2c66affSColin Finck BOOL WINAPI InternetGetProxyInfo(LPCSTR, DWORD, LPSTR, DWORD, LPSTR *, LPDWORD); 1814c2c66affSColin Finck BOOL WINAPI InternetInitializeAutoProxyDll(DWORD, LPSTR, LPSTR, void *, struct AUTO_PROXY_SCRIPT_BUFFER *); 1815c2c66affSColin Finck 1816c2c66affSColin Finck static BOOL run_script( char *script, DWORD size, const WCHAR *url, WINHTTP_PROXY_INFO *info ) 1817c2c66affSColin Finck { 1818c2c66affSColin Finck BOOL ret; 1819c2c66affSColin Finck char *result, *urlA; 1820c2c66affSColin Finck DWORD len_result; 1821c2c66affSColin Finck struct AUTO_PROXY_SCRIPT_BUFFER buffer; 1822c2c66affSColin Finck URL_COMPONENTSW uc; 1823c2c66affSColin Finck 1824c2c66affSColin Finck buffer.dwStructSize = sizeof(buffer); 1825c2c66affSColin Finck buffer.lpszScriptBuffer = script; 1826c2c66affSColin Finck buffer.dwScriptBufferSize = size; 1827c2c66affSColin Finck 1828c2c66affSColin Finck if (!(urlA = strdupWA( url ))) return FALSE; 1829c2c66affSColin Finck if (!(ret = InternetInitializeAutoProxyDll( 0, NULL, NULL, NULL, &buffer ))) 1830c2c66affSColin Finck { 1831c2c66affSColin Finck heap_free( urlA ); 1832c2c66affSColin Finck return FALSE; 1833c2c66affSColin Finck } 1834c2c66affSColin Finck 1835c2c66affSColin Finck memset( &uc, 0, sizeof(uc) ); 1836c2c66affSColin Finck uc.dwStructSize = sizeof(uc); 1837c2c66affSColin Finck uc.dwHostNameLength = -1; 1838c2c66affSColin Finck 1839c2c66affSColin Finck if (WinHttpCrackUrl( url, 0, 0, &uc )) 1840c2c66affSColin Finck { 1841c2c66affSColin Finck char *hostnameA = strdupWA_sized( uc.lpszHostName, uc.dwHostNameLength ); 1842c2c66affSColin Finck 1843c2c66affSColin Finck if ((ret = InternetGetProxyInfo( urlA, strlen(urlA), 1844c2c66affSColin Finck hostnameA, strlen(hostnameA), &result, &len_result ))) 1845c2c66affSColin Finck { 1846c2c66affSColin Finck ret = parse_script_result( result, info ); 1847c2c66affSColin Finck heap_free( result ); 1848c2c66affSColin Finck } 1849c2c66affSColin Finck 1850c2c66affSColin Finck heap_free( hostnameA ); 1851c2c66affSColin Finck } 1852c2c66affSColin Finck heap_free( urlA ); 1853c2c66affSColin Finck return InternetDeInitializeAutoProxyDll( NULL, 0 ); 1854c2c66affSColin Finck } 1855c2c66affSColin Finck 1856c2c66affSColin Finck /*********************************************************************** 1857c2c66affSColin Finck * WinHttpGetProxyForUrl (winhttp.@) 1858c2c66affSColin Finck */ 1859c2c66affSColin Finck BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTOPROXY_OPTIONS *options, 1860c2c66affSColin Finck WINHTTP_PROXY_INFO *info ) 1861c2c66affSColin Finck { 1862c2c66affSColin Finck WCHAR *detected_pac_url = NULL; 1863c2c66affSColin Finck const WCHAR *pac_url; 1864c2c66affSColin Finck session_t *session; 1865c2c66affSColin Finck char *script; 1866c2c66affSColin Finck DWORD size; 1867c2c66affSColin Finck BOOL ret = FALSE; 1868c2c66affSColin Finck 1869c2c66affSColin Finck TRACE("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info); 1870c2c66affSColin Finck 1871c2c66affSColin Finck if (!(session = (session_t *)grab_object( hsession ))) 1872c2c66affSColin Finck { 1873c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 1874c2c66affSColin Finck return FALSE; 1875c2c66affSColin Finck } 1876c2c66affSColin Finck if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION) 1877c2c66affSColin Finck { 1878c2c66affSColin Finck release_object( &session->hdr ); 1879c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 1880c2c66affSColin Finck return FALSE; 1881c2c66affSColin Finck } 1882c2c66affSColin Finck if (!url || !options || !info || 1883c2c66affSColin Finck !(options->dwFlags & (WINHTTP_AUTOPROXY_AUTO_DETECT|WINHTTP_AUTOPROXY_CONFIG_URL)) || 1884c2c66affSColin Finck ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) && !options->dwAutoDetectFlags) || 1885c2c66affSColin Finck ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) && 1886c2c66affSColin Finck (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL))) 1887c2c66affSColin Finck { 1888c2c66affSColin Finck release_object( &session->hdr ); 1889c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1890c2c66affSColin Finck return FALSE; 1891c2c66affSColin Finck } 1892c2c66affSColin Finck if (options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT && 1893c2c66affSColin Finck !WinHttpDetectAutoProxyConfigUrl( options->dwAutoDetectFlags, &detected_pac_url )) 1894c2c66affSColin Finck goto done; 1895c2c66affSColin Finck 1896c2c66affSColin Finck if (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL) pac_url = options->lpszAutoConfigUrl; 1897c2c66affSColin Finck else pac_url = detected_pac_url; 1898c2c66affSColin Finck 1899c2c66affSColin Finck if ((script = download_script( pac_url, &size ))) 1900c2c66affSColin Finck { 1901c2c66affSColin Finck ret = run_script( script, size, url, info ); 1902c2c66affSColin Finck heap_free( script ); 1903c2c66affSColin Finck } 1904c2c66affSColin Finck 1905c2c66affSColin Finck done: 1906c2c66affSColin Finck GlobalFree( detected_pac_url ); 1907c2c66affSColin Finck release_object( &session->hdr ); 1908c2c66affSColin Finck if (ret) set_last_error( ERROR_SUCCESS ); 1909c2c66affSColin Finck return ret; 1910c2c66affSColin Finck } 1911c2c66affSColin Finck 1912c2c66affSColin Finck /*********************************************************************** 1913c2c66affSColin Finck * WinHttpSetDefaultProxyConfiguration (winhttp.@) 1914c2c66affSColin Finck */ 1915c2c66affSColin Finck BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) 1916c2c66affSColin Finck { 1917c2c66affSColin Finck LONG l; 1918c2c66affSColin Finck HKEY key; 1919c2c66affSColin Finck BOOL ret = FALSE; 1920c2c66affSColin Finck const WCHAR *src; 1921c2c66affSColin Finck 1922c2c66affSColin Finck TRACE("%p\n", info); 1923c2c66affSColin Finck 1924c2c66affSColin Finck if (!info) 1925c2c66affSColin Finck { 1926c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1927c2c66affSColin Finck return FALSE; 1928c2c66affSColin Finck } 1929c2c66affSColin Finck switch (info->dwAccessType) 1930c2c66affSColin Finck { 1931c2c66affSColin Finck case WINHTTP_ACCESS_TYPE_NO_PROXY: 1932c2c66affSColin Finck break; 1933c2c66affSColin Finck case WINHTTP_ACCESS_TYPE_NAMED_PROXY: 1934c2c66affSColin Finck if (!info->lpszProxy) 1935c2c66affSColin Finck { 1936c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1937c2c66affSColin Finck return FALSE; 1938c2c66affSColin Finck } 1939c2c66affSColin Finck /* Only ASCII characters are allowed */ 1940c2c66affSColin Finck for (src = info->lpszProxy; *src; src++) 1941c2c66affSColin Finck if (*src > 0x7f) 1942c2c66affSColin Finck { 1943c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1944c2c66affSColin Finck return FALSE; 1945c2c66affSColin Finck } 1946c2c66affSColin Finck if (info->lpszProxyBypass) 1947c2c66affSColin Finck { 1948c2c66affSColin Finck for (src = info->lpszProxyBypass; *src; src++) 1949c2c66affSColin Finck if (*src > 0x7f) 1950c2c66affSColin Finck { 1951c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1952c2c66affSColin Finck return FALSE; 1953c2c66affSColin Finck } 1954c2c66affSColin Finck } 1955c2c66affSColin Finck break; 1956c2c66affSColin Finck default: 1957c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 1958c2c66affSColin Finck return FALSE; 1959c2c66affSColin Finck } 1960c2c66affSColin Finck 1961c2c66affSColin Finck l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, 1962c2c66affSColin Finck KEY_WRITE, NULL, &key, NULL ); 1963c2c66affSColin Finck if (!l) 1964c2c66affSColin Finck { 1965c2c66affSColin Finck DWORD size = sizeof(struct connection_settings_header) + 2 * sizeof(DWORD); 1966c2c66affSColin Finck BYTE *buf; 1967c2c66affSColin Finck 1968c2c66affSColin Finck if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY) 1969c2c66affSColin Finck { 1970c2c66affSColin Finck size += strlenW( info->lpszProxy ); 1971c2c66affSColin Finck if (info->lpszProxyBypass) 1972c2c66affSColin Finck size += strlenW( info->lpszProxyBypass ); 1973c2c66affSColin Finck } 1974c2c66affSColin Finck buf = heap_alloc( size ); 1975c2c66affSColin Finck if (buf) 1976c2c66affSColin Finck { 1977c2c66affSColin Finck struct connection_settings_header *hdr = 1978c2c66affSColin Finck (struct connection_settings_header *)buf; 1979c2c66affSColin Finck DWORD *len = (DWORD *)(hdr + 1); 1980c2c66affSColin Finck 1981c2c66affSColin Finck hdr->magic = WINHTTP_SETTINGS_MAGIC; 1982c2c66affSColin Finck hdr->unknown = 0; 1983c2c66affSColin Finck if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY) 1984c2c66affSColin Finck { 1985c2c66affSColin Finck BYTE *dst; 1986c2c66affSColin Finck 1987c2c66affSColin Finck hdr->flags = PROXY_TYPE_PROXY; 1988c2c66affSColin Finck *len++ = strlenW( info->lpszProxy ); 1989c2c66affSColin Finck for (dst = (BYTE *)len, src = info->lpszProxy; *src; 1990c2c66affSColin Finck src++, dst++) 1991c2c66affSColin Finck *dst = *src; 1992c2c66affSColin Finck len = (DWORD *)dst; 1993c2c66affSColin Finck if (info->lpszProxyBypass) 1994c2c66affSColin Finck { 1995c2c66affSColin Finck *len++ = strlenW( info->lpszProxyBypass ); 1996c2c66affSColin Finck for (dst = (BYTE *)len, src = info->lpszProxyBypass; *src; 1997c2c66affSColin Finck src++, dst++) 1998c2c66affSColin Finck *dst = *src; 1999c2c66affSColin Finck } 2000c2c66affSColin Finck else 2001c2c66affSColin Finck *len++ = 0; 2002c2c66affSColin Finck } 2003c2c66affSColin Finck else 2004c2c66affSColin Finck { 2005c2c66affSColin Finck hdr->flags = PROXY_TYPE_DIRECT; 2006c2c66affSColin Finck *len++ = 0; 2007c2c66affSColin Finck *len++ = 0; 2008c2c66affSColin Finck } 2009c2c66affSColin Finck l = RegSetValueExW( key, WinHttpSettings, 0, REG_BINARY, buf, size ); 2010c2c66affSColin Finck if (!l) 2011c2c66affSColin Finck ret = TRUE; 2012c2c66affSColin Finck heap_free( buf ); 2013c2c66affSColin Finck } 2014c2c66affSColin Finck RegCloseKey( key ); 2015c2c66affSColin Finck } 2016c2c66affSColin Finck if (ret) set_last_error( ERROR_SUCCESS ); 2017c2c66affSColin Finck return ret; 2018c2c66affSColin Finck } 2019c2c66affSColin Finck 2020c2c66affSColin Finck /*********************************************************************** 2021c2c66affSColin Finck * WinHttpSetStatusCallback (winhttp.@) 2022c2c66affSColin Finck */ 2023c2c66affSColin Finck WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback, 2024c2c66affSColin Finck DWORD flags, DWORD_PTR reserved ) 2025c2c66affSColin Finck { 2026c2c66affSColin Finck object_header_t *hdr; 2027c2c66affSColin Finck WINHTTP_STATUS_CALLBACK ret; 2028c2c66affSColin Finck 2029c2c66affSColin Finck TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved); 2030c2c66affSColin Finck 2031c2c66affSColin Finck if (!(hdr = grab_object( handle ))) 2032c2c66affSColin Finck { 2033c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 2034c2c66affSColin Finck return WINHTTP_INVALID_STATUS_CALLBACK; 2035c2c66affSColin Finck } 2036c2c66affSColin Finck ret = hdr->callback; 2037c2c66affSColin Finck hdr->callback = callback; 2038c2c66affSColin Finck hdr->notify_mask = flags; 2039c2c66affSColin Finck 2040c2c66affSColin Finck release_object( hdr ); 2041c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 2042c2c66affSColin Finck return ret; 2043c2c66affSColin Finck } 2044c2c66affSColin Finck 2045c2c66affSColin Finck /*********************************************************************** 2046c2c66affSColin Finck * WinHttpSetTimeouts (winhttp.@) 2047c2c66affSColin Finck */ 2048c2c66affSColin Finck BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive ) 2049c2c66affSColin Finck { 2050c2c66affSColin Finck BOOL ret = TRUE; 2051c2c66affSColin Finck object_header_t *hdr; 2052c2c66affSColin Finck request_t *request; 2053c2c66affSColin Finck session_t *session; 2054c2c66affSColin Finck 2055c2c66affSColin Finck TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive); 2056c2c66affSColin Finck 2057c2c66affSColin Finck if (resolve < -1 || connect < -1 || send < -1 || receive < -1) 2058c2c66affSColin Finck { 2059c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 2060c2c66affSColin Finck return FALSE; 2061c2c66affSColin Finck } 2062c2c66affSColin Finck 2063c2c66affSColin Finck if (!(hdr = grab_object( handle ))) 2064c2c66affSColin Finck { 2065c2c66affSColin Finck set_last_error( ERROR_INVALID_HANDLE ); 2066c2c66affSColin Finck return FALSE; 2067c2c66affSColin Finck } 2068c2c66affSColin Finck 2069c2c66affSColin Finck switch(hdr->type) 2070c2c66affSColin Finck { 2071c2c66affSColin Finck case WINHTTP_HANDLE_TYPE_REQUEST: 2072c2c66affSColin Finck request = (request_t *)hdr; 2073c2c66affSColin Finck request->connect_timeout = connect; 2074c2c66affSColin Finck 2075c2c66affSColin Finck if (resolve < 0) resolve = 0; 2076c2c66affSColin Finck request->resolve_timeout = resolve; 2077c2c66affSColin Finck 2078c2c66affSColin Finck if (send < 0) send = 0; 2079c2c66affSColin Finck request->send_timeout = send; 2080c2c66affSColin Finck 2081c2c66affSColin Finck if (receive < 0) receive = 0; 2082c2c66affSColin Finck request->recv_timeout = receive; 2083c2c66affSColin Finck 2084c2c66affSColin Finck if (request->netconn) 2085c2c66affSColin Finck { 2086c2c66affSColin Finck if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE; 2087c2c66affSColin Finck if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE; 2088c2c66affSColin Finck } 2089c2c66affSColin Finck break; 2090c2c66affSColin Finck 2091c2c66affSColin Finck case WINHTTP_HANDLE_TYPE_SESSION: 2092c2c66affSColin Finck session = (session_t *)hdr; 2093c2c66affSColin Finck session->connect_timeout = connect; 2094c2c66affSColin Finck 2095c2c66affSColin Finck if (resolve < 0) resolve = 0; 2096c2c66affSColin Finck session->resolve_timeout = resolve; 2097c2c66affSColin Finck 2098c2c66affSColin Finck if (send < 0) send = 0; 2099c2c66affSColin Finck session->send_timeout = send; 2100c2c66affSColin Finck 2101c2c66affSColin Finck if (receive < 0) receive = 0; 2102c2c66affSColin Finck session->recv_timeout = receive; 2103c2c66affSColin Finck break; 2104c2c66affSColin Finck 2105c2c66affSColin Finck default: 2106c2c66affSColin Finck set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); 2107c2c66affSColin Finck ret = FALSE; 2108c2c66affSColin Finck } 2109c2c66affSColin Finck release_object( hdr ); 2110c2c66affSColin Finck if (ret) set_last_error( ERROR_SUCCESS ); 2111c2c66affSColin Finck return ret; 2112c2c66affSColin Finck } 2113c2c66affSColin Finck 2114c2c66affSColin Finck static const WCHAR wkday[7][4] = 2115c2c66affSColin Finck {{'S','u','n', 0}, {'M','o','n', 0}, {'T','u','e', 0}, {'W','e','d', 0}, 2116c2c66affSColin Finck {'T','h','u', 0}, {'F','r','i', 0}, {'S','a','t', 0}}; 2117c2c66affSColin Finck static const WCHAR month[12][4] = 2118c2c66affSColin Finck {{'J','a','n', 0}, {'F','e','b', 0}, {'M','a','r', 0}, {'A','p','r', 0}, 2119c2c66affSColin Finck {'M','a','y', 0}, {'J','u','n', 0}, {'J','u','l', 0}, {'A','u','g', 0}, 2120c2c66affSColin Finck {'S','e','p', 0}, {'O','c','t', 0}, {'N','o','v', 0}, {'D','e','c', 0}}; 2121c2c66affSColin Finck 2122c2c66affSColin Finck /*********************************************************************** 2123c2c66affSColin Finck * WinHttpTimeFromSystemTime (WININET.@) 2124c2c66affSColin Finck */ 2125c2c66affSColin Finck BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string ) 2126c2c66affSColin Finck { 2127c2c66affSColin Finck static const WCHAR format[] = 2128c2c66affSColin Finck {'%','s',',',' ','%','0','2','d',' ','%','s',' ','%','4','d',' ','%','0', 2129c2c66affSColin Finck '2','d',':','%','0','2','d',':','%','0','2','d',' ','G','M','T', 0}; 2130c2c66affSColin Finck 2131c2c66affSColin Finck TRACE("%p, %p\n", time, string); 2132c2c66affSColin Finck 2133c2c66affSColin Finck if (!time || !string) 2134c2c66affSColin Finck { 2135c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 2136c2c66affSColin Finck return FALSE; 2137c2c66affSColin Finck } 2138c2c66affSColin Finck 2139c2c66affSColin Finck sprintfW( string, format, 2140c2c66affSColin Finck wkday[time->wDayOfWeek], 2141c2c66affSColin Finck time->wDay, 2142c2c66affSColin Finck month[time->wMonth - 1], 2143c2c66affSColin Finck time->wYear, 2144c2c66affSColin Finck time->wHour, 2145c2c66affSColin Finck time->wMinute, 2146c2c66affSColin Finck time->wSecond ); 2147c2c66affSColin Finck 2148c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 2149c2c66affSColin Finck return TRUE; 2150c2c66affSColin Finck } 2151c2c66affSColin Finck 2152c2c66affSColin Finck /*********************************************************************** 2153c2c66affSColin Finck * WinHttpTimeToSystemTime (WININET.@) 2154c2c66affSColin Finck */ 2155c2c66affSColin Finck BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time ) 2156c2c66affSColin Finck { 2157c2c66affSColin Finck unsigned int i; 2158c2c66affSColin Finck const WCHAR *s = string; 2159c2c66affSColin Finck WCHAR *end; 2160c2c66affSColin Finck 2161c2c66affSColin Finck TRACE("%s, %p\n", debugstr_w(string), time); 2162c2c66affSColin Finck 2163c2c66affSColin Finck if (!string || !time) 2164c2c66affSColin Finck { 2165c2c66affSColin Finck set_last_error( ERROR_INVALID_PARAMETER ); 2166c2c66affSColin Finck return FALSE; 2167c2c66affSColin Finck } 2168c2c66affSColin Finck 2169c2c66affSColin Finck /* Windows does this too */ 2170c2c66affSColin Finck GetSystemTime( time ); 2171c2c66affSColin Finck 2172c2c66affSColin Finck /* Convert an RFC1123 time such as 'Fri, 07 Jan 2005 12:06:35 GMT' into 2173c2c66affSColin Finck * a SYSTEMTIME structure. 2174c2c66affSColin Finck */ 2175c2c66affSColin Finck 2176c2c66affSColin Finck set_last_error( ERROR_SUCCESS ); 2177c2c66affSColin Finck 2178c2c66affSColin Finck while (*s && !isalphaW( *s )) s++; 2179c2c66affSColin Finck if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE; 2180c2c66affSColin Finck time->wDayOfWeek = 7; 2181c2c66affSColin Finck 2182c2c66affSColin Finck for (i = 0; i < 7; i++) 2183c2c66affSColin Finck { 2184c2c66affSColin Finck if (toupperW( wkday[i][0] ) == toupperW( s[0] ) && 2185c2c66affSColin Finck toupperW( wkday[i][1] ) == toupperW( s[1] ) && 2186c2c66affSColin Finck toupperW( wkday[i][2] ) == toupperW( s[2] ) ) 2187c2c66affSColin Finck { 2188c2c66affSColin Finck time->wDayOfWeek = i; 2189c2c66affSColin Finck break; 2190c2c66affSColin Finck } 2191c2c66affSColin Finck } 2192c2c66affSColin Finck 2193c2c66affSColin Finck if (time->wDayOfWeek > 6) return TRUE; 2194c2c66affSColin Finck while (*s && !isdigitW( *s )) s++; 2195c2c66affSColin Finck time->wDay = strtolW( s, &end, 10 ); 2196c2c66affSColin Finck s = end; 2197c2c66affSColin Finck 2198c2c66affSColin Finck while (*s && !isalphaW( *s )) s++; 2199c2c66affSColin Finck if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE; 2200c2c66affSColin Finck time->wMonth = 0; 2201c2c66affSColin Finck 2202c2c66affSColin Finck for (i = 0; i < 12; i++) 2203c2c66affSColin Finck { 2204c2c66affSColin Finck if (toupperW( month[i][0]) == toupperW( s[0] ) && 2205c2c66affSColin Finck toupperW( month[i][1]) == toupperW( s[1] ) && 2206c2c66affSColin Finck toupperW( month[i][2]) == toupperW( s[2] ) ) 2207c2c66affSColin Finck { 2208c2c66affSColin Finck time->wMonth = i + 1; 2209c2c66affSColin Finck break; 2210c2c66affSColin Finck } 2211c2c66affSColin Finck } 2212c2c66affSColin Finck if (time->wMonth == 0) return TRUE; 2213c2c66affSColin Finck 2214c2c66affSColin Finck while (*s && !isdigitW( *s )) s++; 2215c2c66affSColin Finck if (*s == '\0') return TRUE; 2216c2c66affSColin Finck time->wYear = strtolW( s, &end, 10 ); 2217c2c66affSColin Finck s = end; 2218c2c66affSColin Finck 2219c2c66affSColin Finck while (*s && !isdigitW( *s )) s++; 2220c2c66affSColin Finck if (*s == '\0') return TRUE; 2221c2c66affSColin Finck time->wHour = strtolW( s, &end, 10 ); 2222c2c66affSColin Finck s = end; 2223c2c66affSColin Finck 2224c2c66affSColin Finck while (*s && !isdigitW( *s )) s++; 2225c2c66affSColin Finck if (*s == '\0') return TRUE; 2226c2c66affSColin Finck time->wMinute = strtolW( s, &end, 10 ); 2227c2c66affSColin Finck s = end; 2228c2c66affSColin Finck 2229c2c66affSColin Finck while (*s && !isdigitW( *s )) s++; 2230c2c66affSColin Finck if (*s == '\0') return TRUE; 2231c2c66affSColin Finck time->wSecond = strtolW( s, &end, 10 ); 2232c2c66affSColin Finck 2233c2c66affSColin Finck time->wMilliseconds = 0; 2234c2c66affSColin Finck return TRUE; 2235c2c66affSColin Finck } 2236