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
22 #include "wine/port.h"
24 #if defined(__MINGW32__) || defined (_MSC_VER)
36 #include "wine/debug.h"
38 #define NO_SHLWAPI_STREAM
40 #include "cryptuiapi.h"
44 #include "wine/unicode.h"
48 #define MAX_STRING_LEN 1024
50 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
52 struct WININET_ErrorDlgParams
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 )
70 static const WCHAR szRealm[] = { 'r','e','a','l','m','=',0 };
73 query = HTTP_QUERY_PROXY_AUTHENTICATE;
75 query = HTTP_QUERY_WWW_AUTHENTICATE;
77 /* extract the Realm from the response and show it */
79 if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
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));
98 q = strrchrW( p, '"' );
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];
119 HWND hUserItem, hPassItem;
120 DWORD r, dwMagic = 19;
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.
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 )
165 p = strchrW( szUserPass, ':' );
169 SetWindowTextW( hUserItem, szUserPass );
170 SetWindowTextW( hPassItem, p+1 );
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;
185 p = heap_strdupW(username);
189 q = heap_strdupW(password);
198 appinfo_t *hIC = session->appInfo;
200 heap_free(hIC->proxyUsername);
201 hIC->proxyUsername = p;
203 heap_free(hIC->proxyPassword);
204 hIC->proxyPassword = q;
208 heap_free(session->userName);
209 session->userName = p;
211 heap_free(session->password);
212 session->password = q;
218 /***********************************************************************
219 * WININET_ProxyPasswordDialog
221 static INT_PTR WINAPI WININET_ProxyPasswordDialog(
222 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
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 );
252 params = (struct WININET_ErrorDlgParams*)
253 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
260 WCHAR username[0x20], password[0x20];
263 hitem = GetDlgItem( hdlg, IDC_USERNAME );
265 GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) );
268 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
270 GetWindowTextW( hitem, password, sizeof password/sizeof(WCHAR) );
272 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
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 );
283 if( wParam == IDCANCEL )
285 EndDialog( hdlg, 0 );
293 /***********************************************************************
294 * WININET_PasswordDialog
296 static INT_PTR WINAPI WININET_PasswordDialog(
297 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
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 );
327 params = (struct WININET_ErrorDlgParams*)
328 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
335 WCHAR username[0x20], password[0x20];
338 hitem = GetDlgItem( hdlg, IDC_USERNAME );
340 GetWindowTextW( hitem, username, sizeof username/sizeof(WCHAR) );
343 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
345 GetWindowTextW( hitem, password, sizeof password/sizeof(WCHAR) );
347 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
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 );
360 if( wParam == IDCANCEL )
362 EndDialog( hdlg, 0 );
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;
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 );
393 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
394 LoadStringW( WININET_hModule, IDS_CERT_DATE_INVALID, buf, 1024 );
396 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
397 LoadStringW( WININET_hModule, IDS_CERT_CN_INVALID, buf, 1024 );
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 );
406 FIXME( "No message for error %d\n", params->dwError );
410 hitem = GetDlgItem( hdlg, IDC_CERT_ERROR );
411 SetWindowTextW( hitem, buf );
416 params = (struct WININET_ErrorDlgParams*)
417 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
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;
437 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
438 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
440 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
441 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
443 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
444 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
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;
457 /* FIXME: Use helper function */
458 flags |= SECURITY_FLAG_SECURE;
459 req->security_flags |= flags;
461 req->netconn->security_flags |= flags;
464 EndDialog( hdlg, res ? ERROR_SUCCESS : ERROR_NOT_SUPPORTED );
467 if( wParam == IDCANCEL )
469 TRACE("Pressed cancel.\n");
471 EndDialog( hdlg, ERROR_CANCELLED );
480 /***********************************************************************
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;
496 req = (http_request_t*)get_handle_object(hRequest);
498 return ERROR_INVALID_HANDLE;
499 if(req->hdr.htype != WH_HHTTPREQ)
500 return ERROR_SUCCESS; /* Yes, that was tested */
505 params.dwError = dwError;
506 params.dwFlags = dwFlags;
507 params.lppvData = lppvData;
512 case ERROR_INTERNET_INCORRECT_PASSWORD: {
513 if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
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) ¶ms );
523 case HTTP_STATUS_DENIED:
524 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
525 hWnd, WININET_PasswordDialog, (LPARAM) ¶ms );
528 WARN("unhandled status %u\n", req->status_code);
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;
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) ¶ms );
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);
557 res = ERROR_NOT_SUPPORTED;
561 WININET_Release(&req->hdr);
565 /***********************************************************************
566 * InternetShowSecurityInfoByURLA (@)
568 BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
570 FIXME("stub: %s %p\n", url, window);
574 /***********************************************************************
575 * InternetShowSecurityInfoByURLW (@)
577 BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
579 FIXME("stub: %s %p\n", debugstr_w(url), window);
583 /***********************************************************************
584 * ShowX509EncodedCertificate (@)
586 DWORD WINAPI ShowX509EncodedCertificate(HWND parent, LPBYTE cert, DWORD len)
588 PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
594 CRYPTUI_VIEWCERTIFICATE_STRUCTW view;
596 memset(&view, 0, sizeof(view));
597 view.hwndParent = parent;
598 view.pCertContext = certContext;
599 if (CryptUIDlgViewCertificateW(&view, NULL))
602 ret = GetLastError();
603 CertFreeCertificateContext(certContext);
606 ret = GetLastError();