You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1086 lines
31 KiB
1086 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ierrui.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains immplimentation of generic Error UI API.
|
|
|
|
Contents:
|
|
InternetErrorDlg
|
|
InternetConfirmZoneCrossing
|
|
(wErrorUIInvalidPassword)
|
|
|
|
Author:
|
|
|
|
Arthur L Bierer (arthurbi) 04-Apr-1996
|
|
|
|
Revision History:
|
|
|
|
04-Apr-1996 arthurbi
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <wininetp.h>
|
|
#include <persist.h>
|
|
#include "ierrui.hxx"
|
|
|
|
|
|
//
|
|
// private prototypes
|
|
//
|
|
|
|
|
|
|
|
PRIVATE
|
|
DWORD
|
|
wErrorUIInvalidPassword(
|
|
IN HWND hWnd,
|
|
IN OUT HINTERNET hRequest,
|
|
IN DWORD dwError,
|
|
IN DWORD dwFlags,
|
|
IN OUT LPVOID *lppvData
|
|
);
|
|
|
|
|
|
//
|
|
// public functions
|
|
//
|
|
|
|
INTERNETAPI_(DWORD) InternetErrorDlg(IN HWND hWnd,
|
|
IN OUT HINTERNET hRequest,
|
|
IN DWORD dwError,
|
|
IN DWORD dwFlags,
|
|
IN OUT LPVOID *lppvData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates an Error Dialog informing the User of a problem with a WinINet HttpSendRequest.
|
|
Can optionally store the results of dialog in the HTTP handle.
|
|
Data may be specified in the lppvData pointer, or optionally InternetErrorDlg
|
|
will gather the information from the HTTP handle
|
|
|
|
Arguments:
|
|
|
|
hWnd - Window handle to be used as the parent window of a Error Dialog.
|
|
|
|
hRequest - An open HTTP request handle
|
|
where headers will be added if needed.
|
|
|
|
dwError - The Error code to which the appropriate UI will be shown for.
|
|
|
|
dwFlags - Can be any of all of the following Flags:
|
|
|
|
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA - generates lppvData, and queries
|
|
internet handle for information.
|
|
|
|
FLAGS_ERROR_UI_FILTER_FOR_ERRORS - scans the returned headers,
|
|
and determines if there is a "hidden" error, such as an authentication
|
|
failure.
|
|
|
|
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS - On successful return of the dialog,
|
|
this flag will causes the results to be stored in the handle.
|
|
|
|
FLAGS_ERROR_UI_SERIALIZE_DIALOGS - display only one auth dlg and
|
|
notify subsequent threads when the dialog has been dismissed.
|
|
|
|
lppvData - Contains a Pointer to a Pointer where a stucture is stored containing
|
|
error specific data, and Dialog results.
|
|
|
|
|
|
Return Value:
|
|
|
|
DWORD
|
|
Success - ERROR_SUCCESS
|
|
|
|
Failure - One of Serveral Error codes defined in winerror.h or wininet.w
|
|
|
|
Comments:
|
|
|
|
BUGBUG - need to look into multiple authentication scheme handling, and
|
|
how it relates to the UI
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_HTTP,
|
|
Dword,
|
|
"InternetErrorDlg",
|
|
"%#x, %#x, %s (%d), %#x, %#x",
|
|
hWnd,
|
|
hRequest,
|
|
InternetMapError(dwError),
|
|
dwError,
|
|
dwFlags,
|
|
lppvData
|
|
));
|
|
|
|
DWORD dwStatusCode = HTTP_STATUS_OK;
|
|
DWORD error = ERROR_SUCCESS;
|
|
HINTERNET hMappedRequestHandle = NULL;
|
|
HINTERNET_HANDLE_TYPE handleType;
|
|
HTTP_REQUEST_HANDLE_OBJECT *lpRequest;
|
|
|
|
LPVOID lpVoidData;
|
|
|
|
//
|
|
// Check Parameters
|
|
//
|
|
|
|
if ( !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) &&
|
|
!IsWindow(hWnd) )
|
|
{
|
|
error = ERROR_INVALID_HANDLE;
|
|
goto quit;
|
|
}
|
|
|
|
if (!GlobalDataInitialized) {
|
|
error = GlobalDataInitialize();
|
|
if (error != ERROR_SUCCESS) {
|
|
goto quit;
|
|
}
|
|
}
|
|
|
|
if ( hRequest )
|
|
{
|
|
error = MapHandleToAddress(hRequest, (LPVOID *)&hMappedRequestHandle, FALSE);
|
|
|
|
if ( error != ERROR_SUCCESS )
|
|
goto quit;
|
|
|
|
//
|
|
// We only support HttpRequestHandles for this form of UI.
|
|
//
|
|
|
|
|
|
error = RGetHandleType(hMappedRequestHandle, &handleType);
|
|
|
|
if ( error != ERROR_SUCCESS || handleType != TypeHttpRequestHandle )
|
|
goto quit;
|
|
|
|
lpRequest = (HTTP_REQUEST_HANDLE_OBJECT *) hMappedRequestHandle;
|
|
|
|
//
|
|
// See if we can detect an error if needed
|
|
//
|
|
|
|
if ( dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS )
|
|
{
|
|
dwStatusCode = lpRequest->GetStatusCode();
|
|
|
|
if ( dwStatusCode == HTTP_STATUS_DENIED || dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ )
|
|
dwError = ERROR_INTERNET_INCORRECT_PASSWORD;
|
|
|
|
if ( lpRequest->GetBlockingFilter())
|
|
dwError = ERROR_INTERNET_NEED_UI;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( ERROR_INTERNET_NEED_UI == dwError ||
|
|
ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED == dwError ||
|
|
ERROR_INTERNET_INSERT_CDROM == dwError ||
|
|
ERROR_INTERNET_INCORRECT_PASSWORD == dwError )
|
|
{
|
|
|
|
error = ERROR_INVALID_PARAMETER;
|
|
goto quit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the Caller didn't pass us anything, then we create our own
|
|
// structure. Lets NULL it, and then allocate it later
|
|
//
|
|
//
|
|
|
|
if ( !lppvData )
|
|
{
|
|
lppvData = &lpVoidData;
|
|
*lppvData = NULL;
|
|
}
|
|
|
|
if ( dwFlags & FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
|
|
&& !(dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS))
|
|
{
|
|
*lppvData = NULL;
|
|
}
|
|
|
|
//
|
|
// Determine what Function to handle this based on what error where given
|
|
//
|
|
|
|
BOOL fRet;
|
|
|
|
switch ( dwError )
|
|
{
|
|
case ERROR_INTERNET_NEED_UI:
|
|
fRet = HttpFiltOnBlockingOps
|
|
(lpRequest, hRequest, hWnd);
|
|
error = fRet? ERROR_SUCCESS : GetLastError();
|
|
break;
|
|
|
|
case ERROR_INTERNET_INCORRECT_PASSWORD:
|
|
error = wErrorUIInvalidPassword(hWnd,
|
|
hMappedRequestHandle,
|
|
dwError,
|
|
dwFlags,
|
|
lppvData);
|
|
|
|
break;
|
|
|
|
case ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION:
|
|
// If we are in silent mode, we will have to
|
|
// decline the cookie without throwing up a
|
|
// dialog
|
|
if((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
|
|
{
|
|
error = ERROR_HTTP_COOKIE_DECLINED;
|
|
}
|
|
else
|
|
{
|
|
COOKIE_DLG_INFO info;
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
info.dwOperation = COOKIE_OP_SET;
|
|
info.pic = (INTERNET_COOKIE*)(*lppvData);
|
|
|
|
if(info.pic->dwFlags & INTERNET_COOKIE_IS_SESSION)
|
|
{
|
|
info.dwOperation |= COOKIE_OP_SESSION;
|
|
}
|
|
|
|
error = ConfirmCookie(hWnd,
|
|
lpRequest,
|
|
&info);
|
|
|
|
}
|
|
break;
|
|
|
|
case ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION_EX:
|
|
// If we are in silent mode, we will have to
|
|
// decline the cookie without throwing up a
|
|
// dialog
|
|
if((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
|
|
{
|
|
error = ERROR_HTTP_COOKIE_DECLINED;
|
|
}
|
|
else
|
|
{
|
|
error = ConfirmCookie(hWnd,
|
|
lpRequest,
|
|
(COOKIE_DLG_INFO *)(*lppvData));
|
|
}
|
|
break;
|
|
|
|
case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED:
|
|
//
|
|
// Call the function which gets the cert context from the
|
|
// Fortezza CSP.
|
|
|
|
error = FortezzaLogOn(hWnd);
|
|
break;
|
|
|
|
case ERROR_INTERNET_SEC_CERT_REVOKED:
|
|
{
|
|
static WCHAR szMsgBoxText[128] = L"\0";
|
|
static WCHAR szCaption[64] = L"\0";
|
|
if (!szCaption[0])
|
|
{
|
|
LoadStringWrapW(GlobalDllHandle, IDS_CERT_REVOKED, szMsgBoxText, sizeof(szMsgBoxText));
|
|
LoadStringWrapW(GlobalDllHandle, IDS_SECURITY_CAPTION, szCaption, sizeof(szCaption));
|
|
}
|
|
MessageBoxWrapW(hWnd, szMsgBoxText, szCaption, MB_OK | MB_ICONWARNING);
|
|
error = ERROR_CANCELLED;
|
|
}
|
|
break;
|
|
|
|
case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
|
|
case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
|
|
|
|
//
|
|
// Read the registry, and check to make sure
|
|
// the user hasn't overriden this.
|
|
//
|
|
|
|
GlobalDataReadWarningUIFlags();
|
|
|
|
if ( ! GlobalWarnOnZoneCrossing )
|
|
break;
|
|
|
|
|
|
//
|
|
// fall through to launch dlg code.
|
|
//
|
|
|
|
goto l_launchdlg;
|
|
|
|
case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
|
|
//
|
|
// Read the registry, and check to make sure
|
|
// the user hasn't overriden this.
|
|
//
|
|
|
|
GlobalDataReadWarningUIFlags();
|
|
|
|
if ( ! GlobalWarnOnPostRedirect )
|
|
break;
|
|
|
|
|
|
//
|
|
// fall through to launch dlg code.
|
|
//
|
|
|
|
goto l_launchdlg;
|
|
|
|
case ERROR_INTERNET_POST_IS_NON_SECURE:
|
|
case ERROR_INTERNET_CHG_POST_IS_NON_SECURE:
|
|
|
|
//
|
|
// Read the registry, and check to make sure
|
|
// the user hasn't overriden this.
|
|
//
|
|
|
|
GlobalDataReadWarningUIFlags();
|
|
|
|
if ( ! GlobalWarnOnPost )
|
|
break;
|
|
|
|
//
|
|
// If we're not warning always, ie only warning
|
|
// if the user actually changed some fields, then
|
|
// bail out, and don't warn.
|
|
//
|
|
|
|
if ( ! GlobalWarnAlways &&
|
|
dwError == ERROR_INTERNET_POST_IS_NON_SECURE )
|
|
break;
|
|
|
|
//
|
|
// fall through to launch dlg code.
|
|
//
|
|
|
|
goto l_launchdlg;
|
|
|
|
case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
|
|
case ERROR_INTERNET_SEC_CERT_CN_INVALID:
|
|
case ERROR_INTERNET_MIXED_SECURITY:
|
|
case ERROR_INTERNET_INVALID_CA:
|
|
case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
|
|
case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT:
|
|
case ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT:
|
|
case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR:
|
|
case ERROR_INTERNET_INSERT_CDROM:
|
|
case ERROR_INTERNET_SEC_CERT_ERRORS:
|
|
case ERROR_INTERNET_SEC_CERT_REV_FAILED:
|
|
|
|
l_launchdlg:
|
|
// if silent flag is set, we can just pass
|
|
// ERROR_CANCELLED back without throwing up
|
|
// a dialog
|
|
if ((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
|
|
{
|
|
error = ERROR_CANCELLED;
|
|
}
|
|
else
|
|
{
|
|
ERRORINFODLGTYPE ErrorInfoDlgInfo;
|
|
DLGPROC pDlgProc;
|
|
|
|
|
|
MapWininetErrorToDlgId(
|
|
dwError,
|
|
&ErrorInfoDlgInfo.dwDlgId,
|
|
&ErrorInfoDlgInfo.dwDlgFlags,
|
|
&pDlgProc
|
|
);
|
|
|
|
|
|
INET_ASSERT(pDlgProc);
|
|
|
|
ErrorInfoDlgInfo.hInternetMapped =
|
|
hMappedRequestHandle;
|
|
if (ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED == dwError)
|
|
{
|
|
CERT_CONTEXT_ARRAY* pCertContextArray =
|
|
((HTTP_REQUEST_HANDLE_OBJECT *)hMappedRequestHandle)->GetCertContextArray();
|
|
|
|
if (pCertContextArray)
|
|
{
|
|
const DWORD c_dwArraySize = pCertContextArray->GetArraySize();
|
|
|
|
if (1 == c_dwArraySize || 0 == c_dwArraySize)
|
|
{
|
|
const BOOL fRestricted =
|
|
lpRequest->GetOpenFlags() & INTERNET_FLAG_RESTRICTED_ZONE;
|
|
const DWORD dwClientCertPromptPolicy =
|
|
::GetClientCertPromptPolicy(lpRequest->GetURL(), fRestricted);
|
|
if (dwClientCertPromptPolicy == URLPOLICY_ALLOW)
|
|
{
|
|
// If 1, select index 0, otherwise -1 if none
|
|
pCertContextArray->SelectCertContext(c_dwArraySize ? 0 : -1);
|
|
error = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
error = LaunchDlg(
|
|
hWnd,
|
|
(LPVOID) &ErrorInfoDlgInfo,
|
|
ErrorInfoDlgInfo.dwDlgId,
|
|
pDlgProc
|
|
);
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
default:
|
|
//
|
|
// if we're filtering for errors, then its not an error
|
|
// since we're intented to process all errors
|
|
//
|
|
|
|
if ( ! (dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS) )
|
|
error = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
quit:
|
|
|
|
if ( hMappedRequestHandle != NULL )
|
|
DereferenceObject((LPVOID)hMappedRequestHandle);
|
|
|
|
DEBUG_LEAVE_API(error);
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(DWORD) InternetConfirmZoneCrossingA(
|
|
IN HWND hWnd,
|
|
IN LPSTR szUrlPrev,
|
|
IN LPSTR szUrlNew,
|
|
BOOL bPost
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates an Error Dialog informing the User of a zone crossing ( going
|
|
between HTTPS to HTTP or HTTPS to HTTP ) when one is detected.
|
|
|
|
Arguments:
|
|
|
|
hWnd - Window handle to be used as the parent window of a Error Dialog.
|
|
|
|
szUrlPrev - Previous URL string.
|
|
|
|
szUrlNew - New URL string that the User is about to go to.
|
|
|
|
bPost - TRUE if a POST is being done, FALSE otherwise.
|
|
|
|
Return Value:
|
|
|
|
DWORD
|
|
Success - ERROR_SUCCESS
|
|
( user either confirmed OK to continue, or there was no
|
|
UI needed )
|
|
|
|
Failure - ERROR_CANCELLED ( user canceled, we want to stop )
|
|
ERROR_NOT_ENOUGH_MEMORY
|
|
|
|
Comments:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Dword,
|
|
"InternetConfirmZoneCrossingA",
|
|
"%#x, %q, %q, %d",
|
|
hWnd,
|
|
szUrlPrev,
|
|
szUrlNew,
|
|
bPost));
|
|
|
|
DWORD error = ERROR_SUCCESS;
|
|
INTERNET_SCHEME ustPrevScheme;
|
|
INTERNET_SCHEME ustNewScheme;
|
|
|
|
INET_ASSERT(szUrlNew);
|
|
|
|
|
|
//
|
|
// If the Previous one is NULL, then we could be starting out
|
|
// for the first time
|
|
//
|
|
|
|
if ( szUrlPrev == NULL )
|
|
goto quit;
|
|
|
|
|
|
error = CrackUrl(szUrlPrev,
|
|
lstrlen(szUrlPrev),
|
|
FALSE,
|
|
&ustPrevScheme,
|
|
NULL, // Scheme Name
|
|
NULL, // Scheme Length
|
|
NULL, // Host Name
|
|
NULL, // Host Length
|
|
NULL, // Internet Port
|
|
NULL, // UserName
|
|
NULL, // UserName Length
|
|
NULL, // Password
|
|
NULL, // Password Length
|
|
NULL, // Path
|
|
NULL, // Path Length
|
|
NULL, // Extra
|
|
NULL, // Extra Length
|
|
NULL
|
|
);
|
|
|
|
if ( error != ERROR_SUCCESS )
|
|
{
|
|
error = ERROR_SUCCESS;
|
|
ustPrevScheme = INTERNET_SCHEME_UNKNOWN;
|
|
}
|
|
|
|
|
|
error = CrackUrl(szUrlNew,
|
|
lstrlen(szUrlNew),
|
|
FALSE,
|
|
&ustNewScheme,
|
|
NULL, // Scheme Name
|
|
NULL, // Scheme Length
|
|
NULL, // Host Name
|
|
NULL, // Host Length
|
|
NULL, // Internet Port
|
|
NULL, // UserName
|
|
NULL, // UserName Length
|
|
NULL, // Password
|
|
NULL, // Password Length
|
|
NULL, // Path
|
|
NULL, // Path Length
|
|
NULL, // Extra
|
|
NULL, // Extra Length
|
|
NULL
|
|
);
|
|
|
|
if ( error != ERROR_SUCCESS )
|
|
{
|
|
error = ERROR_SUCCESS;
|
|
ustNewScheme = INTERNET_SCHEME_UNKNOWN;
|
|
}
|
|
|
|
//
|
|
// First Eliminate the obvious.
|
|
//
|
|
|
|
if ( ustPrevScheme == ustNewScheme )
|
|
goto quit;
|
|
|
|
|
|
//
|
|
// Next, if it wasn't HTTPS, and it is now
|
|
// we've caught one zone cross.
|
|
//
|
|
|
|
if ( ustPrevScheme != INTERNET_SCHEME_HTTPS &&
|
|
ustNewScheme == INTERNET_SCHEME_HTTPS )
|
|
{
|
|
error = ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR;
|
|
}
|
|
|
|
|
|
//
|
|
// Otherwise, if it was HTTPS, and it is now
|
|
// no longer HTTPS, we also flag it.
|
|
//
|
|
|
|
else if ((ustPrevScheme == INTERNET_SCHEME_HTTPS)
|
|
&& ((ustNewScheme != INTERNET_SCHEME_HTTPS)
|
|
&& (ustNewScheme != INTERNET_SCHEME_JAVASCRIPT)
|
|
&& (ustNewScheme != INTERNET_SCHEME_VBSCRIPT))) {
|
|
error = ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR;
|
|
}
|
|
|
|
|
|
if ( error != ERROR_SUCCESS &&
|
|
hWnd )
|
|
{
|
|
error = InternetErrorDlg(
|
|
hWnd,
|
|
NULL, // hRequest
|
|
error,
|
|
0,
|
|
NULL // non Data structure to pass.
|
|
);
|
|
}
|
|
|
|
quit:
|
|
DEBUG_LEAVE_API(error);
|
|
return error;
|
|
}
|
|
|
|
|
|
//
|
|
// private functions
|
|
//
|
|
|
|
|
|
PRIVATE
|
|
DWORD
|
|
wErrorUIInvalidPassword(IN HWND hWnd,
|
|
IN HINTERNET hRequest,
|
|
IN DWORD dwError,
|
|
IN DWORD dwFlags,
|
|
IN OUT LPVOID *lppvData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates an Error Dialog asking the User for his Username and Password.
|
|
|
|
Arguments:
|
|
|
|
hWnd - Window handle to be used as the parent window of a Error Dialog.
|
|
|
|
hRequest - An open HTTP request handle, that is MAPPED,
|
|
where headers will be added if needed.
|
|
|
|
dwError - The Error code to which the appropriate UI will be shown for.
|
|
|
|
dwFlags - Can be any of all of the following Flags:
|
|
|
|
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA - generates lppvData, and queries
|
|
internet handle for information.
|
|
|
|
FLAGS_ERROR_UI_FILTER_FOR_ERRORS - scans the returned headers,
|
|
and determines if there is a "hidden" error, such as an authentication
|
|
failure.
|
|
|
|
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS - On successful return of the dialog,
|
|
this flag will causes the results to be stored in the handle.
|
|
|
|
FLAGS_ERROR_UI_FLAGS_NO_UI - Don't show any User interface. Silently,
|
|
accepts the Username, and Password that is passed in.
|
|
|
|
lppvData - Contains a Pointer to a Pointer where a stucture is stored containing
|
|
error specific data, and Dialog results.
|
|
|
|
|
|
Return Value:
|
|
|
|
DWORD
|
|
Success - ERROR_SUCCESS
|
|
|
|
Failure - One of Serveral Error codes defined in winerror.h or wininet.w
|
|
|
|
Comments:
|
|
|
|
BUGBUG - need to look into multiple authentication scheme handling, and
|
|
how it relates to the UI
|
|
BUGBUG - need to handle case where one thread calls into this function,
|
|
and a second threads also calls in to put up UI on the same User-Pass Info
|
|
as the first.
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER((DBG_INET,
|
|
Dword,
|
|
"wErrorUIInvalidPassword",
|
|
"%#x, %#x, %d (%s), %#x, %#x",
|
|
hWnd,
|
|
hRequest,
|
|
dwError,
|
|
InternetMapError(dwError),
|
|
dwFlags,
|
|
lppvData
|
|
));
|
|
|
|
DWORD error = ERROR_SUCCESS;
|
|
BOOL fMustLock = FALSE;
|
|
InvalidPassType ipt;
|
|
ipt.lpszPassword = NULL;
|
|
|
|
// Get the request handle and connect handle.
|
|
HTTP_REQUEST_HANDLE_OBJECT *pRequest =
|
|
(HTTP_REQUEST_HANDLE_OBJECT *) hRequest;
|
|
INTERNET_CONNECT_HANDLE_OBJECT *pConnect =
|
|
(INTERNET_CONNECT_HANDLE_OBJECT *) pRequest->GetParent();
|
|
|
|
// Validate parameters.
|
|
if (!pConnect || (!(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) && !IsWindow(hWnd)))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
goto quit;
|
|
}
|
|
|
|
// Get the authentication context.
|
|
AUTHCTX *pAuthCtx;
|
|
pAuthCtx = pRequest->GetAuthCtx();
|
|
if (!pAuthCtx)
|
|
{
|
|
pAuthCtx = pRequest->GetTunnelAuthCtx();
|
|
if (!pAuthCtx)
|
|
{
|
|
error = ERROR_SUCCESS;
|
|
goto quit;
|
|
}
|
|
}
|
|
|
|
PWC *pwc;
|
|
pwc = pAuthCtx->_pPWC;
|
|
// INET_ASSERT (pwc && pwc->nLockCount); w/ Passport, this is no longer true
|
|
|
|
//
|
|
// Initialize InvalidPassType struct
|
|
//
|
|
|
|
if (pAuthCtx->GetSchemeType() != AUTHCTX::SCHEME_PASSPORT)
|
|
{
|
|
char szUserBuf[MAX_FIELD_LENGTH], szPassBuf[MAX_FIELD_LENGTH];
|
|
ipt.ulMaxField = MAX_FIELD_LENGTH - 1;
|
|
ipt.lpszPassword = szUserBuf;
|
|
ipt.lpszUsername = szPassBuf;
|
|
|
|
if (pAuthCtx->_pszFQDN)
|
|
{
|
|
ipt.lpszHost = (LPSTR)pAuthCtx->_pszFQDN;
|
|
}
|
|
else
|
|
{
|
|
ipt.lpszHost = pAuthCtx->_pPWC->lpszHost;
|
|
}
|
|
|
|
ipt.fIsProxy = pAuthCtx->_fIsProxy;
|
|
|
|
|
|
//
|
|
// Transfer password cache entry fields to UI structure.
|
|
//
|
|
AuthLock();
|
|
LPSTR lpszPass = pwc->GetPass();
|
|
|
|
if (pwc->lpszUser)
|
|
lstrcpyn (ipt.lpszUsername, pwc->lpszUser, MAX_FIELD_LENGTH);
|
|
else
|
|
ipt.lpszUsername[0] = 0;
|
|
if (lpszPass)
|
|
lstrcpyn (ipt.lpszPassword, lpszPass, MAX_FIELD_LENGTH);
|
|
else
|
|
ipt.lpszPassword[0] = 0;
|
|
ipt.lpszRealm = pwc->lpszRealm;
|
|
|
|
if (lpszPass)
|
|
{
|
|
SecureZeroMemory(lpszPass, strlen(lpszPass));
|
|
FREE_MEMORY(lpszPass);
|
|
}
|
|
|
|
AuthUnlock();
|
|
}
|
|
|
|
if (dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS)
|
|
{
|
|
// Queue this thread if we're already in a dialog.
|
|
INET_ASSERT (lppvData);
|
|
INTERNET_AUTH_NOTIFY_DATA *pNotify =
|
|
(INTERNET_AUTH_NOTIFY_DATA *) *lppvData;
|
|
if (IsBadReadPtr (pNotify, sizeof(*pNotify)))
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
goto quit;
|
|
}
|
|
if (AuthInDialog (pAuthCtx, pNotify, &fMustLock))
|
|
{
|
|
// The auth context maintains a context handle
|
|
// to correctly process the 'stale' subheader.
|
|
// Setting _nRetries to 0 will cause no context handle to
|
|
// be passed into the package and restart auth for this context
|
|
// from scratch. Therefore, no attempt will be made to parse the
|
|
// stale header which is the correct behavior.
|
|
if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_DIGEST)
|
|
{
|
|
((DIGEST_CTX*)pAuthCtx)->_nRetries = 0;
|
|
}
|
|
error = ERROR_INTERNET_DIALOG_PENDING;
|
|
goto quit;
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
|
|
{
|
|
// No UI - retrieve any persisted credentials.
|
|
error = InetGetCachedCredentials(pwc->lpszHost, pwc->lpszRealm,
|
|
ipt.lpszUsername, ipt.lpszPassword);
|
|
}
|
|
else // Launch the appropriate dialog.
|
|
{
|
|
if ((pAuthCtx->GetFlags() & PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI))
|
|
{
|
|
// If auth package handles its own UI, let it.
|
|
error = LaunchAuthPlugInDlg
|
|
(pRequest, pAuthCtx, hWnd, dwError, dwFlags, &ipt);
|
|
}
|
|
else
|
|
{
|
|
if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_BASIC
|
|
|| pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_DIGEST)
|
|
{
|
|
ipt.eAuthType = REALM_AUTH;
|
|
}
|
|
else if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_PASSPORT)
|
|
{
|
|
ipt.eAuthType = PASSPORT_AUTH;
|
|
}
|
|
else
|
|
{
|
|
INET_ASSERT(pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_NTLM
|
|
|| pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_KERBEROS
|
|
|| pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_NEGOTIATE);
|
|
ipt.eAuthType = NTLM_AUTH;
|
|
}
|
|
|
|
CREDINFODLGTYPE CredInfoDlgInfo;
|
|
CredInfoDlgInfo.pipt = &ipt;
|
|
CredInfoDlgInfo.pRequest = pRequest;
|
|
CredInfoDlgInfo.pAuthCtx = pAuthCtx;
|
|
|
|
if (ipt.eAuthType == REALM_AUTH)
|
|
error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, IDD_REALM_AUTH, NULL);
|
|
else if (ipt.eAuthType == PASSPORT_AUTH)
|
|
error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, 0, NULL);
|
|
else
|
|
error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, IDD_NTLM_AUTH, NULL);
|
|
}
|
|
}
|
|
|
|
// If dialog was OK, return as follows.
|
|
if (error == ERROR_SUCCESS)
|
|
{
|
|
AuthLock();
|
|
|
|
if (ipt.eAuthType == NTLM_AUTH)
|
|
{
|
|
// Update user/pass which would overwrite PWC.
|
|
pRequest->SetUserOrPass (ipt.lpszUsername, IS_USER, pAuthCtx->_fIsProxy);
|
|
pRequest->SetUserOrPass (ipt.lpszPassword, IS_PASS, pAuthCtx->_fIsProxy);
|
|
|
|
// Update PWC so related requests will be retried.
|
|
pwc->SetUser (ipt.lpszUsername);
|
|
pwc->SetPass (ipt.lpszPassword);
|
|
}
|
|
else if (pAuthCtx->GetSchemeType() != AUTHCTX::SCHEME_PASSPORT)
|
|
{
|
|
// Update user/pass which would overwrite PWC.
|
|
// Update PWC so related requests will be retried.
|
|
|
|
//if (ipt.lpszUsername[0])
|
|
{
|
|
pRequest->SetUserOrPass (ipt.lpszUsername, IS_USER, pAuthCtx->_fIsProxy);
|
|
pwc->SetUser (ipt.lpszUsername);
|
|
}
|
|
|
|
//if (ipt.lpszPassword[0])
|
|
{
|
|
pRequest->SetUserOrPass (ipt.lpszPassword, IS_PASS, pAuthCtx->_fIsProxy);
|
|
pwc->SetPass (ipt.lpszPassword);
|
|
}
|
|
|
|
}
|
|
AuthUnlock();
|
|
|
|
// Retry this request.
|
|
error = ERROR_INTERNET_FORCE_RETRY;
|
|
}
|
|
|
|
// Notify any waiting threads.
|
|
|
|
if (dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS)
|
|
{
|
|
if (fMustLock)
|
|
{
|
|
// fMustLock will have been set by AuthInDialog if this is
|
|
// a reentrant call to InternetErrorDlg by AuthNotify. If this
|
|
// is the case, acquire the lock and do not call AuthNotify.
|
|
// so that when control is returned to AuthNotify the lock will
|
|
// already be correctly acquired.
|
|
AuthLock();
|
|
}
|
|
else
|
|
{
|
|
AuthNotify (pwc, error);
|
|
}
|
|
}
|
|
|
|
quit:
|
|
|
|
if (ipt.lpszPassword)
|
|
{
|
|
SecureZeroMemory(ipt.lpszPassword, strlen(ipt.lpszPassword));
|
|
}
|
|
|
|
//
|
|
// IE30 compat: must return ERROR_SUCCESS to avoid bogus dialog.
|
|
//
|
|
if ( error == ERROR_CANCELLED )
|
|
error = ERROR_SUCCESS;
|
|
|
|
DEBUG_LEAVE(error);
|
|
return error;
|
|
}
|
|
|
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
DWORD
|
|
ConfirmCookie(
|
|
HWND hwnd,
|
|
HTTP_REQUEST_HANDLE_OBJECT *lpRequest,
|
|
COOKIE_DLG_INFO *pcdi
|
|
)
|
|
{
|
|
DWORD dw;
|
|
BYTE *buf = NULL;
|
|
|
|
//
|
|
// Get the server name
|
|
//
|
|
WCHAR wszServer[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
|
if (lpRequest)
|
|
{
|
|
DEBUG_ONLY(lpRequest->GetHostName(&dw));
|
|
INET_ASSERT(dw <= ARRAYSIZE(wszServer));
|
|
CHAR szServerTmp[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
|
lpRequest->CopyHostName(szServerTmp);
|
|
if(SHAnsiToUnicode(szServerTmp, wszServer, ARRAYSIZE(wszServer)))
|
|
pcdi->pszServer = wszServer;
|
|
}
|
|
else if(pcdi->pic)
|
|
{
|
|
if(SHAnsiToUnicode(pcdi->pic->pszDomain, wszServer, ARRAYSIZE(wszServer)))
|
|
pcdi->pszServer = wszServer;
|
|
}
|
|
|
|
/* Consult per-site decisions one more time.
|
|
By the time the prompt is being displayed, another instance
|
|
of the cookie-prompt MAY have already written a decision. */
|
|
unsigned long dwPerSiteDecision = COOKIE_STATE_UNKNOWN;
|
|
|
|
if (InternetGetPerSiteCookieDecisionW(pcdi->pszServer, &dwPerSiteDecision) &&
|
|
dwPerSiteDecision!=COOKIE_STATE_UNKNOWN)
|
|
{
|
|
if (dwPerSiteDecision==COOKIE_STATE_ACCEPT)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return ERROR_HTTP_COOKIE_DECLINED;
|
|
}
|
|
|
|
ULONG_PTR uCookie = 0;
|
|
SHActivateContext(&uCookie);
|
|
|
|
// Can typecast as long as "CookieDialogProc" only returns true or false
|
|
dw = (BOOL ) DialogBoxParamWrapW(GetModuleHandle("WININET.DLL"),
|
|
MAKEINTRESOURCEW(IDD_CONFIRM_COOKIE),
|
|
hwnd,
|
|
CookieDialogProc,
|
|
(LPARAM) pcdi);
|
|
|
|
if (uCookie)
|
|
{
|
|
SHDeactivateContext(uCookie);
|
|
}
|
|
|
|
return dw;
|
|
}
|
|
|
|
|
|
INTERNETAPI_(DWORD) InternetConfirmZoneCrossingW(
|
|
IN HWND hWnd,
|
|
IN LPWSTR szUrlPrev,
|
|
IN LPWSTR szUrlNew,
|
|
BOOL bPost
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates an Error Dialog informing the User of a zone crossing ( going
|
|
between HTTPS to HTTP or HTTPS to HTTP ) when one is detected.
|
|
|
|
Arguments:
|
|
|
|
hWnd - Window handle to be used as the parent window of a Error Dialog.
|
|
|
|
szUrlPrev - Previous URL string.
|
|
|
|
szUrlNew - New URL string that the User is about to go to.
|
|
|
|
bPost - TRUE if a POST is being done, FALSE otherwise.
|
|
|
|
Return Value:
|
|
|
|
DWORD
|
|
Success - ERROR_SUCCESS
|
|
( user either confirmed OK to continue, or there was no
|
|
UI needed )
|
|
|
|
Failure - ERROR_CANCELLED ( user canceled, we want to stop )
|
|
ERROR_NOT_ENOUGH_MEMORY
|
|
|
|
Comments:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
DEBUG_ENTER_API((DBG_API,
|
|
Dword,
|
|
"InternetConfirmZoneCrossingW",
|
|
"%wq, %wq, %d",
|
|
szUrlPrev,
|
|
szUrlNew,
|
|
bPost));
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
MEMORYPACKET mpNew, mpPrev;
|
|
|
|
if (!(szUrlPrev && szUrlNew))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
ALLOC_MB(szUrlPrev,0,mpPrev);
|
|
ALLOC_MB(szUrlNew,0,mpNew);
|
|
if (!(mpPrev.psStr && mpNew.psStr))
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
UNICODE_TO_ANSI(szUrlPrev,mpPrev);
|
|
UNICODE_TO_ANSI(szUrlNew,mpNew);
|
|
dwErr = InternetConfirmZoneCrossingA(hWnd, mpPrev.psStr, mpNew.psStr, bPost);
|
|
|
|
cleanup:
|
|
if (dwErr!=ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwErr);
|
|
DEBUG_ERROR(INET, dwErr);
|
|
}
|
|
DEBUG_LEAVE_API(dwErr);
|
|
return dwErr;
|
|
}
|