Leaked source code of windows server 2003
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

//////////////////////////////////////////////////////////////////////////////
//
// 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