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.
 
 
 
 
 
 

998 lines
27 KiB

#include "pch.h"
#include <urlmon.h>
#pragma hdrstop
/*-----------------------------------------------------------------------------
/ Internal only string APIs
/----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
/ StringToDWORD
/ -------------
/ Scan the string converting it to a DWORD, cope with hex and decimal alike,
/ more than likely we will receive a hex number though.
/
/ In:
/ pString -> string to parse
/
/ Out:
/ DWORD
/----------------------------------------------------------------------------*/
DWORD StringToDWORD(LPWSTR pString)
{
DWORD dwResult = 0x0;
TraceEnter(TRACE_COMMONAPI, "StringToDWORD");
Trace(TEXT("pString %s"), pString);
// Is the leading sequence 0x? If so then lets parse as hex, otherwise
// we can pass to StrToInt.
if ( pString[0] == L'0' && pString[1] == L'x' )
{
for ( pString += 2; *pString; pString++ )
{
WCHAR ch = *pString;
if ( InRange(ch, L'0', L'9') )
{
dwResult = (dwResult << 4) | (ch - L'0');
}
else if ( InRange(ch | (L'a'-L'A'), L'a', L'f') )
{
dwResult = (dwResult << 4) | (ch - L'a' + 10);
}
else
{
break; // tread non 0-9, A-F as end of string
}
}
}
else
{
dwResult = (DWORD)StrToIntW(pString);
}
Trace(TEXT("DWORD result is %08x"), dwResult);
TraceLeaveValue(dwResult);
}
/*-----------------------------------------------------------------------------
/ StringToURL
/ -----------
/ Convert a string to URL format, mashing the characters as required.
/
/ In:
/ pString -> string to be converted
/ ppResult -> receives a pointer to the new string (free using LocalFreeString).
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
HRESULT StringToURL(LPCTSTR pString, LPTSTR* ppResult)
{
HRESULT hr;
TCHAR szEncodedURL[INTERNET_MAX_URL_LENGTH];
DWORD dwLen = ARRAYSIZE(szEncodedURL);
int i;
TraceEnter(TRACE_COMMONAPI, "StringToURL");
TraceAssert(pString);
TraceAssert(ppResult);
*ppResult = NULL; // incase of failure
if ( !InternetCanonicalizeUrl(pString, szEncodedURL, &dwLen, 0) )
ExitGracefully(hr, E_FAIL, "Failed to convert URL to encoded format");
hr = LocalAllocString(ppResult, szEncodedURL);
FailGracefully(hr, "Failed to allocate copy of URL");
hr = S_OK; // success
exit_gracefully:
if ( FAILED(hr) && *ppResult )
LocalFreeString(ppResult);
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ Exported APIs
/----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
/ StringDPA_InsertString
/ ----------------------
/ Make a copy of the given string and place it into the DPA. It can then
/ be accessed using the StringDPA_GetString, or free'd using the
/ StringDPA_Destroy/StringDPA_DeleteString.
/
/ In:
/ hdpa = DPA to put string into
/ i = index to insert at
/ pString -> string to be inserted
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI StringDPA_InsertStringA(HDPA hdpa, INT i, LPCSTR pString)
{
if ( hdpa && pString )
{
LPSTR pStringCopy = NULL;
HRESULT hr = LocalAllocStringA(&pStringCopy, pString);
if ( FAILED(hr) )
return hr;
if ( -1 == DPA_InsertPtr(hdpa, i, pStringCopy) )
{
LocalFreeStringA(&pStringCopy);
return E_OUTOFMEMORY;
}
}
return S_OK;
}
STDAPI StringDPA_InsertStringW(HDPA hdpa, INT i, LPCWSTR pString)
{
if ( hdpa && pString )
{
LPWSTR pStringCopy = NULL;
HRESULT hr = LocalAllocStringW(&pStringCopy, pString);
if ( FAILED(hr) )
return hr;
if ( -1 == DPA_InsertPtr(hdpa, i, pStringCopy) )
{
LocalFreeStringW(&pStringCopy);
return E_OUTOFMEMORY;
}
}
return S_OK;
}
/*-----------------------------------------------------------------------------
/ StringDPA_AppendString
/ ----------------------
/ Make a copy of the given string and place it into the DPA. It can then
/ be accessed using the StringDPA_GetString, or free'd using the
/ StringDPA_Destroy/StringDPA_DeleteString.
/
/ In:
/ hdpa = DPA to put string into
/ pString -> string to be append
/ pres = resulting index
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI StringDPA_AppendStringA(HDPA hdpa, LPCSTR pString, PUINT_PTR pres)
{
HRESULT hr;
INT ires = 0;
LPSTR pStringCopy = NULL;
TraceEnter(TRACE_COMMONAPI, "StringDPA_AppendStringA");
TraceAssert(hdpa);
TraceAssert(pString);
if ( hdpa && pString )
{
hr = LocalAllocStringA(&pStringCopy, pString);
FailGracefully(hr, "Failed to allocate string copy");
ires = DPA_AppendPtr(hdpa, pStringCopy);
if ( -1 == ires )
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to add string to DPA");
if ( pres )
*pres = ires;
}
hr = S_OK;
exit_gracefully:
if ( FAILED(hr) )
LocalFreeStringA(&pStringCopy);
TraceLeaveResult(hr);
}
STDAPI StringDPA_AppendStringW(HDPA hdpa, LPCWSTR pString, PUINT_PTR pres)
{
HRESULT hr;
INT ires = 0;
LPWSTR pStringCopy = NULL;
TraceEnter(TRACE_COMMONAPI, "StringDPA_AppendStringW");
TraceAssert(hdpa);
TraceAssert(pString);
if ( hdpa && pString )
{
hr = LocalAllocStringW(&pStringCopy, pString);
FailGracefully(hr, "Failed to allocate string copy");
ires = DPA_AppendPtr(hdpa, pStringCopy);
if ( -1 == ires )
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to add string to DPA");
if ( pres )
*pres = ires;
}
hr = S_OK;
exit_gracefully:
if ( FAILED(hr) )
LocalFreeStringW(&pStringCopy);
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ StringDPA_DeleteString
/ ----------------------
/ Delete the specified index from the DPA, freeing the string element
/ that we have dangling from the index.
/
/ In:
/ hdpa -> handle to DPA to be destroyed
/ index = index of item to free
/
/ Out:
/ -
/----------------------------------------------------------------------------*/
STDAPI_(VOID) StringDPA_DeleteString(HDPA hdpa, INT index)
{
TraceEnter(TRACE_COMMONAPI, "StringDPA_DeleteString");
if ( hdpa && (index < DPA_GetPtrCount(hdpa)) )
{
// assumes LocalAllocString uses LocalAlloc (fair enough I guess)
LocalFree((HLOCAL)DPA_FastGetPtr(hdpa, index));
DPA_DeletePtr(hdpa, index);
}
TraceLeave();
}
/*-----------------------------------------------------------------------------
/ StringDPA_Destroy
/ -----------------
/ Take the given string DPA and destory it.
/
/ In:
/ pHDPA -> handle to DPA to be destroyed
/
/ Out:
/ -
/----------------------------------------------------------------------------*/
INT _DestroyStringDPA(LPVOID pItem, LPVOID pData)
{
// assumes that LocalAllocString does just that,
// to store the string.
LocalFree((HLOCAL)pItem);
return 1;
}
STDAPI_(VOID) StringDPA_Destroy(HDPA* pHDPA)
{
TraceEnter(TRACE_COMMONAPI, "StringDPA_Destroy");
if ( pHDPA && *pHDPA )
{
DPA_DestroyCallback(*pHDPA, _DestroyStringDPA, NULL);
*pHDPA = NULL;
}
TraceLeave();
}
/*-----------------------------------------------------------------------------
/ LocalAllocString
/ ------------------
/ Allocate a string, and initialize it with the specified contents.
/
/ In:
/ ppResult -> recieves pointer to the new string
/ pString -> string to initialize with
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI LocalAllocStringA(LPSTR* ppResult, LPCSTR pString)
{
*ppResult = NULL;
if ( pString )
{
*ppResult = (LPSTR)LocalAlloc(LPTR, StringByteSizeA(pString));
if ( !*ppResult )
return E_OUTOFMEMORY;
StrCpyA(*ppResult, pString); // buffer allocated above based on size
}
return S_OK;
}
STDAPI LocalAllocStringW(LPWSTR* ppResult, LPCWSTR pString)
{
*ppResult = NULL;
if ( pString )
{
*ppResult = (LPWSTR)LocalAlloc(LPTR, StringByteSizeW(pString));
if ( !*ppResult )
return E_OUTOFMEMORY;
StrCpyW(*ppResult, pString); // buffer allocated above based on size
}
return S_OK;
}
/*----------------------------------------------------------------------------
/ LocalAllocStringLen
/ -------------------
/ Given a length return a buffer of that size.
/
/ In:
/ ppResult -> receives the pointer to the string
/ cLen = length in characters to allocate
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI LocalAllocStringLenA(LPSTR* ppResult, UINT cLen)
{
*ppResult = (LPSTR)LocalAlloc(LPTR, (cLen+1)*SIZEOF(CHAR));
return (*ppResult) ? S_OK:E_OUTOFMEMORY;
}
STDAPI LocalAllocStringLenW(LPWSTR* ppResult, UINT cLen)
{
*ppResult = (LPWSTR)LocalAlloc(LPTR, (cLen+1)*SIZEOF(WCHAR));
return (*ppResult) ? S_OK:E_OUTOFMEMORY;
}
/*-----------------------------------------------------------------------------
/ LocalFreeString
/ -----------------
/ Release the string pointed to be *ppString (which can be null) and
/ then reset the pointer back to NULL.
/
/ In:
/ ppString -> pointer to string pointer to be free'd
/
/ Out:
/ -
/----------------------------------------------------------------------------*/
VOID LocalFreeStringA(LPSTR* ppString)
{
LocalFreeStringW((LPWSTR*)ppString);
}
VOID LocalFreeStringW(LPWSTR* ppString)
{
if ( ppString )
{
if ( *ppString )
LocalFree((HLOCAL)*ppString);
*ppString = NULL;
}
}
/*-----------------------------------------------------------------------------
/ LocalQueryString
/ ------------------
/ Hit the registry returning the wide version of the given string,
/ we dynamically allocate the buffer to put the result into,
/ this should be free'd by calling LocalFreeString.
/
/ In:
/ ppString -> receives the string point
/ hkey = key to query from
/ pSubKey -> pointer to sub key identifier
/
/
/ Out:
/ -
/----------------------------------------------------------------------------*/
STDAPI _LocalQueryString(LPTSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
{
HRESULT hr;
DWORD dwSize = NULL;
DWORD dwType;
TraceEnter(TRACE_COMMONAPI, "_LocalQueryString");
*ppResult = NULL;
if ( ERROR_SUCCESS != RegQueryValueEx(hKey, pSubKey, NULL, &dwType, NULL, &dwSize) )
ExitGracefully(hr, E_FAIL, "Failed when querying for key size");
if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
ExitGracefully(hr, E_FAIL, "Registry value is not a string");
if (dwSize > (MAX_PATH *sizeof(TCHAR)))
ExitGracefully(hr, E_FAIL, "Unexpected string size for query value");
dwSize += SIZEOF(TCHAR);
*ppResult = (LPTSTR)LocalAlloc(LPTR, dwSize);
if ( !*ppResult )
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate buffer for value");
if ( ERROR_SUCCESS != RegQueryValueEx(hKey, pSubKey, NULL, NULL, (LPBYTE)*ppResult, &dwSize) )
ExitGracefully(hr, E_FAIL, "Failed to read key value into buffer");
hr = S_OK;
exit_gracefully:
if ( FAILED(hr) )
LocalFreeString(ppResult);
TraceLeaveResult(hr);
}
// Query string as ANSI, converting to ANSI if build UNICODE
STDAPI LocalQueryStringA(LPSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
{
HRESULT hr;
LPTSTR pResult = NULL;
TraceEnter(TRACE_COMMONAPI, "LocalQueryStringA");
*ppResult = NULL; // incase of failure
hr = _LocalQueryString(&pResult, hKey, pSubKey);
FailGracefully(hr, "Failed to read the UNICODE version of string");
hr = LocalAllocStringW2A(ppResult, pResult);
FailGracefully(hr, "Failed to allocate ANSI version of string");
exit_gracefully:
if ( FAILED(hr) )
LocalFreeStringA(ppResult);
LocalFreeString(&pResult);
TraceLeaveResult(hr);
}
// Query string as UNICODE, converting to UNICODE if built ANSI
STDAPI LocalQueryStringW(LPWSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
{
HRESULT hr;
LPTSTR pResult = NULL;
TraceEnter(TRACE_COMMONAPI, "LocalQueryStringW");
*ppResult = NULL; // incase of failure
hr = _LocalQueryString(ppResult, hKey, pSubKey);
FailGracefully(hr, "Falied to get key value");
exit_gracefully:
if ( FAILED(hr) )
LocalFreeStringW(ppResult);
LocalFreeString(&pResult);
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ LocalAllocStringA2W / W2A
/ -------------------------
/ Alloc a string converting using MultiByteToWideChar or vice versa. This
/ allows in place thunking of strings without extra buffer usage.
/
/ In:
/ ppResult -> receives the string point
/ pString -> source string
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI LocalAllocStringA2W(LPWSTR* ppResult, LPCSTR pString)
{
HRESULT hr;
INT iLen;
TraceEnter(TRACE_COMMONAPI, "LocalAllocStringA2W");
if ( !ppResult && !pString )
ExitGracefully(hr, E_INVALIDARG, "Bad args for thunked allocate");
iLen = MultiByteToWideChar(CP_ACP, 0, pString, -1, NULL, 0);
hr = LocalAllocStringLenW(ppResult, iLen);
FailGracefully(hr, "Failed to allocate buffer for string");
MultiByteToWideChar(CP_ACP, 0, pString, -1, *ppResult, iLen+1);
hr = S_OK;
exit_gracefully:
TraceLeaveResult(hr);
}
STDAPI LocalAllocStringW2A(LPSTR* ppResult, LPCWSTR pString)
{
HRESULT hr;
INT iLen;
TraceEnter(TRACE_COMMONAPI, "LocalAllocStringW2A");
if ( !ppResult && !pString )
ExitGracefully(hr, E_INVALIDARG, "Bad args for thunked allocate");
iLen = WideCharToMultiByte(CP_ACP, 0, pString, -1, NULL, 0, NULL, NULL);
hr = LocalAllocStringLenA(ppResult, iLen);
FailGracefully(hr, "Failed to allocate buffer for string");
WideCharToMultiByte(CP_ACP, 0, pString, -1, *ppResult, iLen+1, NULL, NULL);
hr = S_OK;
exit_gracefully:
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ PutStringElement
/ -----------------
/ Add a string to the given buffer, always updating the cLen to indicate
/ how many characters would have been added
/
/ In:
/ pBuffer -> buffer to append to
/ pLen -> length value (updated)
/ pString -> string to add to buffer
/
/ Out:
/ -
/----------------------------------------------------------------------------*/
STDAPI_(VOID) PutStringElementA(LPSTR pBuffer, UINT* pLen, LPCSTR pElement)
{
TraceEnter(TRACE_COMMONAPI, "PutStringElementA");
if ( pElement )
{
if ( pBuffer )
StrCatA(pBuffer, pElement);
if ( pLen )
*pLen += lstrlenA(pElement);
}
TraceLeave();
}
STDAPI_(VOID) PutStringElementW(LPWSTR pBuffer, UINT* pLen, LPCWSTR pElement)
{
TraceEnter(TRACE_COMMONAPI, "PutStringElementW");
if ( pElement )
{
if ( pBuffer )
StrCatW(pBuffer, pElement);
if ( pLen )
*pLen += lstrlenW(pElement);
}
TraceLeave();
}
/*-----------------------------------------------------------------------------
/ GetStringElement
/ ----------------
/ Extract the n'th element from the given string. Each element is assumed
/ to be terminated with either a "," or a NULL.
/
/ In:
/ pString -> string to parse
/ index = element to retrieve
/ pBuffer, cchBuffer = buffer to fill
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI GetStringElementA(LPSTR pString, INT index, LPSTR pBuffer, INT cchBuffer)
{
return E_NOTIMPL;
}
STDAPI GetStringElementW(LPWSTR pString, INT index, LPWSTR pBuffer, INT cchBuffer)
{
// NTRAID#NTBUG9-762169-2003/01/15-lucios
// Good test arguments: ("a",0,buf,2), ("ab",0,buf,2)
// ("abcde",0,buf,2), ("ab,cd",34,buf,100).
HRESULT hr = E_FAIL;
TraceEnter(TRACE_COMMONAPI, "GetStringElement");
Trace(TEXT("pString %s, index %d"), pString, index);
if
(
(pString == NULL) || (index < 0) ||
(pBuffer == NULL) || (cchBuffer < 0)
) return E_INVALIDARG;
// 0 cchBuffer means we're done.
if (cchBuffer == 0) return S_OK;
// From here on we know cchBuffer >= 1
*pBuffer = L'\0';
for ( ; index > 0 ; index-- )
{
while ( *pString != L',' && *pString != L'\0' )
pString++;
if ( *pString == L',' )
pString++;
}
if ( !index )
{
while ( *pString == L' ' )
pString++;
// We need cchBuffer-- instead of --cchBuffer. We can do that
// because we know cchBuffer is at least 1.
// We don't want to copy nothing from pString if cchBuffer is 1
while ( --cchBuffer && (*pString != L',') && (*pString != L'\0') )
*pBuffer++ = *pString++;
// We can always do that because cchBuffer is at least 1
*pBuffer = L'\0';
hr = (*pString == L',') || (*pString == L'\0') ? S_OK : E_FAIL;
}
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ FormatMsgResource
/ -----------------
/ Load a string resource and pass it to format message, allocating a buffer
/ as we go.
/
/ In:
/ ppString -> receives the string point
/ hInstance = module handle for template string
/ uID = template string
/ ... = format parameters
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI FormatMsgResource(LPTSTR* ppString, HINSTANCE hInstance, UINT uID, ...)
{
HRESULT hr;
TCHAR szBuffer[MAX_PATH];
va_list va;
TraceEnter(TRACE_COMMONAPI, "FormatMsgResource");
va_start(va, uID);
if ( !LoadString(hInstance, uID, szBuffer, ARRAYSIZE(szBuffer)) )
ExitGracefully(hr, E_FAIL, "Failed to load template string");
if ( !FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
(LPVOID)szBuffer, 0, 0,
(LPTSTR)ppString,
0,
&va) )
{
ExitGracefully(hr, E_OUTOFMEMORY, "Failed to format the message");
}
Trace(TEXT("Resulting string: %s"), *ppString);
hr = S_OK; // success
exit_gracefully:
va_end(va);
TraceLeaveResult(hr);
}
/*-----------------------------------------------------------------------------
/ FormatMsgBox
/ ------------
/ Call FormatMessage and MessageBox together having built a suitable
/ string to display to the user.
/
/ In:
/ ppString -> receives the string point
/ hInstance = module handle for template string
/ uID = template string
/ ... = format parameters
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI_(INT) FormatMsgBox(HWND hWnd, HINSTANCE hInstance, UINT uidTitle, UINT uidPrompt, UINT uType, ...)
{
INT iResult = -1; // failure
LPTSTR pPrompt = NULL;
TCHAR szTitle[MAX_PATH];
TCHAR szBuffer[MAX_PATH];
va_list va;
TraceEnter(TRACE_COMMONAPI, "FormatMsgBox");
va_start(va, uType);
LoadString(hInstance, uidTitle, szTitle, ARRAYSIZE(szTitle));
LoadString(hInstance, uidPrompt, szBuffer, ARRAYSIZE(szBuffer));
if ( FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
(LPVOID)szBuffer, 0, 0,
(LPTSTR)&pPrompt,
0,
&va) )
{
Trace(TEXT("Title: %s"), szTitle);
Trace(TEXT("Prompt: %s"), pPrompt);
iResult = MessageBox(hWnd, pPrompt, szTitle, uType);
LocalFree(pPrompt);
}
Trace(TEXT("Result is %d"), iResult);
va_end(va);
TraceLeaveValue(iResult);
}
/*-----------------------------------------------------------------------------
/ FormatDirectoryName
/ -------------------
/ Collect the directory name and format it using a text resource specified.
/
/ In:
/ ppString = receives the string pointer for the result
/ clisdNamespace = namespace instance
/ hInstance = instance handle to load resource from
/ uID = resource ID for string
/
/ Out:
/ HRESULT
/----------------------------------------------------------------------------*/
STDAPI FormatDirectoryName(LPTSTR* ppString, HINSTANCE hInstance, UINT uID)
{
HRESULT hr;
TCHAR szBuffer[MAX_PATH];
LPTSTR pDisplayName = NULL;
HKEY hKey = NULL;
TraceEnter(TRACE_COMMONAPI, "FormatDirectoryName");
// No IDsFolder then lets ensure that we have one
hr = GetKeyForCLSID(CLSID_MicrosoftDS, NULL, &hKey);
FailGracefully(hr, "Failed to open namespace's registry key");
hr = LocalQueryString(&pDisplayName, hKey, NULL);
FailGracefully(hr, "Failed to get the namespace display name");
Trace(TEXT("Display name is: %s"), pDisplayName);
if ( hInstance )
{
hr = FormatMsgResource(ppString, hInstance, uID, pDisplayName);
FailGracefully(hr, "Failed to format from resource");
}
else
{
*ppString = pDisplayName;
pDisplayName = NULL;
}
hr = S_OK; // success
exit_gracefully:
LocalFreeString(&pDisplayName);
if ( hKey )
RegCloseKey(hKey);
TraceLeaveResult(hr);
}
///////////////////////////////////////////////////////////////////
// Function: cchLoadHrMsg
//
// Given an HRESULT error code and a flag TryADsIErrors,
// it loads the string for the error. It returns the # of characters returned
// NOTICE: free the returned string using LocalFree.
int cchLoadHrMsg( IN HRESULT hr, OUT PTSTR* pptzSysMsg, IN BOOL TryADsIErrors )
{
HRESULT Localhr = S_OK;
DWORD status;
HRESULT originalHr = hr;
// first check if we have extended ADs errors
if ((hr != S_OK) && TryADsIErrors) {
WCHAR Buf1[256], Buf2[256];
Localhr = ADsGetLastError (&status,
Buf1, 256, Buf2, 256);
if ((status != ERROR_INVALID_DATA) &&
(status != 0)) {
hr = status;
}
}
int cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
if (!cch)
{ //try ads errors
static HMODULE g_adsMod = 0;
if (0 == g_adsMod)
{
g_adsMod = GetModuleHandle (L"activeds.dll");
}
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
g_adsMod,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
#ifdef DSADMIN
if (!cch)
{
// Try NTSTATUS error codes
hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(hr));
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
}
#endif // DSADMIN
}
if (!cch)
{
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
originalHr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
if (!cch)
{ //try ads errors
static HMODULE g_adsMod = 0;
if (0 == g_adsMod)
{
g_adsMod = GetModuleHandle (L"activeds.dll");
}
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
g_adsMod,
originalHr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
#ifdef DSADMIN
if (!cch)
{
// Try NTSTATUS error codes
hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(originalHr));
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)pptzSysMsg,
0,
NULL);
}
#endif // DSADMIN
}
}
return cch;
}
void StringErrorFromHr(HRESULT hr, PWSTR* szError, BOOL bTryADsIErrors)
{
PWSTR lpsz = NULL;
int cch = cchLoadHrMsg(hr, &lpsz, bTryADsIErrors);
if (cch)
{
*szError = new WCHAR[wcslen(lpsz) + 1];
if (*szError)
{
StrCpyN(*szError, lpsz, wcslen(lpsz) + 1);
}
}
else
{
UINT maxError = 40;
*szError = new WCHAR[maxError];
if (*szError)
{
ZeroMemory(*szError, sizeof(WCHAR) * maxError);
wnsprintf(*szError, maxError, L"Error 0x%x", hr);
}
}
if (lpsz != NULL)
::LocalFree(lpsz);
}