wrc: Store version and characteristics as simple integers.
[wine.git] / dlls / wininet / dialogs.c
blobabd8621e76cd9ab045e41731ce20d09648596051
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 "ws2tcpip.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "wininet.h"
30 #include "winnetwk.h"
31 #include "wine/debug.h"
32 #include "winerror.h"
33 #define NO_SHLWAPI_STREAM
34 #include "shlwapi.h"
35 #include "cryptuiapi.h"
37 #include "internet.h"
38 #include "resource.h"
40 #define MAX_STRING_LEN 1024
42 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
44 struct WININET_ErrorDlgParams
46 http_request_t *req;
47 HWND hWnd;
48 DWORD dwError;
49 DWORD dwFlags;
50 LPVOID* lppvData;
53 /***********************************************************************
54 * WININET_GetAuthRealm
56 * Determine the name of the (basic) Authentication realm
58 static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz, BOOL proxy )
60 LPWSTR p, q;
61 DWORD index, query;
63 if (proxy)
64 query = HTTP_QUERY_PROXY_AUTHENTICATE;
65 else
66 query = HTTP_QUERY_WWW_AUTHENTICATE;
68 /* extract the Realm from the response and show it */
69 index = 0;
70 if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
71 return FALSE;
74 * FIXME: maybe we should check that we're
75 * dealing with 'Basic' Authentication
77 p = wcschr( szBuf, ' ' );
78 if( !p || wcsncmp( p+1, L"realm=", lstrlenW(L"realm=") ) )
80 ERR("response wrong? (%s)\n", debugstr_w(szBuf));
81 return FALSE;
84 /* remove quotes */
85 p += 7;
86 if( *p == '"' )
88 p++;
89 q = wcsrchr( p, '"' );
90 if( q )
91 *q = 0;
93 lstrcpyW( szBuf, p );
95 return TRUE;
98 /* These two are not defined in the public headers */
99 extern DWORD WINAPI WNetCachePassword(LPSTR,WORD,LPSTR,WORD,BYTE,WORD);
100 extern DWORD WINAPI WNetGetCachedPassword(LPSTR,WORD,LPSTR,LPWORD,BYTE);
102 /***********************************************************************
103 * WININET_GetSetPassword
105 static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer,
106 LPCWSTR szRealm, BOOL bSet )
108 WCHAR szResource[0x80], szUserPass[0x40];
109 LPWSTR p;
110 HWND hUserItem, hPassItem;
111 DWORD r, dwMagic = 19;
112 UINT r_len, u_len;
113 WORD sz;
115 hUserItem = GetDlgItem( hdlg, IDC_USERNAME );
116 hPassItem = GetDlgItem( hdlg, IDC_PASSWORD );
118 /* now try fetch the username and password */
119 lstrcpyW( szResource, szServer);
120 lstrcatW( szResource, L"/");
121 lstrcatW( szResource, szRealm);
124 * WNetCachePassword is only concerned with the length
125 * of the data stored (which we tell it) and it does
126 * not use strlen() internally so we can add WCHAR data
127 * instead of ASCII data and get it back the same way.
129 if( bSet )
131 szUserPass[0] = 0;
132 GetWindowTextW( hUserItem, szUserPass, ARRAY_SIZE( szUserPass ) - 1 );
133 lstrcatW(szUserPass, L":");
134 u_len = lstrlenW( szUserPass );
135 GetWindowTextW( hPassItem, szUserPass+u_len, ARRAY_SIZE( szUserPass ) - u_len );
137 r_len = (lstrlenW( szResource ) + 1)*sizeof(WCHAR);
138 u_len = (lstrlenW( szUserPass ) + 1)*sizeof(WCHAR);
139 r = WNetCachePassword( (CHAR*)szResource, r_len,
140 (CHAR*)szUserPass, u_len, dwMagic, 0 );
142 return ( r == WN_SUCCESS );
145 sz = sizeof szUserPass;
146 r_len = (lstrlenW( szResource ) + 1)*sizeof(WCHAR);
147 r = WNetGetCachedPassword( (CHAR*)szResource, r_len,
148 (CHAR*)szUserPass, &sz, dwMagic );
149 if( r != WN_SUCCESS )
150 return FALSE;
152 p = wcschr( szUserPass, ':' );
153 if( p )
155 *p = 0;
156 SetWindowTextW( hUserItem, szUserPass );
157 SetWindowTextW( hPassItem, p+1 );
160 return TRUE;
163 /***********************************************************************
164 * WININET_SetAuthorization
166 static BOOL WININET_SetAuthorization( http_request_t *request, LPWSTR username,
167 LPWSTR password, BOOL proxy )
169 http_session_t *session = request->session;
170 LPWSTR p, q;
172 p = heap_strdupW(username);
173 if( !p )
174 return FALSE;
176 q = heap_strdupW(password);
177 if( !q )
179 heap_free(p);
180 return FALSE;
183 if (proxy)
185 appinfo_t *hIC = session->appInfo;
187 heap_free(hIC->proxyUsername);
188 hIC->proxyUsername = p;
190 heap_free(hIC->proxyPassword);
191 hIC->proxyPassword = q;
193 else
195 heap_free(session->userName);
196 session->userName = p;
198 heap_free(session->password);
199 session->password = q;
202 return TRUE;
205 /***********************************************************************
206 * WININET_ProxyPasswordDialog
208 static INT_PTR WINAPI WININET_ProxyPasswordDialog(
209 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
211 HWND hitem;
212 struct WININET_ErrorDlgParams *params;
213 WCHAR szRealm[0x80];
215 if( uMsg == WM_INITDIALOG )
217 TRACE("WM_INITDIALOG (%08Ix)\n", lParam);
219 /* save the parameter list */
220 params = (struct WININET_ErrorDlgParams*) lParam;
221 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
223 /* extract the Realm from the proxy response and show it */
224 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
225 szRealm, ARRAY_SIZE( szRealm ), TRUE ) )
227 hitem = GetDlgItem( hdlg, IDC_REALM );
228 SetWindowTextW( hitem, szRealm );
231 hitem = GetDlgItem( hdlg, IDC_PROXY );
232 SetWindowTextW( hitem, params->req->session->appInfo->proxy );
234 WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, FALSE );
236 return TRUE;
239 params = (struct WININET_ErrorDlgParams*)
240 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
242 switch( uMsg )
244 case WM_COMMAND:
245 if( wParam == IDOK )
247 WCHAR username[0x20], password[0x20];
249 username[0] = 0;
250 hitem = GetDlgItem( hdlg, IDC_USERNAME );
251 if( hitem )
252 GetWindowTextW( hitem, username, ARRAY_SIZE( username ));
254 password[0] = 0;
255 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
256 if( hitem )
257 GetWindowTextW( hitem, password, ARRAY_SIZE( password ));
259 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
260 if( hitem &&
261 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
262 WININET_GetAuthRealm( params->req->hdr.hInternet,
263 szRealm, ARRAY_SIZE( szRealm ), TRUE) )
264 WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, TRUE );
265 WININET_SetAuthorization( params->req, username, password, TRUE );
267 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
268 return TRUE;
270 if( wParam == IDCANCEL )
272 EndDialog( hdlg, 0 );
273 return TRUE;
275 break;
277 return FALSE;
280 /***********************************************************************
281 * WININET_PasswordDialog
283 static INT_PTR WINAPI WININET_PasswordDialog(
284 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
286 HWND hitem;
287 struct WININET_ErrorDlgParams *params;
288 WCHAR szRealm[0x80];
290 if( uMsg == WM_INITDIALOG )
292 TRACE("WM_INITDIALOG (%08Ix)\n", lParam);
294 /* save the parameter list */
295 params = (struct WININET_ErrorDlgParams*) lParam;
296 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
298 /* extract the Realm from the response and show it */
299 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
300 szRealm, ARRAY_SIZE( szRealm ), FALSE ) )
302 hitem = GetDlgItem( hdlg, IDC_REALM );
303 SetWindowTextW( hitem, szRealm );
306 hitem = GetDlgItem( hdlg, IDC_SERVER );
307 SetWindowTextW( hitem, params->req->session->hostName );
309 WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, FALSE );
311 return TRUE;
314 params = (struct WININET_ErrorDlgParams*)
315 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
317 switch( uMsg )
319 case WM_COMMAND:
320 if( wParam == IDOK )
322 WCHAR username[0x20], password[0x20];
324 username[0] = 0;
325 hitem = GetDlgItem( hdlg, IDC_USERNAME );
326 if( hitem )
327 GetWindowTextW( hitem, username, ARRAY_SIZE( username ));
329 password[0] = 0;
330 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
331 if( hitem )
332 GetWindowTextW( hitem, password, ARRAY_SIZE( password ));
334 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
335 if( hitem &&
336 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
337 WININET_GetAuthRealm( params->req->hdr.hInternet,
338 szRealm, ARRAY_SIZE( szRealm ), FALSE ))
340 WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, TRUE );
342 WININET_SetAuthorization( params->req, username, password, FALSE );
344 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
345 return TRUE;
347 if( wParam == IDCANCEL )
349 EndDialog( hdlg, 0 );
350 return TRUE;
352 break;
354 return FALSE;
357 /***********************************************************************
358 * WININET_InvalidCertificateDialog
360 static INT_PTR WINAPI WININET_InvalidCertificateDialog(
361 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
363 struct WININET_ErrorDlgParams *params;
364 HWND hitem;
365 WCHAR buf[1024];
367 if( uMsg == WM_INITDIALOG )
369 TRACE("WM_INITDIALOG (%08Ix)\n", lParam);
371 /* save the parameter list */
372 params = (struct WININET_ErrorDlgParams*) lParam;
373 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
375 switch( params->dwError )
377 case ERROR_INTERNET_INVALID_CA:
378 LoadStringW( WININET_hModule, IDS_CERT_CA_INVALID, buf, 1024 );
379 break;
380 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
381 LoadStringW( WININET_hModule, IDS_CERT_DATE_INVALID, buf, 1024 );
382 break;
383 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
384 LoadStringW( WININET_hModule, IDS_CERT_CN_INVALID, buf, 1024 );
385 break;
386 case ERROR_INTERNET_SEC_CERT_ERRORS:
387 /* FIXME: We should fetch information about the
388 * certificate here and show all the relevant errors.
390 LoadStringW( WININET_hModule, IDS_CERT_ERRORS, buf, 1024 );
391 break;
392 default:
393 FIXME( "No message for error %ld\n", params->dwError );
394 buf[0] = '\0';
397 hitem = GetDlgItem( hdlg, IDC_CERT_ERROR );
398 SetWindowTextW( hitem, buf );
400 return TRUE;
403 params = (struct WININET_ErrorDlgParams*)
404 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
406 switch( uMsg )
408 case WM_COMMAND:
409 if( wParam == IDOK )
411 if( params->dwFlags & FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
413 http_request_t *req = params->req;
414 DWORD flags, size = sizeof(flags);
416 InternetQueryOptionW( req->hdr.hInternet, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
417 switch( params->dwError )
419 case ERROR_INTERNET_INVALID_CA:
420 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
421 break;
422 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
423 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
424 break;
425 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
426 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
427 break;
428 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
429 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
430 break;
431 case ERROR_INTERNET_SEC_CERT_ERRORS:
432 if(flags & _SECURITY_FLAG_CERT_REV_FAILED)
433 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
434 if(flags & _SECURITY_FLAG_CERT_INVALID_CA)
435 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
436 if(flags & _SECURITY_FLAG_CERT_INVALID_CN)
437 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
438 if(flags & _SECURITY_FLAG_CERT_INVALID_DATE)
439 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
440 break;
442 /* FIXME: Use helper function */
443 flags |= SECURITY_FLAG_SECURE;
444 req->security_flags |= flags;
445 if(is_valid_netconn(req->netconn))
446 req->netconn->security_flags |= flags;
449 EndDialog( hdlg, ERROR_SUCCESS );
450 return TRUE;
452 if( wParam == IDCANCEL )
454 TRACE("Pressed cancel.\n");
456 EndDialog( hdlg, ERROR_CANCELLED );
457 return TRUE;
459 break;
462 return FALSE;
465 /***********************************************************************
466 * InternetErrorDlg
468 DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
469 DWORD dwError, DWORD dwFlags, LPVOID* lppvData)
471 struct WININET_ErrorDlgParams params;
472 http_request_t *req = NULL;
473 DWORD res = ERROR_SUCCESS;
475 TRACE("%p %p %ld %08lx %p\n", hWnd, hRequest, dwError, dwFlags, lppvData);
477 if( !hWnd && !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) )
478 return ERROR_INVALID_HANDLE;
480 if(hRequest) {
481 req = (http_request_t*)get_handle_object(hRequest);
482 if(!req)
483 return ERROR_INVALID_HANDLE;
484 if(req->hdr.htype != WH_HHTTPREQ)
485 return ERROR_SUCCESS; /* Yes, that was tested */
488 params.req = req;
489 params.hWnd = hWnd;
490 params.dwError = dwError;
491 params.dwFlags = dwFlags;
492 params.lppvData = lppvData;
494 switch( dwError )
496 case ERROR_SUCCESS:
497 case ERROR_INTERNET_INCORRECT_PASSWORD: {
498 if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
499 break;
500 if(!req)
501 return ERROR_INVALID_PARAMETER;
503 switch(req->status_code) {
504 case HTTP_STATUS_PROXY_AUTH_REQ:
505 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
506 hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
507 break;
508 case HTTP_STATUS_DENIED:
509 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
510 hWnd, WININET_PasswordDialog, (LPARAM) &params );
511 break;
512 default:
513 WARN("unhandled status %lu\n", req->status_code);
515 break;
518 case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
519 if(!req)
520 return ERROR_INVALID_PARAMETER;
521 /* fall through */
522 case ERROR_INTERNET_SEC_CERT_ERRORS:
523 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
524 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
525 case ERROR_INTERNET_INVALID_CA:
526 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
527 case ERROR_INTERNET_SEC_CERT_WEAK_SIGNATURE:
528 if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI ) {
529 res = ERROR_CANCELLED;
530 break;
533 if( dwFlags & ~FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
534 FIXME("%08lx contains unsupported flags.\n", dwFlags);
536 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
537 hWnd, WININET_InvalidCertificateDialog, (LPARAM) &params );
538 break;
540 case ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION:
541 if(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) {
542 res = ERROR_HTTP_COOKIE_DECLINED;
543 break;
545 FIXME("Need to display dialog for error %ld\n", dwError);
546 res = ERROR_CANCELLED;
547 break;
549 case ERROR_INTERNET_INSERT_CDROM:
550 if(!req)
551 return ERROR_INVALID_PARAMETER;
552 /* fall through */
553 case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
554 case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT:
555 case ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT:
556 case ERROR_INTERNET_MIXED_SECURITY:
557 case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR:
558 if(!(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
559 FIXME("Need to display dialog for error %ld\n", dwError);
560 res = ERROR_CANCELLED;
561 break;
563 case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
564 case ERROR_INTERNET_CHG_POST_IS_NON_SECURE:
565 if(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) {
566 res = ERROR_SUCCESS;
567 break;
569 FIXME("Need to display dialog for error %ld\n", dwError);
570 res = ERROR_CANCELLED;
571 break;
573 case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
574 case ERROR_INTERNET_POST_IS_NON_SECURE:
575 if (!(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
576 FIXME("Need to display dialog for error %ld\n", dwError);
577 res = ERROR_SUCCESS;
578 break;
580 default:
581 if(!(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS))
582 res = ERROR_CANCELLED;
583 break;
586 if(req)
587 WININET_Release(&req->hdr);
588 return res;
591 /***********************************************************************
592 * InternetShowSecurityInfoByURLA (@)
594 BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
596 FIXME("stub: %s %p\n", url, window);
597 return FALSE;
600 /***********************************************************************
601 * InternetShowSecurityInfoByURLW (@)
603 BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
605 FIXME("stub: %s %p\n", debugstr_w(url), window);
606 return FALSE;
609 /***********************************************************************
610 * ParseX509EncodedCertificateForListBoxEntry (@)
612 DWORD WINAPI ParseX509EncodedCertificateForListBoxEntry(LPBYTE cert, DWORD len, LPSTR szlistbox, LPDWORD listbox)
614 FIXME("stub: %p %ld %s %p\n", cert, len, debugstr_a(szlistbox), listbox);
615 return ERROR_CALL_NOT_IMPLEMENTED;
618 /***********************************************************************
619 * ShowX509EncodedCertificate (@)
621 DWORD WINAPI ShowX509EncodedCertificate(HWND parent, LPBYTE cert, DWORD len)
623 PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
624 cert, len);
625 DWORD ret;
627 if (certContext)
629 CRYPTUI_VIEWCERTIFICATE_STRUCTW view;
631 memset(&view, 0, sizeof(view));
632 view.hwndParent = parent;
633 view.pCertContext = certContext;
634 if (CryptUIDlgViewCertificateW(&view, NULL))
635 ret = ERROR_SUCCESS;
636 else
637 ret = GetLastError();
638 CertFreeCertificateContext(certContext);
640 else
641 ret = GetLastError();
642 return ret;