windows-nt/Source/XPSP1/NT/base/cluster/mgmt/common/loadstring.cpp
2020-09-26 16:20:57 +08:00

1298 lines
30 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2001 Microsoft Corporation
//
// Module Name:
// LoadString.cpp
//
// Description:
// LoadStringIntoBSTR implementation.
//
// Maintained By:
// David Potter (DavidP) 01-FEB-2001
// Geoffrey Pease (GPease) 22-MAY-2000
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "LoadString.h"
//////////////////////////////////////////////////////////////////////////////
// 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;
PBYTE pbStringData;
PBYTE pbStringDataMax;
PBYTE pbStringTable;
int cbStringTable;
int nTable;
int nOffset;
int idxString;
int iRet;
int cch = 0;
Assert( idsIn != 0 );
Assert( pbstrInout != NULL );
if ( pbstrInout == NULL )
{
goto InvalidPointer;
}
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 )
{
goto Win32Error;
}
// Load the table.
hgbl = LoadResource( hInstanceIn, hrsrc );
if ( hgbl == NULL )
{
goto Win32Error;
}
// Lock the table so we access its data.
pbStringTable = reinterpret_cast< PBYTE >( LockResource( hgbl ) );
if ( pbStringTable == NULL )
{
goto Win32Error;
}
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 )
{
goto NotFound;
}
// 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." );
//
// Allocate a BSTR for the string.
//
if ( *pbstrInout == NULL )
{
//
// BUGBUG: 23-FEB-2001 GalenB
//
// The memory tracking is complaining bitterly, and often, about this allocation leaking.
//
*pbstrInout = TraceSysAllocStringLen( (OLECHAR *) pbStringData, cch );
if ( *pbstrInout == NULL )
{
goto OutOfMemory;
}
} // if: no string allocated previously
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, (OLECHAR *) pbStringData, cch );
if ( ! iRet )
{
goto OutOfMemory;
}
} // else: string was allocated previously
TraceFlow1( "HrLoadStringIntoBSTR() - Loaded string = '%ws'", *pbstrInout );
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
goto Cleanup;
NotFound:
hr = HRESULT_FROM_WIN32( TW32( ERROR_RESOURCE_NAME_NOT_FOUND ) );
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
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;
INT iRet;
LPWSTR psz = NULL;
Assert( pbstrInout != NULL );
if ( pbstrInout == NULL )
{
goto InvalidPointer;
}
//
// Load the string resource.
//
hr = HrLoadStringIntoBSTR( hInstanceIn, langidIn, idsIn, &bstrStringResource );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Format the message with the arguments.
//
cch = FormatMessage(
( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING )
, bstrStringResource
, 0
, 0
, (LPWSTR) &psz
, 0
, &valistIn
);
AssertMsg( cch != 0, "Missing string??" );
if ( cch == 0 )
{
goto Win32Error;
}
//
// Copy the string to a BSTR.
//
if ( *pbstrInout == NULL )
{
*pbstrInout = TraceSysAllocStringLen( psz, cch );
if ( *pbstrInout == NULL )
{
goto OutOfMemory;
}
}
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
if ( ! iRet )
{
goto OutOfMemory;
}
}
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
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;
INT iRet;
LPWSTR psz = NULL;
if ( ( pbstrInout == NULL )
|| ( pcwszFmtIn == NULL ) )
{
goto InvalidPointer;
}
//
// Format the message with the arguments.
//
cch = FormatMessage(
( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING )
, pcwszFmtIn
, 0
, 0
, (LPWSTR) &psz
, 0
, &valistIn
);
AssertMsg( cch != 0, "Missing string??" );
if ( cch == 0 )
{
goto Win32Error;
}
if ( *pbstrInout == NULL )
{
*pbstrInout = TraceSysAllocStringLen( psz, cch );
if ( *pbstrInout == NULL )
{
goto OutOfMemory;
}
}
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
if ( ! iRet )
{
goto OutOfMemory;
}
}
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
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;
INT iRet;
LPWSTR psz = NULL;
HRESULT hr = S_OK;
DWORD dw;
WCHAR szBuf[ 255 ];
if ( pbstrInout == NULL )
goto InvalidPointer;
va_start( valist, pbstrInout );
dw = LoadString( g_hInstance, uIDIn, szBuf, ARRAYSIZE( szBuf ) );
AssertMsg( dw != 0, "Missing string??" );
cch = FormatMessage( 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 )
goto Win32Error;
if ( *pbstrInout == NULL )
{
*pbstrInout = TraceSysAllocStringLen( psz, cch );
if ( *pbstrInout == NULL )
goto OutOfMemory;
}
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
if ( !iRet )
goto OutOfMemory;
}
Cleanup:
LocalFree( psz );
HRETURN( hr );
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
} //*** 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()
//////////////////////////////////////////////////////////////////////////////
//++
//
// 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;
DWORD sc = 0;
DWORD cch;
INT iRet;
LPWSTR psz = NULL;
HMODULE hModule = NULL;
LPWSTR pszSysDir = NULL;
UINT cchSysDir = MAX_PATH + 1;
LPWSTR pszModule = NULL;
size_t cchModule = 0;
Assert( pbstrInout != NULL );
if ( pbstrInout == NULL )
{
goto InvalidPointer;
} // if:
cch = FormatMessageW(
( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
/*| FORMAT_MESSAGE_IGNORE_INSERTS*/ )
, NULL
, hrIn
, 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 )
{
goto OutOfMemory;
} // if:
sc = GetSystemDirectoryW( pszSysDir, cchSysDir );
if ( sc > ( cchSysDir - 1 ) )
{
delete [] pszSysDir;
pszSysDir = NULL;
cchSysDir = sc + 1;
pszSysDir = new WCHAR[ cchSysDir ];
if ( pszSysDir == NULL )
{
goto OutOfMemory;
} // if:
sc = GetSystemDirectoryW( pszSysDir, 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 )
{
goto OutOfMemory;
} // if:
wcscpy( pszModule, pszSysDir );
wcscat( pszModule, 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
, hrIn
, 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 ( *pbstrInout == NULL )
{
*pbstrInout = TraceSysAllocStringLen( psz, cch );
if ( *pbstrInout == NULL )
{
goto OutOfMemory;
}
}
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, psz, cch );
if ( ! iRet )
{
goto OutOfMemory;
}
}
//
// 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;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
Cleanup:
if ( psz != NULL )
{
LocalFree( psz );
}
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 = E_OUTOFMEMORY;
goto Cleanup;
}
} // if: no destination string specified
else
{
UINT cchSrc;
UINT cchDst;
BSTR bstr = NULL;
cchSrc = SysStringLen( bstrSrcIn );
cchDst = SysStringLen( *pbstrDstInout );
bstr = TraceSysAllocStringLen( NULL, cchSrc + cchDst + 1 );
if ( bstr == NULL )
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
wcscpy( bstr, *pbstrDstInout );
wcscat( bstr, bstrSrcIn );
SysFreeString( *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 ];
DWORD cch;
INT iRet;
if ( ( pbstrInout == NULL )
|| ( pguidIn == NULL ) )
{
goto InvalidPointer;
}
cch = _snwprintf(
wszGuid
, ARRAYSIZE( wszGuid )
, 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 ( *pbstrInout == NULL )
{
*pbstrInout = TraceSysAllocStringLen( wszGuid, cch );
if ( *pbstrInout == NULL )
{
goto OutOfMemory;
}
}
else
{
iRet = TraceSysReAllocStringLen( pbstrInout, wszGuid, cch );
if ( ! iRet )
{
goto OutOfMemory;
}
}
goto Cleanup;
OutOfMemory:
hr = E_OUTOFMEMORY;
goto Cleanup;
InvalidPointer:
hr = THR( E_POINTER );
goto Cleanup;
Cleanup:
HRETURN( hr );
} //*** HrFormatGuidIntoBSTR()