user32/tests: Test pending redraw state with owner-drawn list box.
[wine.git] / dlls / winhttp / session.c
blobe4e8f1cec5637f887318c1d9da52a7e95f466d9d
1 /*
2 * Copyright 2008 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winsock2.h"
24 #include "ws2ipdef.h"
25 #include "ws2tcpip.h"
26 #include "winhttp.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "iphlpapi.h"
30 #include "dhcpcsdk.h"
31 #define COBJMACROS
32 #include "ole2.h"
33 #include "dispex.h"
34 #include "activscp.h"
36 #include "wine/debug.h"
37 #include "winhttp_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
41 #define DEFAULT_RESOLVE_TIMEOUT 0
42 #define DEFAULT_CONNECT_TIMEOUT 20000
43 #define DEFAULT_SEND_TIMEOUT 30000
44 #define DEFAULT_RECEIVE_TIMEOUT 30000
45 #define DEFAULT_RECEIVE_RESPONSE_TIMEOUT ~0u
47 void send_callback( struct object_header *hdr, DWORD status, void *info, DWORD buflen )
49 if (hdr->callback && (hdr->notify_mask & status))
51 TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen);
52 hdr->callback( hdr->handle, hdr->context, status, info, buflen );
53 TRACE("returning from 0x%08x callback\n", status);
57 /***********************************************************************
58 * WinHttpCheckPlatform (winhttp.@)
60 BOOL WINAPI WinHttpCheckPlatform( void )
62 TRACE("\n");
63 return TRUE;
66 static void session_destroy( struct object_header *hdr )
68 struct session *session = (struct session *)hdr;
70 TRACE("%p\n", session);
72 if (session->unload_event) SetEvent( session->unload_event );
73 destroy_cookies( session );
75 session->cs.DebugInfo->Spare[0] = 0;
76 DeleteCriticalSection( &session->cs );
77 free( session->agent );
78 free( session->proxy_server );
79 free( session->proxy_bypass );
80 free( session->proxy_username );
81 free( session->proxy_password );
82 free( session );
85 static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
87 struct session *session = (struct session *)hdr;
89 switch (option)
91 case WINHTTP_OPTION_REDIRECT_POLICY:
93 if (!buffer || *buflen < sizeof(DWORD))
95 *buflen = sizeof(DWORD);
96 SetLastError( ERROR_INSUFFICIENT_BUFFER );
97 return FALSE;
100 *(DWORD *)buffer = hdr->redirect_policy;
101 *buflen = sizeof(DWORD);
102 return TRUE;
104 case WINHTTP_OPTION_RESOLVE_TIMEOUT:
105 *(DWORD *)buffer = session->resolve_timeout;
106 *buflen = sizeof(DWORD);
107 return TRUE;
109 case WINHTTP_OPTION_CONNECT_TIMEOUT:
110 *(DWORD *)buffer = session->connect_timeout;
111 *buflen = sizeof(DWORD);
112 return TRUE;
114 case WINHTTP_OPTION_SEND_TIMEOUT:
115 *(DWORD *)buffer = session->send_timeout;
116 *buflen = sizeof(DWORD);
117 return TRUE;
119 case WINHTTP_OPTION_RECEIVE_TIMEOUT:
120 *(DWORD *)buffer = session->receive_timeout;
121 *buflen = sizeof(DWORD);
122 return TRUE;
124 case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
125 *(DWORD *)buffer = session->receive_response_timeout;
126 *buflen = sizeof(DWORD);
127 return TRUE;
129 default:
130 FIXME("unimplemented option %u\n", option);
131 SetLastError( ERROR_INVALID_PARAMETER );
132 return FALSE;
136 static BOOL session_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
138 struct session *session = (struct session *)hdr;
140 switch (option)
142 case WINHTTP_OPTION_PROXY:
144 WINHTTP_PROXY_INFO *pi = buffer;
146 FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
147 return TRUE;
149 case WINHTTP_OPTION_REDIRECT_POLICY:
151 DWORD policy;
153 if (buflen != sizeof(policy))
155 SetLastError( ERROR_INSUFFICIENT_BUFFER );
156 return FALSE;
159 policy = *(DWORD *)buffer;
160 TRACE("0x%x\n", policy);
161 hdr->redirect_policy = policy;
162 return TRUE;
164 case WINHTTP_OPTION_SECURE_PROTOCOLS:
166 if (buflen != sizeof(session->secure_protocols))
168 SetLastError( ERROR_INSUFFICIENT_BUFFER );
169 return FALSE;
171 EnterCriticalSection( &session->cs );
172 session->secure_protocols = *(DWORD *)buffer;
173 LeaveCriticalSection( &session->cs );
174 TRACE("0x%x\n", session->secure_protocols);
175 return TRUE;
177 case WINHTTP_OPTION_DISABLE_FEATURE:
178 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
179 return FALSE;
181 case WINHTTP_OPTION_RESOLVE_TIMEOUT:
182 session->resolve_timeout = *(DWORD *)buffer;
183 return TRUE;
185 case WINHTTP_OPTION_CONNECT_TIMEOUT:
186 session->connect_timeout = *(DWORD *)buffer;
187 return TRUE;
189 case WINHTTP_OPTION_SEND_TIMEOUT:
190 session->send_timeout = *(DWORD *)buffer;
191 return TRUE;
193 case WINHTTP_OPTION_RECEIVE_TIMEOUT:
194 session->receive_timeout = *(DWORD *)buffer;
195 return TRUE;
197 case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
198 session->receive_response_timeout = *(DWORD *)buffer;
199 return TRUE;
201 case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
202 session->passport_flags = *(DWORD *)buffer;
203 return TRUE;
205 case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
206 TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer);
207 session->unload_event = *(HANDLE *)buffer;
208 return TRUE;
210 case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
211 FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer);
212 return TRUE;
214 case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
215 FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer);
216 return TRUE;
218 default:
219 FIXME("unimplemented option %u\n", option);
220 SetLastError( ERROR_WINHTTP_INVALID_OPTION );
221 return FALSE;
225 static const struct object_vtbl session_vtbl =
227 session_destroy,
228 session_query_option,
229 session_set_option
232 /***********************************************************************
233 * WinHttpOpen (winhttp.@)
235 HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags )
237 struct session *session;
238 HINTERNET handle = NULL;
240 TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags);
242 if (!(session = calloc( 1, sizeof(*session) ))) return NULL;
244 session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION;
245 session->hdr.vtbl = &session_vtbl;
246 session->hdr.flags = flags;
247 session->hdr.refs = 1;
248 session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
249 session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
250 session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
251 session->send_timeout = DEFAULT_SEND_TIMEOUT;
252 session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT;
253 session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT;
254 list_init( &session->cookie_cache );
255 InitializeCriticalSection( &session->cs );
256 session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs");
258 if (agent && !(session->agent = strdupW( agent ))) goto end;
259 if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
261 WINHTTP_PROXY_INFO info;
263 WinHttpGetDefaultProxyConfiguration( &info );
264 session->access = info.dwAccessType;
265 if (info.lpszProxy && !(session->proxy_server = strdupW( info.lpszProxy )))
267 GlobalFree( info.lpszProxy );
268 GlobalFree( info.lpszProxyBypass );
269 goto end;
271 if (info.lpszProxyBypass && !(session->proxy_bypass = strdupW( info.lpszProxyBypass )))
273 GlobalFree( info.lpszProxy );
274 GlobalFree( info.lpszProxyBypass );
275 goto end;
278 else if (access == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
280 session->access = access;
281 if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
282 if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
285 handle = alloc_handle( &session->hdr );
287 end:
288 release_object( &session->hdr );
289 TRACE("returning %p\n", handle);
290 if (handle) SetLastError( ERROR_SUCCESS );
291 return handle;
294 static void connect_destroy( struct object_header *hdr )
296 struct connect *connect = (struct connect *)hdr;
298 TRACE("%p\n", connect);
300 release_object( &connect->session->hdr );
302 free( connect->hostname );
303 free( connect->servername );
304 free( connect->username );
305 free( connect->password );
306 free( connect );
309 static BOOL connect_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
311 struct connect *connect = (struct connect *)hdr;
313 switch (option)
315 case WINHTTP_OPTION_PARENT_HANDLE:
317 if (!buffer || *buflen < sizeof(HINTERNET))
319 *buflen = sizeof(HINTERNET);
320 SetLastError( ERROR_INSUFFICIENT_BUFFER );
321 return FALSE;
324 *(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle;
325 *buflen = sizeof(HINTERNET);
326 return TRUE;
328 case WINHTTP_OPTION_RESOLVE_TIMEOUT:
329 *(DWORD *)buffer = connect->session->resolve_timeout;
330 *buflen = sizeof(DWORD);
331 return TRUE;
333 case WINHTTP_OPTION_CONNECT_TIMEOUT:
334 *(DWORD *)buffer = connect->session->connect_timeout;
335 *buflen = sizeof(DWORD);
336 return TRUE;
338 case WINHTTP_OPTION_SEND_TIMEOUT:
339 *(DWORD *)buffer = connect->session->send_timeout;
340 *buflen = sizeof(DWORD);
341 return TRUE;
343 case WINHTTP_OPTION_RECEIVE_TIMEOUT:
344 *(DWORD *)buffer = connect->session->receive_timeout;
345 *buflen = sizeof(DWORD);
346 return TRUE;
348 case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
349 *(DWORD *)buffer = connect->session->receive_response_timeout;
350 *buflen = sizeof(DWORD);
351 return TRUE;
353 default:
354 FIXME("unimplemented option %u\n", option);
355 SetLastError( ERROR_INVALID_PARAMETER );
356 return FALSE;
360 static const struct object_vtbl connect_vtbl =
362 connect_destroy,
363 connect_query_option,
364 NULL
367 static BOOL domain_matches(LPCWSTR server, LPCWSTR domain)
369 BOOL ret = FALSE;
371 if (!wcsicmp( domain, L"<local>" ) && !wcschr( server, '.' ))
372 ret = TRUE;
373 else if (*domain == '*')
375 if (domain[1] == '.')
377 LPCWSTR dot;
379 /* For a hostname to match a wildcard, the last domain must match
380 * the wildcard exactly. E.g. if the wildcard is *.a.b, and the
381 * hostname is www.foo.a.b, it matches, but a.b does not.
383 dot = wcschr( server, '.' );
384 if (dot)
386 int len = lstrlenW( dot + 1 );
388 if (len > lstrlenW( domain + 2 ))
390 LPCWSTR ptr;
392 /* The server's domain is longer than the wildcard, so it
393 * could be a subdomain. Compare the last portion of the
394 * server's domain.
396 ptr = dot + len + 1 - lstrlenW( domain + 2 );
397 if (!wcsicmp( ptr, domain + 2 ))
399 /* This is only a match if the preceding character is
400 * a '.', i.e. that it is a matching domain. E.g.
401 * if domain is '*.b.c' and server is 'www.ab.c' they
402 * do not match.
404 ret = *(ptr - 1) == '.';
407 else
408 ret = !wcsicmp( dot + 1, domain + 2 );
412 else
413 ret = !wcsicmp( server, domain );
414 return ret;
417 /* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */
418 #define MAX_HOST_NAME_LENGTH 256
420 static BOOL should_bypass_proxy(struct session *session, LPCWSTR server)
422 LPCWSTR ptr;
423 BOOL ret = FALSE;
425 if (!session->proxy_bypass) return FALSE;
426 ptr = session->proxy_bypass;
427 do {
428 LPCWSTR tmp = ptr;
430 ptr = wcschr( ptr, ';' );
431 if (!ptr)
432 ptr = wcschr( tmp, ' ' );
433 if (ptr)
435 if (ptr - tmp < MAX_HOST_NAME_LENGTH)
437 WCHAR domain[MAX_HOST_NAME_LENGTH];
439 memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) );
440 domain[ptr - tmp] = 0;
441 ret = domain_matches( server, domain );
443 ptr += 1;
445 else if (*tmp)
446 ret = domain_matches( server, tmp );
447 } while (ptr && !ret);
448 return ret;
451 BOOL set_server_for_hostname( struct connect *connect, const WCHAR *server, INTERNET_PORT port )
453 struct session *session = connect->session;
454 BOOL ret = TRUE;
456 if (session->proxy_server && !should_bypass_proxy(session, server))
458 LPCWSTR colon;
460 if ((colon = wcschr( session->proxy_server, ':' )))
462 if (!connect->servername || wcsnicmp( connect->servername,
463 session->proxy_server, colon - session->proxy_server - 1 ))
465 free( connect->servername );
466 connect->resolved = FALSE;
467 if (!(connect->servername = malloc( (colon - session->proxy_server + 1) * sizeof(WCHAR) )))
469 ret = FALSE;
470 goto end;
472 memcpy( connect->servername, session->proxy_server, (colon - session->proxy_server) * sizeof(WCHAR) );
473 connect->servername[colon - session->proxy_server] = 0;
474 if (*(colon + 1))
475 connect->serverport = wcstol( colon + 1, NULL, 10 );
476 else
477 connect->serverport = INTERNET_DEFAULT_PORT;
480 else
482 if (!connect->servername || wcsicmp( connect->servername, session->proxy_server ))
484 free( connect->servername );
485 connect->resolved = FALSE;
486 if (!(connect->servername = strdupW( session->proxy_server )))
488 ret = FALSE;
489 goto end;
491 connect->serverport = INTERNET_DEFAULT_PORT;
495 else if (server)
497 free( connect->servername );
498 connect->resolved = FALSE;
499 if (!(connect->servername = strdupW( server )))
501 ret = FALSE;
502 goto end;
504 connect->serverport = port;
506 end:
507 return ret;
510 /***********************************************************************
511 * WinHttpConnect (winhttp.@)
513 HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved )
515 struct connect *connect;
516 struct session *session;
517 HINTERNET hconnect = NULL;
519 TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved);
521 if (!server)
523 SetLastError( ERROR_INVALID_PARAMETER );
524 return NULL;
526 if (!(session = (struct session *)grab_object( hsession )))
528 SetLastError( ERROR_INVALID_HANDLE );
529 return NULL;
531 if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
533 release_object( &session->hdr );
534 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
535 return NULL;
537 if (!(connect = calloc( 1, sizeof(*connect) )))
539 release_object( &session->hdr );
540 return NULL;
542 connect->hdr.type = WINHTTP_HANDLE_TYPE_CONNECT;
543 connect->hdr.vtbl = &connect_vtbl;
544 connect->hdr.refs = 1;
545 connect->hdr.flags = session->hdr.flags;
546 connect->hdr.callback = session->hdr.callback;
547 connect->hdr.notify_mask = session->hdr.notify_mask;
548 connect->hdr.context = session->hdr.context;
549 connect->hdr.redirect_policy = session->hdr.redirect_policy;
551 addref_object( &session->hdr );
552 connect->session = session;
554 if (!(connect->hostname = strdupW( server ))) goto end;
555 connect->hostport = port;
556 if (!set_server_for_hostname( connect, server, port )) goto end;
558 if ((hconnect = alloc_handle( &connect->hdr )))
560 send_callback( &session->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hconnect, sizeof(hconnect) );
563 end:
564 release_object( &connect->hdr );
565 release_object( &session->hdr );
566 TRACE("returning %p\n", hconnect);
567 if (hconnect) SetLastError( ERROR_SUCCESS );
568 return hconnect;
571 static void request_destroy( struct object_header *hdr )
573 struct request *request = (struct request *)hdr;
574 unsigned int i, j;
576 TRACE("%p\n", request);
578 stop_queue( &request->queue );
579 release_object( &request->connect->hdr );
581 if (request->cred_handle_initialized) FreeCredentialsHandle( &request->cred_handle );
582 CertFreeCertificateContext( request->server_cert );
583 CertFreeCertificateContext( request->client_cert );
585 destroy_authinfo( request->authinfo );
586 destroy_authinfo( request->proxy_authinfo );
588 free( request->verb );
589 free( request->path );
590 free( request->version );
591 free( request->raw_headers );
592 free( request->status_text );
593 for (i = 0; i < request->num_headers; i++)
595 free( request->headers[i].field );
596 free( request->headers[i].value );
598 free( request->headers );
599 for (i = 0; i < TARGET_MAX; i++)
601 for (j = 0; j < SCHEME_MAX; j++)
603 free( request->creds[i][j].username );
604 free( request->creds[i][j].password );
608 free( request );
611 static void str_to_buffer( WCHAR *buffer, const WCHAR *str, LPDWORD buflen )
613 int len = 0;
614 if (str) len = lstrlenW( str );
615 if (buffer && *buflen > len)
617 if (str) memcpy( buffer, str, len * sizeof(WCHAR) );
618 buffer[len] = 0;
620 *buflen = len * sizeof(WCHAR);
623 static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob )
625 WCHAR *ret;
626 DWORD size, format = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG;
628 size = CertNameToStrW( encoding, blob, format, NULL, 0 );
629 if ((ret = LocalAlloc( 0, size * sizeof(WCHAR) )))
630 CertNameToStrW( encoding, blob, format, ret, size );
632 return ret;
635 static BOOL copy_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
637 switch (addr->sa_family)
639 case AF_INET:
641 struct sockaddr_in *addr_in = (struct sockaddr_in *)addr_storage;
643 memcpy( addr_in, addr, sizeof(*addr_in) );
644 memset( addr_in + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in) );
645 return TRUE;
647 case AF_INET6:
649 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr_storage;
651 memcpy( addr_in6, addr, sizeof(*addr_in6) );
652 memset( addr_in6 + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in6) );
653 return TRUE;
655 default:
656 ERR("unhandled family %u\n", addr->sa_family);
657 return FALSE;
661 static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
663 struct request *request = (struct request *)hdr;
665 switch (option)
667 case WINHTTP_OPTION_SECURITY_FLAGS:
669 DWORD flags;
670 int bits;
672 if (!buffer || *buflen < sizeof(flags))
674 *buflen = sizeof(flags);
675 SetLastError( ERROR_INSUFFICIENT_BUFFER );
676 return FALSE;
679 flags = request->security_flags;
680 if (request->netconn)
682 bits = netconn_get_cipher_strength( request->netconn );
683 if (bits >= 128)
684 flags |= SECURITY_FLAG_STRENGTH_STRONG;
685 else if (bits >= 56)
686 flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
687 else
688 flags |= SECURITY_FLAG_STRENGTH_WEAK;
690 *(DWORD *)buffer = flags;
691 *buflen = sizeof(flags);
692 return TRUE;
694 case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
696 const CERT_CONTEXT *cert;
698 if (!buffer || *buflen < sizeof(cert))
700 *buflen = sizeof(cert);
701 SetLastError( ERROR_INSUFFICIENT_BUFFER );
702 return FALSE;
705 if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE;
706 *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
707 *buflen = sizeof(cert);
708 return TRUE;
710 case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
712 const CERT_CONTEXT *cert = request->server_cert;
713 const CRYPT_OID_INFO *oidInfo;
714 WINHTTP_CERTIFICATE_INFO *ci = buffer;
716 FIXME("partial stub\n");
718 if (!buffer || *buflen < sizeof(*ci))
720 *buflen = sizeof(*ci);
721 SetLastError( ERROR_INSUFFICIENT_BUFFER );
722 return FALSE;
724 if (!cert) return FALSE;
726 ci->ftExpiry = cert->pCertInfo->NotAfter;
727 ci->ftStart = cert->pCertInfo->NotBefore;
728 ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject );
729 ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer );
730 ci->lpszProtocolName = NULL;
731 oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 );
732 if (oidInfo)
733 ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
734 else
735 ci->lpszSignatureAlgName = NULL;
736 ci->lpszEncryptionAlgName = NULL;
737 ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
739 *buflen = sizeof(*ci);
740 return TRUE;
742 case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
744 if (!buffer || *buflen < sizeof(DWORD))
746 *buflen = sizeof(DWORD);
747 SetLastError( ERROR_INSUFFICIENT_BUFFER );
748 return FALSE;
751 *(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
752 *buflen = sizeof(DWORD);
753 return TRUE;
755 case WINHTTP_OPTION_CONNECTION_INFO:
757 WINHTTP_CONNECTION_INFO *info = buffer;
758 struct sockaddr local;
759 socklen_t len = sizeof(local);
760 const struct sockaddr *remote = (const struct sockaddr *)&request->connect->sockaddr;
762 if (!buffer || *buflen < sizeof(*info))
764 *buflen = sizeof(*info);
765 SetLastError( ERROR_INSUFFICIENT_BUFFER );
766 return FALSE;
768 if (!request->netconn)
770 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
771 return FALSE;
773 if (getsockname( request->netconn->socket, &local, &len )) return FALSE;
774 if (!copy_sockaddr( &local, &info->LocalAddress )) return FALSE;
775 if (!copy_sockaddr( remote, &info->RemoteAddress )) return FALSE;
776 info->cbSize = sizeof(*info);
777 return TRUE;
779 case WINHTTP_OPTION_RESOLVE_TIMEOUT:
780 *(DWORD *)buffer = request->resolve_timeout;
781 *buflen = sizeof(DWORD);
782 return TRUE;
784 case WINHTTP_OPTION_CONNECT_TIMEOUT:
785 *(DWORD *)buffer = request->connect_timeout;
786 *buflen = sizeof(DWORD);
787 return TRUE;
789 case WINHTTP_OPTION_SEND_TIMEOUT:
790 *(DWORD *)buffer = request->send_timeout;
791 *buflen = sizeof(DWORD);
792 return TRUE;
794 case WINHTTP_OPTION_RECEIVE_TIMEOUT:
795 *(DWORD *)buffer = request->receive_timeout;
796 *buflen = sizeof(DWORD);
797 return TRUE;
799 case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
800 *(DWORD *)buffer = request->receive_response_timeout;
801 *buflen = sizeof(DWORD);
802 return TRUE;
804 case WINHTTP_OPTION_USERNAME:
805 str_to_buffer( buffer, request->connect->username, buflen );
806 return TRUE;
808 case WINHTTP_OPTION_PASSWORD:
809 str_to_buffer( buffer, request->connect->password, buflen );
810 return TRUE;
812 case WINHTTP_OPTION_PROXY_USERNAME:
813 str_to_buffer( buffer, request->connect->session->proxy_username, buflen );
814 return TRUE;
816 case WINHTTP_OPTION_PROXY_PASSWORD:
817 str_to_buffer( buffer, request->connect->session->proxy_password, buflen );
818 return TRUE;
820 case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
821 *(DWORD *)buffer = request->max_redirects;
822 *buflen = sizeof(DWORD);
823 return TRUE;
825 default:
826 FIXME("unimplemented option %u\n", option);
827 SetLastError( ERROR_INVALID_PARAMETER );
828 return FALSE;
832 static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen )
834 WCHAR *ret;
835 if ((ret = malloc( (buflen + 1) * sizeof(WCHAR))))
837 memcpy( ret, buffer, buflen * sizeof(WCHAR) );
838 ret[buflen] = 0;
839 return ret;
841 SetLastError( ERROR_OUTOFMEMORY );
842 return NULL;
845 static BOOL request_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
847 struct request *request = (struct request *)hdr;
849 switch (option)
851 case WINHTTP_OPTION_PROXY:
853 WINHTTP_PROXY_INFO *pi = buffer;
855 FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
856 return TRUE;
858 case WINHTTP_OPTION_DISABLE_FEATURE:
860 DWORD disable;
862 if (buflen != sizeof(DWORD))
864 SetLastError( ERROR_INSUFFICIENT_BUFFER );
865 return FALSE;
868 disable = *(DWORD *)buffer;
869 TRACE("0x%x\n", disable);
870 hdr->disable_flags |= disable;
871 return TRUE;
873 case WINHTTP_OPTION_AUTOLOGON_POLICY:
875 DWORD policy;
877 if (buflen != sizeof(DWORD))
879 SetLastError( ERROR_INSUFFICIENT_BUFFER );
880 return FALSE;
883 policy = *(DWORD *)buffer;
884 TRACE("0x%x\n", policy);
885 hdr->logon_policy = policy;
886 return TRUE;
888 case WINHTTP_OPTION_REDIRECT_POLICY:
890 DWORD policy;
892 if (buflen != sizeof(DWORD))
894 SetLastError( ERROR_INSUFFICIENT_BUFFER );
895 return FALSE;
898 policy = *(DWORD *)buffer;
899 TRACE("0x%x\n", policy);
900 hdr->redirect_policy = policy;
901 return TRUE;
903 case WINHTTP_OPTION_SECURITY_FLAGS:
905 DWORD flags;
906 static const DWORD accepted = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
907 SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
908 SECURITY_FLAG_IGNORE_UNKNOWN_CA |
909 SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
911 if (buflen < sizeof(DWORD))
913 SetLastError( ERROR_INSUFFICIENT_BUFFER );
914 return FALSE;
916 flags = *(DWORD *)buffer;
917 TRACE("0x%x\n", flags);
918 if (flags && (flags & ~accepted))
920 SetLastError( ERROR_INVALID_PARAMETER );
921 return FALSE;
923 request->security_flags = flags;
924 return TRUE;
926 case WINHTTP_OPTION_RESOLVE_TIMEOUT:
927 request->resolve_timeout = *(DWORD *)buffer;
928 return TRUE;
930 case WINHTTP_OPTION_CONNECT_TIMEOUT:
931 request->connect_timeout = *(DWORD *)buffer;
932 return TRUE;
934 case WINHTTP_OPTION_SEND_TIMEOUT:
935 request->send_timeout = *(DWORD *)buffer;
936 return TRUE;
938 case WINHTTP_OPTION_RECEIVE_TIMEOUT:
939 request->receive_timeout = *(DWORD *)buffer;
940 return TRUE;
942 case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
943 request->receive_response_timeout = *(DWORD *)buffer;
944 return TRUE;
946 case WINHTTP_OPTION_USERNAME:
948 struct connect *connect = request->connect;
950 free( connect->username );
951 if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE;
952 return TRUE;
954 case WINHTTP_OPTION_PASSWORD:
956 struct connect *connect = request->connect;
958 free( connect->password );
959 if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE;
960 return TRUE;
962 case WINHTTP_OPTION_PROXY_USERNAME:
964 struct session *session = request->connect->session;
966 free( session->proxy_username );
967 if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE;
968 return TRUE;
970 case WINHTTP_OPTION_PROXY_PASSWORD:
972 struct session *session = request->connect->session;
974 free( session->proxy_password );
975 if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE;
976 return TRUE;
978 case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
980 const CERT_CONTEXT *cert;
982 if (!(hdr->flags & WINHTTP_FLAG_SECURE))
984 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
985 return FALSE;
987 if (!buffer)
989 CertFreeCertificateContext( request->client_cert );
990 request->client_cert = NULL;
992 else if (buflen >= sizeof(*cert))
994 if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE;
995 CertFreeCertificateContext( request->client_cert );
996 request->client_cert = cert;
998 else
1000 SetLastError( ERROR_INVALID_PARAMETER );
1001 return FALSE;
1004 if (request->cred_handle_initialized)
1006 FreeCredentialsHandle( &request->cred_handle );
1007 request->cred_handle_initialized = FALSE;
1010 return TRUE;
1012 case WINHTTP_OPTION_ENABLE_FEATURE:
1013 if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
1015 request->check_revocation = TRUE;
1016 SetLastError( NO_ERROR );
1017 return TRUE;
1019 else
1021 SetLastError( ERROR_INVALID_PARAMETER );
1022 return FALSE;
1025 case WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET:
1026 request->flags |= REQUEST_FLAG_WEBSOCKET_UPGRADE;
1027 return TRUE;
1029 case WINHTTP_OPTION_CONNECT_RETRIES:
1030 FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n");
1031 return TRUE;
1033 case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
1034 if (buflen == sizeof(DWORD))
1036 request->max_redirects = *(DWORD *)buffer;
1037 SetLastError(NO_ERROR);
1038 return TRUE;
1041 SetLastError(ERROR_INVALID_PARAMETER);
1042 return FALSE;
1044 case WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE:
1045 FIXME("WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE\n");
1046 return TRUE;
1048 case WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE:
1049 FIXME("WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE\n");
1050 return TRUE;
1052 default:
1053 FIXME("unimplemented option %u\n", option);
1054 SetLastError( ERROR_WINHTTP_INVALID_OPTION );
1055 return FALSE;
1059 static const struct object_vtbl request_vtbl =
1061 request_destroy,
1062 request_query_option,
1063 request_set_option
1066 static BOOL add_accept_types_header( struct request *request, const WCHAR **types )
1068 static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
1070 if (!types) return TRUE;
1071 while (*types)
1073 if (process_header( request, L"Accept", *types, flags, TRUE )) return FALSE;
1074 types++;
1076 return TRUE;
1079 static WCHAR *get_request_path( const WCHAR *object )
1081 int len = object ? lstrlenW(object) : 0;
1082 WCHAR *p, *ret;
1084 if (!object || object[0] != '/') len++;
1085 if (!(p = ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
1086 if (!object || object[0] != '/') *p++ = '/';
1087 if (object) lstrcpyW( p, object );
1088 ret[len] = 0;
1089 return ret;
1092 /***********************************************************************
1093 * WinHttpOpenRequest (winhttp.@)
1095 HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version,
1096 LPCWSTR referrer, LPCWSTR *types, DWORD flags )
1098 struct request *request;
1099 struct connect *connect;
1100 HINTERNET hrequest = NULL;
1102 TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object),
1103 debugstr_w(version), debugstr_w(referrer), types, flags);
1105 if (types && TRACE_ON(winhttp))
1107 const WCHAR **iter;
1108 TRACE("accept types:\n");
1109 for (iter = types; *iter; iter++) TRACE(" %s\n", debugstr_w(*iter));
1112 if (!(connect = (struct connect *)grab_object( hconnect )))
1114 SetLastError( ERROR_INVALID_HANDLE );
1115 return NULL;
1117 if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT)
1119 release_object( &connect->hdr );
1120 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1121 return NULL;
1123 if (!(request = calloc( 1, sizeof(*request) )))
1125 release_object( &connect->hdr );
1126 return NULL;
1128 request->hdr.type = WINHTTP_HANDLE_TYPE_REQUEST;
1129 request->hdr.vtbl = &request_vtbl;
1130 request->hdr.refs = 1;
1131 request->hdr.flags = flags;
1132 request->hdr.callback = connect->hdr.callback;
1133 request->hdr.notify_mask = connect->hdr.notify_mask;
1134 request->hdr.context = connect->hdr.context;
1135 request->hdr.redirect_policy = connect->hdr.redirect_policy;
1137 addref_object( &connect->hdr );
1138 request->connect = connect;
1140 request->resolve_timeout = connect->session->resolve_timeout;
1141 request->connect_timeout = connect->session->connect_timeout;
1142 request->send_timeout = connect->session->send_timeout;
1143 request->receive_timeout = connect->session->receive_timeout;
1144 request->receive_response_timeout = connect->session->receive_response_timeout;
1145 request->max_redirects = 10;
1147 if (!verb || !verb[0]) verb = L"GET";
1148 if (!(request->verb = strdupW( verb ))) goto end;
1149 if (!(request->path = get_request_path( object ))) goto end;
1151 if (!version || !version[0]) version = L"HTTP/1.1";
1152 if (!(request->version = strdupW( version ))) goto end;
1153 if (!(add_accept_types_header( request, types ))) goto end;
1155 if ((hrequest = alloc_handle( &request->hdr )))
1157 send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hrequest, sizeof(hrequest) );
1160 end:
1161 release_object( &request->hdr );
1162 release_object( &connect->hdr );
1163 TRACE("returning %p\n", hrequest);
1164 if (hrequest) SetLastError( ERROR_SUCCESS );
1165 return hrequest;
1168 /***********************************************************************
1169 * WinHttpCloseHandle (winhttp.@)
1171 BOOL WINAPI WinHttpCloseHandle( HINTERNET handle )
1173 struct object_header *hdr;
1175 TRACE("%p\n", handle);
1177 if (!(hdr = grab_object( handle )))
1179 SetLastError( ERROR_INVALID_HANDLE );
1180 return FALSE;
1182 release_object( hdr );
1183 free_handle( handle );
1184 SetLastError( ERROR_SUCCESS );
1185 return TRUE;
1188 static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
1190 BOOL ret = FALSE;
1192 if (!buflen)
1194 SetLastError( ERROR_INVALID_PARAMETER );
1195 return FALSE;
1198 switch (option)
1200 case WINHTTP_OPTION_CONTEXT_VALUE:
1202 if (!buffer || *buflen < sizeof(DWORD_PTR))
1204 *buflen = sizeof(DWORD_PTR);
1205 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1206 return FALSE;
1209 *(DWORD_PTR *)buffer = hdr->context;
1210 *buflen = sizeof(DWORD_PTR);
1211 return TRUE;
1213 default:
1214 if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen );
1215 else
1217 FIXME("unimplemented option %u\n", option);
1218 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1219 return FALSE;
1221 break;
1223 return ret;
1226 /***********************************************************************
1227 * WinHttpQueryOption (winhttp.@)
1229 BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen )
1231 BOOL ret = FALSE;
1232 struct object_header *hdr;
1234 TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen);
1236 if (!(hdr = grab_object( handle )))
1238 SetLastError( ERROR_INVALID_HANDLE );
1239 return FALSE;
1242 ret = query_option( hdr, option, buffer, buflen );
1244 release_object( hdr );
1245 if (ret) SetLastError( ERROR_SUCCESS );
1246 return ret;
1249 static BOOL set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
1251 BOOL ret = TRUE;
1253 if (!buffer && buflen)
1255 SetLastError( ERROR_INVALID_PARAMETER );
1256 return FALSE;
1259 switch (option)
1261 case WINHTTP_OPTION_CONTEXT_VALUE:
1263 if (buflen != sizeof(DWORD_PTR))
1265 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1266 return FALSE;
1269 hdr->context = *(DWORD_PTR *)buffer;
1270 return TRUE;
1272 default:
1273 if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen );
1274 else
1276 FIXME("unimplemented option %u\n", option);
1277 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1278 return FALSE;
1280 break;
1282 return ret;
1285 /***********************************************************************
1286 * WinHttpSetOption (winhttp.@)
1288 BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen )
1290 BOOL ret = FALSE;
1291 struct object_header *hdr;
1293 TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen);
1295 if (!(hdr = grab_object( handle )))
1297 SetLastError( ERROR_INVALID_HANDLE );
1298 return FALSE;
1301 ret = set_option( hdr, option, buffer, buflen );
1303 release_object( hdr );
1304 if (ret) SetLastError( ERROR_SUCCESS );
1305 return ret;
1308 static IP_ADAPTER_ADDRESSES *get_adapters(void)
1310 ULONG err, size = 1024, flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
1311 GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
1312 IP_ADAPTER_ADDRESSES *tmp, *ret;
1314 if (!(ret = malloc( size ))) return NULL;
1315 err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
1316 while (err == ERROR_BUFFER_OVERFLOW)
1318 if (!(tmp = realloc( ret, size ))) break;
1319 ret = tmp;
1320 err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
1322 if (err == ERROR_SUCCESS) return ret;
1323 free( ret );
1324 return NULL;
1327 static WCHAR *detect_autoproxyconfig_url_dhcp(void)
1329 IP_ADAPTER_ADDRESSES *adapters, *ptr;
1330 DHCPCAPI_PARAMS_ARRAY send_params, recv_params;
1331 DHCPCAPI_PARAMS param;
1332 WCHAR name[MAX_ADAPTER_NAME_LENGTH + 1], *ret = NULL;
1333 DWORD err, size;
1334 BYTE *tmp, *buf = NULL;
1336 if (!(adapters = get_adapters())) return NULL;
1338 memset( &send_params, 0, sizeof(send_params) );
1339 memset( &param, 0, sizeof(param) );
1340 param.OptionId = OPTION_MSFT_IE_PROXY;
1341 recv_params.nParams = 1;
1342 recv_params.Params = &param;
1344 for (ptr = adapters; ptr; ptr = ptr->Next)
1346 MultiByteToWideChar( CP_ACP, 0, ptr->AdapterName, -1, name, ARRAY_SIZE(name) );
1347 TRACE( "adapter '%s' type %u dhcpv4 enabled %d\n", wine_dbgstr_w(name), ptr->IfType, ptr->Dhcpv4Enabled );
1349 if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
1350 /* FIXME: also skip adapters where DHCP is disabled */
1352 size = 256;
1353 if (!(buf = malloc( size ))) goto done;
1354 err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params,
1355 buf, &size, NULL );
1356 while (err == ERROR_MORE_DATA)
1358 if (!(tmp = realloc( buf, size ))) goto done;
1359 buf = tmp;
1360 err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params,
1361 buf, &size, NULL );
1363 if (err == ERROR_SUCCESS && param.nBytesData)
1365 int len = MultiByteToWideChar( CP_ACP, 0, (const char *)param.Data, param.nBytesData, NULL, 0 );
1366 if ((ret = malloc( (len + 1) * sizeof(WCHAR) )))
1368 MultiByteToWideChar( CP_ACP, 0, (const char *)param.Data, param.nBytesData, ret, len );
1369 ret[len] = 0;
1371 TRACE("returning %s\n", debugstr_w(ret));
1372 break;
1376 done:
1377 free( buf );
1378 free( adapters );
1379 return ret;
1382 static char *get_computer_name( COMPUTER_NAME_FORMAT format )
1384 char *ret;
1385 DWORD size = 0;
1387 GetComputerNameExA( format, NULL, &size );
1388 if (GetLastError() != ERROR_MORE_DATA) return NULL;
1389 if (!(ret = malloc( size ))) return NULL;
1390 if (!GetComputerNameExA( format, ret, &size ))
1392 free( ret );
1393 return NULL;
1395 return ret;
1398 static BOOL is_domain_suffix( const char *domain, const char *suffix )
1400 int len_domain = strlen( domain ), len_suffix = strlen( suffix );
1402 if (len_suffix > len_domain) return FALSE;
1403 if (!stricmp( domain + len_domain - len_suffix, suffix )) return TRUE;
1404 return FALSE;
1407 static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len )
1409 return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
1412 static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
1414 char name[NI_MAXHOST];
1415 WCHAR *ret, *p;
1416 int len;
1418 while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next;
1419 if (!ai) return NULL;
1421 if (!reverse_lookup( ai, name, sizeof(name) )) hostname = name;
1423 len = lstrlenW( L"http://" ) + strlen( hostname ) + lstrlenW( L"/wpad.dat" );
1424 if (!(ret = p = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
1425 lstrcpyW( p, L"http://" );
1426 p += lstrlenW( L"http://" );
1427 while (*hostname) { *p++ = *hostname++; }
1428 lstrcpyW( p, L"/wpad.dat" );
1429 return ret;
1432 static WCHAR *detect_autoproxyconfig_url_dns(void)
1434 char *fqdn, *domain, *p;
1435 WCHAR *ret = NULL;
1437 if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return NULL;
1438 if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain )))
1440 free( fqdn );
1441 return NULL;
1443 p = fqdn;
1444 while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain ))
1446 char *name;
1447 struct addrinfo *ai;
1448 int res;
1450 if (!(name = malloc( sizeof("wpad") + strlen(p) )))
1452 free( fqdn );
1453 free( domain );
1454 return NULL;
1456 strcpy( name, "wpad" );
1457 strcat( name, p );
1458 res = getaddrinfo( name, NULL, NULL, &ai );
1459 if (!res)
1461 ret = build_wpad_url( name, ai );
1462 freeaddrinfo( ai );
1463 if (ret)
1465 TRACE("returning %s\n", debugstr_w(ret));
1466 free( name );
1467 break;
1470 free( name );
1471 p++;
1473 free( domain );
1474 free( fqdn );
1475 return ret;
1478 /***********************************************************************
1479 * WinHttpDetectAutoProxyConfigUrl (winhttp.@)
1481 BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
1483 TRACE("0x%08x, %p\n", flags, url);
1485 if (!flags || !url)
1487 SetLastError( ERROR_INVALID_PARAMETER );
1488 return FALSE;
1490 *url = NULL;
1491 if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP)
1493 *url = detect_autoproxyconfig_url_dhcp();
1495 if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A)
1497 if (!*url) *url = detect_autoproxyconfig_url_dns();
1499 if (!*url)
1501 SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED );
1502 return FALSE;
1504 SetLastError( ERROR_SUCCESS );
1505 return TRUE;
1508 static const WCHAR path_connections[] =
1509 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Connections";
1511 static const DWORD WINHTTP_SETTINGS_MAGIC = 0x18;
1512 static const DWORD WININET_SETTINGS_MAGIC = 0x46;
1513 static const DWORD PROXY_TYPE_DIRECT = 1;
1514 static const DWORD PROXY_TYPE_PROXY = 2;
1515 static const DWORD PROXY_USE_PAC_SCRIPT = 4;
1516 static const DWORD PROXY_AUTODETECT_SETTINGS = 8;
1518 struct connection_settings_header
1520 DWORD magic;
1521 DWORD unknown; /* always zero? */
1522 DWORD flags; /* one or more of PROXY_* */
1525 static inline void copy_char_to_wchar_sz(const BYTE *src, DWORD len, WCHAR *dst)
1527 const BYTE *begin;
1529 for (begin = src; src - begin < len; src++, dst++)
1530 *dst = *src;
1531 *dst = 0;
1534 /***********************************************************************
1535 * WinHttpGetDefaultProxyConfiguration (winhttp.@)
1537 BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
1539 LONG l;
1540 HKEY key;
1541 BOOL got_from_reg = FALSE, direct = TRUE;
1542 WCHAR *envproxy;
1544 TRACE("%p\n", info);
1546 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, path_connections, 0, KEY_READ, &key );
1547 if (!l)
1549 DWORD type, size = 0;
1551 l = RegQueryValueExW( key, L"WinHttpSettings", NULL, &type, NULL, &size );
1552 if (!l && type == REG_BINARY &&
1553 size >= sizeof(struct connection_settings_header) + 2 * sizeof(DWORD))
1555 BYTE *buf = malloc( size );
1557 if (buf)
1559 struct connection_settings_header *hdr =
1560 (struct connection_settings_header *)buf;
1561 DWORD *len = (DWORD *)(hdr + 1);
1563 l = RegQueryValueExW( key, L"WinHttpSettings", NULL, NULL, buf,
1564 &size );
1565 if (!l && hdr->magic == WINHTTP_SETTINGS_MAGIC &&
1566 hdr->unknown == 0)
1568 if (hdr->flags & PROXY_TYPE_PROXY)
1570 BOOL sane = FALSE;
1571 LPWSTR proxy = NULL;
1572 LPWSTR proxy_bypass = NULL;
1574 /* Sanity-check length of proxy string */
1575 if ((BYTE *)len - buf + *len <= size)
1577 sane = TRUE;
1578 proxy = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
1579 if (proxy)
1580 copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy );
1581 len = (DWORD *)((BYTE *)(len + 1) + *len);
1583 if (sane)
1585 /* Sanity-check length of proxy bypass string */
1586 if ((BYTE *)len - buf + *len <= size)
1588 proxy_bypass = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
1589 if (proxy_bypass)
1590 copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy_bypass );
1592 else
1594 sane = FALSE;
1595 GlobalFree( proxy );
1596 proxy = NULL;
1599 info->lpszProxy = proxy;
1600 info->lpszProxyBypass = proxy_bypass;
1601 if (sane)
1603 got_from_reg = TRUE;
1604 direct = FALSE;
1605 info->dwAccessType =
1606 WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1607 TRACE("http proxy (from registry) = %s, bypass = %s\n",
1608 debugstr_w(info->lpszProxy),
1609 debugstr_w(info->lpszProxyBypass));
1613 free( buf );
1616 RegCloseKey( key );
1618 if (!got_from_reg && (envproxy = _wgetenv( L"http_proxy" )))
1620 WCHAR *colon, *http_proxy = NULL;
1622 if (!(colon = wcschr( envproxy, ':' ))) http_proxy = envproxy;
1623 else
1625 if (*(colon + 1) == '/' && *(colon + 2) == '/')
1627 /* It's a scheme, check that it's http */
1628 if (!wcsncmp( envproxy, L"http://", 7 )) http_proxy = envproxy + 7;
1629 else WARN("unsupported scheme in $http_proxy: %s\n", debugstr_w(envproxy));
1631 else http_proxy = envproxy;
1634 if (http_proxy && http_proxy[0])
1636 direct = FALSE;
1637 info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1638 info->lpszProxy = GlobalAlloc( 0, (lstrlenW(http_proxy) + 1) * sizeof(WCHAR) );
1639 wcscpy( info->lpszProxy, http_proxy );
1640 info->lpszProxyBypass = NULL;
1641 TRACE("http proxy (from environment) = %s\n", debugstr_w(info->lpszProxy));
1644 if (direct)
1646 info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
1647 info->lpszProxy = NULL;
1648 info->lpszProxyBypass = NULL;
1650 SetLastError( ERROR_SUCCESS );
1651 return TRUE;
1654 /***********************************************************************
1655 * WinHttpGetIEProxyConfigForCurrentUser (winhttp.@)
1657 BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *config )
1659 HKEY hkey = NULL;
1660 struct connection_settings_header *hdr = NULL;
1661 DWORD type, offset, len, size = 0;
1662 BOOL ret = FALSE;
1664 TRACE("%p\n", config);
1666 if (!config)
1668 SetLastError( ERROR_INVALID_PARAMETER );
1669 return FALSE;
1671 memset( config, 0, sizeof(*config) );
1672 config->fAutoDetect = TRUE;
1674 if (RegOpenKeyExW( HKEY_CURRENT_USER, path_connections, 0, KEY_READ, &hkey ) ||
1675 RegQueryValueExW( hkey, L"DefaultConnectionSettings", NULL, &type, NULL, &size ) ||
1676 type != REG_BINARY || size < sizeof(struct connection_settings_header))
1678 ret = TRUE;
1679 goto done;
1681 if (!(hdr = malloc( size ))) goto done;
1682 if (RegQueryValueExW( hkey, L"DefaultConnectionSettings", NULL, &type, (BYTE *)hdr, &size ) ||
1683 hdr->magic != WININET_SETTINGS_MAGIC)
1685 ret = TRUE;
1686 goto done;
1689 config->fAutoDetect = (hdr->flags & PROXY_AUTODETECT_SETTINGS) != 0;
1690 offset = sizeof(*hdr);
1691 if (offset + sizeof(DWORD) > size) goto done;
1692 len = *(DWORD *)((char *)hdr + offset);
1693 offset += sizeof(DWORD);
1694 if (len && hdr->flags & PROXY_TYPE_PROXY)
1696 if (!(config->lpszProxy = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1697 copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxy );
1699 offset += len;
1700 if (offset + sizeof(DWORD) > size) goto done;
1701 len = *(DWORD *)((char *)hdr + offset);
1702 offset += sizeof(DWORD);
1703 if (len && (hdr->flags & PROXY_TYPE_PROXY))
1705 if (!(config->lpszProxyBypass = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1706 copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxyBypass );
1708 offset += len;
1709 if (offset + sizeof(DWORD) > size) goto done;
1710 len = *(DWORD *)((char *)hdr + offset);
1711 offset += sizeof(DWORD);
1712 if (len && (hdr->flags & PROXY_USE_PAC_SCRIPT))
1714 if (!(config->lpszAutoConfigUrl = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1715 copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszAutoConfigUrl );
1717 ret = TRUE;
1719 done:
1720 RegCloseKey( hkey );
1721 free( hdr );
1722 if (!ret)
1724 GlobalFree( config->lpszAutoConfigUrl );
1725 config->lpszAutoConfigUrl = NULL;
1726 GlobalFree( config->lpszProxy );
1727 config->lpszProxy = NULL;
1728 GlobalFree( config->lpszProxyBypass );
1729 config->lpszProxyBypass = NULL;
1731 else SetLastError( ERROR_SUCCESS );
1732 return ret;
1735 static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info )
1737 const char *p;
1738 WCHAR *q;
1739 int len;
1741 info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
1742 info->lpszProxy = NULL;
1743 info->lpszProxyBypass = NULL;
1745 TRACE("%s\n", debugstr_a( result ));
1747 p = result;
1748 while (*p == ' ') p++;
1749 len = strlen( p );
1750 if (len >= 5 && !_strnicmp( p, "PROXY", sizeof("PROXY") - 1 ))
1752 p += 5;
1753 while (*p == ' ') p++;
1754 if (!*p || *p == ';') return TRUE;
1755 if (!(info->lpszProxy = q = strdupAW( p ))) return FALSE;
1756 info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1757 for (; *q; q++)
1759 if (*q == ' ' || *q == ';')
1761 *q = 0;
1762 break;
1766 return TRUE;
1769 static char *download_script( const WCHAR *url, DWORD *out_size )
1771 static const WCHAR *acceptW[] = {L"*/*", NULL};
1772 HINTERNET ses, con = NULL, req = NULL;
1773 WCHAR *hostname;
1774 URL_COMPONENTSW uc;
1775 DWORD status, size = sizeof(status), offset, to_read, bytes_read, flags = 0;
1776 char *tmp, *buffer = NULL;
1778 *out_size = 0;
1780 memset( &uc, 0, sizeof(uc) );
1781 uc.dwStructSize = sizeof(uc);
1782 uc.dwHostNameLength = -1;
1783 uc.dwUrlPathLength = -1;
1784 if (!WinHttpCrackUrl( url, 0, 0, &uc )) return NULL;
1785 if (!(hostname = malloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return NULL;
1786 memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
1787 hostname[uc.dwHostNameLength] = 0;
1789 if (!(ses = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ))) goto done;
1790 if (!(con = WinHttpConnect( ses, hostname, uc.nPort, 0 ))) goto done;
1791 if (uc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE;
1792 if (!(req = WinHttpOpenRequest( con, NULL, uc.lpszUrlPath, NULL, NULL, acceptW, flags ))) goto done;
1793 if (!WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 )) goto done;
1795 if (!WinHttpReceiveResponse( req, 0 )) goto done;
1796 if (!WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status,
1797 &size, NULL ) || status != HTTP_STATUS_OK) goto done;
1799 size = 4096;
1800 if (!(buffer = malloc( size ))) goto done;
1801 to_read = size;
1802 offset = 0;
1803 for (;;)
1805 if (!WinHttpReadData( req, buffer + offset, to_read, &bytes_read )) goto done;
1806 if (!bytes_read) break;
1807 to_read -= bytes_read;
1808 offset += bytes_read;
1809 *out_size += bytes_read;
1810 if (!to_read)
1812 to_read = size;
1813 size *= 2;
1814 if (!(tmp = realloc( buffer, size ))) goto done;
1815 buffer = tmp;
1819 done:
1820 WinHttpCloseHandle( req );
1821 WinHttpCloseHandle( con );
1822 WinHttpCloseHandle( ses );
1823 free( hostname );
1824 if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT );
1825 return buffer;
1828 struct AUTO_PROXY_SCRIPT_BUFFER
1830 DWORD dwStructSize;
1831 LPSTR lpszScriptBuffer;
1832 DWORD dwScriptBufferSize;
1835 BOOL WINAPI InternetDeInitializeAutoProxyDll(LPSTR, DWORD);
1836 BOOL WINAPI InternetGetProxyInfo(LPCSTR, DWORD, LPSTR, DWORD, LPSTR *, LPDWORD);
1837 BOOL WINAPI InternetInitializeAutoProxyDll(DWORD, LPSTR, LPSTR, void *, struct AUTO_PROXY_SCRIPT_BUFFER *);
1839 static BOOL run_script( char *script, DWORD size, const WCHAR *url, WINHTTP_PROXY_INFO *info )
1841 BOOL ret;
1842 char *result, *urlA;
1843 DWORD len_result;
1844 struct AUTO_PROXY_SCRIPT_BUFFER buffer;
1845 URL_COMPONENTSW uc;
1847 buffer.dwStructSize = sizeof(buffer);
1848 buffer.lpszScriptBuffer = script;
1849 buffer.dwScriptBufferSize = size;
1851 if (!(urlA = strdupWA( url ))) return FALSE;
1852 if (!(ret = InternetInitializeAutoProxyDll( 0, NULL, NULL, NULL, &buffer )))
1854 free( urlA );
1855 return FALSE;
1858 memset( &uc, 0, sizeof(uc) );
1859 uc.dwStructSize = sizeof(uc);
1860 uc.dwHostNameLength = -1;
1862 if ((ret = WinHttpCrackUrl( url, 0, 0, &uc )))
1864 char *hostnameA = strdupWA_sized( uc.lpszHostName, uc.dwHostNameLength );
1866 if ((ret = InternetGetProxyInfo( urlA, strlen(urlA),
1867 hostnameA, strlen(hostnameA), &result, &len_result )))
1869 ret = parse_script_result( result, info );
1870 free( result );
1873 free( hostnameA );
1875 free( urlA );
1876 InternetDeInitializeAutoProxyDll( NULL, 0 );
1877 return ret;
1880 /***********************************************************************
1881 * WinHttpGetProxyForUrl (winhttp.@)
1883 BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTOPROXY_OPTIONS *options,
1884 WINHTTP_PROXY_INFO *info )
1886 WCHAR *detected_pac_url = NULL;
1887 const WCHAR *pac_url;
1888 struct session *session;
1889 char *script;
1890 DWORD size;
1891 BOOL ret = FALSE;
1893 TRACE("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info);
1895 if (!(session = (struct session *)grab_object( hsession )))
1897 SetLastError( ERROR_INVALID_HANDLE );
1898 return FALSE;
1900 if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
1902 release_object( &session->hdr );
1903 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1904 return FALSE;
1906 if (!url || !options || !info ||
1907 !(options->dwFlags & (WINHTTP_AUTOPROXY_AUTO_DETECT|WINHTTP_AUTOPROXY_CONFIG_URL)) ||
1908 ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) && !options->dwAutoDetectFlags) ||
1909 ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) &&
1910 (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL)))
1912 release_object( &session->hdr );
1913 SetLastError( ERROR_INVALID_PARAMETER );
1914 return FALSE;
1916 if (options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT &&
1917 !WinHttpDetectAutoProxyConfigUrl( options->dwAutoDetectFlags, &detected_pac_url ))
1918 goto done;
1920 if (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL) pac_url = options->lpszAutoConfigUrl;
1921 else pac_url = detected_pac_url;
1923 if ((script = download_script( pac_url, &size )))
1925 ret = run_script( script, size, url, info );
1926 free( script );
1929 done:
1930 GlobalFree( detected_pac_url );
1931 release_object( &session->hdr );
1932 if (ret) SetLastError( ERROR_SUCCESS );
1933 return ret;
1936 /***********************************************************************
1937 * WinHttpSetDefaultProxyConfiguration (winhttp.@)
1939 BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
1941 LONG l;
1942 HKEY key;
1943 BOOL ret = FALSE;
1944 const WCHAR *src;
1946 TRACE("%p\n", info);
1948 if (!info)
1950 SetLastError( ERROR_INVALID_PARAMETER );
1951 return FALSE;
1953 switch (info->dwAccessType)
1955 case WINHTTP_ACCESS_TYPE_NO_PROXY:
1956 break;
1957 case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
1958 if (!info->lpszProxy)
1960 SetLastError( ERROR_INVALID_PARAMETER );
1961 return FALSE;
1963 /* Only ASCII characters are allowed */
1964 for (src = info->lpszProxy; *src; src++)
1965 if (*src > 0x7f)
1967 SetLastError( ERROR_INVALID_PARAMETER );
1968 return FALSE;
1970 if (info->lpszProxyBypass)
1972 for (src = info->lpszProxyBypass; *src; src++)
1973 if (*src > 0x7f)
1975 SetLastError( ERROR_INVALID_PARAMETER );
1976 return FALSE;
1979 break;
1980 default:
1981 SetLastError( ERROR_INVALID_PARAMETER );
1982 return FALSE;
1985 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, path_connections, 0, NULL, 0,
1986 KEY_WRITE, NULL, &key, NULL );
1987 if (!l)
1989 DWORD size = sizeof(struct connection_settings_header) + 2 * sizeof(DWORD);
1990 BYTE *buf;
1992 if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
1994 size += lstrlenW( info->lpszProxy );
1995 if (info->lpszProxyBypass)
1996 size += lstrlenW( info->lpszProxyBypass );
1998 if ((buf = malloc( size )))
2000 struct connection_settings_header *hdr =
2001 (struct connection_settings_header *)buf;
2002 DWORD *len = (DWORD *)(hdr + 1);
2004 hdr->magic = WINHTTP_SETTINGS_MAGIC;
2005 hdr->unknown = 0;
2006 if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
2008 BYTE *dst;
2010 hdr->flags = PROXY_TYPE_PROXY;
2011 *len++ = lstrlenW( info->lpszProxy );
2012 for (dst = (BYTE *)len, src = info->lpszProxy; *src;
2013 src++, dst++)
2014 *dst = *src;
2015 len = (DWORD *)dst;
2016 if (info->lpszProxyBypass)
2018 *len++ = lstrlenW( info->lpszProxyBypass );
2019 for (dst = (BYTE *)len, src = info->lpszProxyBypass; *src;
2020 src++, dst++)
2021 *dst = *src;
2023 else
2024 *len++ = 0;
2026 else
2028 hdr->flags = PROXY_TYPE_DIRECT;
2029 *len++ = 0;
2030 *len++ = 0;
2032 l = RegSetValueExW( key, L"WinHttpSettings", 0, REG_BINARY, buf, size );
2033 if (!l)
2034 ret = TRUE;
2035 free( buf );
2037 RegCloseKey( key );
2039 if (ret) SetLastError( ERROR_SUCCESS );
2040 return ret;
2043 /***********************************************************************
2044 * WinHttpCreateProxyResolver (winhttp.@)
2046 DWORD WINAPI WinHttpCreateProxyResolver( HINTERNET hsession, HINTERNET *hresolver )
2048 FIXME("%p, %p\n", hsession, hresolver);
2049 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2052 /***********************************************************************
2053 * WinHttpFreeProxyResult (winhttp.@)
2055 void WINAPI WinHttpFreeProxyResult( WINHTTP_PROXY_RESULT *result )
2057 FIXME("%p\n", result);
2060 /***********************************************************************
2061 * WinHttpFreeProxyResultEx (winhttp.@)
2063 void WINAPI WinHttpFreeProxyResultEx( WINHTTP_PROXY_RESULT_EX *result )
2065 FIXME("%p\n", result);
2068 /***********************************************************************
2069 * WinHttpFreeProxySettings (winhttp.@)
2071 void WINAPI WinHttpFreeProxySettings( WINHTTP_PROXY_SETTINGS *settings )
2073 FIXME("%p\n", settings);
2076 /***********************************************************************
2077 * WinHttpGetProxyForUrlEx (winhttp.@)
2079 DWORD WINAPI WinHttpGetProxyForUrlEx( HINTERNET hresolver, const WCHAR *url, WINHTTP_AUTOPROXY_OPTIONS *options,
2080 DWORD_PTR ctx )
2082 FIXME("%p, %s, %p, %lx\n", hresolver, debugstr_w(url), options, ctx);
2083 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2086 /***********************************************************************
2087 * WinHttpGetProxyForUrlEx2 (winhttp.@)
2089 DWORD WINAPI WinHttpGetProxyForUrlEx2( HINTERNET hresolver, const WCHAR *url, WINHTTP_AUTOPROXY_OPTIONS *options,
2090 DWORD selection_len, BYTE *selection, DWORD_PTR ctx )
2092 FIXME("%p, %s, %p, %u, %p, %lx\n", hresolver, debugstr_w(url), options, selection_len, selection, ctx);
2093 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2096 /***********************************************************************
2097 * WinHttpGetProxyResult (winhttp.@)
2099 DWORD WINAPI WinHttpGetProxyResult( HINTERNET hresolver, WINHTTP_PROXY_RESULT *result )
2101 FIXME("%p, %p\n", hresolver, result);
2102 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2105 /***********************************************************************
2106 * WinHttpGetProxyResultEx (winhttp.@)
2108 DWORD WINAPI WinHttpGetProxyResultEx( HINTERNET hresolver, WINHTTP_PROXY_RESULT_EX *result )
2110 FIXME("%p, %p\n", hresolver, result);
2111 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2114 /***********************************************************************
2115 * WinHttpGetProxySettingsVersion (winhttp.@)
2117 DWORD WINAPI WinHttpGetProxySettingsVersion( HINTERNET hsession, DWORD *version )
2119 FIXME("%p, %p\n", hsession, version);
2120 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2123 /***********************************************************************
2124 * WinHttpReadProxySettings (winhttp.@)
2126 DWORD WINAPI WinHttpReadProxySettings( HINTERNET hsession, const WCHAR *connection, BOOL use_defaults,
2127 BOOL set_autodiscover, DWORD *version, BOOL *defaults_returned,
2128 WINHTTP_PROXY_SETTINGS *settings)
2130 FIXME("%p, %s, %d, %d, %p, %p, %p\n", hsession, debugstr_w(connection), use_defaults, set_autodiscover,
2131 version, defaults_returned, settings);
2132 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2135 /***********************************************************************
2136 * WinHttpResetAutoProxy (winhttp.@)
2138 DWORD WINAPI WinHttpResetAutoProxy( HINTERNET hsession, DWORD flags )
2140 FIXME("%p, %08x\n", hsession, flags);
2141 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2144 DWORD WINAPI WinHttpWriteProxySettings( HINTERNET hsession, BOOL force, WINHTTP_PROXY_SETTINGS *settings )
2146 FIXME("%p, %d, %p\n", hsession, force, settings);
2147 return ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR;
2150 /***********************************************************************
2151 * WinHttpSetStatusCallback (winhttp.@)
2153 WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback,
2154 DWORD flags, DWORD_PTR reserved )
2156 struct object_header *hdr;
2157 WINHTTP_STATUS_CALLBACK ret;
2159 TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved);
2161 if (!(hdr = grab_object( handle )))
2163 SetLastError( ERROR_INVALID_HANDLE );
2164 return WINHTTP_INVALID_STATUS_CALLBACK;
2166 ret = hdr->callback;
2167 hdr->callback = callback;
2168 hdr->notify_mask = flags;
2170 release_object( hdr );
2171 SetLastError( ERROR_SUCCESS );
2172 return ret;
2175 /***********************************************************************
2176 * WinHttpSetTimeouts (winhttp.@)
2178 BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive )
2180 BOOL ret = TRUE;
2181 struct object_header *hdr;
2183 TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
2185 if (resolve < -1 || connect < -1 || send < -1 || receive < -1)
2187 SetLastError( ERROR_INVALID_PARAMETER );
2188 return FALSE;
2191 if (!(hdr = grab_object( handle )))
2193 SetLastError( ERROR_INVALID_HANDLE );
2194 return FALSE;
2197 switch(hdr->type)
2199 case WINHTTP_HANDLE_TYPE_REQUEST:
2201 struct request *request = (struct request *)hdr;
2202 request->connect_timeout = connect;
2204 if (resolve < 0) resolve = 0;
2205 request->resolve_timeout = resolve;
2207 if (send < 0) send = 0;
2208 request->send_timeout = send;
2210 if (receive < 0) receive = 0;
2211 request->receive_timeout = receive;
2213 if (request->netconn)
2215 if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
2216 if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
2218 break;
2220 case WINHTTP_HANDLE_TYPE_SESSION:
2222 struct session *session = (struct session *)hdr;
2223 session->connect_timeout = connect;
2225 if (resolve < 0) resolve = 0;
2226 session->resolve_timeout = resolve;
2228 if (send < 0) send = 0;
2229 session->send_timeout = send;
2231 if (receive < 0) receive = 0;
2232 session->receive_timeout = receive;
2233 break;
2235 default:
2236 SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
2237 ret = FALSE;
2239 release_object( hdr );
2240 if (ret) SetLastError( ERROR_SUCCESS );
2241 return ret;
2244 static const WCHAR wkday[7][4] =
2245 {L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"};
2246 static const WCHAR month[12][4] =
2247 {L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"};
2249 /***********************************************************************
2250 * WinHttpTimeFromSystemTime (WININET.@)
2252 BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string )
2254 TRACE("%p, %p\n", time, string);
2256 if (!time || !string)
2258 SetLastError( ERROR_INVALID_PARAMETER );
2259 return FALSE;
2262 swprintf( string, WINHTTP_TIME_FORMAT_BUFSIZE / sizeof(WCHAR),
2263 L"%s, %02d %s %4d %02d:%02d:%02d GMT",
2264 wkday[time->wDayOfWeek],
2265 time->wDay,
2266 month[time->wMonth - 1],
2267 time->wYear,
2268 time->wHour,
2269 time->wMinute,
2270 time->wSecond );
2272 SetLastError( ERROR_SUCCESS );
2273 return TRUE;
2276 /***********************************************************************
2277 * WinHttpTimeToSystemTime (WININET.@)
2279 BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time )
2281 unsigned int i;
2282 const WCHAR *s = string;
2283 WCHAR *end;
2285 TRACE("%s, %p\n", debugstr_w(string), time);
2287 if (!string || !time)
2289 SetLastError( ERROR_INVALID_PARAMETER );
2290 return FALSE;
2293 /* Windows does this too */
2294 GetSystemTime( time );
2296 /* Convert an RFC1123 time such as 'Fri, 07 Jan 2005 12:06:35 GMT' into
2297 * a SYSTEMTIME structure.
2300 SetLastError( ERROR_SUCCESS );
2302 while (*s && !iswalpha( *s )) s++;
2303 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
2304 time->wDayOfWeek = 7;
2306 for (i = 0; i < 7; i++)
2308 if (towupper( wkday[i][0] ) == towupper( s[0] ) &&
2309 towupper( wkday[i][1] ) == towupper( s[1] ) &&
2310 towupper( wkday[i][2] ) == towupper( s[2] ) )
2312 time->wDayOfWeek = i;
2313 break;
2317 if (time->wDayOfWeek > 6) return TRUE;
2318 while (*s && !iswdigit( *s )) s++;
2319 time->wDay = wcstol( s, &end, 10 );
2320 s = end;
2322 while (*s && !iswalpha( *s )) s++;
2323 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
2324 time->wMonth = 0;
2326 for (i = 0; i < 12; i++)
2328 if (towupper( month[i][0]) == towupper( s[0] ) &&
2329 towupper( month[i][1]) == towupper( s[1] ) &&
2330 towupper( month[i][2]) == towupper( s[2] ) )
2332 time->wMonth = i + 1;
2333 break;
2336 if (time->wMonth == 0) return TRUE;
2338 while (*s && !iswdigit( *s )) s++;
2339 if (*s == '\0') return TRUE;
2340 time->wYear = wcstol( s, &end, 10 );
2341 s = end;
2343 while (*s && !iswdigit( *s )) s++;
2344 if (*s == '\0') return TRUE;
2345 time->wHour = wcstol( s, &end, 10 );
2346 s = end;
2348 while (*s && !iswdigit( *s )) s++;
2349 if (*s == '\0') return TRUE;
2350 time->wMinute = wcstol( s, &end, 10 );
2351 s = end;
2353 while (*s && !iswdigit( *s )) s++;
2354 if (*s == '\0') return TRUE;
2355 time->wSecond = wcstol( s, &end, 10 );
2357 time->wMilliseconds = 0;
2358 return TRUE;