|
|
#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); }
|