wininet: Use current server in HTTP_GetRedirectURL.
[wine/multimedia.git] / dlls / wininet / dialogs.c
blob52a18f3f53d3d40baf6985efd6ea34c3a4ef47ba
1 /*
2 * Wininet
4 * Copyright 2003 Mike McCormack for CodeWeavers Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #if defined(__MINGW32__) || defined (_MSC_VER)
25 #include <ws2tcpip.h>
26 #endif
28 #include <stdarg.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "winreg.h"
34 #include "wininet.h"
35 #include "winnetwk.h"
36 #include "wine/debug.h"
37 #include "winerror.h"
38 #define NO_SHLWAPI_STREAM
39 #include "shlwapi.h"
40 #include "cryptuiapi.h"
42 #include "internet.h"
44 #include "wine/unicode.h"
46 #include "resource.h"
48 #define MAX_STRING_LEN 1024
50 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
52 struct WININET_ErrorDlgParams
54 http_request_t *req;
55 HWND hWnd;
56 DWORD dwError;
57 DWORD dwFlags;
58 LPVOID* lppvData;
61 /***********************************************************************
62 * WININET_GetAuthRealm
64 * Determine the name of the (basic) Authentication realm
66 static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz, BOOL proxy )
68 LPWSTR p, q;
69 DWORD index, query;
70 static const WCHAR szRealm[] = { 'r','e','a','l','m','=',0 };
72 if (proxy)
73 query = HTTP_QUERY_PROXY_AUTHENTICATE;
74 else
75 query = HTTP_QUERY_WWW_AUTHENTICATE;
77 /* extract the Realm from the response and show it */
78 index = 0;
79 if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
80 return FALSE;
83 * FIXME: maybe we should check that we're
84 * dealing with 'Basic' Authentication
86 p = strchrW( szBuf, ' ' );
87 if( !p || strncmpW( p+1, szRealm, strlenW(szRealm) ) )
89 ERR("response wrong? (%s)\n", debugstr_w(szBuf));
90 return FALSE;
93 /* remove quotes */
94 p += 7;
95 if( *p == '"' )
97 p++;
98 q = strrchrW( p, '"' );
99 if( q )
100 *q = 0;
102 strcpyW( szBuf, p );
104 return TRUE;
107 /* These two are not defined in the public headers */
108 extern DWORD WINAPI WNetCachePassword(LPSTR,WORD,LPSTR,WORD,BYTE,WORD);
109 extern DWORD WINAPI WNetGetCachedPassword(LPSTR,WORD,LPSTR,LPWORD,BYTE);
111 /***********************************************************************
112 * WININET_GetSetPassword
114 static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer,
115 LPCWSTR szRealm, BOOL bSet )
117 WCHAR szResource[0x80], szUserPass[0x40];
118 LPWSTR p;
119 HWND hUserItem, hPassItem;
120 DWORD r, dwMagic = 19;
121 UINT r_len, u_len;
122 WORD sz;
123 static const WCHAR szColon[] = { ':',0 };
124 static const WCHAR szbs[] = { '/', 0 };
126 hUserItem = GetDlgItem( hdlg, IDC_USERNAME );
127 hPassItem = GetDlgItem( hdlg, IDC_PASSWORD );
129 /* now try fetch the username and password */
130 lstrcpyW( szResource, szServer);
131 lstrcatW( szResource, szbs);
132 lstrcatW( szResource, szRealm);
135 * WNetCachePassword is only concerned with the length
136 * of the data stored (which we tell it) and it does
137 * not use strlen() internally so we can add WCHAR data
138 * instead of ASCII data and get it back the same way.
140 if( bSet )
142 szUserPass[0] = 0;
143 GetWindowTextW( hUserItem, szUserPass,
144 (sizeof szUserPass-1)/sizeof(WCHAR) );
145 lstrcatW(szUserPass, szColon);
146 u_len = strlenW( szUserPass );
147 GetWindowTextW( hPassItem, szUserPass+u_len,
148 (sizeof szUserPass)/sizeof(WCHAR)-u_len );
150 r_len = (strlenW( szResource ) + 1)*sizeof(WCHAR);
151 u_len = (strlenW( szUserPass ) + 1)*sizeof(WCHAR);
152 r = WNetCachePassword( (CHAR*)szResource, r_len,
153 (CHAR*)szUserPass, u_len, dwMagic, 0 );
155 return ( r == WN_SUCCESS );
158 sz = sizeof szUserPass;
159 r_len = (strlenW( szResource ) + 1)*sizeof(WCHAR);
160 r = WNetGetCachedPassword( (CHAR*)szResource, r_len,
161 (CHAR*)szUserPass, &sz, dwMagic );
162 if( r != WN_SUCCESS )
163 return FALSE;
165 p = strchrW( szUserPass, ':' );
166 if( p )
168 *p = 0;
169 SetWindowTextW( hUserItem, szUserPass );
170 SetWindowTextW( hPassItem, p+1 );
173 return TRUE;
176 /***********************************************************************
177 * WININET_SetAuthorization
179 static BOOL WININET_SetAuthorization( http_request_t *request, LPWSTR username,
180 LPWSTR password, BOOL proxy )
182 http_session_t *session = request->session;
183 LPWSTR p, q;
185 p = heap_strdupW(username);
186 if( !p )
187 return FALSE;
189 q = heap_strdupW(password);
190 if( !q )
192 heap_free(p);
193 return FALSE;
196 if (proxy)
198 appinfo_t *hIC = session->appInfo;
200 heap_free(hIC->proxyUsername);
201 hIC->proxyUsername = p;
203 heap_free(hIC->proxyPassword);
204 hIC->proxyPassword = q;
206 else
208 heap_free(session->userName);
209 session->userName = p;
211 heap_free(session->password);
212 session->password = q;
215 return TRUE;
218 /***********************************************************************
219 * WININET_ProxyPasswordDialog
221 static INT_PTR WINAPI WININET_ProxyPasswordDialog(
222 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
224 HWND hitem;
225 struct WININET_ErrorDlgParams *params;
226 WCHAR szRealm[0x80], szServer[0x80];
228 if( uMsg == WM_INITDIALOG )
230 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
232 /* save the parameter list */
233 params = (struct WININET_ErrorDlgParams*) lParam;
234 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
236 /* extract the Realm from the proxy response and show it */
237 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
238 szRealm, sizeof szRealm/sizeof(WCHAR), TRUE ) )
240 hitem = GetDlgItem( hdlg, IDC_REALM );
241 SetWindowTextW( hitem, szRealm );
244 hitem = GetDlgItem( hdlg, IDC_PROXY );
245 SetWindowTextW( hitem, params->req->session->appInfo->proxy );
247 WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE );
249 return TRUE;
252 params = (struct WININET_ErrorDlgParams*)
253 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
255 switch( uMsg )
257 case WM_COMMAND:
258 if( wParam == IDOK )
260 WCHAR username[0x20], password[0x20];
262 username[0] = 0;
263 hitem = GetDlgItem( hdlg, IDC_USERNAME );
264 if( hitem )
265 GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) );
267 password[0] = 0;
268 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
269 if( hitem )
270 GetWindowTextW( hitem, password, sizeof password/sizeof(WCHAR) );
272 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
273 if( hitem &&
274 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
275 WININET_GetAuthRealm( params->req->hdr.hInternet,
276 szRealm, sizeof szRealm/sizeof(WCHAR), TRUE) )
277 WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, TRUE );
278 WININET_SetAuthorization( params->req, username, password, TRUE );
280 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
281 return TRUE;
283 if( wParam == IDCANCEL )
285 EndDialog( hdlg, 0 );
286 return TRUE;
288 break;
290 return FALSE;
293 /***********************************************************************
294 * WININET_PasswordDialog
296 static INT_PTR WINAPI WININET_PasswordDialog(
297 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
299 HWND hitem;
300 struct WININET_ErrorDlgParams *params;
301 WCHAR szRealm[0x80], szServer[0x80];
303 if( uMsg == WM_INITDIALOG )
305 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
307 /* save the parameter list */
308 params = (struct WININET_ErrorDlgParams*) lParam;
309 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
311 /* extract the Realm from the response and show it */
312 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
313 szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ) )
315 hitem = GetDlgItem( hdlg, IDC_REALM );
316 SetWindowTextW( hitem, szRealm );
319 hitem = GetDlgItem( hdlg, IDC_SERVER );
320 SetWindowTextW( hitem, params->req->session->hostName );
322 WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE );
324 return TRUE;
327 params = (struct WININET_ErrorDlgParams*)
328 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
330 switch( uMsg )
332 case WM_COMMAND:
333 if( wParam == IDOK )
335 WCHAR username[0x20], password[0x20];
337 username[0] = 0;
338 hitem = GetDlgItem( hdlg, IDC_USERNAME );
339 if( hitem )
340 GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) );
342 password[0] = 0;
343 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
344 if( hitem )
345 GetWindowTextW( hitem, password, sizeof password/sizeof(WCHAR) );
347 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
348 if( hitem &&
349 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
350 WININET_GetAuthRealm( params->req->hdr.hInternet,
351 szRealm, sizeof szRealm/sizeof(WCHAR), FALSE ))
353 WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, TRUE );
355 WININET_SetAuthorization( params->req, username, password, FALSE );
357 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
358 return TRUE;
360 if( wParam == IDCANCEL )
362 EndDialog( hdlg, 0 );
363 return TRUE;
365 break;
367 return FALSE;
370 /***********************************************************************
371 * WININET_InvalidCertificateDialog
373 static INT_PTR WINAPI WININET_InvalidCertificateDialog(
374 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
376 struct WININET_ErrorDlgParams *params;
377 HWND hitem;
378 WCHAR buf[1024];
380 if( uMsg == WM_INITDIALOG )
382 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
384 /* save the parameter list */
385 params = (struct WININET_ErrorDlgParams*) lParam;
386 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
388 switch( params->dwError )
390 case ERROR_INTERNET_INVALID_CA:
391 LoadStringW( WININET_hModule, IDS_CERT_CA_INVALID, buf, 1024 );
392 break;
393 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
394 LoadStringW( WININET_hModule, IDS_CERT_DATE_INVALID, buf, 1024 );
395 break;
396 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
397 LoadStringW( WININET_hModule, IDS_CERT_CN_INVALID, buf, 1024 );
398 break;
399 case ERROR_INTERNET_SEC_CERT_ERRORS:
400 /* FIXME: We should fetch information about the
401 * certificate here and show all the relevant errors.
403 LoadStringW( WININET_hModule, IDS_CERT_ERRORS, buf, 1024 );
404 break;
405 default:
406 FIXME( "No message for error %d\n", params->dwError );
407 buf[0] = '\0';
410 hitem = GetDlgItem( hdlg, IDC_CERT_ERROR );
411 SetWindowTextW( hitem, buf );
413 return TRUE;
416 params = (struct WININET_ErrorDlgParams*)
417 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
419 switch( uMsg )
421 case WM_COMMAND:
422 if( wParam == IDOK )
424 BOOL res = TRUE;
426 if( params->dwFlags & FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
428 http_request_t *req = params->req;
429 DWORD flags, size = sizeof(flags);
431 InternetQueryOptionW( req->hdr.hInternet, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
432 switch( params->dwError )
434 case ERROR_INTERNET_INVALID_CA:
435 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
436 break;
437 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
438 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
439 break;
440 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
441 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
442 break;
443 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
444 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
445 break;
446 case ERROR_INTERNET_SEC_CERT_ERRORS:
447 if(flags & _SECURITY_FLAG_CERT_REV_FAILED)
448 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
449 if(flags & _SECURITY_FLAG_CERT_INVALID_CA)
450 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
451 if(flags & _SECURITY_FLAG_CERT_INVALID_CN)
452 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
453 if(flags & _SECURITY_FLAG_CERT_INVALID_DATE)
454 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
455 break;
457 /* FIXME: Use helper function */
458 flags |= SECURITY_FLAG_SECURE;
459 req->security_flags |= flags;
460 if(is_valid_netconn(req->netconn))
461 req->netconn->security_flags |= flags;
464 EndDialog( hdlg, res ? ERROR_SUCCESS : ERROR_NOT_SUPPORTED );
465 return TRUE;
467 if( wParam == IDCANCEL )
469 TRACE("Pressed cancel.\n");
471 EndDialog( hdlg, ERROR_CANCELLED );
472 return TRUE;
474 break;
477 return FALSE;
480 /***********************************************************************
481 * InternetErrorDlg
483 DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
484 DWORD dwError, DWORD dwFlags, LPVOID* lppvData)
486 struct WININET_ErrorDlgParams params;
487 http_request_t *req = NULL;
488 DWORD res = ERROR_SUCCESS;
490 TRACE("%p %p %d %08x %p\n", hWnd, hRequest, dwError, dwFlags, lppvData);
492 if( !hWnd && !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) )
493 return ERROR_INVALID_HANDLE;
495 if(hRequest) {
496 req = (http_request_t*)get_handle_object(hRequest);
497 if(!req)
498 return ERROR_INVALID_HANDLE;
499 if(req->hdr.htype != WH_HHTTPREQ)
500 return ERROR_SUCCESS; /* Yes, that was tested */
503 params.req = req;
504 params.hWnd = hWnd;
505 params.dwError = dwError;
506 params.dwFlags = dwFlags;
507 params.lppvData = lppvData;
509 switch( dwError )
511 case ERROR_SUCCESS:
512 case ERROR_INTERNET_INCORRECT_PASSWORD: {
513 if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
514 break;
515 if(!req)
516 return ERROR_INVALID_HANDLE;
518 switch(req->status_code) {
519 case HTTP_STATUS_PROXY_AUTH_REQ:
520 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
521 hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
522 break;
523 case HTTP_STATUS_DENIED:
524 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
525 hWnd, WININET_PasswordDialog, (LPARAM) &params );
526 break;
527 default:
528 WARN("unhandled status %u\n", req->status_code);
530 break;
532 case ERROR_INTERNET_SEC_CERT_ERRORS:
533 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
534 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
535 case ERROR_INTERNET_INVALID_CA:
536 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
537 if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI ) {
538 res = ERROR_CANCELLED;
539 break;
541 if(!req)
542 return ERROR_INVALID_HANDLE;
545 if( dwFlags & ~FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
546 FIXME("%08x contains unsupported flags.\n", dwFlags);
548 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
549 hWnd, WININET_InvalidCertificateDialog, (LPARAM) &params );
550 break;
551 case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
552 case ERROR_INTERNET_POST_IS_NON_SECURE:
553 FIXME("Need to display dialog for error %d\n", dwError);
554 res = ERROR_SUCCESS;
555 break;
556 default:
557 res = ERROR_NOT_SUPPORTED;
560 if(req)
561 WININET_Release(&req->hdr);
562 return res;
565 /***********************************************************************
566 * InternetShowSecurityInfoByURLA (@)
568 BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
570 FIXME("stub: %s %p\n", url, window);
571 return FALSE;
574 /***********************************************************************
575 * InternetShowSecurityInfoByURLW (@)
577 BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
579 FIXME("stub: %s %p\n", debugstr_w(url), window);
580 return FALSE;
583 /***********************************************************************
584 * ShowX509EncodedCertificate (@)
586 DWORD WINAPI ShowX509EncodedCertificate(HWND parent, LPBYTE cert, DWORD len)
588 PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
589 cert, len);
590 DWORD ret;
592 if (certContext)
594 CRYPTUI_VIEWCERTIFICATE_STRUCTW view;
596 memset(&view, 0, sizeof(view));
597 view.hwndParent = parent;
598 view.pCertContext = certContext;
599 if (CryptUIDlgViewCertificateW(&view, NULL))
600 ret = ERROR_SUCCESS;
601 else
602 ret = GetLastError();
603 CertFreeCertificateContext(certContext);
605 else
606 ret = GetLastError();
607 return ret;