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