2 * Copyright 2008 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
21 #include "wine/debug.h"
30 #include "winhttp_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
34 void set_last_error( DWORD error )
37 SetLastError( error );
40 DWORD get_last_error( void )
43 return GetLastError();
46 void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen )
48 TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen);
50 if (hdr->notify_mask & status) hdr->callback( hdr->handle, hdr->context, status, info, buflen );
53 /***********************************************************************
54 * WinHttpCheckPlatform (winhttp.@)
56 BOOL WINAPI WinHttpCheckPlatform( void )
62 /***********************************************************************
63 * session_destroy (internal)
65 static void session_destroy( object_header_t *hdr )
67 session_t *session = (session_t *)hdr;
69 TRACE("%p\n", session);
71 heap_free( session->agent );
72 heap_free( session->proxy_server );
73 heap_free( session->proxy_bypass );
74 heap_free( session->proxy_username );
75 heap_free( session->proxy_password );
79 static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
83 case WINHTTP_OPTION_PROXY:
85 WINHTTP_PROXY_INFO *pi = buffer;
87 FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
90 case WINHTTP_OPTION_REDIRECT_POLICY:
92 DWORD policy = *(DWORD *)buffer;
94 TRACE("0x%x\n", policy);
95 hdr->redirect_policy = policy;
99 FIXME("unimplemented option %u\n", option);
104 static const object_vtbl_t session_vtbl =
111 /***********************************************************************
112 * WinHttpOpen (winhttp.@)
114 HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags )
117 HINTERNET handle = NULL;
119 TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags);
121 if (!(session = heap_alloc_zero( sizeof(session_t) ))) return NULL;
123 session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION;
124 session->hdr.vtbl = &session_vtbl;
125 session->hdr.flags = flags;
126 session->hdr.refs = 1;
127 session->access = access;
129 if (agent && !(session->agent = strdupW( agent ))) goto end;
130 if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
131 if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
133 if (!(handle = alloc_handle( &session->hdr ))) goto end;
134 session->hdr.handle = handle;
137 release_object( &session->hdr );
138 TRACE("returning %p\n", handle);
142 /***********************************************************************
143 * connect_destroy (internal)
145 static void connect_destroy( object_header_t *hdr )
147 connect_t *connect = (connect_t *)hdr;
149 TRACE("%p\n", connect);
151 release_object( &connect->session->hdr );
153 heap_free( connect->hostname );
154 heap_free( connect->servername );
155 heap_free( connect->username );
156 heap_free( connect->password );
157 heap_free( connect );
160 static const object_vtbl_t connect_vtbl =
167 /***********************************************************************
168 * WinHttpConnect (winhttp.@)
170 HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved )
174 HINTERNET hconnect = NULL;
176 TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved);
180 set_last_error( ERROR_INVALID_PARAMETER );
183 if (!(session = (session_t *)grab_object( hsession )))
185 set_last_error( ERROR_INVALID_HANDLE );
188 if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION)
190 release_object( &session->hdr );
191 set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
194 if (!(connect = heap_alloc_zero( sizeof(connect_t) )))
196 release_object( &session->hdr );
199 connect->hdr.type = WINHTTP_HANDLE_TYPE_CONNECT;
200 connect->hdr.vtbl = &connect_vtbl;
201 connect->hdr.refs = 1;
202 connect->hdr.flags = session->hdr.flags;
203 connect->hdr.callback = session->hdr.callback;
204 connect->hdr.notify_mask = session->hdr.notify_mask;
205 connect->hdr.context = session->hdr.context;
207 addref_object( &session->hdr );
208 connect->session = session;
209 list_add_head( &session->hdr.children, &connect->hdr.entry );
211 if (server && !(connect->hostname = strdupW( server ))) goto end;
212 connect->hostport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
214 if (server && !(connect->servername = strdupW( server ))) goto end;
215 connect->serverport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
217 if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
218 connect->hdr.handle = hconnect;
220 send_callback( &session->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hconnect, sizeof(hconnect) );
223 release_object( &connect->hdr );
225 TRACE("returning %p\n", hconnect);
229 /***********************************************************************
230 * request_destroy (internal)
232 static void request_destroy( object_header_t *hdr )
234 request_t *request = (request_t *)hdr;
237 TRACE("%p\n", request);
239 release_object( &request->connect->hdr );
241 heap_free( request->verb );
242 heap_free( request->path );
243 heap_free( request->version );
244 heap_free( request->raw_headers );
245 heap_free( request->status_text );
246 for (i = 0; i < request->num_headers; i++)
248 heap_free( request->headers[i].field );
249 heap_free( request->headers[i].value );
251 heap_free( request->headers );
252 heap_free( request );
255 static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
259 case WINHTTP_OPTION_SECURITY_FLAGS:
263 if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
264 *(DWORD *)buffer = flags;
265 *buflen = sizeof(DWORD);
268 case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
270 const CERT_CONTEXT *cert;
271 request_t *request = (request_t *)hdr;
273 if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE;
274 *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
275 *buflen = sizeof(cert);
278 case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
280 *(DWORD *)buffer = 128; /* FIXME */
281 *buflen = sizeof(DWORD);
285 FIXME("unimplemented option %u\n", option);
290 static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
294 case WINHTTP_OPTION_PROXY:
296 WINHTTP_PROXY_INFO *pi = buffer;
298 FIXME("%u %s %s\n", pi->dwAccessType, debugstr_w(pi->lpszProxy), debugstr_w(pi->lpszProxyBypass));
301 case WINHTTP_OPTION_DISABLE_FEATURE:
303 DWORD disable = *(DWORD *)buffer;
305 TRACE("0x%x\n", disable);
306 hdr->disable_flags &= disable;
309 case WINHTTP_OPTION_AUTOLOGON_POLICY:
311 DWORD policy = *(DWORD *)buffer;
313 TRACE("0x%x\n", policy);
314 hdr->logon_policy = policy;
317 case WINHTTP_OPTION_REDIRECT_POLICY:
319 DWORD policy = *(DWORD *)buffer;
321 TRACE("0x%x\n", policy);
322 hdr->redirect_policy = policy;
326 FIXME("unimplemented option %u\n", option);
331 static const object_vtbl_t request_vtbl =
334 request_query_option,
338 /***********************************************************************
339 * WinHttpOpenRequest (winhttp.@)
341 HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version,
342 LPCWSTR referrer, LPCWSTR *types, DWORD flags )
346 HINTERNET hrequest = NULL;
348 TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object),
349 debugstr_w(version), debugstr_w(referrer), types, flags);
351 if (!(connect = (connect_t *)grab_object( hconnect )))
353 set_last_error( ERROR_INVALID_HANDLE );
356 if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT)
358 release_object( &connect->hdr );
359 set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
362 if (!(request = heap_alloc_zero( sizeof(request_t) )))
364 release_object( &connect->hdr );
367 request->hdr.type = WINHTTP_HANDLE_TYPE_REQUEST;
368 request->hdr.vtbl = &request_vtbl;
369 request->hdr.refs = 1;
370 request->hdr.flags = flags;
371 request->hdr.callback = connect->hdr.callback;
372 request->hdr.notify_mask = connect->hdr.notify_mask;
373 request->hdr.context = connect->hdr.context;
375 addref_object( &connect->hdr );
376 request->connect = connect;
377 list_add_head( &connect->hdr.children, &request->hdr.entry );
379 if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
381 if (verb && !(request->verb = strdupW( verb ))) goto end;
382 if (object && !(request->path = strdupW( object ))) goto end;
383 if (version && !(request->version = strdupW( version ))) goto end;
385 if (!(hrequest = alloc_handle( &request->hdr ))) goto end;
386 request->hdr.handle = hrequest;
388 send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hrequest, sizeof(hrequest) );
391 release_object( &request->hdr );
393 TRACE("returning %p\n", hrequest);
397 /***********************************************************************
398 * WinHttpCloseHandle (winhttp.@)
400 BOOL WINAPI WinHttpCloseHandle( HINTERNET handle )
402 object_header_t *hdr;
404 TRACE("%p\n", handle);
406 if (!(hdr = grab_object( handle )))
408 set_last_error( ERROR_INVALID_HANDLE );
411 release_object( hdr );
412 free_handle( handle );
416 static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
422 case WINHTTP_OPTION_CONTEXT_VALUE:
424 *(DWORD_PTR *)buffer = hdr->context;
425 *buflen = sizeof(DWORD_PTR);
430 if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen );
431 else FIXME("unimplemented option %u\n", option);
437 /***********************************************************************
438 * WinHttpQueryOption (winhttp.@)
440 BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen )
443 object_header_t *hdr;
445 TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen);
447 if (!(hdr = grab_object( handle )))
449 set_last_error( ERROR_INVALID_HANDLE );
453 ret = query_option( hdr, option, buffer, buflen );
455 release_object( hdr );
459 static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
465 case WINHTTP_OPTION_CONTEXT_VALUE:
467 hdr->context = *(DWORD_PTR *)buffer;
472 if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen );
473 else FIXME("unimplemented option %u\n", option);
479 /***********************************************************************
480 * WinHttpSetOption (winhttp.@)
482 BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen )
485 object_header_t *hdr;
487 TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen);
489 if (!(hdr = grab_object( handle )))
491 set_last_error( ERROR_INVALID_HANDLE );
495 ret = set_option( hdr, option, buffer, buflen );
497 release_object( hdr );
501 /***********************************************************************
502 * WinHttpDetectAutoProxyConfigUrl (winhttp.@)
504 BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
506 FIXME("0x%08x, %p\n", flags, url);
508 set_last_error( ERROR_WINHTTP_AUTODETECTION_FAILED );
512 /***********************************************************************
513 * WinHttpGetDefaultProxyConfiguration (winhttp.@)
515 BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
519 info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
520 info->lpszProxy = NULL;
521 info->lpszProxyBypass = NULL;
526 /***********************************************************************
527 * WinHttpGetIEProxyConfigForCurrentUser (winhttp.@)
529 BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *config )
531 TRACE("%p\n", config);
535 set_last_error( ERROR_INVALID_PARAMETER );
539 /* FIXME: read from HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings */
541 FIXME("returning no proxy used\n");
542 config->fAutoDetect = FALSE;
543 config->lpszAutoConfigUrl = NULL;
544 config->lpszProxy = NULL;
545 config->lpszProxyBypass = NULL;
550 /***********************************************************************
551 * WinHttpGetProxyForUrl (winhttp.@)
553 BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTOPROXY_OPTIONS *options,
554 WINHTTP_PROXY_INFO *info )
556 FIXME("%p, %s, %p, %p\n", hsession, debugstr_w(url), options, info);
558 set_last_error( ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR );
562 /***********************************************************************
563 * WinHttpSetDefaultProxyConfiguration (winhttp.@)
565 BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
567 FIXME("%p [%u, %s, %s]\n", info, info->dwAccessType, debugstr_w(info->lpszProxy),
568 debugstr_w(info->lpszProxyBypass));
572 /***********************************************************************
573 * WinHttpSetStatusCallback (winhttp.@)
575 WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHTTP_STATUS_CALLBACK callback,
576 DWORD flags, DWORD_PTR reserved )
578 object_header_t *hdr;
579 WINHTTP_STATUS_CALLBACK ret;
581 TRACE("%p, %p, 0x%08x, 0x%lx\n", handle, callback, flags, reserved);
583 if (!(hdr = grab_object( handle )))
585 set_last_error( ERROR_INVALID_HANDLE );
586 return WINHTTP_INVALID_STATUS_CALLBACK;
589 hdr->callback = callback;
590 hdr->notify_mask = flags;
592 release_object( hdr );
596 /***********************************************************************
597 * WinHttpSetTimeouts (winhttp.@)
599 BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive )
601 FIXME("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
605 static const WCHAR wkday[7][4] =
606 {{'S','u','n', 0}, {'M','o','n', 0}, {'T','u','e', 0}, {'W','e','d', 0},
607 {'T','h','u', 0}, {'F','r','i', 0}, {'S','a','t', 0}};
608 static const WCHAR month[12][4] =
609 {{'J','a','n', 0}, {'F','e','b', 0}, {'M','a','r', 0}, {'A','p','r', 0},
610 {'M','a','y', 0}, {'J','u','n', 0}, {'J','u','l', 0}, {'A','u','g', 0},
611 {'S','e','p', 0}, {'O','c','t', 0}, {'N','o','v', 0}, {'D','e','c', 0}};
613 /***********************************************************************
614 * WinHttpTimeFromSystemTime (WININET.@)
616 BOOL WINAPI WinHttpTimeFromSystemTime( const SYSTEMTIME *time, LPWSTR string )
618 static const WCHAR format[] =
619 {'%','s',',',' ','%','0','2','d',' ','%','s',' ','%','4','d',' ','%','0',
620 '2','d',':','%','0','2','d',':','%','0','2','d',' ','G','M','T', 0};
622 TRACE("%p, %p\n", time, string);
624 if (!time || !string) return FALSE;
626 sprintfW( string, format,
627 wkday[time->wDayOfWeek],
629 month[time->wMonth - 1],
638 /***********************************************************************
639 * WinHttpTimeToSystemTime (WININET.@)
641 BOOL WINAPI WinHttpTimeToSystemTime( LPCWSTR string, SYSTEMTIME *time )
644 const WCHAR *s = string;
647 TRACE("%s, %p\n", debugstr_w(string), time);
649 if (!string || !time) return FALSE;
651 /* Windows does this too */
652 GetSystemTime( time );
654 /* Convert an RFC1123 time such as 'Fri, 07 Jan 2005 12:06:35 GMT' into
655 * a SYSTEMTIME structure.
658 while (*s && !isalphaW( *s )) s++;
659 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
660 time->wDayOfWeek = 7;
662 for (i = 0; i < 7; i++)
664 if (toupperW( wkday[i][0] ) == toupperW( s[0] ) &&
665 toupperW( wkday[i][1] ) == toupperW( s[1] ) &&
666 toupperW( wkday[i][2] ) == toupperW( s[2] ) )
668 time->wDayOfWeek = i;
673 if (time->wDayOfWeek > 6) return TRUE;
674 while (*s && !isdigitW( *s )) s++;
675 time->wDay = strtolW( s, &end, 10 );
678 while (*s && !isalphaW( *s )) s++;
679 if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0') return TRUE;
682 for (i = 0; i < 12; i++)
684 if (toupperW( month[i][0]) == toupperW( s[0] ) &&
685 toupperW( month[i][1]) == toupperW( s[1] ) &&
686 toupperW( month[i][2]) == toupperW( s[2] ) )
688 time->wMonth = i + 1;
692 if (time->wMonth == 0) return TRUE;
694 while (*s && !isdigitW( *s )) s++;
695 if (*s == '\0') return TRUE;
696 time->wYear = strtolW( s, &end, 10 );
699 while (*s && !isdigitW( *s )) s++;
700 if (*s == '\0') return TRUE;
701 time->wHour = strtolW( s, &end, 10 );
704 while (*s && !isdigitW( *s )) s++;
705 if (*s == '\0') return TRUE;
706 time->wMinute = strtolW( s, &end, 10 );
709 while (*s && !isdigitW( *s )) s++;
710 if (*s == '\0') return TRUE;
711 time->wSecond = strtolW( s, &end, 10 );
714 time->wMilliseconds = 0;