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.
1076 lines
30 KiB
1076 lines
30 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// WizardUtils.cpp
|
|
//
|
|
// Maintained By:
|
|
// David Potter (DavidP) 30-JAN-2001
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Pch.h"
|
|
#include "WizardUtils.h"
|
|
#include "Nameutil.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrCreateFQN
|
|
//
|
|
// Description:
|
|
// Validate a label (or IP address) and domain by creating an FQN from
|
|
// them, prompting the user to choose whether to accept any non-RFC
|
|
// characters present.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
// Parent window for user prompts.
|
|
//
|
|
// pcwszLabelIn
|
|
// The label (or IP address) of the FQN.
|
|
//
|
|
// pcwszDomainIn
|
|
// The domain of the FQN.
|
|
//
|
|
// pfnLabelValidatorIn
|
|
// Pointer to a function that determines whether the label is valid.
|
|
//
|
|
// pbstrFQNOut
|
|
// Upon success, the created FQN.
|
|
//
|
|
// pefeoOut
|
|
// Upon failure, indicates whether the problem arose from the label,
|
|
// the domain, or a system call (such as allocating memory).
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// The label and domain are valid, and *pbstrFQNOut is a BSTR that
|
|
// contains the resulting FQN; the caller must free *pbstrFQNOut with
|
|
// SysFreeString.
|
|
//
|
|
// Failure
|
|
// pefeoOut provides additional information regarding the source of
|
|
// the failure.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// This function enforces the UI policy of prohibiting users from
|
|
// entering FQDNs for machine names; the label must be only a label.
|
|
//
|
|
// pefeoOut lets the caller take further action (such as setting the
|
|
// focus on a control) according to the source of an error.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrCreateFQN(
|
|
HWND hwndParentIn
|
|
, LPCWSTR pcwszLabelIn
|
|
, LPCWSTR pcwszDomainIn
|
|
, PFN_LABEL_VALIDATOR pfnLabelValidatorIn
|
|
, BSTR * pbstrFQNOut
|
|
, EFQNErrorOrigin * pefeoOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
bool fTryAgain = true;
|
|
bool fAcceptNonRFCLabel = false;
|
|
bool fAcceptNonRFCDomain = false;
|
|
|
|
EFQNErrorOrigin efeo = feoSYSTEM;
|
|
|
|
Assert( pcwszLabelIn != NULL );
|
|
// pcwszDomainIn can be null, which means to use local machine's domain.
|
|
Assert( pfnLabelValidatorIn != NULL );
|
|
Assert( pbstrFQNOut != NULL );
|
|
Assert( *pbstrFQNOut == NULL );
|
|
// pefeoOut can be null, which means the caller doesn't care about the source of failure.
|
|
|
|
// Disallow FQDNs for the label, and allow IP addresses.
|
|
hr = THR( ( *pfnLabelValidatorIn )( pcwszLabelIn, true ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
efeo = feoLABEL;
|
|
THR( HrShowInvalidLabelPrompt( hwndParentIn, pcwszLabelIn, hr, &fAcceptNonRFCLabel ) );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Make the FQN, trying first without RFC chars, and again if it makes a difference.
|
|
//
|
|
while ( fTryAgain )
|
|
{
|
|
hr = THR( HrMakeFQN( pcwszLabelIn, pcwszDomainIn, fAcceptNonRFCLabel || fAcceptNonRFCDomain, pbstrFQNOut, &efeo ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
if ( efeo == feoLABEL )
|
|
{
|
|
HRESULT hrPrompt = S_OK;
|
|
hrPrompt = THR( HrShowInvalidLabelPrompt( hwndParentIn, pcwszLabelIn, hr, &fAcceptNonRFCLabel ) );
|
|
if ( FAILED( hrPrompt ) )
|
|
{
|
|
goto Error;
|
|
}
|
|
fTryAgain = fAcceptNonRFCLabel;
|
|
}
|
|
else if ( efeo == feoDOMAIN )
|
|
{
|
|
HRESULT hrPrompt = S_OK;
|
|
hrPrompt = THR( HrShowInvalidDomainPrompt( hwndParentIn, pcwszDomainIn, hr, &fAcceptNonRFCDomain ) );
|
|
if ( FAILED( hrPrompt ) )
|
|
{
|
|
goto Error;
|
|
}
|
|
fTryAgain = fAcceptNonRFCDomain;
|
|
}
|
|
else // efeo is neither feoLABEL nor feoDOMAIN
|
|
{
|
|
THR( HrMessageBoxWithStatus(
|
|
hwndParentIn
|
|
, IDS_ERR_FQN_CREATE_TITLE
|
|
, IDS_ERR_FQN_CREATE_TEXT
|
|
, hr
|
|
, 0
|
|
, MB_OK | MB_ICONSTOP
|
|
, NULL
|
|
, pcwszLabelIn
|
|
, pcwszDomainIn
|
|
) );
|
|
fTryAgain = false;
|
|
}
|
|
}
|
|
else // FQN creation succeeded, so trying again is not necessary.
|
|
{
|
|
fTryAgain = false;
|
|
}
|
|
} // Loop to attempt FQN creation.
|
|
goto Cleanup;
|
|
|
|
Error:
|
|
|
|
if ( pefeoOut != NULL )
|
|
{
|
|
*pefeoOut = efeo;
|
|
}
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrCreateFQN
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrShowInvalidLabelPrompt
|
|
//
|
|
// Description:
|
|
// Show a message box to the user indicating a problem with the given
|
|
// label; if the label contains non-RFC characters, allow the user to
|
|
// choose to proceed with the label.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
// Parent window for the message box.
|
|
//
|
|
// pcwszLabelIn
|
|
// The label of interest.
|
|
//
|
|
// hrErrorIn
|
|
// The error that arose when validating the label.
|
|
//
|
|
// pfAcceptedNonRFCOut
|
|
// The user chose to accept non-RFC characters.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// The message box displayed successfully, and if the error was that
|
|
// the label contained non-RFC characters, *pfAcceptedNonRFCOut
|
|
// indicates whether the user chose to accept them.
|
|
//
|
|
// Failure
|
|
// The message box did not display successfully.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrShowInvalidLabelPrompt(
|
|
HWND hwndParentIn
|
|
, LPCWSTR pcwszLabelIn
|
|
, HRESULT hrErrorIn
|
|
, bool * pfAcceptedNonRFCOut
|
|
)
|
|
{
|
|
TraceFunc1( "pcwszLabelIn = '%1!ws!", pcwszLabelIn );
|
|
|
|
HRESULT hr = S_OK;
|
|
int iRet = IDNO;
|
|
UINT idsStatus = 0;
|
|
UINT idsSubStatus = 0;
|
|
UINT idsMsgTitle = IDS_ERR_VALIDATING_NAME_TITLE;
|
|
UINT idsMsgText = IDS_ERR_VALIDATING_NAME_TEXT;
|
|
UINT nMsgBoxType = MB_OK | MB_ICONSTOP;
|
|
|
|
Assert( pcwszLabelIn != NULL );
|
|
// pfAcceptedNonRFCOut can be NULL, which means the caller doesn't expect
|
|
// or care about the non-RFC case.
|
|
Assert( FAILED( hrErrorIn ) );
|
|
|
|
if ( pfAcceptedNonRFCOut != NULL )
|
|
{
|
|
*pfAcceptedNonRFCOut = false;
|
|
}
|
|
|
|
// Format the error message string for the message box.
|
|
switch ( hrErrorIn )
|
|
{
|
|
case HRESULT_FROM_WIN32( ERROR_NOT_FOUND ):
|
|
idsStatus = IDS_ERR_INVALID_DNS_NAME_TEXT;
|
|
idsSubStatus = IDS_ERR_DNS_HOSTNAME_LABEL_EMPTY_TEXT;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( ERROR_DS_NAME_TOO_LONG ):
|
|
idsStatus = IDS_ERR_DNS_HOSTNAME_LABEL_NO_NETBIOS;
|
|
idsSubStatus = IDS_ERR_DNS_HOSTNAME_LABEL_LONG_TEXT;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( DNS_ERROR_NON_RFC_NAME ):
|
|
idsStatus = IDS_ERR_NON_RFC_NAME_STATUS;
|
|
idsSubStatus = IDS_ERR_NON_RFC_NAME_QUERY;
|
|
idsMsgTitle = IDS_ERR_NON_RFC_NAME_TITLE;
|
|
idsMsgText = IDS_ERR_NON_RFC_NAME_TEXT;
|
|
nMsgBoxType = MB_YESNO | MB_ICONQUESTION;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( DNS_ERROR_INVALID_NAME_CHAR ):
|
|
default:
|
|
idsStatus = 0;
|
|
idsSubStatus = IDS_ERR_DNS_HOSTNAME_INVALID_CHAR;
|
|
break;
|
|
}// end switch ( hrErrorIn )
|
|
|
|
// Display the error message box.
|
|
if ( idsStatus == 0 )
|
|
{
|
|
hr = THR( HrMessageBoxWithStatus(
|
|
hwndParentIn
|
|
, idsMsgTitle
|
|
, idsMsgText
|
|
, hrErrorIn
|
|
, idsSubStatus
|
|
, nMsgBoxType
|
|
, &iRet
|
|
, pcwszLabelIn
|
|
) );
|
|
} // end if ( idsStatus == 0 )
|
|
else // idsStatus != 0
|
|
{
|
|
hr = THR( HrMessageBoxWithStatusString(
|
|
hwndParentIn
|
|
, idsMsgTitle
|
|
, idsMsgText
|
|
, idsStatus
|
|
, idsSubStatus
|
|
, nMsgBoxType
|
|
, &iRet
|
|
, pcwszLabelIn
|
|
) );
|
|
} // end idsStatus != 0
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( ( iRet == IDYES ) && ( pfAcceptedNonRFCOut != NULL ) )
|
|
{
|
|
*pfAcceptedNonRFCOut = true;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrShowInvalidLabelPrompt
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrShowInvalidDomainPrompt
|
|
//
|
|
// Description:
|
|
// Show a message box to the user indicating a problem with the given
|
|
// domain; if the domain contains non-RFC characters, allow the user to
|
|
// choose to proceed with the domain.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
// Parent window for the message box.
|
|
//
|
|
// pcwszDomainIn
|
|
// The domain of interest.
|
|
//
|
|
// hrErrorIn
|
|
// The error that arose when validating the domain.
|
|
//
|
|
// pfAcceptedNonRFCOut
|
|
// The user chose to accept non-RFC characters.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// The message box displayed successfully, and if the error was that
|
|
// the domain contained non-RFC characters, *pfAcceptedNonRFCOut
|
|
// indicates whether the user chose to accept them.
|
|
//
|
|
// Failure
|
|
// The message box did not display successfully.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrShowInvalidDomainPrompt(
|
|
HWND hwndParentIn
|
|
, LPCWSTR pcwszDomainIn
|
|
, HRESULT hrErrorIn
|
|
, bool * pfAcceptedNonRFCOut
|
|
)
|
|
{
|
|
TraceFunc1( "pcwszDomainIn = '%1!ws!", pcwszDomainIn );
|
|
|
|
HRESULT hr = S_OK;
|
|
int iRet = IDNO;
|
|
UINT idsStatus = 0;
|
|
UINT idsSubStatus = 0;
|
|
UINT idsMsgTitle = IDS_ERR_VALIDATING_NAME_TITLE;
|
|
UINT idsMsgText = IDS_ERR_VALIDATING_NAME_TEXT;
|
|
UINT nMsgBoxType = MB_OK | MB_ICONSTOP;
|
|
|
|
Assert( pcwszDomainIn != NULL );
|
|
Assert( pfAcceptedNonRFCOut != NULL );
|
|
Assert( FAILED( hrErrorIn ) );
|
|
|
|
*pfAcceptedNonRFCOut = false;
|
|
|
|
// Format the error message string for the message box.
|
|
switch ( hrErrorIn )
|
|
{
|
|
case HRESULT_FROM_WIN32( ERROR_INVALID_NAME ):
|
|
idsStatus = IDS_ERR_INVALID_DNS_NAME_TEXT;
|
|
idsSubStatus = IDS_ERR_FULL_DNS_NAME_INFO_TEXT;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( DNS_ERROR_NON_RFC_NAME ):
|
|
idsStatus = IDS_ERR_NON_RFC_NAME_STATUS;
|
|
idsSubStatus = IDS_ERR_NON_RFC_NAME_QUERY;
|
|
idsMsgTitle = IDS_ERR_NON_RFC_NAME_TITLE;
|
|
idsMsgText = IDS_ERR_NON_RFC_NAME_TEXT;
|
|
nMsgBoxType = MB_YESNO | MB_ICONQUESTION;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( DNS_ERROR_NUMERIC_NAME ):
|
|
idsStatus = IDS_ERR_INVALID_DNS_NAME_TEXT;
|
|
idsSubStatus = IDS_ERR_FULL_DNS_NAME_NUMERIC;
|
|
break;
|
|
|
|
case HRESULT_FROM_WIN32( DNS_ERROR_INVALID_NAME_CHAR ):
|
|
default:
|
|
idsStatus = 0;
|
|
idsSubStatus = IDS_ERR_DNS_NAME_INVALID_CHAR;
|
|
break;
|
|
}// end switch ( hrErrorIn )
|
|
|
|
// Display the error message box.
|
|
if ( idsStatus == 0 )
|
|
{
|
|
hr = THR( HrMessageBoxWithStatus(
|
|
hwndParentIn
|
|
, idsMsgTitle
|
|
, idsMsgText
|
|
, hrErrorIn
|
|
, idsSubStatus
|
|
, nMsgBoxType
|
|
, &iRet
|
|
, pcwszDomainIn
|
|
) );
|
|
} // end if ( idsStatus == 0 )
|
|
else // idsStatus != 0
|
|
{
|
|
hr = THR( HrMessageBoxWithStatusString(
|
|
hwndParentIn
|
|
, idsMsgTitle
|
|
, idsMsgText
|
|
, idsStatus
|
|
, idsSubStatus
|
|
, nMsgBoxType
|
|
, &iRet
|
|
, pcwszDomainIn
|
|
) );
|
|
} // end idsStatus != 0
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( iRet == IDYES )
|
|
{
|
|
*pfAcceptedNonRFCOut = true;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrShowInvalidDomainPrompt
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrMessageBoxWithStatus
|
|
//
|
|
// Description:
|
|
// Display an error message box.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
// idsTitleIn
|
|
// idsOperationIn
|
|
// hrStatusIn
|
|
// idsSubStatusIn
|
|
// uTypeIn
|
|
// pidReturnOut -- IDABORT on error or any return value from MessageBox()
|
|
// ...
|
|
//
|
|
// Return Values:
|
|
// Any return values from the MessageBox() Win32 API.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrMessageBoxWithStatus(
|
|
HWND hwndParentIn
|
|
, UINT idsTitleIn
|
|
, UINT idsOperationIn
|
|
, HRESULT hrStatusIn
|
|
, UINT idsSubStatusIn
|
|
, UINT uTypeIn
|
|
, int * pidReturnOut
|
|
, ...
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
int idReturn = IDABORT; // Default in case of error.
|
|
BSTR bstrTitle = NULL;
|
|
BSTR bstrOperation = NULL;
|
|
BSTR bstrStatus = NULL;
|
|
BSTR bstrSubStatus = NULL;
|
|
BSTR bstrFullText = NULL;
|
|
va_list valist;
|
|
|
|
va_start( valist, pidReturnOut );
|
|
|
|
// Load the title string if one is specified.
|
|
if ( idsTitleIn != 0 )
|
|
{
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsTitleIn, &bstrTitle ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Load the text string.
|
|
hr = THR( HrFormatStringWithVAListIntoBSTR( g_hInstance, idsOperationIn, &bstrOperation, valist ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Format the status.
|
|
hr = THR( HrFormatErrorIntoBSTR( hrStatusIn, &bstrStatus ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Load the substatus string if specified.
|
|
if ( idsSubStatusIn != 0 )
|
|
{
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsSubStatusIn, &bstrSubStatus ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Format all the strings into a single string.
|
|
if ( bstrSubStatus == NULL )
|
|
{
|
|
hr = THR( HrFormatStringIntoBSTR(
|
|
L"%1!ws!\n\n%2!ws!"
|
|
, &bstrFullText
|
|
, bstrOperation
|
|
, bstrStatus
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
hr = THR( HrFormatStringIntoBSTR(
|
|
L"%1!ws!\n\n%2!ws!\n\n%3!ws!"
|
|
, &bstrFullText
|
|
, bstrOperation
|
|
, bstrStatus
|
|
, bstrSubStatus
|
|
) );
|
|
}
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Display the status.
|
|
idReturn = MessageBox( hwndParentIn, bstrFullText, bstrTitle, uTypeIn );
|
|
|
|
Cleanup:
|
|
TraceSysFreeString( bstrTitle );
|
|
TraceSysFreeString( bstrOperation );
|
|
TraceSysFreeString( bstrStatus );
|
|
TraceSysFreeString( bstrSubStatus );
|
|
TraceSysFreeString( bstrFullText );
|
|
va_end( valist );
|
|
|
|
if ( pidReturnOut != NULL )
|
|
{
|
|
*pidReturnOut = idReturn;
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrMessageBoxWithStatus( hrStatusIn )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrMessageBoxWithStatusString
|
|
//
|
|
// Description:
|
|
// Display an error message box.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
// idsTitleIn
|
|
// idsOperationIn
|
|
// idsStatusIn
|
|
// idsSubStatusIn
|
|
// uTypeIn
|
|
// pidReturnOut -- IDABORT on error or any return value from MessageBox()
|
|
// ...
|
|
//
|
|
// Return Values:
|
|
// Any return values from the MessageBox() Win32 API.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrMessageBoxWithStatusString(
|
|
HWND hwndParentIn
|
|
, UINT idsTitleIn
|
|
, UINT idsOperationIn
|
|
, UINT idsStatusIn
|
|
, UINT idsSubStatusIn
|
|
, UINT uTypeIn
|
|
, int * pidReturnOut
|
|
, ...
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
int idReturn = IDABORT; // Default in case of error.
|
|
BSTR bstrTitle = NULL;
|
|
BSTR bstrOperation = NULL;
|
|
BSTR bstrStatus = NULL;
|
|
BSTR bstrSubStatus = NULL;
|
|
BSTR bstrFullText = NULL;
|
|
va_list valist;
|
|
|
|
va_start( valist, pidReturnOut );
|
|
|
|
// Load the title string if one is specified.
|
|
if ( idsTitleIn != 0 )
|
|
{
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsTitleIn, &bstrTitle ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Load the text string.
|
|
hr = THR( HrFormatStringWithVAListIntoBSTR( g_hInstance, idsOperationIn, &bstrOperation, valist ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Format the status.
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsStatusIn, &bstrStatus ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Load the substatus string if specified.
|
|
if ( idsSubStatusIn != 0 )
|
|
{
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance, idsSubStatusIn, &bstrSubStatus ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Format all the strings into a single string.
|
|
if ( bstrSubStatus == NULL )
|
|
{
|
|
hr = THR( HrFormatStringIntoBSTR(
|
|
L"%1!ws!\n\n%2!ws!"
|
|
, &bstrFullText
|
|
, bstrOperation
|
|
, bstrStatus
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
hr = THR( HrFormatStringIntoBSTR(
|
|
L"%1!ws!\n\n%2!ws!\n\n%3!ws!"
|
|
, &bstrFullText
|
|
, bstrOperation
|
|
, bstrStatus
|
|
, bstrSubStatus
|
|
) );
|
|
}
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Display the status.
|
|
idReturn = MessageBox( hwndParentIn, bstrFullText, bstrTitle, uTypeIn );
|
|
|
|
Cleanup:
|
|
TraceSysFreeString( bstrTitle );
|
|
TraceSysFreeString( bstrOperation );
|
|
TraceSysFreeString( bstrStatus );
|
|
TraceSysFreeString( bstrSubStatus );
|
|
TraceSysFreeString( bstrFullText );
|
|
va_end( valist );
|
|
|
|
if ( pidReturnOut != NULL )
|
|
{
|
|
*pidReturnOut = idReturn;
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrMessageBoxWithStatusString( idsStatusTextIn )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrViewLogFile
|
|
//
|
|
// Description:
|
|
// View the log file.
|
|
//
|
|
// Arguments:
|
|
// hwndParentIn
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully
|
|
// Other HRESULT values from ShellExecute().
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrViewLogFile(
|
|
HWND hwndParentIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
static const WCHAR s_szVerb[] = L"open";
|
|
static LPCTSTR s_pszLogFileName = PszLogFilePath();
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD sc;
|
|
DWORD cch;
|
|
DWORD cchRet;
|
|
LPWSTR pszFile = NULL;
|
|
|
|
//
|
|
// Expand environment variables in the file to open.
|
|
//
|
|
|
|
// Get the size of the output buffer.
|
|
cch = 0;
|
|
cchRet = ExpandEnvironmentStrings( s_pszLogFileName, NULL, cch );
|
|
if ( cchRet == 0 )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
goto Win32Error;
|
|
} // if: error getting length of the expansion string
|
|
|
|
// Allocate the output buffer.
|
|
cch = cchRet;
|
|
pszFile = new WCHAR[ cch ];
|
|
if ( pszFile == NULL )
|
|
{
|
|
sc = TW32( ERROR_OUTOFMEMORY );
|
|
goto Win32Error;
|
|
}
|
|
|
|
// Expand the string into the output buffer.
|
|
cchRet = ExpandEnvironmentStrings( s_pszLogFileName, pszFile, cch );
|
|
if ( cchRet == 0 )
|
|
{
|
|
sc = TW32( GetLastError() );
|
|
goto Win32Error;
|
|
}
|
|
Assert( cchRet == cch );
|
|
|
|
//
|
|
// Execute the file.
|
|
//
|
|
|
|
sc = HandleToULong( ShellExecute(
|
|
hwndParentIn // hwnd
|
|
, s_szVerb // lpVerb
|
|
, pszFile // lpFile
|
|
, NULL // lpParameters
|
|
, NULL // lpDirectory
|
|
, SW_SHOWNORMAL // nShowCommand
|
|
) );
|
|
if ( sc < 32 )
|
|
{
|
|
// Values less than 32 indicate an error occurred.
|
|
TW32( sc );
|
|
goto Win32Error;
|
|
} // if: error executing the file
|
|
|
|
goto Cleanup;
|
|
|
|
Win32Error:
|
|
|
|
THR( HrMessageBoxWithStatus(
|
|
hwndParentIn
|
|
, IDS_ERR_VIEW_LOG_TITLE
|
|
, IDS_ERR_VIEW_LOG_TEXT
|
|
, sc
|
|
, 0 // idsSubStatusIn
|
|
, ( MB_OK
|
|
| MB_ICONEXCLAMATION )
|
|
, NULL // pidReturnOut
|
|
, s_pszLogFileName
|
|
) );
|
|
hr = HRESULT_FROM_WIN32( sc );
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
|
|
delete [] pszFile;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** HrViewLogFile()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrGetTrimmedText
|
|
//
|
|
// Description:
|
|
// Extract a control's text, if any, with leading and trailing spaces
|
|
// removed.
|
|
//
|
|
// Arguments:
|
|
// hwndControlIn - The control.
|
|
// pbstrTrimmedTextOut - On success, the trimmed text.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// *pbstrTrimmedTextOut points to the trimmed text and the caller
|
|
// must free it.
|
|
//
|
|
// S_FALSE
|
|
// Either the control is empty or it contains only spaces, and
|
|
// *pbstrTrimmedTextOut is null.
|
|
//
|
|
// E_POINTER
|
|
// pbstrTrimmedTextOut was null.
|
|
//
|
|
// E_OUTOFMEMORY
|
|
// Couldn't allocate memory for *pbstrTrimmedTextOut.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrGetTrimmedText(
|
|
HWND hwndControlIn
|
|
, BSTR* pbstrTrimmedTextOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD cchControlText = 0;
|
|
LPWSTR wszUntrimmedText = NULL;
|
|
|
|
Assert( pbstrTrimmedTextOut != NULL );
|
|
if ( pbstrTrimmedTextOut == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
}
|
|
*pbstrTrimmedTextOut = NULL;
|
|
|
|
cchControlText = GetWindowTextLength( hwndControlIn );
|
|
if ( cchControlText == 0 )
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
wszUntrimmedText = new WCHAR[ cchControlText + 1 ];
|
|
if ( wszUntrimmedText == NULL )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
}
|
|
|
|
cchControlText = GetWindowText( hwndControlIn, wszUntrimmedText, cchControlText + 1 );
|
|
if ( cchControlText == 0 )
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
{
|
|
DWORD idxNonBlankStart = 0;
|
|
DWORD idxNonBlankEnd = cchControlText - 1;
|
|
while ( ( idxNonBlankStart < cchControlText ) && ( wszUntrimmedText[ idxNonBlankStart ] == L' ' ) )
|
|
{
|
|
idxNonBlankStart += 1;
|
|
}
|
|
|
|
while ( ( idxNonBlankEnd > idxNonBlankStart ) && ( wszUntrimmedText[ idxNonBlankEnd ] == L' ' ) )
|
|
{
|
|
idxNonBlankEnd -= 1;
|
|
}
|
|
|
|
if ( idxNonBlankStart <= idxNonBlankEnd )
|
|
{
|
|
DWORD cchTrimmedText = idxNonBlankEnd - idxNonBlankStart + 1;
|
|
*pbstrTrimmedTextOut = TraceSysAllocStringLen( wszUntrimmedText + idxNonBlankStart, cchTrimmedText );
|
|
if ( *pbstrTrimmedTextOut == NULL )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( wszUntrimmedText != NULL )
|
|
{
|
|
delete [] wszUntrimmedText;
|
|
}
|
|
|
|
HRETURN( hr );
|
|
} //*** HrGetTrimmedText
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// HrGetPrincipalName
|
|
//
|
|
// Description:
|
|
// Form a user-domain pair from a given pair of controls, ignoring the
|
|
// second control and using the domain from the first if the first has
|
|
// a string in the user@domain format.
|
|
//
|
|
// Arguments:
|
|
// hwndUserNameControlIn
|
|
// The control for either the user name or the user@domain pair.
|
|
//
|
|
// hwndDomainControlIn
|
|
// The control for the domain name in the non-user@domain case.
|
|
//
|
|
// pbstrUserNameOut
|
|
// On success, the user name.
|
|
//
|
|
// pbstrDomainNameOut
|
|
// On success, the domain name.
|
|
//
|
|
// pfUserIsDNSNameOut
|
|
// Tells the caller whether hwndUserNameControlIn has text in the
|
|
// user@domain format. Can be null if the caller doesn't care.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// *pbstrUserNameOut and *pbstrDomainNameOut point to the
|
|
// corresponding names, and the caller must free them.
|
|
//
|
|
// S_FALSE
|
|
// Either the user control is empty, or it does not have a user@domain
|
|
// pair and the domain control is empty.
|
|
// The two BSTR out parameters are null.
|
|
//
|
|
// E_POINTER
|
|
// pbstrUserNameOut or pbstrDomainNameOut was null.
|
|
//
|
|
// E_OUTOFMEMORY
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
HrGetPrincipalName(
|
|
HWND hwndUserNameControlIn
|
|
, HWND hwndDomainControlIn
|
|
, BSTR* pbstrUserNameOut
|
|
, BSTR* pbstrDomainNameOut
|
|
, BOOL* pfUserIsDNSNameOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrFullUserText = NULL;
|
|
BSTR bstrUserName = NULL;
|
|
BSTR bstrDomainName = NULL;
|
|
BOOL fUserIsDNSName = FALSE;
|
|
LPWSTR wszDNSDelimiter = NULL;
|
|
|
|
Assert( pbstrUserNameOut != NULL );
|
|
if ( pbstrUserNameOut == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
}
|
|
*pbstrUserNameOut = NULL;
|
|
|
|
Assert( pbstrDomainNameOut != NULL );
|
|
if ( pbstrDomainNameOut == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
}
|
|
*pbstrDomainNameOut = NULL;
|
|
|
|
// pfUserIsDNSNameOut can be null, which means the caller doesn't care.
|
|
|
|
// Get text from user control.
|
|
hr = STHR( HrGetTrimmedText( hwndUserNameControlIn, &bstrFullUserText ) );
|
|
if ( hr != S_OK )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// If the user text has an @ sign,
|
|
wszDNSDelimiter = wcschr( bstrFullUserText, L'@' );
|
|
if ( wszDNSDelimiter != NULL )
|
|
{
|
|
// Split user text into user name and domain name.
|
|
DWORD cchUserName = (DWORD)( wszDNSDelimiter - bstrFullUserText );
|
|
DWORD cchDomainName = SysStringLen( bstrFullUserText ) - cchUserName - 1; // -1 to account for the @ sign.
|
|
LPWSTR wszDomainStart = wszDNSDelimiter + 1; // +1 to skip the @ sign.
|
|
fUserIsDNSName = TRUE;
|
|
|
|
// If either user or domain are empty, bail out.
|
|
if ( ( cchUserName == 0 ) || ( cchDomainName == 0 ) )
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
bstrUserName = TraceSysAllocStringLen( bstrFullUserText, cchUserName );
|
|
if ( bstrUserName == NULL )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
}
|
|
|
|
bstrDomainName = TraceSysAllocString( wszDomainStart );
|
|
if ( bstrDomainName == NULL )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Cleanup;
|
|
}
|
|
} // if: the user text has an @ sign.
|
|
else
|
|
{
|
|
// Set user name to full user control text.
|
|
bstrUserName = bstrFullUserText;
|
|
bstrFullUserText = NULL;
|
|
|
|
// Get domain name from domain control.
|
|
hr = STHR( HrGetTrimmedText( hwndDomainControlIn, &bstrDomainName ) );
|
|
if ( hr != S_OK )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Transfer ownership of the strings to the caller.
|
|
*pbstrUserNameOut = bstrUserName;
|
|
bstrUserName = NULL;
|
|
|
|
*pbstrDomainNameOut = bstrDomainName;
|
|
bstrDomainName = NULL;
|
|
|
|
Cleanup:
|
|
|
|
if ( pfUserIsDNSNameOut != NULL )
|
|
{
|
|
*pfUserIsDNSNameOut = fUserIsDNSName;
|
|
}
|
|
|
|
TraceSysFreeString( bstrFullUserText );
|
|
TraceSysFreeString( bstrUserName );
|
|
TraceSysFreeString( bstrDomainName );
|
|
|
|
HRETURN( hr );
|
|
} //*** HrGetPrincipalName
|
|
|