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
190530cb8bSAmine Khaldi #include "config.h"
200530cb8bSAmine Khaldi #include <stdarg.h>
210530cb8bSAmine Khaldi #include <stdlib.h>
220530cb8bSAmine Khaldi
230530cb8bSAmine Khaldi #ifdef HAVE_CORESERVICES_CORESERVICES_H
240530cb8bSAmine Khaldi #define GetCurrentThread MacGetCurrentThread
250530cb8bSAmine Khaldi #define LoadResource MacLoadResource
260530cb8bSAmine Khaldi #include <CoreServices/CoreServices.h>
270530cb8bSAmine Khaldi #undef GetCurrentThread
280530cb8bSAmine Khaldi #undef LoadResource
290530cb8bSAmine Khaldi #endif
300530cb8bSAmine Khaldi
310530cb8bSAmine Khaldi #include "windef.h"
320530cb8bSAmine Khaldi #include "winbase.h"
330530cb8bSAmine Khaldi #include "winsock2.h"
340530cb8bSAmine Khaldi #include "ws2ipdef.h"
355bd6580fSAmine Khaldi #include "ws2tcpip.h"
360530cb8bSAmine Khaldi #include "winhttp.h"
370530cb8bSAmine Khaldi #include "winreg.h"
385bd6580fSAmine Khaldi #include "wine/winternl.h"
390530cb8bSAmine Khaldi #define COBJMACROS
400530cb8bSAmine Khaldi #include "ole2.h"
410530cb8bSAmine Khaldi #include "dispex.h"
420530cb8bSAmine Khaldi #include "activscp.h"
430530cb8bSAmine Khaldi
445bd6580fSAmine Khaldi #include "wine/debug.h"
45c2c66affSColin Finck #include "winhttp_private.h"
46c2c66affSColin Finck
470530cb8bSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
48c2c66affSColin Finck
49c2c66affSColin Finck #define DEFAULT_RESOLVE_TIMEOUT 0
50c2c66affSColin Finck #define DEFAULT_CONNECT_TIMEOUT 20000
51c2c66affSColin Finck #define DEFAULT_SEND_TIMEOUT 30000
52c2c66affSColin Finck #define DEFAULT_RECEIVE_TIMEOUT 30000
535bd6580fSAmine Khaldi #define DEFAULT_RECEIVE_RESPONSE_TIMEOUT ~0u
54c2c66affSColin Finck
send_callback(struct object_header * hdr,DWORD status,void * info,DWORD buflen)555bd6580fSAmine Khaldi void send_callback( struct object_header *hdr, DWORD status, void *info, DWORD buflen )
56c2c66affSColin Finck {
57c2c66affSColin Finck if (hdr->callback && (hdr->notify_mask & status))
58c2c66affSColin Finck {
59c2c66affSColin Finck TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen);
60c2c66affSColin Finck hdr->callback( hdr->handle, hdr->context, status, info, buflen );
61c2c66affSColin Finck TRACE("returning from 0x%08x callback\n", status);
62c2c66affSColin Finck }
63c2c66affSColin Finck }
64c2c66affSColin Finck
65c2c66affSColin Finck /***********************************************************************
66c2c66affSColin Finck * WinHttpCheckPlatform (winhttp.@)
67c2c66affSColin Finck */
WinHttpCheckPlatform(void)68c2c66affSColin Finck BOOL WINAPI WinHttpCheckPlatform( void )
69c2c66affSColin Finck {
70c2c66affSColin Finck TRACE("\n");
71c2c66affSColin Finck return TRUE;
72c2c66affSColin Finck }
73c2c66affSColin Finck
74c2c66affSColin Finck /***********************************************************************
75c2c66affSColin Finck * session_destroy (internal)
76c2c66affSColin Finck */
session_destroy(struct object_header * hdr)775bd6580fSAmine Khaldi static void session_destroy( struct object_header *hdr )
78c2c66affSColin Finck {
795bd6580fSAmine Khaldi struct session *session = (struct session *)hdr;
80c2c66affSColin Finck
81c2c66affSColin Finck TRACE("%p\n", session);
82c2c66affSColin Finck
83c2c66affSColin Finck if (session->unload_event) SetEvent( session->unload_event );
845bd6580fSAmine Khaldi destroy_cookies( session );
85c2c66affSColin Finck
865bd6580fSAmine Khaldi session->cs.DebugInfo->Spare[0] = 0;
875bd6580fSAmine Khaldi DeleteCriticalSection( &session->cs );
88c2c66affSColin Finck heap_free( session->agent );
89c2c66affSColin Finck heap_free( session->proxy_server );
90c2c66affSColin Finck heap_free( session->proxy_bypass );
91c2c66affSColin Finck heap_free( session->proxy_username );
92c2c66affSColin Finck heap_free( session->proxy_password );
93c2c66affSColin Finck heap_free( session );
94c2c66affSColin Finck }
95c2c66affSColin Finck
session_query_option(struct object_header * hdr,DWORD option,void * buffer,DWORD * buflen)965bd6580fSAmine Khaldi static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
97c2c66affSColin Finck {
985bd6580fSAmine Khaldi struct session *session = (struct session *)hdr;
99c2c66affSColin Finck
100c2c66affSColin Finck switch (option)
101c2c66affSColin Finck {
102c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY:
103c2c66affSColin Finck {
104c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD))
105c2c66affSColin Finck {
106c2c66affSColin Finck *buflen = sizeof(DWORD);
1075bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
108c2c66affSColin Finck return FALSE;
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck *(DWORD *)buffer = hdr->redirect_policy;
112c2c66affSColin Finck *buflen = sizeof(DWORD);
113c2c66affSColin Finck return TRUE;
114c2c66affSColin Finck }
115c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT:
116c2c66affSColin Finck *(DWORD *)buffer = session->resolve_timeout;
117c2c66affSColin Finck *buflen = sizeof(DWORD);
118c2c66affSColin Finck return TRUE;
1195bd6580fSAmine Khaldi
120c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT:
121c2c66affSColin Finck *(DWORD *)buffer = session->connect_timeout;
122c2c66affSColin Finck *buflen = sizeof(DWORD);
123c2c66affSColin Finck return TRUE;
1245bd6580fSAmine Khaldi
125c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT:
126c2c66affSColin Finck *(DWORD *)buffer = session->send_timeout;
127c2c66affSColin Finck *buflen = sizeof(DWORD);
128c2c66affSColin Finck return TRUE;
1295bd6580fSAmine Khaldi
130c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT:
1315bd6580fSAmine Khaldi *(DWORD *)buffer = session->receive_timeout;
132c2c66affSColin Finck *buflen = sizeof(DWORD);
133c2c66affSColin Finck return TRUE;
1345bd6580fSAmine Khaldi
1355bd6580fSAmine Khaldi case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
1365bd6580fSAmine Khaldi *(DWORD *)buffer = session->receive_response_timeout;
1375bd6580fSAmine Khaldi *buflen = sizeof(DWORD);
1385bd6580fSAmine Khaldi return TRUE;
1395bd6580fSAmine Khaldi
140c2c66affSColin Finck default:
141c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
1425bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
143c2c66affSColin Finck return FALSE;
144c2c66affSColin Finck }
145c2c66affSColin Finck }
146c2c66affSColin Finck
session_set_option(struct object_header * hdr,DWORD option,void * buffer,DWORD buflen)1475bd6580fSAmine Khaldi static BOOL session_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
148c2c66affSColin Finck {
1495bd6580fSAmine Khaldi struct session *session = (struct session *)hdr;
150c2c66affSColin Finck
151c2c66affSColin Finck switch (option)
152c2c66affSColin Finck {
153c2c66affSColin Finck case WINHTTP_OPTION_PROXY:
154c2c66affSColin Finck {
155c2c66affSColin Finck WINHTTP_PROXY_INFO *pi = buffer;
156c2c66affSColin Finck
157c2c66affSColin Finck FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
158c2c66affSColin Finck return TRUE;
159c2c66affSColin Finck }
160c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY:
161c2c66affSColin Finck {
162c2c66affSColin Finck DWORD policy;
163c2c66affSColin Finck
164c2c66affSColin Finck if (buflen != sizeof(policy))
165c2c66affSColin Finck {
1665bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
167c2c66affSColin Finck return FALSE;
168c2c66affSColin Finck }
169c2c66affSColin Finck
170c2c66affSColin Finck policy = *(DWORD *)buffer;
171c2c66affSColin Finck TRACE("0x%x\n", policy);
172c2c66affSColin Finck hdr->redirect_policy = policy;
173c2c66affSColin Finck return TRUE;
174c2c66affSColin Finck }
1759048bdf9SAmine Khaldi case WINHTTP_OPTION_SECURE_PROTOCOLS:
1769048bdf9SAmine Khaldi {
1779048bdf9SAmine Khaldi if (buflen != sizeof(session->secure_protocols))
1789048bdf9SAmine Khaldi {
1795bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
1809048bdf9SAmine Khaldi return FALSE;
1819048bdf9SAmine Khaldi }
1825bd6580fSAmine Khaldi EnterCriticalSection( &session->cs );
1839048bdf9SAmine Khaldi session->secure_protocols = *(DWORD *)buffer;
1845bd6580fSAmine Khaldi LeaveCriticalSection( &session->cs );
1859048bdf9SAmine Khaldi TRACE("0x%x\n", session->secure_protocols);
1869048bdf9SAmine Khaldi return TRUE;
1879048bdf9SAmine Khaldi }
188c2c66affSColin Finck case WINHTTP_OPTION_DISABLE_FEATURE:
1895bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
190c2c66affSColin Finck return FALSE;
1915bd6580fSAmine Khaldi
192c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT:
193c2c66affSColin Finck session->resolve_timeout = *(DWORD *)buffer;
194c2c66affSColin Finck return TRUE;
1955bd6580fSAmine Khaldi
196c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT:
197c2c66affSColin Finck session->connect_timeout = *(DWORD *)buffer;
198c2c66affSColin Finck return TRUE;
1995bd6580fSAmine Khaldi
200c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT:
201c2c66affSColin Finck session->send_timeout = *(DWORD *)buffer;
202c2c66affSColin Finck return TRUE;
2035bd6580fSAmine Khaldi
204c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT:
2055bd6580fSAmine Khaldi session->receive_timeout = *(DWORD *)buffer;
206c2c66affSColin Finck return TRUE;
2075bd6580fSAmine Khaldi
2085bd6580fSAmine Khaldi case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
2095bd6580fSAmine Khaldi session->receive_response_timeout = *(DWORD *)buffer;
2105bd6580fSAmine Khaldi return TRUE;
2115bd6580fSAmine Khaldi
212c2c66affSColin Finck case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
2135bd6580fSAmine Khaldi session->passport_flags = *(DWORD *)buffer;
214c2c66affSColin Finck return TRUE;
2155bd6580fSAmine Khaldi
216c2c66affSColin Finck case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
217c2c66affSColin Finck TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer);
218c2c66affSColin Finck session->unload_event = *(HANDLE *)buffer;
219c2c66affSColin Finck return TRUE;
2205bd6580fSAmine Khaldi
221c2c66affSColin Finck case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
222c2c66affSColin Finck FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer);
223c2c66affSColin Finck return TRUE;
2245bd6580fSAmine Khaldi
225c2c66affSColin Finck case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
226c2c66affSColin Finck FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer);
227c2c66affSColin Finck return TRUE;
2285bd6580fSAmine Khaldi
229c2c66affSColin Finck default:
230c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
2315bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INVALID_OPTION );
232c2c66affSColin Finck return FALSE;
233c2c66affSColin Finck }
234c2c66affSColin Finck }
235c2c66affSColin Finck
2365bd6580fSAmine Khaldi static const struct object_vtbl session_vtbl =
237c2c66affSColin Finck {
238c2c66affSColin Finck session_destroy,
239c2c66affSColin Finck session_query_option,
240c2c66affSColin Finck session_set_option
241c2c66affSColin Finck };
242c2c66affSColin Finck
243*4bf76a65SVictor Perevertkin #ifdef __REACTOS__
244*4bf76a65SVictor Perevertkin void winsock_init(void);
245*4bf76a65SVictor Perevertkin #endif
246*4bf76a65SVictor Perevertkin
247c2c66affSColin Finck /***********************************************************************
248c2c66affSColin Finck * WinHttpOpen (winhttp.@)
249c2c66affSColin Finck */
WinHttpOpen(LPCWSTR agent,DWORD access,LPCWSTR proxy,LPCWSTR bypass,DWORD flags)250c2c66affSColin Finck HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags )
251c2c66affSColin Finck {
2525bd6580fSAmine Khaldi struct session *session;
253c2c66affSColin Finck HINTERNET handle = NULL;
254c2c66affSColin Finck
255c2c66affSColin Finck TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags);
256c2c66affSColin Finck
2575bd6580fSAmine Khaldi if (!(session = heap_alloc_zero( sizeof(struct session) ))) return NULL;
258c2c66affSColin Finck
259c2c66affSColin Finck session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION;
260c2c66affSColin Finck session->hdr.vtbl = &session_vtbl;
261c2c66affSColin Finck session->hdr.flags = flags;
262c2c66affSColin Finck session->hdr.refs = 1;
263c2c66affSColin Finck session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
264c2c66affSColin Finck list_init( &session->hdr.children );
265c2c66affSColin Finck session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
266c2c66affSColin Finck session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
267c2c66affSColin Finck session->send_timeout = DEFAULT_SEND_TIMEOUT;
2685bd6580fSAmine Khaldi session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT;
2695bd6580fSAmine Khaldi session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT;
270c2c66affSColin Finck list_init( &session->cookie_cache );
2715bd6580fSAmine Khaldi InitializeCriticalSection( &session->cs );
2725bd6580fSAmine Khaldi session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs");
273c2c66affSColin Finck
274c2c66affSColin Finck if (agent && !(session->agent = strdupW( agent ))) goto end;
275c2c66affSColin Finck if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
276c2c66affSColin Finck {
277c2c66affSColin Finck WINHTTP_PROXY_INFO info;
278c2c66affSColin Finck
279c2c66affSColin Finck WinHttpGetDefaultProxyConfiguration( &info );
280c2c66affSColin Finck session->access = info.dwAccessType;
281c2c66affSColin Finck if (info.lpszProxy && !(session->proxy_server = strdupW( info.lpszProxy )))
282c2c66affSColin Finck {
283c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxy );
284c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxyBypass );
285c2c66affSColin Finck goto end;
286c2c66affSColin Finck }
287c2c66affSColin Finck if (info.lpszProxyBypass && !(session->proxy_bypass = strdupW( info.lpszProxyBypass )))
288c2c66affSColin Finck {
289c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxy );
290c2c66affSColin Finck GlobalFree( (LPWSTR)info.lpszProxyBypass );
291c2c66affSColin Finck goto end;
292c2c66affSColin Finck }
293c2c66affSColin Finck }
294c2c66affSColin Finck else if (access == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
295c2c66affSColin Finck {
296c2c66affSColin Finck session->access = access;
297c2c66affSColin Finck if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
298c2c66affSColin Finck if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
299c2c66affSColin Finck }
300c2c66affSColin Finck
301c2c66affSColin Finck if (!(handle = alloc_handle( &session->hdr ))) goto end;
302c2c66affSColin Finck session->hdr.handle = handle;
303c2c66affSColin Finck
304*4bf76a65SVictor Perevertkin #ifdef __REACTOS__
305*4bf76a65SVictor Perevertkin winsock_init();
306*4bf76a65SVictor Perevertkin #endif
307*4bf76a65SVictor Perevertkin
308c2c66affSColin Finck end:
309c2c66affSColin Finck release_object( &session->hdr );
310c2c66affSColin Finck TRACE("returning %p\n", handle);
3115bd6580fSAmine Khaldi if (handle) SetLastError( ERROR_SUCCESS );
312c2c66affSColin Finck return handle;
313c2c66affSColin Finck }
314c2c66affSColin Finck
315c2c66affSColin Finck /***********************************************************************
316c2c66affSColin Finck * connect_destroy (internal)
317c2c66affSColin Finck */
connect_destroy(struct object_header * hdr)3185bd6580fSAmine Khaldi static void connect_destroy( struct object_header *hdr )
319c2c66affSColin Finck {
3205bd6580fSAmine Khaldi struct connect *connect = (struct connect *)hdr;
321c2c66affSColin Finck
322c2c66affSColin Finck TRACE("%p\n", connect);
323c2c66affSColin Finck
324c2c66affSColin Finck release_object( &connect->session->hdr );
325c2c66affSColin Finck
326c2c66affSColin Finck heap_free( connect->hostname );
327c2c66affSColin Finck heap_free( connect->servername );
328c2c66affSColin Finck heap_free( connect->username );
329c2c66affSColin Finck heap_free( connect->password );
330c2c66affSColin Finck heap_free( connect );
331c2c66affSColin Finck }
332c2c66affSColin Finck
connect_query_option(struct object_header * hdr,DWORD option,void * buffer,DWORD * buflen)3335bd6580fSAmine Khaldi static BOOL connect_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
334c2c66affSColin Finck {
3355bd6580fSAmine Khaldi struct connect *connect = (struct connect *)hdr;
336c2c66affSColin Finck
337c2c66affSColin Finck switch (option)
338c2c66affSColin Finck {
339c2c66affSColin Finck case WINHTTP_OPTION_PARENT_HANDLE:
340c2c66affSColin Finck {
341c2c66affSColin Finck if (!buffer || *buflen < sizeof(HINTERNET))
342c2c66affSColin Finck {
343c2c66affSColin Finck *buflen = sizeof(HINTERNET);
3445bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
345c2c66affSColin Finck return FALSE;
346c2c66affSColin Finck }
347c2c66affSColin Finck
3485bd6580fSAmine Khaldi *(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle;
349c2c66affSColin Finck *buflen = sizeof(HINTERNET);
350c2c66affSColin Finck return TRUE;
351c2c66affSColin Finck }
352c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT:
353c2c66affSColin Finck *(DWORD *)buffer = connect->session->resolve_timeout;
354c2c66affSColin Finck *buflen = sizeof(DWORD);
355c2c66affSColin Finck return TRUE;
3565bd6580fSAmine Khaldi
357c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT:
358c2c66affSColin Finck *(DWORD *)buffer = connect->session->connect_timeout;
359c2c66affSColin Finck *buflen = sizeof(DWORD);
360c2c66affSColin Finck return TRUE;
3615bd6580fSAmine Khaldi
362c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT:
363c2c66affSColin Finck *(DWORD *)buffer = connect->session->send_timeout;
364c2c66affSColin Finck *buflen = sizeof(DWORD);
365c2c66affSColin Finck return TRUE;
3665bd6580fSAmine Khaldi
367c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT:
3685bd6580fSAmine Khaldi *(DWORD *)buffer = connect->session->receive_timeout;
369c2c66affSColin Finck *buflen = sizeof(DWORD);
370c2c66affSColin Finck return TRUE;
3715bd6580fSAmine Khaldi
3725bd6580fSAmine Khaldi case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
3735bd6580fSAmine Khaldi *(DWORD *)buffer = connect->session->receive_response_timeout;
3745bd6580fSAmine Khaldi *buflen = sizeof(DWORD);
3755bd6580fSAmine Khaldi return TRUE;
3765bd6580fSAmine Khaldi
377c2c66affSColin Finck default:
378c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
3795bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
380c2c66affSColin Finck return FALSE;
381c2c66affSColin Finck }
382c2c66affSColin Finck }
383c2c66affSColin Finck
3845bd6580fSAmine Khaldi static const struct object_vtbl connect_vtbl =
385c2c66affSColin Finck {
386c2c66affSColin Finck connect_destroy,
387c2c66affSColin Finck connect_query_option,
388c2c66affSColin Finck NULL
389c2c66affSColin Finck };
390c2c66affSColin Finck
domain_matches(LPCWSTR server,LPCWSTR domain)391c2c66affSColin Finck static BOOL domain_matches(LPCWSTR server, LPCWSTR domain)
392c2c66affSColin Finck {
393c2c66affSColin Finck static const WCHAR localW[] = { '<','l','o','c','a','l','>',0 };
394c2c66affSColin Finck BOOL ret = FALSE;
395c2c66affSColin Finck
396c2c66affSColin Finck if (!strcmpiW( domain, localW ) && !strchrW( server, '.' ))
397c2c66affSColin Finck ret = TRUE;
398c2c66affSColin Finck else if (*domain == '*')
399c2c66affSColin Finck {
400c2c66affSColin Finck if (domain[1] == '.')
401c2c66affSColin Finck {
402c2c66affSColin Finck LPCWSTR dot;
403c2c66affSColin Finck
404c2c66affSColin Finck /* For a hostname to match a wildcard, the last domain must match
405c2c66affSColin Finck * the wildcard exactly. E.g. if the wildcard is *.a.b, and the
406c2c66affSColin Finck * hostname is www.foo.a.b, it matches, but a.b does not.
407c2c66affSColin Finck */
408c2c66affSColin Finck dot = strchrW( server, '.' );
409c2c66affSColin Finck if (dot)
410c2c66affSColin Finck {
411c2c66affSColin Finck int len = strlenW( dot + 1 );
412c2c66affSColin Finck
413c2c66affSColin Finck if (len > strlenW( domain + 2 ))
414c2c66affSColin Finck {
415c2c66affSColin Finck LPCWSTR ptr;
416c2c66affSColin Finck
417c2c66affSColin Finck /* The server's domain is longer than the wildcard, so it
418c2c66affSColin Finck * could be a subdomain. Compare the last portion of the
419c2c66affSColin Finck * server's domain.
420c2c66affSColin Finck */
421c2c66affSColin Finck ptr = dot + len + 1 - strlenW( domain + 2 );
422c2c66affSColin Finck if (!strcmpiW( ptr, domain + 2 ))
423c2c66affSColin Finck {
424c2c66affSColin Finck /* This is only a match if the preceding character is
425c2c66affSColin Finck * a '.', i.e. that it is a matching domain. E.g.
426c2c66affSColin Finck * if domain is '*.b.c' and server is 'www.ab.c' they
427c2c66affSColin Finck * do not match.
428c2c66affSColin Finck */
429c2c66affSColin Finck ret = *(ptr - 1) == '.';
430c2c66affSColin Finck }
431c2c66affSColin Finck }
432c2c66affSColin Finck else
433c2c66affSColin Finck ret = !strcmpiW( dot + 1, domain + 2 );
434c2c66affSColin Finck }
435c2c66affSColin Finck }
436c2c66affSColin Finck }
437c2c66affSColin Finck else
438c2c66affSColin Finck ret = !strcmpiW( server, domain );
439c2c66affSColin Finck return ret;
440c2c66affSColin Finck }
441c2c66affSColin Finck
442c2c66affSColin Finck /* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */
443c2c66affSColin Finck #define MAX_HOST_NAME_LENGTH 256
444c2c66affSColin Finck
should_bypass_proxy(struct session * session,LPCWSTR server)4455bd6580fSAmine Khaldi static BOOL should_bypass_proxy(struct session *session, LPCWSTR server)
446c2c66affSColin Finck {
447c2c66affSColin Finck LPCWSTR ptr;
448c2c66affSColin Finck BOOL ret = FALSE;
449c2c66affSColin Finck
450c2c66affSColin Finck if (!session->proxy_bypass) return FALSE;
451c2c66affSColin Finck ptr = session->proxy_bypass;
452c2c66affSColin Finck do {
453c2c66affSColin Finck LPCWSTR tmp = ptr;
454c2c66affSColin Finck
455c2c66affSColin Finck ptr = strchrW( ptr, ';' );
456c2c66affSColin Finck if (!ptr)
457c2c66affSColin Finck ptr = strchrW( tmp, ' ' );
458c2c66affSColin Finck if (ptr)
459c2c66affSColin Finck {
460c2c66affSColin Finck if (ptr - tmp < MAX_HOST_NAME_LENGTH)
461c2c66affSColin Finck {
462c2c66affSColin Finck WCHAR domain[MAX_HOST_NAME_LENGTH];
463c2c66affSColin Finck
464c2c66affSColin Finck memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) );
465c2c66affSColin Finck domain[ptr - tmp] = 0;
466c2c66affSColin Finck ret = domain_matches( server, domain );
467c2c66affSColin Finck }
468c2c66affSColin Finck ptr += 1;
469c2c66affSColin Finck }
470c2c66affSColin Finck else if (*tmp)
471c2c66affSColin Finck ret = domain_matches( server, tmp );
472c2c66affSColin Finck } while (ptr && !ret);
473c2c66affSColin Finck return ret;
474c2c66affSColin Finck }
475c2c66affSColin Finck
set_server_for_hostname(struct connect * connect,const WCHAR * server,INTERNET_PORT port)4765bd6580fSAmine Khaldi BOOL set_server_for_hostname( struct connect *connect, const WCHAR *server, INTERNET_PORT port )
477c2c66affSColin Finck {
4785bd6580fSAmine Khaldi struct session *session = connect->session;
479c2c66affSColin Finck BOOL ret = TRUE;
480c2c66affSColin Finck
481c2c66affSColin Finck if (session->proxy_server && !should_bypass_proxy(session, server))
482c2c66affSColin Finck {
483c2c66affSColin Finck LPCWSTR colon;
484c2c66affSColin Finck
485c2c66affSColin Finck if ((colon = strchrW( session->proxy_server, ':' )))
486c2c66affSColin Finck {
487c2c66affSColin Finck if (!connect->servername || strncmpiW( connect->servername,
488c2c66affSColin Finck session->proxy_server, colon - session->proxy_server - 1 ))
489c2c66affSColin Finck {
490c2c66affSColin Finck heap_free( connect->servername );
491c2c66affSColin Finck connect->resolved = FALSE;
492c2c66affSColin Finck if (!(connect->servername = heap_alloc(
493c2c66affSColin Finck (colon - session->proxy_server + 1) * sizeof(WCHAR) )))
494c2c66affSColin Finck {
495c2c66affSColin Finck ret = FALSE;
496c2c66affSColin Finck goto end;
497c2c66affSColin Finck }
498c2c66affSColin Finck memcpy( connect->servername, session->proxy_server,
499c2c66affSColin Finck (colon - session->proxy_server) * sizeof(WCHAR) );
500c2c66affSColin Finck connect->servername[colon - session->proxy_server] = 0;
501c2c66affSColin Finck if (*(colon + 1))
502c2c66affSColin Finck connect->serverport = atoiW( colon + 1 );
503c2c66affSColin Finck else
504c2c66affSColin Finck connect->serverport = INTERNET_DEFAULT_PORT;
505c2c66affSColin Finck }
506c2c66affSColin Finck }
507c2c66affSColin Finck else
508c2c66affSColin Finck {
509c2c66affSColin Finck if (!connect->servername || strcmpiW( connect->servername,
510c2c66affSColin Finck session->proxy_server ))
511c2c66affSColin Finck {
512c2c66affSColin Finck heap_free( connect->servername );
513c2c66affSColin Finck connect->resolved = FALSE;
514c2c66affSColin Finck if (!(connect->servername = strdupW( session->proxy_server )))
515c2c66affSColin Finck {
516c2c66affSColin Finck ret = FALSE;
517c2c66affSColin Finck goto end;
518c2c66affSColin Finck }
519c2c66affSColin Finck connect->serverport = INTERNET_DEFAULT_PORT;
520c2c66affSColin Finck }
521c2c66affSColin Finck }
522c2c66affSColin Finck }
523c2c66affSColin Finck else if (server)
524c2c66affSColin Finck {
525c2c66affSColin Finck heap_free( connect->servername );
526c2c66affSColin Finck connect->resolved = FALSE;
527c2c66affSColin Finck if (!(connect->servername = strdupW( server )))
528c2c66affSColin Finck {
529c2c66affSColin Finck ret = FALSE;
530c2c66affSColin Finck goto end;
531c2c66affSColin Finck }
532c2c66affSColin Finck connect->serverport = port;
533c2c66affSColin Finck }
534c2c66affSColin Finck end:
535c2c66affSColin Finck return ret;
536c2c66affSColin Finck }
537c2c66affSColin Finck
538c2c66affSColin Finck /***********************************************************************
539c2c66affSColin Finck * WinHttpConnect (winhttp.@)
540c2c66affSColin Finck */
WinHttpConnect(HINTERNET hsession,LPCWSTR server,INTERNET_PORT port,DWORD reserved)541c2c66affSColin Finck HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved )
542c2c66affSColin Finck {
5435bd6580fSAmine Khaldi struct connect *connect;
5445bd6580fSAmine Khaldi struct session *session;
545c2c66affSColin Finck HINTERNET hconnect = NULL;
546c2c66affSColin Finck
547c2c66affSColin Finck TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved);
548c2c66affSColin Finck
549c2c66affSColin Finck if (!server)
550c2c66affSColin Finck {
5515bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
552c2c66affSColin Finck return NULL;
553c2c66affSColin Finck }
5545bd6580fSAmine Khaldi if (!(session = (struct session *)grab_object( hsession )))
555c2c66affSColin Finck {
5565bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
557c2c66affSColin Finck return NULL;
558c2c66affSColin Finck }
559c2c66affSColin Finck if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
560c2c66affSColin Finck {
561c2c66affSColin Finck release_object( &session->hdr );
5625bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
563c2c66affSColin Finck return NULL;
564c2c66affSColin Finck }
5655bd6580fSAmine Khaldi if (!(connect = heap_alloc_zero( sizeof(struct connect) )))
566c2c66affSColin Finck {
567c2c66affSColin Finck release_object( &session->hdr );
568c2c66affSColin Finck return NULL;
569c2c66affSColin Finck }
570c2c66affSColin Finck connect->hdr.type = WINHTTP_HANDLE_TYPE_CONNECT;
571c2c66affSColin Finck connect->hdr.vtbl = &connect_vtbl;
572c2c66affSColin Finck connect->hdr.refs = 1;
573c2c66affSColin Finck connect->hdr.flags = session->hdr.flags;
574c2c66affSColin Finck connect->hdr.callback = session->hdr.callback;
575c2c66affSColin Finck connect->hdr.notify_mask = session->hdr.notify_mask;
576c2c66affSColin Finck connect->hdr.context = session->hdr.context;
577c2c66affSColin Finck connect->hdr.redirect_policy = session->hdr.redirect_policy;
578c2c66affSColin Finck list_init( &connect->hdr.children );
579c2c66affSColin Finck
580c2c66affSColin Finck addref_object( &session->hdr );
581c2c66affSColin Finck connect->session = session;
582c2c66affSColin Finck list_add_head( &session->hdr.children, &connect->hdr.entry );
583c2c66affSColin Finck
584c2c66affSColin Finck if (!(connect->hostname = strdupW( server ))) goto end;
585c2c66affSColin Finck connect->hostport = port;
586c2c66affSColin Finck if (!set_server_for_hostname( connect, server, port )) goto end;
587c2c66affSColin Finck
588c2c66affSColin Finck if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
589c2c66affSColin Finck connect->hdr.handle = hconnect;
590c2c66affSColin Finck
591c2c66affSColin Finck send_callback( &session->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hconnect, sizeof(hconnect) );
592c2c66affSColin Finck
593c2c66affSColin Finck end:
594c2c66affSColin Finck release_object( &connect->hdr );
595c2c66affSColin Finck release_object( &session->hdr );
596c2c66affSColin Finck TRACE("returning %p\n", hconnect);
5975bd6580fSAmine Khaldi if (hconnect) SetLastError( ERROR_SUCCESS );
598c2c66affSColin Finck return hconnect;
599c2c66affSColin Finck }
600c2c66affSColin Finck
601c2c66affSColin Finck /***********************************************************************
602c2c66affSColin Finck * request_destroy (internal)
603c2c66affSColin Finck */
request_destroy(struct object_header * hdr)6045bd6580fSAmine Khaldi static void request_destroy( struct object_header *hdr )
605c2c66affSColin Finck {
6065bd6580fSAmine Khaldi struct request *request = (struct request *)hdr;
607c2c66affSColin Finck unsigned int i, j;
608c2c66affSColin Finck
609c2c66affSColin Finck TRACE("%p\n", request);
610c2c66affSColin Finck
6115bd6580fSAmine Khaldi #ifdef __REACTOS__
612c2c66affSColin Finck if (request->task_thread)
6135bd6580fSAmine Khaldi #else
6145bd6580fSAmine Khaldi if (request->task_proc_running)
6155bd6580fSAmine Khaldi #endif
616c2c66affSColin Finck {
6175bd6580fSAmine Khaldi /* Signal to the task proc to quit. It will call this again when it does. */
6185bd6580fSAmine Khaldi #ifdef __REACTOS__
619c2c66affSColin Finck HANDLE thread = request->task_thread;
620c2c66affSColin Finck request->task_thread = 0;
621c2c66affSColin Finck SetEvent( request->task_cancel );
622c2c66affSColin Finck CloseHandle( thread );
6235bd6580fSAmine Khaldi #else
6245bd6580fSAmine Khaldi request->task_proc_running = FALSE;
6255bd6580fSAmine Khaldi SetEvent( request->task_cancel );
6265bd6580fSAmine Khaldi #endif
627c2c66affSColin Finck return;
628c2c66affSColin Finck }
629c2c66affSColin Finck release_object( &request->connect->hdr );
630c2c66affSColin Finck
6315bd6580fSAmine Khaldi if (request->cred_handle_initialized) FreeCredentialsHandle( &request->cred_handle );
6325bd6580fSAmine Khaldi CertFreeCertificateContext( request->server_cert );
6335bd6580fSAmine Khaldi CertFreeCertificateContext( request->client_cert );
6345bd6580fSAmine Khaldi
635c2c66affSColin Finck destroy_authinfo( request->authinfo );
636c2c66affSColin Finck destroy_authinfo( request->proxy_authinfo );
637c2c66affSColin Finck
638c2c66affSColin Finck heap_free( request->verb );
639c2c66affSColin Finck heap_free( request->path );
640c2c66affSColin Finck heap_free( request->version );
641c2c66affSColin Finck heap_free( request->raw_headers );
642c2c66affSColin Finck heap_free( request->status_text );
643c2c66affSColin Finck for (i = 0; i < request->num_headers; i++)
644c2c66affSColin Finck {
645c2c66affSColin Finck heap_free( request->headers[i].field );
646c2c66affSColin Finck heap_free( request->headers[i].value );
647c2c66affSColin Finck }
648c2c66affSColin Finck heap_free( request->headers );
649c2c66affSColin Finck for (i = 0; i < TARGET_MAX; i++)
650c2c66affSColin Finck {
651c2c66affSColin Finck for (j = 0; j < SCHEME_MAX; j++)
652c2c66affSColin Finck {
653c2c66affSColin Finck heap_free( request->creds[i][j].username );
654c2c66affSColin Finck heap_free( request->creds[i][j].password );
655c2c66affSColin Finck }
656c2c66affSColin Finck }
657c2c66affSColin Finck heap_free( request );
658c2c66affSColin Finck }
659c2c66affSColin Finck
str_to_buffer(WCHAR * buffer,const WCHAR * str,LPDWORD buflen)660c2c66affSColin Finck static void str_to_buffer( WCHAR *buffer, const WCHAR *str, LPDWORD buflen )
661c2c66affSColin Finck {
662c2c66affSColin Finck int len = 0;
663c2c66affSColin Finck if (str) len = strlenW( str );
664c2c66affSColin Finck if (buffer && *buflen > len)
665c2c66affSColin Finck {
666c2c66affSColin Finck if (str) memcpy( buffer, str, len * sizeof(WCHAR) );
667c2c66affSColin Finck buffer[len] = 0;
668c2c66affSColin Finck }
669c2c66affSColin Finck *buflen = len * sizeof(WCHAR);
670c2c66affSColin Finck }
671c2c66affSColin Finck
blob_to_str(DWORD encoding,CERT_NAME_BLOB * blob)672c2c66affSColin Finck static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob )
673c2c66affSColin Finck {
674c2c66affSColin Finck WCHAR *ret;
675c2c66affSColin Finck DWORD size, format = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG;
676c2c66affSColin Finck
677c2c66affSColin Finck size = CertNameToStrW( encoding, blob, format, NULL, 0 );
678c2c66affSColin Finck if ((ret = LocalAlloc( 0, size * sizeof(WCHAR) )))
679c2c66affSColin Finck CertNameToStrW( encoding, blob, format, ret, size );
680c2c66affSColin Finck
681c2c66affSColin Finck return ret;
682c2c66affSColin Finck }
683c2c66affSColin Finck
copy_sockaddr(const struct sockaddr * addr,SOCKADDR_STORAGE * addr_storage)6845bd6580fSAmine Khaldi static BOOL copy_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage )
685c2c66affSColin Finck {
686c2c66affSColin Finck switch (addr->sa_family)
687c2c66affSColin Finck {
688c2c66affSColin Finck case AF_INET:
689c2c66affSColin Finck {
690c2c66affSColin Finck struct sockaddr_in *addr_in = (struct sockaddr_in *)addr_storage;
691c2c66affSColin Finck
692c2c66affSColin Finck memcpy( addr_in, addr, sizeof(*addr_in) );
693c2c66affSColin Finck memset( addr_in + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in) );
694c2c66affSColin Finck return TRUE;
695c2c66affSColin Finck }
696c2c66affSColin Finck case AF_INET6:
697c2c66affSColin Finck {
698c2c66affSColin Finck struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr_storage;
699c2c66affSColin Finck
700c2c66affSColin Finck memcpy( addr_in6, addr, sizeof(*addr_in6) );
701c2c66affSColin Finck memset( addr_in6 + 1, 0, sizeof(*addr_storage) - sizeof(*addr_in6) );
702c2c66affSColin Finck return TRUE;
703c2c66affSColin Finck }
704c2c66affSColin Finck default:
705c2c66affSColin Finck ERR("unhandled family %u\n", addr->sa_family);
706c2c66affSColin Finck return FALSE;
707c2c66affSColin Finck }
708c2c66affSColin Finck }
709c2c66affSColin Finck
request_query_option(struct object_header * hdr,DWORD option,void * buffer,DWORD * buflen)7105bd6580fSAmine Khaldi static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
711c2c66affSColin Finck {
7125bd6580fSAmine Khaldi struct request *request = (struct request *)hdr;
713c2c66affSColin Finck
714c2c66affSColin Finck switch (option)
715c2c66affSColin Finck {
716c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_FLAGS:
717c2c66affSColin Finck {
7185bd6580fSAmine Khaldi DWORD flags;
719c2c66affSColin Finck int bits;
720c2c66affSColin Finck
721c2c66affSColin Finck if (!buffer || *buflen < sizeof(flags))
722c2c66affSColin Finck {
723c2c66affSColin Finck *buflen = sizeof(flags);
7245bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
725c2c66affSColin Finck return FALSE;
726c2c66affSColin Finck }
727c2c66affSColin Finck
7285bd6580fSAmine Khaldi flags = request->security_flags;
729c2c66affSColin Finck if (request->netconn)
730c2c66affSColin Finck {
731c2c66affSColin Finck bits = netconn_get_cipher_strength( request->netconn );
732c2c66affSColin Finck if (bits >= 128)
733c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_STRONG;
734c2c66affSColin Finck else if (bits >= 56)
735c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
736c2c66affSColin Finck else
737c2c66affSColin Finck flags |= SECURITY_FLAG_STRENGTH_WEAK;
738c2c66affSColin Finck }
739c2c66affSColin Finck *(DWORD *)buffer = flags;
740c2c66affSColin Finck *buflen = sizeof(flags);
741c2c66affSColin Finck return TRUE;
742c2c66affSColin Finck }
743c2c66affSColin Finck case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
744c2c66affSColin Finck {
745c2c66affSColin Finck const CERT_CONTEXT *cert;
746c2c66affSColin Finck
747c2c66affSColin Finck if (!buffer || *buflen < sizeof(cert))
748c2c66affSColin Finck {
749c2c66affSColin Finck *buflen = sizeof(cert);
7505bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
751c2c66affSColin Finck return FALSE;
752c2c66affSColin Finck }
753c2c66affSColin Finck
7545bd6580fSAmine Khaldi if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE;
755c2c66affSColin Finck *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
756c2c66affSColin Finck *buflen = sizeof(cert);
757c2c66affSColin Finck return TRUE;
758c2c66affSColin Finck }
759c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
760c2c66affSColin Finck {
7615bd6580fSAmine Khaldi const CERT_CONTEXT *cert = request->server_cert;
762c2c66affSColin Finck const CRYPT_OID_INFO *oidInfo;
763c2c66affSColin Finck WINHTTP_CERTIFICATE_INFO *ci = buffer;
764c2c66affSColin Finck
765c2c66affSColin Finck FIXME("partial stub\n");
766c2c66affSColin Finck
767c2c66affSColin Finck if (!buffer || *buflen < sizeof(*ci))
768c2c66affSColin Finck {
769c2c66affSColin Finck *buflen = sizeof(*ci);
7705bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
771c2c66affSColin Finck return FALSE;
772c2c66affSColin Finck }
7735bd6580fSAmine Khaldi if (!cert) return FALSE;
774c2c66affSColin Finck
775c2c66affSColin Finck ci->ftExpiry = cert->pCertInfo->NotAfter;
776c2c66affSColin Finck ci->ftStart = cert->pCertInfo->NotBefore;
777c2c66affSColin Finck ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject );
778c2c66affSColin Finck ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer );
779c2c66affSColin Finck ci->lpszProtocolName = NULL;
7805bd6580fSAmine Khaldi oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 );
781c2c66affSColin Finck if (oidInfo)
782c2c66affSColin Finck ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
783c2c66affSColin Finck else
784c2c66affSColin Finck ci->lpszSignatureAlgName = NULL;
785c2c66affSColin Finck ci->lpszEncryptionAlgName = NULL;
786c2c66affSColin Finck ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
787c2c66affSColin Finck
788c2c66affSColin Finck *buflen = sizeof(*ci);
789c2c66affSColin Finck return TRUE;
790c2c66affSColin Finck }
791c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
792c2c66affSColin Finck {
793c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD))
794c2c66affSColin Finck {
795c2c66affSColin Finck *buflen = sizeof(DWORD);
7965bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
797c2c66affSColin Finck return FALSE;
798c2c66affSColin Finck }
799c2c66affSColin Finck
800c2c66affSColin Finck *(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
801c2c66affSColin Finck *buflen = sizeof(DWORD);
802c2c66affSColin Finck return TRUE;
803c2c66affSColin Finck }
804c2c66affSColin Finck case WINHTTP_OPTION_CONNECTION_INFO:
805c2c66affSColin Finck {
806c2c66affSColin Finck WINHTTP_CONNECTION_INFO *info = buffer;
807c2c66affSColin Finck struct sockaddr local;
808c2c66affSColin Finck socklen_t len = sizeof(local);
809c2c66affSColin Finck const struct sockaddr *remote = (const struct sockaddr *)&request->connect->sockaddr;
810c2c66affSColin Finck
811c2c66affSColin Finck if (!buffer || *buflen < sizeof(*info))
812c2c66affSColin Finck {
813c2c66affSColin Finck *buflen = sizeof(*info);
8145bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
815c2c66affSColin Finck return FALSE;
816c2c66affSColin Finck }
817c2c66affSColin Finck if (!request->netconn)
818c2c66affSColin Finck {
8195bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
820c2c66affSColin Finck return FALSE;
821c2c66affSColin Finck }
822c2c66affSColin Finck if (getsockname( request->netconn->socket, &local, &len )) return FALSE;
8235bd6580fSAmine Khaldi if (!copy_sockaddr( &local, &info->LocalAddress )) return FALSE;
8245bd6580fSAmine Khaldi if (!copy_sockaddr( remote, &info->RemoteAddress )) return FALSE;
825c2c66affSColin Finck info->cbSize = sizeof(*info);
826c2c66affSColin Finck return TRUE;
827c2c66affSColin Finck }
828c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT:
829c2c66affSColin Finck *(DWORD *)buffer = request->resolve_timeout;
830c2c66affSColin Finck *buflen = sizeof(DWORD);
831c2c66affSColin Finck return TRUE;
8325bd6580fSAmine Khaldi
833c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT:
834c2c66affSColin Finck *(DWORD *)buffer = request->connect_timeout;
835c2c66affSColin Finck *buflen = sizeof(DWORD);
836c2c66affSColin Finck return TRUE;
8375bd6580fSAmine Khaldi
838c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT:
839c2c66affSColin Finck *(DWORD *)buffer = request->send_timeout;
840c2c66affSColin Finck *buflen = sizeof(DWORD);
841c2c66affSColin Finck return TRUE;
8425bd6580fSAmine Khaldi
843c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT:
8445bd6580fSAmine Khaldi *(DWORD *)buffer = request->receive_timeout;
8455bd6580fSAmine Khaldi *buflen = sizeof(DWORD);
8465bd6580fSAmine Khaldi return TRUE;
8475bd6580fSAmine Khaldi
8485bd6580fSAmine Khaldi case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
8495bd6580fSAmine Khaldi *(DWORD *)buffer = request->receive_response_timeout;
850c2c66affSColin Finck *buflen = sizeof(DWORD);
851c2c66affSColin Finck return TRUE;
852c2c66affSColin Finck
853c2c66affSColin Finck case WINHTTP_OPTION_USERNAME:
854c2c66affSColin Finck str_to_buffer( buffer, request->connect->username, buflen );
855c2c66affSColin Finck return TRUE;
856c2c66affSColin Finck
857c2c66affSColin Finck case WINHTTP_OPTION_PASSWORD:
858c2c66affSColin Finck str_to_buffer( buffer, request->connect->password, buflen );
859c2c66affSColin Finck return TRUE;
860c2c66affSColin Finck
861c2c66affSColin Finck case WINHTTP_OPTION_PROXY_USERNAME:
862c2c66affSColin Finck str_to_buffer( buffer, request->connect->session->proxy_username, buflen );
863c2c66affSColin Finck return TRUE;
864c2c66affSColin Finck
865c2c66affSColin Finck case WINHTTP_OPTION_PROXY_PASSWORD:
866c2c66affSColin Finck str_to_buffer( buffer, request->connect->session->proxy_password, buflen );
867c2c66affSColin Finck return TRUE;
868c2c66affSColin Finck
869c2c66affSColin Finck default:
870c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
8715bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
872c2c66affSColin Finck return FALSE;
873c2c66affSColin Finck }
874c2c66affSColin Finck }
875c2c66affSColin Finck
buffer_to_str(WCHAR * buffer,DWORD buflen)876c2c66affSColin Finck static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen )
877c2c66affSColin Finck {
878c2c66affSColin Finck WCHAR *ret;
879c2c66affSColin Finck if ((ret = heap_alloc( (buflen + 1) * sizeof(WCHAR))))
880c2c66affSColin Finck {
881c2c66affSColin Finck memcpy( ret, buffer, buflen * sizeof(WCHAR) );
882c2c66affSColin Finck ret[buflen] = 0;
883c2c66affSColin Finck return ret;
884c2c66affSColin Finck }
8855bd6580fSAmine Khaldi SetLastError( ERROR_OUTOFMEMORY );
886c2c66affSColin Finck return NULL;
887c2c66affSColin Finck }
888c2c66affSColin Finck
request_set_option(struct object_header * hdr,DWORD option,void * buffer,DWORD buflen)8895bd6580fSAmine Khaldi static BOOL request_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
890c2c66affSColin Finck {
8915bd6580fSAmine Khaldi struct request *request = (struct request *)hdr;
892c2c66affSColin Finck
893c2c66affSColin Finck switch (option)
894c2c66affSColin Finck {
895c2c66affSColin Finck case WINHTTP_OPTION_PROXY:
896c2c66affSColin Finck {
897c2c66affSColin Finck WINHTTP_PROXY_INFO *pi = buffer;
898c2c66affSColin Finck
899c2c66affSColin Finck FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
900c2c66affSColin Finck return TRUE;
901c2c66affSColin Finck }
902c2c66affSColin Finck case WINHTTP_OPTION_DISABLE_FEATURE:
903c2c66affSColin Finck {
904c2c66affSColin Finck DWORD disable;
905c2c66affSColin Finck
906c2c66affSColin Finck if (buflen != sizeof(DWORD))
907c2c66affSColin Finck {
9085bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
909c2c66affSColin Finck return FALSE;
910c2c66affSColin Finck }
911c2c66affSColin Finck
912c2c66affSColin Finck disable = *(DWORD *)buffer;
913c2c66affSColin Finck TRACE("0x%x\n", disable);
914c2c66affSColin Finck hdr->disable_flags |= disable;
915c2c66affSColin Finck return TRUE;
916c2c66affSColin Finck }
917c2c66affSColin Finck case WINHTTP_OPTION_AUTOLOGON_POLICY:
918c2c66affSColin Finck {
919c2c66affSColin Finck DWORD policy;
920c2c66affSColin Finck
921c2c66affSColin Finck if (buflen != sizeof(DWORD))
922c2c66affSColin Finck {
9235bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
924c2c66affSColin Finck return FALSE;
925c2c66affSColin Finck }
926c2c66affSColin Finck
927c2c66affSColin Finck policy = *(DWORD *)buffer;
928c2c66affSColin Finck TRACE("0x%x\n", policy);
929c2c66affSColin Finck hdr->logon_policy = policy;
930c2c66affSColin Finck return TRUE;
931c2c66affSColin Finck }
932c2c66affSColin Finck case WINHTTP_OPTION_REDIRECT_POLICY:
933c2c66affSColin Finck {
934c2c66affSColin Finck DWORD policy;
935c2c66affSColin Finck
936c2c66affSColin Finck if (buflen != sizeof(DWORD))
937c2c66affSColin Finck {
9385bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
939c2c66affSColin Finck return FALSE;
940c2c66affSColin Finck }
941c2c66affSColin Finck
942c2c66affSColin Finck policy = *(DWORD *)buffer;
943c2c66affSColin Finck TRACE("0x%x\n", policy);
944c2c66affSColin Finck hdr->redirect_policy = policy;
945c2c66affSColin Finck return TRUE;
946c2c66affSColin Finck }
947c2c66affSColin Finck case WINHTTP_OPTION_SECURITY_FLAGS:
948c2c66affSColin Finck {
949c2c66affSColin Finck DWORD flags;
9505bd6580fSAmine Khaldi static const DWORD accepted = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
9515bd6580fSAmine Khaldi SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
9525bd6580fSAmine Khaldi SECURITY_FLAG_IGNORE_UNKNOWN_CA |
9535bd6580fSAmine Khaldi SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
954c2c66affSColin Finck
955c2c66affSColin Finck if (buflen < sizeof(DWORD))
956c2c66affSColin Finck {
9575bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
958c2c66affSColin Finck return FALSE;
959c2c66affSColin Finck }
960c2c66affSColin Finck flags = *(DWORD *)buffer;
961c2c66affSColin Finck TRACE("0x%x\n", flags);
9625bd6580fSAmine Khaldi if (flags && (flags & ~accepted))
963c2c66affSColin Finck {
9645bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
965c2c66affSColin Finck return FALSE;
966c2c66affSColin Finck }
967c2c66affSColin Finck request->security_flags = flags;
968c2c66affSColin Finck return TRUE;
969c2c66affSColin Finck }
970c2c66affSColin Finck case WINHTTP_OPTION_RESOLVE_TIMEOUT:
971c2c66affSColin Finck request->resolve_timeout = *(DWORD *)buffer;
972c2c66affSColin Finck return TRUE;
9735bd6580fSAmine Khaldi
974c2c66affSColin Finck case WINHTTP_OPTION_CONNECT_TIMEOUT:
975c2c66affSColin Finck request->connect_timeout = *(DWORD *)buffer;
976c2c66affSColin Finck return TRUE;
9775bd6580fSAmine Khaldi
978c2c66affSColin Finck case WINHTTP_OPTION_SEND_TIMEOUT:
979c2c66affSColin Finck request->send_timeout = *(DWORD *)buffer;
980c2c66affSColin Finck return TRUE;
9815bd6580fSAmine Khaldi
982c2c66affSColin Finck case WINHTTP_OPTION_RECEIVE_TIMEOUT:
9835bd6580fSAmine Khaldi request->receive_timeout = *(DWORD *)buffer;
9845bd6580fSAmine Khaldi return TRUE;
9855bd6580fSAmine Khaldi
9865bd6580fSAmine Khaldi case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
9875bd6580fSAmine Khaldi request->receive_response_timeout = *(DWORD *)buffer;
988c2c66affSColin Finck return TRUE;
989c2c66affSColin Finck
990c2c66affSColin Finck case WINHTTP_OPTION_USERNAME:
991c2c66affSColin Finck {
9925bd6580fSAmine Khaldi struct connect *connect = request->connect;
993c2c66affSColin Finck
994c2c66affSColin Finck heap_free( connect->username );
995c2c66affSColin Finck if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE;
996c2c66affSColin Finck return TRUE;
997c2c66affSColin Finck }
998c2c66affSColin Finck case WINHTTP_OPTION_PASSWORD:
999c2c66affSColin Finck {
10005bd6580fSAmine Khaldi struct connect *connect = request->connect;
1001c2c66affSColin Finck
1002c2c66affSColin Finck heap_free( connect->password );
1003c2c66affSColin Finck if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE;
1004c2c66affSColin Finck return TRUE;
1005c2c66affSColin Finck }
1006c2c66affSColin Finck case WINHTTP_OPTION_PROXY_USERNAME:
1007c2c66affSColin Finck {
10085bd6580fSAmine Khaldi struct session *session = request->connect->session;
1009c2c66affSColin Finck
1010c2c66affSColin Finck heap_free( session->proxy_username );
1011c2c66affSColin Finck if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE;
1012c2c66affSColin Finck return TRUE;
1013c2c66affSColin Finck }
1014c2c66affSColin Finck case WINHTTP_OPTION_PROXY_PASSWORD:
1015c2c66affSColin Finck {
10165bd6580fSAmine Khaldi struct session *session = request->connect->session;
1017c2c66affSColin Finck
1018c2c66affSColin Finck heap_free( session->proxy_password );
1019c2c66affSColin Finck if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE;
1020c2c66affSColin Finck return TRUE;
1021c2c66affSColin Finck }
1022c2c66affSColin Finck case WINHTTP_OPTION_CLIENT_CERT_CONTEXT:
10235bd6580fSAmine Khaldi {
10245bd6580fSAmine Khaldi const CERT_CONTEXT *cert;
10255bd6580fSAmine Khaldi
1026c2c66affSColin Finck if (!(hdr->flags & WINHTTP_FLAG_SECURE))
1027c2c66affSColin Finck {
1028c2c66affSColin Finck SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
1029c2c66affSColin Finck return FALSE;
1030c2c66affSColin Finck }
10315bd6580fSAmine Khaldi if (!buffer)
10325bd6580fSAmine Khaldi {
10335bd6580fSAmine Khaldi CertFreeCertificateContext( request->client_cert );
10345bd6580fSAmine Khaldi request->client_cert = NULL;
10355bd6580fSAmine Khaldi }
10365bd6580fSAmine Khaldi else if (buflen >= sizeof(cert))
10375bd6580fSAmine Khaldi {
10385bd6580fSAmine Khaldi if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE;
10395bd6580fSAmine Khaldi CertFreeCertificateContext( request->client_cert );
10405bd6580fSAmine Khaldi request->client_cert = cert;
10415bd6580fSAmine Khaldi }
10425bd6580fSAmine Khaldi else
10435bd6580fSAmine Khaldi {
10445bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
10455bd6580fSAmine Khaldi return FALSE;
10465bd6580fSAmine Khaldi }
10475bd6580fSAmine Khaldi
10485bd6580fSAmine Khaldi if (request->cred_handle_initialized)
10495bd6580fSAmine Khaldi {
10505bd6580fSAmine Khaldi FreeCredentialsHandle( &request->cred_handle );
10515bd6580fSAmine Khaldi request->cred_handle_initialized = FALSE;
10525bd6580fSAmine Khaldi }
10535bd6580fSAmine Khaldi
1054c2c66affSColin Finck return TRUE;
10555bd6580fSAmine Khaldi }
10565bd6580fSAmine Khaldi case WINHTTP_OPTION_ENABLE_FEATURE:
10575bd6580fSAmine Khaldi if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
10585bd6580fSAmine Khaldi {
10595bd6580fSAmine Khaldi request->check_revocation = TRUE;
10605bd6580fSAmine Khaldi SetLastError( NO_ERROR );
10615bd6580fSAmine Khaldi return TRUE;
10625bd6580fSAmine Khaldi }
10635bd6580fSAmine Khaldi else
10645bd6580fSAmine Khaldi {
10655bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
10665bd6580fSAmine Khaldi return FALSE;
10675bd6580fSAmine Khaldi }
10685bd6580fSAmine Khaldi
10695bd6580fSAmine Khaldi case WINHTTP_OPTION_CONNECT_RETRIES:
10705bd6580fSAmine Khaldi FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n");
10715bd6580fSAmine Khaldi return TRUE;
10725bd6580fSAmine Khaldi
1073c2c66affSColin Finck default:
1074c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
10755bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INVALID_OPTION );
10768317165dSAmine Khaldi return FALSE;
1077c2c66affSColin Finck }
1078c2c66affSColin Finck }
1079c2c66affSColin Finck
10805bd6580fSAmine Khaldi static const struct object_vtbl request_vtbl =
1081c2c66affSColin Finck {
1082c2c66affSColin Finck request_destroy,
1083c2c66affSColin Finck request_query_option,
1084c2c66affSColin Finck request_set_option
1085c2c66affSColin Finck };
1086c2c66affSColin Finck
add_accept_types_header(struct request * request,const WCHAR ** types)10875bd6580fSAmine Khaldi static BOOL add_accept_types_header( struct request *request, const WCHAR **types )
1088c2c66affSColin Finck {
10895bd6580fSAmine Khaldi static const WCHAR acceptW[] = {'A','c','c','e','p','t',0};
10900530cb8bSAmine Khaldi static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
1091c2c66affSColin Finck
1092c2c66affSColin Finck if (!types) return TRUE;
1093c2c66affSColin Finck while (*types)
1094c2c66affSColin Finck {
10955bd6580fSAmine Khaldi if (!process_header( request, acceptW, *types, flags, TRUE )) return FALSE;
1096c2c66affSColin Finck types++;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck return TRUE;
1099c2c66affSColin Finck }
1100c2c66affSColin Finck
get_request_path(const WCHAR * object)11015bd6580fSAmine Khaldi static WCHAR *get_request_path( const WCHAR *object )
11025bd6580fSAmine Khaldi {
11035bd6580fSAmine Khaldi int len = object ? strlenW(object) : 0;
11045bd6580fSAmine Khaldi WCHAR *p, *ret;
11055bd6580fSAmine Khaldi
11065bd6580fSAmine Khaldi if (!object || object[0] != '/') len++;
11075bd6580fSAmine Khaldi if (!(p = ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
11085bd6580fSAmine Khaldi if (!object || object[0] != '/') *p++ = '/';
11095bd6580fSAmine Khaldi if (object) strcpyW( p, object );
11105bd6580fSAmine Khaldi ret[len] = 0;
11115bd6580fSAmine Khaldi return ret;
11125bd6580fSAmine Khaldi }
11135bd6580fSAmine Khaldi
1114c2c66affSColin Finck /***********************************************************************
1115c2c66affSColin Finck * WinHttpOpenRequest (winhttp.@)
1116c2c66affSColin Finck */
WinHttpOpenRequest(HINTERNET hconnect,LPCWSTR verb,LPCWSTR object,LPCWSTR version,LPCWSTR referrer,LPCWSTR * types,DWORD flags)1117c2c66affSColin Finck HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version,
1118c2c66affSColin Finck LPCWSTR referrer, LPCWSTR *types, DWORD flags )
1119c2c66affSColin Finck {
11205bd6580fSAmine Khaldi struct request *request;
11215bd6580fSAmine Khaldi struct connect *connect;
1122c2c66affSColin Finck HINTERNET hrequest = NULL;
1123c2c66affSColin Finck
1124c2c66affSColin Finck TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object),
1125c2c66affSColin Finck debugstr_w(version), debugstr_w(referrer), types, flags);
1126c2c66affSColin Finck
11275bd6580fSAmine Khaldi if (types && TRACE_ON(winhttp))
11285bd6580fSAmine Khaldi {
1129c2c66affSColin Finck const WCHAR **iter;
1130c2c66affSColin Finck TRACE("accept types:\n");
11315bd6580fSAmine Khaldi for (iter = types; *iter; iter++) TRACE(" %s\n", debugstr_w(*iter));
1132c2c66affSColin Finck }
1133c2c66affSColin Finck
11345bd6580fSAmine Khaldi if (!(connect = (struct connect *)grab_object( hconnect )))
1135c2c66affSColin Finck {
11365bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
1137c2c66affSColin Finck return NULL;
1138c2c66affSColin Finck }
1139c2c66affSColin Finck if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT)
1140c2c66affSColin Finck {
1141c2c66affSColin Finck release_object( &connect->hdr );
11425bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1143c2c66affSColin Finck return NULL;
1144c2c66affSColin Finck }
11455bd6580fSAmine Khaldi if (!(request = heap_alloc_zero( sizeof(struct request) )))
1146c2c66affSColin Finck {
1147c2c66affSColin Finck release_object( &connect->hdr );
1148c2c66affSColin Finck return NULL;
1149c2c66affSColin Finck }
1150c2c66affSColin Finck request->hdr.type = WINHTTP_HANDLE_TYPE_REQUEST;
1151c2c66affSColin Finck request->hdr.vtbl = &request_vtbl;
1152c2c66affSColin Finck request->hdr.refs = 1;
1153c2c66affSColin Finck request->hdr.flags = flags;
1154c2c66affSColin Finck request->hdr.callback = connect->hdr.callback;
1155c2c66affSColin Finck request->hdr.notify_mask = connect->hdr.notify_mask;
1156c2c66affSColin Finck request->hdr.context = connect->hdr.context;
1157c2c66affSColin Finck request->hdr.redirect_policy = connect->hdr.redirect_policy;
1158c2c66affSColin Finck list_init( &request->hdr.children );
1159c2c66affSColin Finck list_init( &request->task_queue );
1160c2c66affSColin Finck
1161c2c66affSColin Finck addref_object( &connect->hdr );
1162c2c66affSColin Finck request->connect = connect;
1163c2c66affSColin Finck list_add_head( &connect->hdr.children, &request->hdr.entry );
1164c2c66affSColin Finck
1165c2c66affSColin Finck request->resolve_timeout = connect->session->resolve_timeout;
1166c2c66affSColin Finck request->connect_timeout = connect->session->connect_timeout;
1167c2c66affSColin Finck request->send_timeout = connect->session->send_timeout;
11685bd6580fSAmine Khaldi request->receive_timeout = connect->session->receive_timeout;
11695bd6580fSAmine Khaldi request->receive_response_timeout = connect->session->receive_response_timeout;
1170c2c66affSColin Finck
1171c2c66affSColin Finck if (!verb || !verb[0]) verb = getW;
1172c2c66affSColin Finck if (!(request->verb = strdupW( verb ))) goto end;
11735bd6580fSAmine Khaldi if (!(request->path = get_request_path( object ))) goto end;
1174c2c66affSColin Finck
1175c2c66affSColin Finck if (!version || !version[0]) version = http1_1;
1176c2c66affSColin Finck if (!(request->version = strdupW( version ))) goto end;
11775bd6580fSAmine Khaldi if (!(add_accept_types_header( request, types ))) goto end;
1178c2c66affSColin Finck
1179c2c66affSColin Finck if (!(hrequest = alloc_handle( &request->hdr ))) goto end;
1180c2c66affSColin Finck request->hdr.handle = hrequest;
1181c2c66affSColin Finck
1182c2c66affSColin Finck send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hrequest, sizeof(hrequest) );
1183c2c66affSColin Finck
1184c2c66affSColin Finck end:
1185c2c66affSColin Finck release_object( &request->hdr );
1186c2c66affSColin Finck release_object( &connect->hdr );
1187c2c66affSColin Finck TRACE("returning %p\n", hrequest);
11885bd6580fSAmine Khaldi if (hrequest) SetLastError( ERROR_SUCCESS );
1189c2c66affSColin Finck return hrequest;
1190c2c66affSColin Finck }
1191c2c66affSColin Finck
1192c2c66affSColin Finck /***********************************************************************
1193c2c66affSColin Finck * WinHttpCloseHandle (winhttp.@)
1194c2c66affSColin Finck */
WinHttpCloseHandle(HINTERNET handle)1195c2c66affSColin Finck BOOL WINAPI WinHttpCloseHandle( HINTERNET handle )
1196c2c66affSColin Finck {
11975bd6580fSAmine Khaldi struct object_header *hdr;
1198c2c66affSColin Finck
1199c2c66affSColin Finck TRACE("%p\n", handle);
1200c2c66affSColin Finck
1201c2c66affSColin Finck if (!(hdr = grab_object( handle )))
1202c2c66affSColin Finck {
12035bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
1204c2c66affSColin Finck return FALSE;
1205c2c66affSColin Finck }
1206c2c66affSColin Finck release_object( hdr );
1207c2c66affSColin Finck free_handle( handle );
12085bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
1209c2c66affSColin Finck return TRUE;
1210c2c66affSColin Finck }
1211c2c66affSColin Finck
query_option(struct object_header * hdr,DWORD option,void * buffer,DWORD * buflen)12125bd6580fSAmine Khaldi static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
1213c2c66affSColin Finck {
1214c2c66affSColin Finck BOOL ret = FALSE;
1215c2c66affSColin Finck
1216c2c66affSColin Finck if (!buflen)
1217c2c66affSColin Finck {
12185bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1219c2c66affSColin Finck return FALSE;
1220c2c66affSColin Finck }
1221c2c66affSColin Finck
1222c2c66affSColin Finck switch (option)
1223c2c66affSColin Finck {
1224c2c66affSColin Finck case WINHTTP_OPTION_CONTEXT_VALUE:
1225c2c66affSColin Finck {
1226c2c66affSColin Finck if (!buffer || *buflen < sizeof(DWORD_PTR))
1227c2c66affSColin Finck {
1228c2c66affSColin Finck *buflen = sizeof(DWORD_PTR);
12295bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
1230c2c66affSColin Finck return FALSE;
1231c2c66affSColin Finck }
1232c2c66affSColin Finck
1233c2c66affSColin Finck *(DWORD_PTR *)buffer = hdr->context;
1234c2c66affSColin Finck *buflen = sizeof(DWORD_PTR);
1235c2c66affSColin Finck return TRUE;
1236c2c66affSColin Finck }
1237c2c66affSColin Finck default:
1238c2c66affSColin Finck if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen );
1239c2c66affSColin Finck else
1240c2c66affSColin Finck {
1241c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
12425bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1243c2c66affSColin Finck return FALSE;
1244c2c66affSColin Finck }
1245c2c66affSColin Finck break;
1246c2c66affSColin Finck }
1247c2c66affSColin Finck return ret;
1248c2c66affSColin Finck }
1249c2c66affSColin Finck
1250c2c66affSColin Finck /***********************************************************************
1251c2c66affSColin Finck * WinHttpQueryOption (winhttp.@)
1252c2c66affSColin Finck */
WinHttpQueryOption(HINTERNET handle,DWORD option,LPVOID buffer,LPDWORD buflen)1253c2c66affSColin Finck BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen )
1254c2c66affSColin Finck {
1255c2c66affSColin Finck BOOL ret = FALSE;
12565bd6580fSAmine Khaldi struct object_header *hdr;
1257c2c66affSColin Finck
1258c2c66affSColin Finck TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen);
1259c2c66affSColin Finck
1260c2c66affSColin Finck if (!(hdr = grab_object( handle )))
1261c2c66affSColin Finck {
12625bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
1263c2c66affSColin Finck return FALSE;
1264c2c66affSColin Finck }
1265c2c66affSColin Finck
1266c2c66affSColin Finck ret = query_option( hdr, option, buffer, buflen );
1267c2c66affSColin Finck
1268c2c66affSColin Finck release_object( hdr );
12695bd6580fSAmine Khaldi if (ret) SetLastError( ERROR_SUCCESS );
1270c2c66affSColin Finck return ret;
1271c2c66affSColin Finck }
1272c2c66affSColin Finck
set_option(struct object_header * hdr,DWORD option,void * buffer,DWORD buflen)12735bd6580fSAmine Khaldi static BOOL set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen )
1274c2c66affSColin Finck {
1275c2c66affSColin Finck BOOL ret = TRUE;
1276c2c66affSColin Finck
1277c2c66affSColin Finck if (!buffer && buflen)
1278c2c66affSColin Finck {
12795bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1280c2c66affSColin Finck return FALSE;
1281c2c66affSColin Finck }
1282c2c66affSColin Finck
1283c2c66affSColin Finck switch (option)
1284c2c66affSColin Finck {
1285c2c66affSColin Finck case WINHTTP_OPTION_CONTEXT_VALUE:
1286c2c66affSColin Finck {
1287c2c66affSColin Finck if (buflen != sizeof(DWORD_PTR))
1288c2c66affSColin Finck {
12895bd6580fSAmine Khaldi SetLastError( ERROR_INSUFFICIENT_BUFFER );
1290c2c66affSColin Finck return FALSE;
1291c2c66affSColin Finck }
1292c2c66affSColin Finck
1293c2c66affSColin Finck hdr->context = *(DWORD_PTR *)buffer;
1294c2c66affSColin Finck return TRUE;
1295c2c66affSColin Finck }
1296c2c66affSColin Finck default:
1297c2c66affSColin Finck if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen );
1298c2c66affSColin Finck else
1299c2c66affSColin Finck {
1300c2c66affSColin Finck FIXME("unimplemented option %u\n", option);
13015bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1302c2c66affSColin Finck return FALSE;
1303c2c66affSColin Finck }
1304c2c66affSColin Finck break;
1305c2c66affSColin Finck }
1306c2c66affSColin Finck return ret;
1307c2c66affSColin Finck }
1308c2c66affSColin Finck
1309c2c66affSColin Finck /***********************************************************************
1310c2c66affSColin Finck * WinHttpSetOption (winhttp.@)
1311c2c66affSColin Finck */
WinHttpSetOption(HINTERNET handle,DWORD option,LPVOID buffer,DWORD buflen)1312c2c66affSColin Finck BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen )
1313c2c66affSColin Finck {
1314c2c66affSColin Finck BOOL ret = FALSE;
13155bd6580fSAmine Khaldi struct object_header *hdr;
1316c2c66affSColin Finck
1317c2c66affSColin Finck TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen);
1318c2c66affSColin Finck
1319c2c66affSColin Finck if (!(hdr = grab_object( handle )))
1320c2c66affSColin Finck {
13215bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
1322c2c66affSColin Finck return FALSE;
1323c2c66affSColin Finck }
1324c2c66affSColin Finck
1325c2c66affSColin Finck ret = set_option( hdr, option, buffer, buflen );
1326c2c66affSColin Finck
1327c2c66affSColin Finck release_object( hdr );
13285bd6580fSAmine Khaldi if (ret) SetLastError( ERROR_SUCCESS );
1329c2c66affSColin Finck return ret;
1330c2c66affSColin Finck }
1331c2c66affSColin Finck
get_computer_name(COMPUTER_NAME_FORMAT format)1332c2c66affSColin Finck static char *get_computer_name( COMPUTER_NAME_FORMAT format )
1333c2c66affSColin Finck {
1334c2c66affSColin Finck char *ret;
1335c2c66affSColin Finck DWORD size = 0;
1336c2c66affSColin Finck
1337c2c66affSColin Finck GetComputerNameExA( format, NULL, &size );
1338c2c66affSColin Finck if (GetLastError() != ERROR_MORE_DATA) return NULL;
1339c2c66affSColin Finck if (!(ret = heap_alloc( size ))) return NULL;
1340c2c66affSColin Finck if (!GetComputerNameExA( format, ret, &size ))
1341c2c66affSColin Finck {
1342c2c66affSColin Finck heap_free( ret );
1343c2c66affSColin Finck return NULL;
1344c2c66affSColin Finck }
1345c2c66affSColin Finck return ret;
1346c2c66affSColin Finck }
1347c2c66affSColin Finck
is_domain_suffix(const char * domain,const char * suffix)1348c2c66affSColin Finck static BOOL is_domain_suffix( const char *domain, const char *suffix )
1349c2c66affSColin Finck {
1350c2c66affSColin Finck int len_domain = strlen( domain ), len_suffix = strlen( suffix );
1351c2c66affSColin Finck
1352c2c66affSColin Finck if (len_suffix > len_domain) return FALSE;
13535bd6580fSAmine Khaldi if (!_strnicmp( domain + len_domain - len_suffix, suffix, -1 )) return TRUE;
1354c2c66affSColin Finck return FALSE;
1355c2c66affSColin Finck }
1356c2c66affSColin Finck
reverse_lookup(const struct addrinfo * ai,char * hostname,size_t len)1357c2c66affSColin Finck static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len )
1358c2c66affSColin Finck {
13595bd6580fSAmine Khaldi return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
1360c2c66affSColin Finck }
1361c2c66affSColin Finck
build_wpad_url(const char * hostname,const struct addrinfo * ai)1362c2c66affSColin Finck static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
1363c2c66affSColin Finck {
1364c2c66affSColin Finck static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
1365c2c66affSColin Finck static const WCHAR wpadW[] = {'/','w','p','a','d','.','d','a','t',0};
1366c2c66affSColin Finck char name[NI_MAXHOST];
1367c2c66affSColin Finck WCHAR *ret, *p;
1368c2c66affSColin Finck int len;
1369c2c66affSColin Finck
1370c2c66affSColin Finck while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next;
1371c2c66affSColin Finck if (!ai) return NULL;
1372c2c66affSColin Finck
1373c2c66affSColin Finck if (!reverse_lookup( ai, name, sizeof(name) )) hostname = name;
1374c2c66affSColin Finck
1375c2c66affSColin Finck len = strlenW( httpW ) + strlen( hostname ) + strlenW( wpadW );
1376c2c66affSColin Finck if (!(ret = p = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
1377c2c66affSColin Finck strcpyW( p, httpW );
1378c2c66affSColin Finck p += strlenW( httpW );
1379c2c66affSColin Finck while (*hostname) { *p++ = *hostname++; }
1380c2c66affSColin Finck strcpyW( p, wpadW );
1381c2c66affSColin Finck return ret;
1382c2c66affSColin Finck }
1383c2c66affSColin Finck
get_system_proxy_autoconfig_url(char * buf,DWORD buflen)1384c2c66affSColin Finck static BOOL get_system_proxy_autoconfig_url( char *buf, DWORD buflen )
1385c2c66affSColin Finck {
1386c2c66affSColin Finck #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1387c2c66affSColin Finck CFDictionaryRef settings = CFNetworkCopySystemProxySettings();
1388c2c66affSColin Finck const void *ref;
1389c2c66affSColin Finck BOOL ret = FALSE;
1390c2c66affSColin Finck
1391c2c66affSColin Finck if (!settings) return FALSE;
1392c2c66affSColin Finck
1393c2c66affSColin Finck if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
1394c2c66affSColin Finck {
1395c2c66affSColin Finck CFRelease( settings );
1396c2c66affSColin Finck return FALSE;
1397c2c66affSColin Finck }
1398c2c66affSColin Finck if (CFStringGetCString( ref, buf, buflen, kCFStringEncodingASCII ))
1399c2c66affSColin Finck {
1400c2c66affSColin Finck TRACE( "returning %s\n", debugstr_a(buf) );
1401c2c66affSColin Finck ret = TRUE;
1402c2c66affSColin Finck }
1403c2c66affSColin Finck CFRelease( settings );
1404c2c66affSColin Finck return ret;
1405c2c66affSColin Finck #else
1406c2c66affSColin Finck static BOOL first = TRUE;
1407c2c66affSColin Finck if (first)
1408c2c66affSColin Finck {
1409c2c66affSColin Finck FIXME( "no support on this platform\n" );
1410c2c66affSColin Finck first = FALSE;
1411c2c66affSColin Finck }
1412c2c66affSColin Finck else
1413c2c66affSColin Finck TRACE( "no support on this platform\n" );
1414c2c66affSColin Finck return FALSE;
1415c2c66affSColin Finck #endif
1416c2c66affSColin Finck }
1417c2c66affSColin Finck
1418c2c66affSColin Finck #define INTERNET_MAX_URL_LENGTH 2084
1419c2c66affSColin Finck
1420c2c66affSColin Finck /***********************************************************************
1421c2c66affSColin Finck * WinHttpDetectAutoProxyConfigUrl (winhttp.@)
1422c2c66affSColin Finck */
WinHttpDetectAutoProxyConfigUrl(DWORD flags,LPWSTR * url)1423c2c66affSColin Finck BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
1424c2c66affSColin Finck {
1425c2c66affSColin Finck BOOL ret = FALSE;
1426c2c66affSColin Finck char system_url[INTERNET_MAX_URL_LENGTH + 1];
1427c2c66affSColin Finck
1428c2c66affSColin Finck TRACE("0x%08x, %p\n", flags, url);
1429c2c66affSColin Finck
1430c2c66affSColin Finck if (!flags || !url)
1431c2c66affSColin Finck {
14325bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1433c2c66affSColin Finck return FALSE;
1434c2c66affSColin Finck }
1435c2c66affSColin Finck if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) ))
1436c2c66affSColin Finck {
1437c2c66affSColin Finck WCHAR *urlW;
1438c2c66affSColin Finck
1439c2c66affSColin Finck if (!(urlW = strdupAW( system_url ))) return FALSE;
1440c2c66affSColin Finck *url = urlW;
14415bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
1442c2c66affSColin Finck return TRUE;
1443c2c66affSColin Finck }
1444c2c66affSColin Finck if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP)
1445c2c66affSColin Finck {
1446c2c66affSColin Finck static int fixme_shown;
1447c2c66affSColin Finck if (!fixme_shown++) FIXME("discovery via DHCP not supported\n");
1448c2c66affSColin Finck }
1449c2c66affSColin Finck if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A)
1450c2c66affSColin Finck {
1451c2c66affSColin Finck char *fqdn, *domain, *p;
1452c2c66affSColin Finck
1453c2c66affSColin Finck if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return FALSE;
1454c2c66affSColin Finck if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain )))
1455c2c66affSColin Finck {
1456c2c66affSColin Finck heap_free( fqdn );
1457c2c66affSColin Finck return FALSE;
1458c2c66affSColin Finck }
1459c2c66affSColin Finck p = fqdn;
1460c2c66affSColin Finck while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain ))
1461c2c66affSColin Finck {
1462c2c66affSColin Finck struct addrinfo *ai;
1463c2c66affSColin Finck char *name;
1464c2c66affSColin Finck int res;
1465c2c66affSColin Finck
1466c2c66affSColin Finck if (!(name = heap_alloc( sizeof("wpad") + strlen(p) )))
1467c2c66affSColin Finck {
1468c2c66affSColin Finck heap_free( fqdn );
1469c2c66affSColin Finck heap_free( domain );
1470c2c66affSColin Finck return FALSE;
1471c2c66affSColin Finck }
1472c2c66affSColin Finck strcpy( name, "wpad" );
1473c2c66affSColin Finck strcat( name, p );
1474c2c66affSColin Finck res = getaddrinfo( name, NULL, NULL, &ai );
1475c2c66affSColin Finck if (!res)
1476c2c66affSColin Finck {
1477c2c66affSColin Finck *url = build_wpad_url( name, ai );
1478c2c66affSColin Finck freeaddrinfo( ai );
1479c2c66affSColin Finck if (*url)
1480c2c66affSColin Finck {
1481c2c66affSColin Finck TRACE("returning %s\n", debugstr_w(*url));
1482c2c66affSColin Finck heap_free( name );
1483c2c66affSColin Finck ret = TRUE;
1484c2c66affSColin Finck break;
1485c2c66affSColin Finck }
1486c2c66affSColin Finck }
1487c2c66affSColin Finck heap_free( name );
1488c2c66affSColin Finck p++;
1489c2c66affSColin Finck }
1490c2c66affSColin Finck heap_free( domain );
1491c2c66affSColin Finck heap_free( fqdn );
1492c2c66affSColin Finck }
1493c2c66affSColin Finck if (!ret)
1494c2c66affSColin Finck {
14955bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED );
1496c2c66affSColin Finck *url = NULL;
1497c2c66affSColin Finck }
14985bd6580fSAmine Khaldi else SetLastError( ERROR_SUCCESS );
1499c2c66affSColin Finck return ret;
1500c2c66affSColin Finck }
1501c2c66affSColin Finck
1502c2c66affSColin Finck static const WCHAR Connections[] = {
1503c2c66affSColin Finck 'S','o','f','t','w','a','r','e','\\',
1504c2c66affSColin Finck 'M','i','c','r','o','s','o','f','t','\\',
1505c2c66affSColin Finck 'W','i','n','d','o','w','s','\\',
1506c2c66affSColin Finck 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1507c2c66affSColin Finck 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1508c2c66affSColin Finck 'C','o','n','n','e','c','t','i','o','n','s',0 };
1509c2c66affSColin Finck static const WCHAR WinHttpSettings[] = {
1510c2c66affSColin Finck 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1511c2c66affSColin Finck static const DWORD WINHTTP_SETTINGS_MAGIC = 0x18;
1512c2c66affSColin Finck static const DWORD WININET_SETTINGS_MAGIC = 0x46;
1513c2c66affSColin Finck static const DWORD PROXY_TYPE_DIRECT = 1;
1514c2c66affSColin Finck static const DWORD PROXY_TYPE_PROXY = 2;
1515c2c66affSColin Finck static const DWORD PROXY_USE_PAC_SCRIPT = 4;
1516c2c66affSColin Finck static const DWORD PROXY_AUTODETECT_SETTINGS = 8;
1517c2c66affSColin Finck
1518c2c66affSColin Finck struct connection_settings_header
1519c2c66affSColin Finck {
1520c2c66affSColin Finck DWORD magic;
1521c2c66affSColin Finck DWORD unknown; /* always zero? */
1522c2c66affSColin Finck DWORD flags; /* one or more of PROXY_* */
1523c2c66affSColin Finck };
1524c2c66affSColin Finck
copy_char_to_wchar_sz(const BYTE * src,DWORD len,WCHAR * dst)1525c2c66affSColin Finck static inline void copy_char_to_wchar_sz(const BYTE *src, DWORD len, WCHAR *dst)
1526c2c66affSColin Finck {
1527c2c66affSColin Finck const BYTE *begin;
1528c2c66affSColin Finck
1529c2c66affSColin Finck for (begin = src; src - begin < len; src++, dst++)
1530c2c66affSColin Finck *dst = *src;
1531c2c66affSColin Finck *dst = 0;
1532c2c66affSColin Finck }
1533c2c66affSColin Finck
1534c2c66affSColin Finck /***********************************************************************
1535c2c66affSColin Finck * WinHttpGetDefaultProxyConfiguration (winhttp.@)
1536c2c66affSColin Finck */
WinHttpGetDefaultProxyConfiguration(WINHTTP_PROXY_INFO * info)1537c2c66affSColin Finck BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
1538c2c66affSColin Finck {
1539c2c66affSColin Finck LONG l;
1540c2c66affSColin Finck HKEY key;
1541c2c66affSColin Finck BOOL got_from_reg = FALSE, direct = TRUE;
1542c2c66affSColin Finck char *envproxy;
1543c2c66affSColin Finck
1544c2c66affSColin Finck TRACE("%p\n", info);
1545c2c66affSColin Finck
1546c2c66affSColin Finck l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1547c2c66affSColin Finck if (!l)
1548c2c66affSColin Finck {
1549c2c66affSColin Finck DWORD type, size = 0;
1550c2c66affSColin Finck
1551c2c66affSColin Finck l = RegQueryValueExW( key, WinHttpSettings, NULL, &type, NULL, &size );
1552c2c66affSColin Finck if (!l && type == REG_BINARY &&
1553c2c66affSColin Finck size >= sizeof(struct connection_settings_header) + 2 * sizeof(DWORD))
1554c2c66affSColin Finck {
1555c2c66affSColin Finck BYTE *buf = heap_alloc( size );
1556c2c66affSColin Finck
1557c2c66affSColin Finck if (buf)
1558c2c66affSColin Finck {
1559c2c66affSColin Finck struct connection_settings_header *hdr =
1560c2c66affSColin Finck (struct connection_settings_header *)buf;
1561c2c66affSColin Finck DWORD *len = (DWORD *)(hdr + 1);
1562c2c66affSColin Finck
1563c2c66affSColin Finck l = RegQueryValueExW( key, WinHttpSettings, NULL, NULL, buf,
1564c2c66affSColin Finck &size );
1565c2c66affSColin Finck if (!l && hdr->magic == WINHTTP_SETTINGS_MAGIC &&
1566c2c66affSColin Finck hdr->unknown == 0)
1567c2c66affSColin Finck {
1568c2c66affSColin Finck if (hdr->flags & PROXY_TYPE_PROXY)
1569c2c66affSColin Finck {
1570c2c66affSColin Finck BOOL sane = FALSE;
1571c2c66affSColin Finck LPWSTR proxy = NULL;
1572c2c66affSColin Finck LPWSTR proxy_bypass = NULL;
1573c2c66affSColin Finck
1574c2c66affSColin Finck /* Sanity-check length of proxy string */
1575c2c66affSColin Finck if ((BYTE *)len - buf + *len <= size)
1576c2c66affSColin Finck {
1577c2c66affSColin Finck sane = TRUE;
1578c2c66affSColin Finck proxy = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
1579c2c66affSColin Finck if (proxy)
1580c2c66affSColin Finck copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy );
1581c2c66affSColin Finck len = (DWORD *)((BYTE *)(len + 1) + *len);
1582c2c66affSColin Finck }
1583c2c66affSColin Finck if (sane)
1584c2c66affSColin Finck {
1585c2c66affSColin Finck /* Sanity-check length of proxy bypass string */
1586c2c66affSColin Finck if ((BYTE *)len - buf + *len <= size)
1587c2c66affSColin Finck {
1588c2c66affSColin Finck proxy_bypass = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
1589c2c66affSColin Finck if (proxy_bypass)
1590c2c66affSColin Finck copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy_bypass );
1591c2c66affSColin Finck }
1592c2c66affSColin Finck else
1593c2c66affSColin Finck {
1594c2c66affSColin Finck sane = FALSE;
1595c2c66affSColin Finck GlobalFree( proxy );
1596c2c66affSColin Finck proxy = NULL;
1597c2c66affSColin Finck }
1598c2c66affSColin Finck }
1599c2c66affSColin Finck info->lpszProxy = proxy;
1600c2c66affSColin Finck info->lpszProxyBypass = proxy_bypass;
1601c2c66affSColin Finck if (sane)
1602c2c66affSColin Finck {
1603c2c66affSColin Finck got_from_reg = TRUE;
1604c2c66affSColin Finck direct = FALSE;
1605c2c66affSColin Finck info->dwAccessType =
1606c2c66affSColin Finck WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1607c2c66affSColin Finck TRACE("http proxy (from registry) = %s, bypass = %s\n",
1608c2c66affSColin Finck debugstr_w(info->lpszProxy),
1609c2c66affSColin Finck debugstr_w(info->lpszProxyBypass));
1610c2c66affSColin Finck }
1611c2c66affSColin Finck }
1612c2c66affSColin Finck }
1613c2c66affSColin Finck heap_free( buf );
1614c2c66affSColin Finck }
1615c2c66affSColin Finck }
1616c2c66affSColin Finck RegCloseKey( key );
1617c2c66affSColin Finck }
1618c2c66affSColin Finck if (!got_from_reg && (envproxy = getenv( "http_proxy" )))
1619c2c66affSColin Finck {
16208317165dSAmine Khaldi char *colon, *http_proxy = NULL;
1621c2c66affSColin Finck
16228317165dSAmine Khaldi if (!(colon = strchr( envproxy, ':' ))) http_proxy = envproxy;
16238317165dSAmine Khaldi else
1624c2c66affSColin Finck {
1625c2c66affSColin Finck if (*(colon + 1) == '/' && *(colon + 2) == '/')
1626c2c66affSColin Finck {
1627c2c66affSColin Finck /* It's a scheme, check that it's http */
16288317165dSAmine Khaldi if (!strncmp( envproxy, "http://", 7 )) http_proxy = envproxy + 7;
16298317165dSAmine Khaldi else WARN("unsupported scheme in $http_proxy: %s\n", envproxy);
1630c2c66affSColin Finck }
16318317165dSAmine Khaldi else http_proxy = envproxy;
1632c2c66affSColin Finck }
16338317165dSAmine Khaldi
16348317165dSAmine Khaldi if (http_proxy && http_proxy[0])
1635c2c66affSColin Finck {
1636c2c66affSColin Finck WCHAR *http_proxyW;
1637c2c66affSColin Finck int len;
1638c2c66affSColin Finck
1639c2c66affSColin Finck len = MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, NULL, 0 );
1640c2c66affSColin Finck if ((http_proxyW = GlobalAlloc( 0, len * sizeof(WCHAR))))
1641c2c66affSColin Finck {
1642c2c66affSColin Finck MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, http_proxyW, len );
1643c2c66affSColin Finck direct = FALSE;
1644c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1645c2c66affSColin Finck info->lpszProxy = http_proxyW;
1646c2c66affSColin Finck info->lpszProxyBypass = NULL;
16478317165dSAmine Khaldi TRACE("http proxy (from environment) = %s\n", debugstr_w(info->lpszProxy));
1648c2c66affSColin Finck }
1649c2c66affSColin Finck }
1650c2c66affSColin Finck }
1651c2c66affSColin Finck if (direct)
1652c2c66affSColin Finck {
1653c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
1654c2c66affSColin Finck info->lpszProxy = NULL;
1655c2c66affSColin Finck info->lpszProxyBypass = NULL;
1656c2c66affSColin Finck }
16575bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
1658c2c66affSColin Finck return TRUE;
1659c2c66affSColin Finck }
1660c2c66affSColin Finck
1661c2c66affSColin Finck /***********************************************************************
1662c2c66affSColin Finck * WinHttpGetIEProxyConfigForCurrentUser (winhttp.@)
1663c2c66affSColin Finck */
WinHttpGetIEProxyConfigForCurrentUser(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * config)1664c2c66affSColin Finck BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *config )
1665c2c66affSColin Finck {
1666c2c66affSColin Finck static const WCHAR settingsW[] =
1667c2c66affSColin 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};
1668c2c66affSColin Finck HKEY hkey = NULL;
1669c2c66affSColin Finck struct connection_settings_header *hdr = NULL;
1670c2c66affSColin Finck DWORD type, offset, len, size = 0;
1671c2c66affSColin Finck BOOL ret = FALSE;
1672c2c66affSColin Finck
1673c2c66affSColin Finck TRACE("%p\n", config);
1674c2c66affSColin Finck
1675c2c66affSColin Finck if (!config)
1676c2c66affSColin Finck {
16775bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1678c2c66affSColin Finck return FALSE;
1679c2c66affSColin Finck }
1680c2c66affSColin Finck memset( config, 0, sizeof(*config) );
1681c2c66affSColin Finck config->fAutoDetect = TRUE;
1682c2c66affSColin Finck
1683c2c66affSColin Finck if (RegOpenKeyExW( HKEY_CURRENT_USER, Connections, 0, KEY_READ, &hkey ) ||
1684c2c66affSColin Finck RegQueryValueExW( hkey, settingsW, NULL, &type, NULL, &size ) ||
1685c2c66affSColin Finck type != REG_BINARY || size < sizeof(struct connection_settings_header))
1686c2c66affSColin Finck {
1687c2c66affSColin Finck ret = TRUE;
1688c2c66affSColin Finck goto done;
1689c2c66affSColin Finck }
1690c2c66affSColin Finck if (!(hdr = heap_alloc( size ))) goto done;
1691c2c66affSColin Finck if (RegQueryValueExW( hkey, settingsW, NULL, &type, (BYTE *)hdr, &size ) ||
1692c2c66affSColin Finck hdr->magic != WININET_SETTINGS_MAGIC)
1693c2c66affSColin Finck {
1694c2c66affSColin Finck ret = TRUE;
1695c2c66affSColin Finck goto done;
1696c2c66affSColin Finck }
1697c2c66affSColin Finck
1698c2c66affSColin Finck config->fAutoDetect = (hdr->flags & PROXY_AUTODETECT_SETTINGS) != 0;
1699c2c66affSColin Finck offset = sizeof(*hdr);
1700c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done;
1701c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset);
1702c2c66affSColin Finck offset += sizeof(DWORD);
1703c2c66affSColin Finck if (len && hdr->flags & PROXY_TYPE_PROXY)
1704c2c66affSColin Finck {
1705c2c66affSColin Finck if (!(config->lpszProxy = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1706c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxy );
1707c2c66affSColin Finck }
1708c2c66affSColin Finck offset += len;
1709c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done;
1710c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset);
1711c2c66affSColin Finck offset += sizeof(DWORD);
1712c2c66affSColin Finck if (len && (hdr->flags & PROXY_TYPE_PROXY))
1713c2c66affSColin Finck {
1714c2c66affSColin Finck if (!(config->lpszProxyBypass = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1715c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszProxyBypass );
1716c2c66affSColin Finck }
1717c2c66affSColin Finck offset += len;
1718c2c66affSColin Finck if (offset + sizeof(DWORD) > size) goto done;
1719c2c66affSColin Finck len = *(DWORD *)((char *)hdr + offset);
1720c2c66affSColin Finck offset += sizeof(DWORD);
1721c2c66affSColin Finck if (len && (hdr->flags & PROXY_USE_PAC_SCRIPT))
1722c2c66affSColin Finck {
1723c2c66affSColin Finck if (!(config->lpszAutoConfigUrl = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) goto done;
1724c2c66affSColin Finck copy_char_to_wchar_sz( (const BYTE *)hdr + offset , len, config->lpszAutoConfigUrl );
1725c2c66affSColin Finck }
1726c2c66affSColin Finck ret = TRUE;
1727c2c66affSColin Finck
1728c2c66affSColin Finck done:
1729c2c66affSColin Finck RegCloseKey( hkey );
1730c2c66affSColin Finck heap_free( hdr );
1731c2c66affSColin Finck if (!ret)
1732c2c66affSColin Finck {
1733c2c66affSColin Finck GlobalFree( config->lpszAutoConfigUrl );
1734c2c66affSColin Finck config->lpszAutoConfigUrl = NULL;
1735c2c66affSColin Finck GlobalFree( config->lpszProxy );
1736c2c66affSColin Finck config->lpszProxy = NULL;
1737c2c66affSColin Finck GlobalFree( config->lpszProxyBypass );
1738c2c66affSColin Finck config->lpszProxyBypass = NULL;
1739c2c66affSColin Finck }
17405bd6580fSAmine Khaldi else SetLastError( ERROR_SUCCESS );
1741c2c66affSColin Finck return ret;
1742c2c66affSColin Finck }
1743c2c66affSColin Finck
parse_script_result(const char * result,WINHTTP_PROXY_INFO * info)1744c2c66affSColin Finck static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info )
1745c2c66affSColin Finck {
1746c2c66affSColin Finck const char *p;
1747c2c66affSColin Finck WCHAR *q;
1748c2c66affSColin Finck int len;
1749c2c66affSColin Finck
1750c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
1751c2c66affSColin Finck info->lpszProxy = NULL;
1752c2c66affSColin Finck info->lpszProxyBypass = NULL;
1753c2c66affSColin Finck
1754c2c66affSColin Finck TRACE("%s\n", debugstr_a( result ));
1755c2c66affSColin Finck
1756c2c66affSColin Finck p = result;
1757c2c66affSColin Finck while (*p == ' ') p++;
1758c2c66affSColin Finck len = strlen( p );
17595bd6580fSAmine Khaldi if (len >= 5 && !_strnicmp( p, "PROXY", sizeof("PROXY") - 1 ))
1760c2c66affSColin Finck {
1761c2c66affSColin Finck p += 5;
1762c2c66affSColin Finck while (*p == ' ') p++;
1763c2c66affSColin Finck if (!*p || *p == ';') return TRUE;
1764c2c66affSColin Finck if (!(info->lpszProxy = q = strdupAW( p ))) return FALSE;
1765c2c66affSColin Finck info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1766c2c66affSColin Finck for (; *q; q++)
1767c2c66affSColin Finck {
1768c2c66affSColin Finck if (*q == ' ' || *q == ';')
1769c2c66affSColin Finck {
1770c2c66affSColin Finck *q = 0;
1771c2c66affSColin Finck break;
1772c2c66affSColin Finck }
1773c2c66affSColin Finck }
1774c2c66affSColin Finck }
1775c2c66affSColin Finck return TRUE;
1776c2c66affSColin Finck }
1777c2c66affSColin Finck
download_script(const WCHAR * url,DWORD * out_size)1778c2c66affSColin Finck static char *download_script( const WCHAR *url, DWORD *out_size )
1779c2c66affSColin Finck {
1780c2c66affSColin Finck static const WCHAR typeW[] = {'*','/','*',0};
1781c2c66affSColin Finck static const WCHAR *acceptW[] = {typeW, NULL};
1782c2c66affSColin Finck HINTERNET ses, con = NULL, req = NULL;
1783c2c66affSColin Finck WCHAR *hostname;
1784c2c66affSColin Finck URL_COMPONENTSW uc;
1785c2c66affSColin Finck DWORD status, size = sizeof(status), offset, to_read, bytes_read, flags = 0;
1786c2c66affSColin Finck char *tmp, *buffer = NULL;
1787c2c66affSColin Finck
1788c2c66affSColin Finck *out_size = 0;
1789c2c66affSColin Finck
1790c2c66affSColin Finck memset( &uc, 0, sizeof(uc) );
1791c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
1792c2c66affSColin Finck uc.dwHostNameLength = -1;
1793c2c66affSColin Finck uc.dwUrlPathLength = -1;
1794c2c66affSColin Finck if (!WinHttpCrackUrl( url, 0, 0, &uc )) return NULL;
1795c2c66affSColin Finck if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) return NULL;
1796c2c66affSColin Finck memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) );
1797c2c66affSColin Finck hostname[uc.dwHostNameLength] = 0;
1798c2c66affSColin Finck
1799c2c66affSColin Finck if (!(ses = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ))) goto done;
1800c2c66affSColin Finck if (!(con = WinHttpConnect( ses, hostname, uc.nPort, 0 ))) goto done;
1801c2c66affSColin Finck if (uc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE;
1802c2c66affSColin Finck if (!(req = WinHttpOpenRequest( con, NULL, uc.lpszUrlPath, NULL, NULL, acceptW, flags ))) goto done;
1803c2c66affSColin Finck if (!WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 )) goto done;
1804c2c66affSColin Finck
1805c2c66affSColin Finck if (!(WinHttpReceiveResponse( req, 0 ))) goto done;
1806c2c66affSColin Finck if (!WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status,
1807c2c66affSColin Finck &size, NULL ) || status != HTTP_STATUS_OK) goto done;
1808c2c66affSColin Finck
1809c2c66affSColin Finck size = 4096;
1810c2c66affSColin Finck if (!(buffer = heap_alloc( size ))) goto done;
1811c2c66affSColin Finck to_read = size;
1812c2c66affSColin Finck offset = 0;
1813c2c66affSColin Finck for (;;)
1814c2c66affSColin Finck {
1815c2c66affSColin Finck if (!WinHttpReadData( req, buffer + offset, to_read, &bytes_read )) goto done;
1816c2c66affSColin Finck if (!bytes_read) break;
1817c2c66affSColin Finck to_read -= bytes_read;
1818c2c66affSColin Finck offset += bytes_read;
1819c2c66affSColin Finck *out_size += bytes_read;
1820c2c66affSColin Finck if (!to_read)
1821c2c66affSColin Finck {
1822c2c66affSColin Finck to_read = size;
1823c2c66affSColin Finck size *= 2;
1824c2c66affSColin Finck if (!(tmp = heap_realloc( buffer, size ))) goto done;
1825c2c66affSColin Finck buffer = tmp;
1826c2c66affSColin Finck }
1827c2c66affSColin Finck }
1828c2c66affSColin Finck
1829c2c66affSColin Finck done:
1830c2c66affSColin Finck WinHttpCloseHandle( req );
1831c2c66affSColin Finck WinHttpCloseHandle( con );
1832c2c66affSColin Finck WinHttpCloseHandle( ses );
1833c2c66affSColin Finck heap_free( hostname );
18345bd6580fSAmine Khaldi if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT );
1835c2c66affSColin Finck return buffer;
1836c2c66affSColin Finck }
1837c2c66affSColin Finck
1838c2c66affSColin Finck struct AUTO_PROXY_SCRIPT_BUFFER
1839c2c66affSColin Finck {
1840c2c66affSColin Finck DWORD dwStructSize;
1841c2c66affSColin Finck LPSTR lpszScriptBuffer;
1842c2c66affSColin Finck DWORD dwScriptBufferSize;
1843c2c66affSColin Finck };
1844c2c66affSColin Finck
1845c2c66affSColin Finck BOOL WINAPI InternetDeInitializeAutoProxyDll(LPSTR, DWORD);
1846c2c66affSColin Finck BOOL WINAPI InternetGetProxyInfo(LPCSTR, DWORD, LPSTR, DWORD, LPSTR *, LPDWORD);
1847c2c66affSColin Finck BOOL WINAPI InternetInitializeAutoProxyDll(DWORD, LPSTR, LPSTR, void *, struct AUTO_PROXY_SCRIPT_BUFFER *);
1848c2c66affSColin Finck
run_script(char * script,DWORD size,const WCHAR * url,WINHTTP_PROXY_INFO * info)1849c2c66affSColin Finck static BOOL run_script( char *script, DWORD size, const WCHAR *url, WINHTTP_PROXY_INFO *info )
1850c2c66affSColin Finck {
1851c2c66affSColin Finck BOOL ret;
1852c2c66affSColin Finck char *result, *urlA;
1853c2c66affSColin Finck DWORD len_result;
1854c2c66affSColin Finck struct AUTO_PROXY_SCRIPT_BUFFER buffer;
1855c2c66affSColin Finck URL_COMPONENTSW uc;
1856c2c66affSColin Finck
1857c2c66affSColin Finck buffer.dwStructSize = sizeof(buffer);
1858c2c66affSColin Finck buffer.lpszScriptBuffer = script;
1859c2c66affSColin Finck buffer.dwScriptBufferSize = size;
1860c2c66affSColin Finck
1861c2c66affSColin Finck if (!(urlA = strdupWA( url ))) return FALSE;
1862c2c66affSColin Finck if (!(ret = InternetInitializeAutoProxyDll( 0, NULL, NULL, NULL, &buffer )))
1863c2c66affSColin Finck {
1864c2c66affSColin Finck heap_free( urlA );
1865c2c66affSColin Finck return FALSE;
1866c2c66affSColin Finck }
1867c2c66affSColin Finck
1868c2c66affSColin Finck memset( &uc, 0, sizeof(uc) );
1869c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
1870c2c66affSColin Finck uc.dwHostNameLength = -1;
1871c2c66affSColin Finck
1872c2c66affSColin Finck if (WinHttpCrackUrl( url, 0, 0, &uc ))
1873c2c66affSColin Finck {
1874c2c66affSColin Finck char *hostnameA = strdupWA_sized( uc.lpszHostName, uc.dwHostNameLength );
1875c2c66affSColin Finck
1876c2c66affSColin Finck if ((ret = InternetGetProxyInfo( urlA, strlen(urlA),
1877c2c66affSColin Finck hostnameA, strlen(hostnameA), &result, &len_result )))
1878c2c66affSColin Finck {
1879c2c66affSColin Finck ret = parse_script_result( result, info );
1880c2c66affSColin Finck heap_free( result );
1881c2c66affSColin Finck }
1882c2c66affSColin Finck
1883c2c66affSColin Finck heap_free( hostnameA );
1884c2c66affSColin Finck }
1885c2c66affSColin Finck heap_free( urlA );
1886c2c66affSColin Finck return InternetDeInitializeAutoProxyDll( NULL, 0 );
1887c2c66affSColin Finck }
1888c2c66affSColin Finck
1889c2c66affSColin Finck /***********************************************************************
1890c2c66affSColin Finck * WinHttpGetProxyForUrl (winhttp.@)
1891c2c66affSColin Finck */
WinHttpGetProxyForUrl(HINTERNET hsession,LPCWSTR url,WINHTTP_AUTOPROXY_OPTIONS * options,WINHTTP_PROXY_INFO * info)1892c2c66affSColin Finck BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTOPROXY_OPTIONS *options,
1893c2c66affSColin Finck WINHTTP_PROXY_INFO *info )
1894c2c66affSColin Finck {
1895c2c66affSColin Finck WCHAR *detected_pac_url = NULL;
1896c2c66affSColin Finck const WCHAR *pac_url;
18975bd6580fSAmine Khaldi struct session *session;
1898c2c66affSColin Finck char *script;
1899c2c66affSColin Finck DWORD size;
1900c2c66affSColin Finck BOOL ret = FALSE;
1901c2c66affSColin Finck
1902c2c66affSColin Finck TRACE("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info);
1903c2c66affSColin Finck
19045bd6580fSAmine Khaldi if (!(session = (struct session *)grab_object( hsession )))
1905c2c66affSColin Finck {
19065bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
1907c2c66affSColin Finck return FALSE;
1908c2c66affSColin Finck }
1909c2c66affSColin Finck if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
1910c2c66affSColin Finck {
1911c2c66affSColin Finck release_object( &session->hdr );
19125bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
1913c2c66affSColin Finck return FALSE;
1914c2c66affSColin Finck }
1915c2c66affSColin Finck if (!url || !options || !info ||
1916c2c66affSColin Finck !(options->dwFlags & (WINHTTP_AUTOPROXY_AUTO_DETECT|WINHTTP_AUTOPROXY_CONFIG_URL)) ||
1917c2c66affSColin Finck ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) && !options->dwAutoDetectFlags) ||
1918c2c66affSColin Finck ((options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) &&
1919c2c66affSColin Finck (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL)))
1920c2c66affSColin Finck {
1921c2c66affSColin Finck release_object( &session->hdr );
19225bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1923c2c66affSColin Finck return FALSE;
1924c2c66affSColin Finck }
1925c2c66affSColin Finck if (options->dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT &&
1926c2c66affSColin Finck !WinHttpDetectAutoProxyConfigUrl( options->dwAutoDetectFlags, &detected_pac_url ))
1927c2c66affSColin Finck goto done;
1928c2c66affSColin Finck
1929c2c66affSColin Finck if (options->dwFlags & WINHTTP_AUTOPROXY_CONFIG_URL) pac_url = options->lpszAutoConfigUrl;
1930c2c66affSColin Finck else pac_url = detected_pac_url;
1931c2c66affSColin Finck
1932c2c66affSColin Finck if ((script = download_script( pac_url, &size )))
1933c2c66affSColin Finck {
1934c2c66affSColin Finck ret = run_script( script, size, url, info );
1935c2c66affSColin Finck heap_free( script );
1936c2c66affSColin Finck }
1937c2c66affSColin Finck
1938c2c66affSColin Finck done:
1939c2c66affSColin Finck GlobalFree( detected_pac_url );
1940c2c66affSColin Finck release_object( &session->hdr );
19415bd6580fSAmine Khaldi if (ret) SetLastError( ERROR_SUCCESS );
1942c2c66affSColin Finck return ret;
1943c2c66affSColin Finck }
1944c2c66affSColin Finck
1945c2c66affSColin Finck /***********************************************************************
1946c2c66affSColin Finck * WinHttpSetDefaultProxyConfiguration (winhttp.@)
1947c2c66affSColin Finck */
WinHttpSetDefaultProxyConfiguration(WINHTTP_PROXY_INFO * info)1948c2c66affSColin Finck BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
1949c2c66affSColin Finck {
1950c2c66affSColin Finck LONG l;
1951c2c66affSColin Finck HKEY key;
1952c2c66affSColin Finck BOOL ret = FALSE;
1953c2c66affSColin Finck const WCHAR *src;
1954c2c66affSColin Finck
1955c2c66affSColin Finck TRACE("%p\n", info);
1956c2c66affSColin Finck
1957c2c66affSColin Finck if (!info)
1958c2c66affSColin Finck {
19595bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1960c2c66affSColin Finck return FALSE;
1961c2c66affSColin Finck }
1962c2c66affSColin Finck switch (info->dwAccessType)
1963c2c66affSColin Finck {
1964c2c66affSColin Finck case WINHTTP_ACCESS_TYPE_NO_PROXY:
1965c2c66affSColin Finck break;
1966c2c66affSColin Finck case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
1967c2c66affSColin Finck if (!info->lpszProxy)
1968c2c66affSColin Finck {
19695bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1970c2c66affSColin Finck return FALSE;
1971c2c66affSColin Finck }
1972c2c66affSColin Finck /* Only ASCII characters are allowed */
1973c2c66affSColin Finck for (src = info->lpszProxy; *src; src++)
1974c2c66affSColin Finck if (*src > 0x7f)
1975c2c66affSColin Finck {
19765bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1977c2c66affSColin Finck return FALSE;
1978c2c66affSColin Finck }
1979c2c66affSColin Finck if (info->lpszProxyBypass)
1980c2c66affSColin Finck {
1981c2c66affSColin Finck for (src = info->lpszProxyBypass; *src; src++)
1982c2c66affSColin Finck if (*src > 0x7f)
1983c2c66affSColin Finck {
19845bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1985c2c66affSColin Finck return FALSE;
1986c2c66affSColin Finck }
1987c2c66affSColin Finck }
1988c2c66affSColin Finck break;
1989c2c66affSColin Finck default:
19905bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
1991c2c66affSColin Finck return FALSE;
1992c2c66affSColin Finck }
1993c2c66affSColin Finck
1994c2c66affSColin Finck l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1995c2c66affSColin Finck KEY_WRITE, NULL, &key, NULL );
1996c2c66affSColin Finck if (!l)
1997c2c66affSColin Finck {
1998c2c66affSColin Finck DWORD size = sizeof(struct connection_settings_header) + 2 * sizeof(DWORD);
1999c2c66affSColin Finck BYTE *buf;
2000c2c66affSColin Finck
2001c2c66affSColin Finck if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
2002c2c66affSColin Finck {
2003c2c66affSColin Finck size += strlenW( info->lpszProxy );
2004c2c66affSColin Finck if (info->lpszProxyBypass)
2005c2c66affSColin Finck size += strlenW( info->lpszProxyBypass );
2006c2c66affSColin Finck }
2007c2c66affSColin Finck buf = heap_alloc( size );
2008c2c66affSColin Finck if (buf)
2009c2c66affSColin Finck {
2010c2c66affSColin Finck struct connection_settings_header *hdr =
2011c2c66affSColin Finck (struct connection_settings_header *)buf;
2012c2c66affSColin Finck DWORD *len = (DWORD *)(hdr + 1);
2013c2c66affSColin Finck
2014c2c66affSColin Finck hdr->magic = WINHTTP_SETTINGS_MAGIC;
2015c2c66affSColin Finck hdr->unknown = 0;
2016c2c66affSColin Finck if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
2017c2c66affSColin Finck {
2018c2c66affSColin Finck BYTE *dst;
2019c2c66affSColin Finck
2020c2c66affSColin Finck hdr->flags = PROXY_TYPE_PROXY;
2021c2c66affSColin Finck *len++ = strlenW( info->lpszProxy );
2022c2c66affSColin Finck for (dst = (BYTE *)len, src = info->lpszProxy; *src;
2023c2c66affSColin Finck src++, dst++)
2024c2c66affSColin Finck *dst = *src;
2025c2c66affSColin Finck len = (DWORD *)dst;
2026c2c66affSColin Finck if (info->lpszProxyBypass)
2027c2c66affSColin Finck {
2028c2c66affSColin Finck *len++ = strlenW( info->lpszProxyBypass );
2029c2c66affSColin Finck for (dst = (BYTE *)len, src = info->lpszProxyBypass; *src;
2030c2c66affSColin Finck src++, dst++)
2031c2c66affSColin Finck *dst = *src;
2032c2c66affSColin Finck }
2033c2c66affSColin Finck else
2034c2c66affSColin Finck *len++ = 0;
2035c2c66affSColin Finck }
2036c2c66affSColin Finck else
2037c2c66affSColin Finck {
2038c2c66affSColin Finck hdr->flags = PROXY_TYPE_DIRECT;
2039c2c66affSColin Finck *len++ = 0;
2040c2c66affSColin Finck *len++ = 0;
2041c2c66affSColin Finck }
2042c2c66affSColin Finck l = RegSetValueExW( key, WinHttpSettings, 0, REG_BINARY, buf, size );
2043c2c66affSColin Finck if (!l)
2044c2c66affSColin Finck ret = TRUE;
2045c2c66affSColin Finck heap_free( buf );
2046c2c66affSColin Finck }
2047c2c66affSColin Finck RegCloseKey( key );
2048c2c66affSColin Finck }
20495bd6580fSAmine Khaldi if (ret) SetLastError( ERROR_SUCCESS );
2050c2c66affSColin Finck return ret;
2051c2c66affSColin Finck }
2052c2c66affSColin Finck
2053c2c66affSColin Finck /***********************************************************************
2054c2c66affSColin Finck * WinHttpSetStatusCallback (winhttp.@)
2055c2c66affSColin Finck */
WinHttpSetStatusCallback(HINTERNET handle,WINHTTP_STATUS_CALLBACK callback,DWORD flags,DWORD_PTR reserved)2056c2c66affSColin Finck WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback,
2057c2c66affSColin Finck DWORD flags, DWORD_PTR reserved )
2058c2c66affSColin Finck {
20595bd6580fSAmine Khaldi struct object_header *hdr;
2060c2c66affSColin Finck WINHTTP_STATUS_CALLBACK ret;
2061c2c66affSColin Finck
2062c2c66affSColin Finck TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved);
2063c2c66affSColin Finck
2064c2c66affSColin Finck if (!(hdr = grab_object( handle )))
2065c2c66affSColin Finck {
20665bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
2067c2c66affSColin Finck return WINHTTP_INVALID_STATUS_CALLBACK;
2068c2c66affSColin Finck }
2069c2c66affSColin Finck ret = hdr->callback;
2070c2c66affSColin Finck hdr->callback = callback;
2071c2c66affSColin Finck hdr->notify_mask = flags;
2072c2c66affSColin Finck
2073c2c66affSColin Finck release_object( hdr );
20745bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
2075c2c66affSColin Finck return ret;
2076c2c66affSColin Finck }
2077c2c66affSColin Finck
2078c2c66affSColin Finck /***********************************************************************
2079c2c66affSColin Finck * WinHttpSetTimeouts (winhttp.@)
2080c2c66affSColin Finck */
WinHttpSetTimeouts(HINTERNET handle,int resolve,int connect,int send,int receive)2081c2c66affSColin Finck BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive )
2082c2c66affSColin Finck {
2083c2c66affSColin Finck BOOL ret = TRUE;
20845bd6580fSAmine Khaldi struct object_header *hdr;
2085c2c66affSColin Finck
2086c2c66affSColin Finck TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
2087c2c66affSColin Finck
2088c2c66affSColin Finck if (resolve < -1 || connect < -1 || send < -1 || receive < -1)
2089c2c66affSColin Finck {
20905bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
2091c2c66affSColin Finck return FALSE;
2092c2c66affSColin Finck }
2093c2c66affSColin Finck
2094c2c66affSColin Finck if (!(hdr = grab_object( handle )))
2095c2c66affSColin Finck {
20965bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_HANDLE );
2097c2c66affSColin Finck return FALSE;
2098c2c66affSColin Finck }
2099c2c66affSColin Finck
2100c2c66affSColin Finck switch(hdr->type)
2101c2c66affSColin Finck {
2102c2c66affSColin Finck case WINHTTP_HANDLE_TYPE_REQUEST:
21035bd6580fSAmine Khaldi {
21045bd6580fSAmine Khaldi struct request *request = (struct request *)hdr;
2105c2c66affSColin Finck request->connect_timeout = connect;
2106c2c66affSColin Finck
2107c2c66affSColin Finck if (resolve < 0) resolve = 0;
2108c2c66affSColin Finck request->resolve_timeout = resolve;
2109c2c66affSColin Finck
2110c2c66affSColin Finck if (send < 0) send = 0;
2111c2c66affSColin Finck request->send_timeout = send;
2112c2c66affSColin Finck
2113c2c66affSColin Finck if (receive < 0) receive = 0;
21145bd6580fSAmine Khaldi request->receive_timeout = receive;
2115c2c66affSColin Finck
2116c2c66affSColin Finck if (request->netconn)
2117c2c66affSColin Finck {
2118c2c66affSColin Finck if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
2119c2c66affSColin Finck if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
2120c2c66affSColin Finck }
2121c2c66affSColin Finck break;
21225bd6580fSAmine Khaldi }
2123c2c66affSColin Finck case WINHTTP_HANDLE_TYPE_SESSION:
21245bd6580fSAmine Khaldi {
21255bd6580fSAmine Khaldi struct session *session = (struct session *)hdr;
2126c2c66affSColin Finck session->connect_timeout = connect;
2127c2c66affSColin Finck
2128c2c66affSColin Finck if (resolve < 0) resolve = 0;
2129c2c66affSColin Finck session->resolve_timeout = resolve;
2130c2c66affSColin Finck
2131c2c66affSColin Finck if (send < 0) send = 0;
2132c2c66affSColin Finck session->send_timeout = send;
2133c2c66affSColin Finck
2134c2c66affSColin Finck if (receive < 0) receive = 0;
21355bd6580fSAmine Khaldi session->receive_timeout = receive;
2136c2c66affSColin Finck break;
21375bd6580fSAmine Khaldi }
2138c2c66affSColin Finck default:
21395bd6580fSAmine Khaldi SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
2140c2c66affSColin Finck ret = FALSE;
2141c2c66affSColin Finck }
2142c2c66affSColin Finck release_object( hdr );
21435bd6580fSAmine Khaldi if (ret) SetLastError( ERROR_SUCCESS );
2144c2c66affSColin Finck return ret;
2145c2c66affSColin Finck }
2146c2c66affSColin Finck
2147c2c66affSColin Finck static const WCHAR wkday[7][4] =
2148c2c66affSColin Finck {{'S','u','n', 0}, {'M','o','n', 0}, {'T','u','e', 0}, {'W','e','d', 0},
2149c2c66affSColin Finck {'T','h','u', 0}, {'F','r','i', 0}, {'S','a','t', 0}};
2150c2c66affSColin Finck static const WCHAR month[12][4] =
2151c2c66affSColin Finck {{'J','a','n', 0}, {'F','e','b', 0}, {'M','a','r', 0}, {'A','p','r', 0},
2152c2c66affSColin Finck {'M','a','y', 0}, {'J','u','n', 0}, {'J','u','l', 0}, {'A','u','g', 0},
2153c2c66affSColin Finck {'S','e','p', 0}, {'O','c','t', 0}, {'N','o','v', 0}, {'D','e','c', 0}};
2154c2c66affSColin Finck
2155c2c66affSColin Finck /***********************************************************************
2156c2c66affSColin Finck * WinHttpTimeFromSystemTime (WININET.@)
2157c2c66affSColin Finck */
WinHttpTimeFromSystemTime(const SYSTEMTIME * time,LPWSTR string)2158c2c66affSColin Finck BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string )
2159c2c66affSColin Finck {
2160c2c66affSColin Finck static const WCHAR format[] =
2161c2c66affSColin Finck {'%','s',',',' ','%','0','2','d',' ','%','s',' ','%','4','d',' ','%','0',
2162c2c66affSColin Finck '2','d',':','%','0','2','d',':','%','0','2','d',' ','G','M','T', 0};
2163c2c66affSColin Finck
2164c2c66affSColin Finck TRACE("%p, %p\n", time, string);
2165c2c66affSColin Finck
2166c2c66affSColin Finck if (!time || !string)
2167c2c66affSColin Finck {
21685bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
2169c2c66affSColin Finck return FALSE;
2170c2c66affSColin Finck }
2171c2c66affSColin Finck
2172c2c66affSColin Finck sprintfW( string, format,
2173c2c66affSColin Finck wkday[time->wDayOfWeek],
2174c2c66affSColin Finck time->wDay,
2175c2c66affSColin Finck month[time->wMonth - 1],
2176c2c66affSColin Finck time->wYear,
2177c2c66affSColin Finck time->wHour,
2178c2c66affSColin Finck time->wMinute,
2179c2c66affSColin Finck time->wSecond );
2180c2c66affSColin Finck
21815bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
2182c2c66affSColin Finck return TRUE;
2183c2c66affSColin Finck }
2184c2c66affSColin Finck
2185c2c66affSColin Finck /***********************************************************************
2186c2c66affSColin Finck * WinHttpTimeToSystemTime (WININET.@)
2187c2c66affSColin Finck */
WinHttpTimeToSystemTime(LPCWSTR string,SYSTEMTIME * time)2188c2c66affSColin Finck BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time )
2189c2c66affSColin Finck {
2190c2c66affSColin Finck unsigned int i;
2191c2c66affSColin Finck const WCHAR *s = string;
2192c2c66affSColin Finck WCHAR *end;
2193c2c66affSColin Finck
2194c2c66affSColin Finck TRACE("%s, %p\n", debugstr_w(string), time);
2195c2c66affSColin Finck
2196c2c66affSColin Finck if (!string || !time)
2197c2c66affSColin Finck {
21985bd6580fSAmine Khaldi SetLastError( ERROR_INVALID_PARAMETER );
2199c2c66affSColin Finck return FALSE;
2200c2c66affSColin Finck }
2201c2c66affSColin Finck
2202c2c66affSColin Finck /* Windows does this too */
2203c2c66affSColin Finck GetSystemTime( time );
2204c2c66affSColin Finck
2205c2c66affSColin Finck /* Convert an RFC1123 time such as 'Fri, 07 Jan 2005 12:06:35 GMT' into
2206c2c66affSColin Finck * a SYSTEMTIME structure.
2207c2c66affSColin Finck */
2208c2c66affSColin Finck
22095bd6580fSAmine Khaldi SetLastError( ERROR_SUCCESS );
2210c2c66affSColin Finck
2211c2c66affSColin Finck while (*s && !isalphaW( *s )) s++;
2212c2c66affSColin Finck if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
2213c2c66affSColin Finck time->wDayOfWeek = 7;
2214c2c66affSColin Finck
2215c2c66affSColin Finck for (i = 0; i < 7; i++)
2216c2c66affSColin Finck {
2217c2c66affSColin Finck if (toupperW( wkday[i][0] ) == toupperW( s[0] ) &&
2218c2c66affSColin Finck toupperW( wkday[i][1] ) == toupperW( s[1] ) &&
2219c2c66affSColin Finck toupperW( wkday[i][2] ) == toupperW( s[2] ) )
2220c2c66affSColin Finck {
2221c2c66affSColin Finck time->wDayOfWeek = i;
2222c2c66affSColin Finck break;
2223c2c66affSColin Finck }
2224c2c66affSColin Finck }
2225c2c66affSColin Finck
2226c2c66affSColin Finck if (time->wDayOfWeek > 6) return TRUE;
2227c2c66affSColin Finck while (*s && !isdigitW( *s )) s++;
2228c2c66affSColin Finck time->wDay = strtolW( s, &end, 10 );
2229c2c66affSColin Finck s = end;
2230c2c66affSColin Finck
2231c2c66affSColin Finck while (*s && !isalphaW( *s )) s++;
2232c2c66affSColin Finck if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
2233c2c66affSColin Finck time->wMonth = 0;
2234c2c66affSColin Finck
2235c2c66affSColin Finck for (i = 0; i < 12; i++)
2236c2c66affSColin Finck {
2237c2c66affSColin Finck if (toupperW( month[i][0]) == toupperW( s[0] ) &&
2238c2c66affSColin Finck toupperW( month[i][1]) == toupperW( s[1] ) &&
2239c2c66affSColin Finck toupperW( month[i][2]) == toupperW( s[2] ) )
2240c2c66affSColin Finck {
2241c2c66affSColin Finck time->wMonth = i + 1;
2242c2c66affSColin Finck break;
2243c2c66affSColin Finck }
2244c2c66affSColin Finck }
2245c2c66affSColin Finck if (time->wMonth == 0) return TRUE;
2246c2c66affSColin Finck
2247c2c66affSColin Finck while (*s && !isdigitW( *s )) s++;
2248c2c66affSColin Finck if (*s == '\0') return TRUE;
2249c2c66affSColin Finck time->wYear = strtolW( s, &end, 10 );
2250c2c66affSColin Finck s = end;
2251c2c66affSColin Finck
2252c2c66affSColin Finck while (*s && !isdigitW( *s )) s++;
2253c2c66affSColin Finck if (*s == '\0') return TRUE;
2254c2c66affSColin Finck time->wHour = strtolW( s, &end, 10 );
2255c2c66affSColin Finck s = end;
2256c2c66affSColin Finck
2257c2c66affSColin Finck while (*s && !isdigitW( *s )) s++;
2258c2c66affSColin Finck if (*s == '\0') return TRUE;
2259c2c66affSColin Finck time->wMinute = strtolW( s, &end, 10 );
2260c2c66affSColin Finck s = end;
2261c2c66affSColin Finck
2262c2c66affSColin Finck while (*s && !isdigitW( *s )) s++;
2263c2c66affSColin Finck if (*s == '\0') return TRUE;
2264c2c66affSColin Finck time->wSecond = strtolW( s, &end, 10 );
2265c2c66affSColin Finck
2266c2c66affSColin Finck time->wMilliseconds = 0;
2267c2c66affSColin Finck return TRUE;
2268c2c66affSColin Finck }
2269