////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2002 Microsoft Corporation // // Module Name: // LoadStringSrc.cpp // // Description: // LoadStringIntoBSTR implementation. // // Maintained By: // David Potter (DavidP) 01-FEB-2001 // Geoffrey Pease (GPease) 22-MAY-2000 // ////////////////////////////////////////////////////////////////////////////// // #include // should be included by includer of this file #include // in case it isn't included by header file ////////////////////////////////////////////////////////////////////////////// // Global Variables ////////////////////////////////////////////////////////////////////////////// const WCHAR g_szWbemClientDLL[] = L"\\WBEM\\WMIUTILS.DLL"; ////////////////////////////////////////////////////////////////////////////// //++ // // HrLoadStringIntoBSTR // // Description: // Retrieves the string resource idsIn from the string table and makes it // into a BSTR. If the BSTR is not NULL coming it, it will assume that // you are trying reuse an existing BSTR. // // Arguments: // hInstanceIn // Handle to an instance of the module whose executable file // contains the string resource. If not specified, defaults to // g_hInstance. // // langidIn // Language ID of string table resource. // // idsIn // Specifies the integer identifier of the string to be loaded. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // Other HRESULTs // The call failed. // // Remarks: // This routine uses LoadResource so that it can get the actual length // of the string resource. If we didn't do this, we would need to call // LoadString and allocate memory in a loop. Very inefficient! // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrLoadStringIntoBSTR( HINSTANCE hInstanceIn , LANGID langidIn , UINT idsIn , BSTR * pbstrInout ) { TraceFunc1( "idsIn = %d", idsIn ); HRESULT hr = S_OK; HRSRC hrsrc = NULL; HGLOBAL hgbl = NULL; int cch = 0; PBYTE pbStringData; PBYTE pbStringDataMax; PBYTE pbStringTable; int cbStringTable; int nTable; int nOffset; int idxString; Assert( idsIn != 0 ); Assert( pbstrInout != NULL ); if ( pbstrInout == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } if ( hInstanceIn == NULL ) { hInstanceIn = g_hInstance; } // The resource Id specified must be converted to an index into // a Windows StringTable. nTable = idsIn / 16; nOffset = idsIn - (nTable * 16); // Internal Table Id's start at 1 not 0. nTable++; // // Find the part of the string table where the string resides. // // Find the table containing the string. // First try to load the language specified. If we can't find it we // try the "neutral" language. hrsrc = FindResourceEx( hInstanceIn, RT_STRING, MAKEINTRESOURCE( nTable ), langidIn ); if ( ( hrsrc == NULL ) && ( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND ) ) { hrsrc = FindResourceEx( hInstanceIn , RT_STRING , MAKEINTRESOURCE( nTable ) , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); } if ( hrsrc == NULL ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } // Load the table. hgbl = LoadResource( hInstanceIn, hrsrc ); if ( hgbl == NULL ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } // Lock the table so we access its data. pbStringTable = reinterpret_cast< PBYTE >( LockResource( hgbl ) ); if ( pbStringTable == NULL ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } cbStringTable = SizeofResource( hInstanceIn, hrsrc ); Assert( cbStringTable != 0 ); TraceFlow3( "HrLoadStringIntoBSTR() - Table = %#.08x, cb = %d, offset = %d", pbStringTable, cbStringTable, nOffset ); // Set the data pointer to the beginning of the table. pbStringData = pbStringTable; pbStringDataMax = pbStringTable + cbStringTable; // // Skip strings in the block of 16 which are before the desired string. // for ( idxString = 0 ; idxString <= nOffset ; idxString++ ) { Assert( pbStringData != NULL ); Assert( pbStringData < pbStringDataMax ); // Get the number of characters excluding the '\0'. cch = * ( (USHORT *) pbStringData ); TraceFlow3( "HrLoadStringIntoBSTR() - pbStringData[ %d ] = %#.08x, cch = %d", idxString, pbStringData, cch ); // Found the string. if ( idxString == nOffset ) { if ( cch == 0 ) { hr = HRESULT_FROM_WIN32( TW32( ERROR_RESOURCE_NAME_NOT_FOUND ) ); goto Cleanup; } // Skip over the string length to get the string. pbStringData += sizeof( WCHAR ); break; } // if: found the string // Add one to account for the string length. // A string length of 0 still takes 1 WCHAR for the length portion. cch++; // Skip over this string to get to the next string. pbStringData += ( cch * sizeof( WCHAR ) ); } // for: each string in the block of 16 strings in the table // Note: nStringLen is the number of characters in the string not including the '\0'. AssertMsg( cch > 0, "Length of string in resource file cannot be zero." ); // // If previously allocated free it before re-allocating it. // if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: string was allocated previously // // Allocate a BSTR for the string. // *pbstrInout = TraceSysAllocStringLen( (OLECHAR *) pbStringData, cch ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: TraceFlow1( "HrLoadStringIntoBSTR() - Loaded string = '%ws'", *pbstrInout ); Cleanup: HRETURN( hr ); } //*** HrLoadStringIntoBSTR( langidIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatStringIntoBSTR // // Description: // Format a string (specified by idsIn, a string resource ID) and // variable arguments into a BSTR using the FormatMessage() Win32 API. // If the BSTR is not NULL on entry, the BSTR will be reused. // // Calls HrFormatStringWithVAListIntoBSTR to perform the actual work. // // Arguments: // hInstanceIn // Handle to an instance of the module whose executable file // contains the string resource. // // langidIn // Language ID of string table resource. // // idsIn // Specifies the integer identifier of the string to be loaded. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // ... // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatStringIntoBSTR( HINSTANCE hInstanceIn , LANGID langidIn , UINT idsIn , BSTR * pbstrInout , ... ) { TraceFunc1( "ids = %d", idsIn ); HRESULT hr; va_list valist; va_start( valist, pbstrInout ); hr = HrFormatStringWithVAListIntoBSTR( hInstanceIn , langidIn , idsIn , pbstrInout , valist ); va_end( valist ); HRETURN( hr ); } //*** HrFormatStringIntoBSTR( langidIn, idsIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatStringWithVAListIntoBSTR // // Description: // Format a string (specified by idsIn, a string resource ID) and // variable arguments into a BSTR using the FormatMessage() Win32 API. // If the BSTR is not NULL on entry, the BSTR will be reused. // // Arguments: // hInstanceIn // Handle to an instance of the module whose executable file // contains the string resource. // // langidIn // Language ID of string table resource. // // idsIn // Specifies the integer identifier of the string to be loaded. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // valistIn // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatStringWithVAListIntoBSTR( HINSTANCE hInstanceIn , LANGID langidIn , UINT idsIn , BSTR * pbstrInout , va_list valistIn ) { TraceFunc1( "ids = %d", idsIn ); HRESULT hr = S_OK; BSTR bstrStringResource = NULL; DWORD cch; LPWSTR psz = NULL; Assert( pbstrInout != NULL ); if ( pbstrInout == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // // Load the string resource. // hr = HrLoadStringIntoBSTR( hInstanceIn, langidIn, idsIn, &bstrStringResource ); if ( FAILED( hr ) ) { goto Cleanup; } // // Format the message with the arguments. // cch = FormatMessageW( ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING ) , bstrStringResource , 0 , 0 , (LPWSTR) &psz , 0 , &valistIn ); AssertMsg( cch != 0, "Missing string??" ); if ( cch == 0 ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } // // If previously allocated free it before re-allocating it. // if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: // // Allocate a BSTR for the string. // *pbstrInout = TraceSysAllocStringLen( psz, cch ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: Cleanup: TraceSysFreeString( bstrStringResource ); LocalFree( psz ); HRETURN( hr ); } //*** HrFormatStringWithVAListIntoBSTR( langidIn, idsIn, valistIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatStringIntoBSTR // // Description: // Format a string (specified by pcwszFmtIn) and variable arguments into // a BSTR using the FormatMessage() Win32 API. If the BSTR is not NULL // on entry, the BSTR will be reused. // // Calls HrFormatStringWithVAListIntoBSTR to perform the actual work. // // Arguments: // pcwszFmtIn // Specifies the format string. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // ... // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatStringIntoBSTR( LPCWSTR pcwszFmtIn , BSTR * pbstrInout , ... ) { TraceFunc1( "pcwszFmtIn = %ws", pcwszFmtIn ); HRESULT hr; va_list valist; va_start( valist, pbstrInout ); hr = HrFormatStringWithVAListIntoBSTR( pcwszFmtIn, pbstrInout, valist ); va_end( valist ); HRETURN( hr ); } //*** HrFormatStringIntoBSTR( pcwszFmtIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatStringWithVAListIntoBSTR // // Description: // Format a string (specified by pcwszFmtIn) and variable arguments into // a BSTR using the FormatMessage() Win32 API. If the BSTR is not NULL // on entry, the BSTR will be reused. // // Arguments: // pcwszFmtIn // Specifies the format string. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // valistIn // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pcwszFmtIn or pbstrInout is NULL. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatStringWithVAListIntoBSTR( LPCWSTR pcwszFmtIn , BSTR * pbstrInout , va_list valistIn ) { TraceFunc1( "pcwszFmtIn = %ws", pcwszFmtIn ); HRESULT hr = S_OK; DWORD cch; LPWSTR psz = NULL; if ( ( pbstrInout == NULL ) || ( pcwszFmtIn == NULL ) ) { hr = THR( E_POINTER ); goto Cleanup; } // // Format the message with the arguments. // cch = FormatMessageW( ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING ) , pcwszFmtIn , 0 , 0 , (LPWSTR) &psz , 0 , &valistIn ); AssertMsg( cch != 0, "Missing string??" ); if ( cch == 0 ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } // // If previously allocated free it before re-allocating it. // if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: // // Allocate a BSTR for the string. // *pbstrInout = TraceSysAllocStringLen( psz, cch ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: Cleanup: LocalFree( psz ); HRETURN( hr ); } //*** HrFormatStringWithVAListIntoBSTR( pcwszFmtIn, valistIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HRESULT // HrFormatMessageIntoBSTR( // HINSTANCE hInstanceIn, // UINT uIDIn, // BSTR * pbstrInout, // ... // ) // // Description: // Retrieves the format string from the string resource uIDIn using // FormatMessage. // // Arguments: // hInstanceIn // Handle to an instance of the module whose executable file // contains the string resource. // // uIDIn // Specifies the integer identifier of the string to be loaded. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatMessageIntoBSTR( HINSTANCE hInstanceIn, UINT uIDIn, BSTR * pbstrInout, ... ) { TraceFunc( "" ); va_list valist; DWORD cch; LPWSTR psz = NULL; HRESULT hr = S_OK; DWORD dw; WCHAR szBuf[ 255 ]; if ( pbstrInout == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } va_start( valist, pbstrInout ); dw = LoadStringW( hInstanceIn, uIDIn, szBuf, RTL_NUMBER_OF( szBuf ) ); AssertMsg( dw != 0, "Missing string??" ); cch = FormatMessageW( ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING ) , szBuf , 0 , 0 , (LPWSTR) &psz , 0 , &valist ); va_end( valist ); AssertMsg( cch != 0, "Missing string??" ); if ( cch == 0 ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); goto Cleanup; } // // If previously allocated free it before re-allocating it. // if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: // // Allocate a BSTR for the string. // *pbstrInout = TraceSysAllocStringLen( psz, cch ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: Cleanup: LocalFree( psz ); HRETURN( hr ); } //*** HrFormatMessageIntoBSTR ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatErrorIntoBSTR // // Description: // Retrieves the system error message associated with the HRESULT. If // additional arguments are specified, it will use them in the formatting // of the error string. // // Arguments: // hrIn // Error code to lookup the message for. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // ... // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatErrorIntoBSTR( HRESULT hrIn , BSTR * pbstrInout , ... ) { TraceFunc1( "hrIn = 0x%08x", hrIn ); HRESULT hr = S_OK; va_list valist; va_start( valist, pbstrInout ); hr = HrFormatErrorWithVAListIntoBSTR( hrIn, pbstrInout, valist ); va_end( valist ); HRETURN( hr ); } //*** HrFormatErrorIntoBSTR ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatErrorIntoBSTR // // Description: // Retrieves the system error message associated with the HRESULT. If // additional arguments are specified, it will use them in the formatting // of the error string. // // Arguments: // hrIn // Error code to lookup the message for. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // phrStatusOut // We may fix up the passed in error code to find better error // message text. If we do that then we send the fixed up status // code back to the caller using this argument. // // ... // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatErrorIntoBSTR( HRESULT hrIn , BSTR * pbstrInout , HRESULT * phrStatusOut , ... ) { TraceFunc1( "hrIn = 0x%08x", hrIn ); Assert( pbstrInout != NULL ); Assert( phrStatusOut != NULL ); HRESULT hr = S_OK; HRESULT hrTemp = S_OK; va_list valist; *phrStatusOut = hrIn; va_start( valist, phrStatusOut ); hr = HrFormatErrorWithVAListIntoBSTR( hrIn, pbstrInout, valist ); if ( ( hr == HRESULT_FROM_WIN32( ERROR_MR_MID_NOT_FOUND ) ) && ( HRESULT_SEVERITY( hrIn ) == SEVERITY_SUCCESS ) ) { // // If the passed in status is a successful failure and we were unable // to look up the error message text then it may be one that we cleared // off the SEVERITY_ERROR bit to make it a warning instead of an error // in the UI. If that's the case then set the SEVERITY_ERROR bit and // try to lookup the error message text again. // hrTemp = MAKE_HRESULT( SEVERITY_ERROR, HRESULT_FACILITY( hrIn ), HRESULT_CODE( hrIn ) ); hr = HrFormatErrorWithVAListIntoBSTR( hrTemp, pbstrInout, valist ); if ( SUCCEEDED( hr ) ) { // // If the new status succeeded in finding error message text then // send it back to the caller. // *phrStatusOut = hrTemp; } // if: } // if: va_end( valist ); HRETURN( hr ); } //*** HrFormatErrorIntoBSTR ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatErrorWithVAListIntoBSTR // // Description: // Retrieves the system error message associated with the HRESULT. If // additional arguments are specified, it will use them in the formatting // of the error string. // // Arguments: // hrIn // Error code to lookup the message for. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // valistIn // Arguments for substitution points in the status text message. // The FormatMessage() API is used for formatting the string, so // substitution points must of the form %1!ws! and not %ws. // // Return Values: // S_OK // The call succeeded. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrInout is NULL. // // other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatErrorWithVAListIntoBSTR( HRESULT hrIn , BSTR * pbstrInout , va_list valistIn ) { TraceFunc1( "hrIn = 0x%08x", hrIn ); HRESULT hr = S_OK; HRESULT hrTemp; DWORD sc = 0; size_t cch; LPWSTR psz = NULL; LPWSTR pszBuf = NULL; HMODULE hModule = NULL; LPWSTR pszSysDir = NULL; size_t cchSysDir = MAX_PATH + 1; LPWSTR pszModule = NULL; size_t cchModule = 0; Assert( pbstrInout != NULL ); if ( pbstrInout == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if: // // Look at the HRESULT coming in and see if we need to modify it a little // to ensure that we get the best possible error message text. // if ( HRESULT_FACILITY( hrIn ) == FACILITY_WIN32 ) { // // If this is a Win32 wrapped in an HRESULT then remove the // HRESULT stuff so that the Win32 error code will be formatted // into the message correctly. // hrTemp = HRESULT_CODE( hrIn ); } // if: Win32 error code else { hrTemp = hrIn; } // else: cch = FormatMessageW( ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM /*| FORMAT_MESSAGE_IGNORE_INSERTS*/ ) , NULL , hrTemp , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) , (LPWSTR) &psz , 0 , &valistIn ); // // If the error message was not found then try WMIUtils since we know // that their error messages are not propertly located for a system lookup. // if ( cch == 0 ) { pszSysDir = new WCHAR[ cchSysDir ]; if ( pszSysDir == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: sc = GetSystemDirectoryW( pszSysDir, static_cast< UINT >( cchSysDir ) ); if ( sc > ( cchSysDir - 1 ) ) { delete [] pszSysDir; pszSysDir = NULL; cchSysDir = sc + 1; pszSysDir = new WCHAR[ cchSysDir ]; if ( pszSysDir == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: sc = GetSystemDirectoryW( pszSysDir, static_cast< UINT >( cchSysDir ) ); } // if: if ( sc == 0 ) { sc = TW32( GetLastError() ); goto Win32Error; } // if: cchModule = wcslen( pszSysDir ) + wcslen( g_szWbemClientDLL ) + 1; pszModule = new WCHAR[ cchModule ]; if ( pszModule == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: THR( StringCchCopyExW( pszModule, cchModule, pszSysDir, &pszBuf, &cch, 0 ) ); THR( StringCchCopyW( pszBuf, cch, g_szWbemClientDLL ) ); hModule = LoadLibraryExW( pszModule, NULL, DONT_RESOLVE_DLL_REFERENCES ); if ( hModule == NULL ) { sc = TW32( GetLastError() ); goto Win32Error; } // if: cch = FormatMessageW( ( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER /*| FORMAT_MESSAGE_IGNORE_INSERTS*/ ) , hModule , hrTemp , MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) , (LPWSTR) &psz , 0 , &valistIn ); if ( cch == 0 ) { sc = TW32( GetLastError() ); } // if: } // if: AssertMsg( cch != 0, "Missing string??" ); if ( cch == 0 ) { goto Win32Error; } // // If previously allocated free it before re-allocating it. // if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: // // Allocate a BSTR for the string. // *pbstrInout = TraceSysAllocStringLen( psz, static_cast< UINT >( cch ) ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: // // Remove CR's and LF's since they aren't printable and usually mess up // the text when displayed. // for( cch = 0 ; cch < SysStringLen( *pbstrInout ) ; cch ++ ) { if ( ( (*pbstrInout)[ cch ] == L'\n' ) || ( (*pbstrInout)[ cch ] == L'\r' ) ) { (*pbstrInout)[ cch ] = L' '; } // if: } // for: goto Cleanup; Win32Error: hr = HRESULT_FROM_WIN32( sc ); goto Cleanup; Cleanup: if ( psz != NULL ) { LocalFree( psz ); } // if: delete [] pszModule; delete [] pszSysDir; if ( hModule != NULL ) { FreeLibrary( hModule ); } // if: HRETURN( hr ); } //*** HrFormatErrorWithVAListIntoBSTR( valistIn ) ////////////////////////////////////////////////////////////////////////////// //++ // // HrAnsiStringToBSTR // // Description: // Convert and ANSI string into a BSTR. // // Arguments: // pcszAnsiIn // Pointer to the ANSI string to convert. // // pbstrOut // Pointer to the BSTR to receive the string.HrAnsiStringToBSTR // // Return Values: // S_OK // The call succeeded. // // S_FALSE // The input string was NULL. // // E_OUTOFMEMORY // Out of memory. // // E_POINTER // pbstrOut is NULL. // // other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrAnsiStringToBSTR( LPCSTR pcszAnsiIn, BSTR * pbstrOut ) { TraceFunc( "" ); HRESULT hr = S_OK; BSTR bstr = NULL; DWORD cch; DWORD sc; int nRet; if ( pbstrOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // if: if ( pcszAnsiIn == NULL ) { *pbstrOut = NULL; hr = S_FALSE; goto Cleanup; } // if: // // Determine number of wide characters to be allocated for the // Unicode string. // cch = (DWORD) strlen( pcszAnsiIn ) + 1; bstr = TraceSysAllocStringLen( NULL, cch ); if ( bstr == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // if: nRet = MultiByteToWideChar( CP_ACP, 0, pcszAnsiIn, cch, bstr, cch ); if ( nRet == 0 ) { sc = TW32( GetLastError() ); hr = HRESULT_FROM_WIN32( sc ); goto Cleanup; } // if: *pbstrOut = bstr; Cleanup: HRETURN( hr ); } //*** HrAnsiStringToBSTR ////////////////////////////////////////////////////////////////////////////// //++ // // HrConcatenateBSTRs // // Description: // Concatenate one BSTR onto another one. // // Arguments: // pbstrDstInout // Specifies the destination BSTR. // // bstrSrcIn // Specifies the source BSTR whose contents will be concatenated // onto pbstrDstInout. // // Return Values: // S_OK // The call succeeded. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrConcatenateBSTRs( BSTR * pbstrDstInout , BSTR bstrSrcIn ) { TraceFunc1( "bstrSrcIn = %ws", bstrSrcIn ); HRESULT hr = S_OK; Assert( pbstrDstInout != NULL ); Assert( bstrSrcIn != NULL ); if ( *pbstrDstInout == NULL ) { *pbstrDstInout = TraceSysAllocString( bstrSrcIn ); if ( pbstrDstInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } } // if: no destination string specified else { size_t cchSrc; size_t cchDst; size_t cchTotal; BSTR bstr = NULL; LPWSTR pszBuf = NULL; cchSrc = SysStringLen( bstrSrcIn ); cchDst = SysStringLen( *pbstrDstInout ); cchTotal = cchSrc + cchDst + 1; bstr = TraceSysAllocStringLen( NULL, static_cast< UINT >( cchTotal ) ); if ( bstr == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } hr = THR( StringCchCopyExW( bstr, cchTotal, *pbstrDstInout, &pszBuf, &cchTotal, 0 ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: hr = THR( StringCchCopyW( pszBuf, cchTotal, bstrSrcIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: TraceSysFreeString( *pbstrDstInout ); *pbstrDstInout = bstr; } // else: destination string was specified Cleanup: HRETURN( hr ); } //*** HrConcatenateBSTRs ////////////////////////////////////////////////////////////////////////////// //++ // // HrFormatGuidIntoBSTR // // Description: // Format a GUID into a BSTR. If the BSTR is not NULL on entry, // the BSTR will be reused. // // Arguments: // pguidIn // Specifies the GUID to format into a string. // // pbstrInout // Pointer to the BSTR to receive the string. On a failure, the BSTR // may be the same or NULL. // // Return Values: // S_OK // The call succeeded. // // Other HRESULTs // The call failed. // //-- ////////////////////////////////////////////////////////////////////////////// HRESULT HrFormatGuidIntoBSTR( GUID * pguidIn , BSTR * pbstrInout ) { TraceFunc( "" ); HRESULT hr = S_OK; WCHAR wszGuid[ 64 ]; size_t cch = 0; size_t cchRemaining = 0; if ( ( pbstrInout == NULL ) || ( pguidIn == NULL ) ) { hr = THR( E_POINTER ); goto Cleanup; } hr = THR( StringCchPrintfExW( wszGuid , RTL_NUMBER_OF( wszGuid ) , NULL , &cchRemaining , 0 , L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}" , pguidIn->Data1 , pguidIn->Data2 , pguidIn->Data3 , pguidIn->Data4[ 0 ] , pguidIn->Data4[ 1 ] , pguidIn->Data4[ 2 ] , pguidIn->Data4[ 3 ] , pguidIn->Data4[ 4 ] , pguidIn->Data4[ 5 ] , pguidIn->Data4[ 6 ] , pguidIn->Data4[ 7 ] ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: cch = RTL_NUMBER_OF( wszGuid ) - cchRemaining; if ( *pbstrInout != NULL ) { TraceSysFreeString( *pbstrInout ); *pbstrInout = NULL; } // if: *pbstrInout = TraceSysAllocStringLen( wszGuid, static_cast< UINT >( cch ) ); if ( *pbstrInout == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } Cleanup: HRETURN( hr ); } //*** HrFormatGuidIntoBSTR