Index: src/installer-ca/dutil/strutil.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/installer-ca/dutil/strutil.cpp |
@@ -0,0 +1,755 @@ |
+//------------------------------------------------------------------------------------------------- |
+// <copyright file="strutil.cpp" company="Outercurve Foundation"> |
+// Copyright (c) 2004, Outercurve Foundation. |
+// This software is released under Microsoft Reciprocal License (MS-RL). |
+// The license and further copyright text can be found in the file |
+// LICENSE.TXT at the root directory of the distribution. |
+// </copyright> |
+// |
+// <summary> |
+// String helper functions. |
+// </summary> |
+//------------------------------------------------------------------------------------------------- |
+ |
+#include "../precomp.h" |
+ |
+#define ARRAY_GROWTH_SIZE 5 |
+ |
+// Forward declarations. |
+static HRESULT StrAllocStringMapInvariant( |
+ __deref_out_z LPWSTR* pscz, |
+ __in_z LPCWSTR wzSource, |
+ __in int cchSource, |
+ __in DWORD dwMapFlags |
+ ); |
+ |
+/******************************************************************** |
+StrAlloc - allocates or reuses dynamic string memory |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+********************************************************************/ |
+extern "C" HRESULT DAPI DAPI StrAlloc( |
+ __deref_out_ecount_part(cch, 0) LPWSTR* ppwz, |
+ __in DWORD_PTR cch |
+ ) |
+{ |
+ Assert(ppwz && cch); |
+ |
+ HRESULT hr = S_OK; |
+ LPWSTR pwz = NULL; |
+ |
+ if (cch >= MAXDWORD / sizeof(WCHAR)) |
+ { |
+ hr = E_OUTOFMEMORY; |
+ ExitOnFailure1(hr, "Not enough memory to allocate string of size: %u", cch); |
+ } |
+ |
+ if (*ppwz) |
+ { |
+ pwz = static_cast<LPWSTR>(MemReAlloc(*ppwz, sizeof(WCHAR) * cch, FALSE)); |
+ } |
+ else |
+ { |
+ pwz = static_cast<LPWSTR>(MemAlloc(sizeof(WCHAR) * cch, TRUE)); |
+ } |
+ |
+ ExitOnNull1(pwz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %u", cch); |
+ |
+ *ppwz = pwz; |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+/******************************************************************** |
+StrTrimCapacity - Frees any unnecessary memory associated with a string. |
+ Purely used for optimization, generally only when a string |
+ has been changing size, and will no longer grow. |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+********************************************************************/ |
+HRESULT DAPI StrTrimCapacity( |
+ __deref_out_z LPWSTR* ppwz |
+ ) |
+{ |
+ Assert(ppwz); |
+ |
+ HRESULT hr = S_OK; |
+ DWORD_PTR cchLen = 0; |
+ |
+ hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen)); |
+ ExitOnFailure(hr, "Failed to calculate length of string"); |
+ |
+ ++cchLen; // Add 1 for null-terminator |
+ |
+ hr = StrAlloc(ppwz, cchLen); |
+ ExitOnFailure(hr, "Failed to reallocate string"); |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+/******************************************************************** |
+StrTrimWhitespace - allocates or reuses dynamic string memory and copies |
+ in an existing string, excluding whitespace |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+********************************************************************/ |
+HRESULT DAPI StrTrimWhitespace( |
+ __deref_out_z LPWSTR* ppwz, |
+ __in_z LPCWSTR wzSource |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ int i = 0; |
+ LPWSTR sczResult = NULL; |
+ |
+ // Ignore beginning whitespace |
+ while (L' ' == *wzSource || L'\t' == *wzSource) |
+ { |
+ wzSource++; |
+ } |
+ |
+ i = lstrlenW(wzSource); |
+ // Overwrite ending whitespace with null characters |
+ if (0 < i) |
+ { |
+ // start from the last non-null-terminator character in the array |
+ for (i = i - 1; i > 0; --i) |
+ { |
+ if (L' ' != wzSource[i] && L'\t' != wzSource[i]) |
+ { |
+ break; |
+ } |
+ } |
+ |
+ ++i; |
+ } |
+ |
+ hr = StrAllocString(&sczResult, wzSource, i); |
+ ExitOnFailure(hr, "Failed to copy result string"); |
+ |
+ // Output result |
+ *ppwz = sczResult; |
+ sczResult = NULL; |
+ |
+LExit: |
+ ReleaseStr(sczResult); |
+ |
+ return hr; |
+} |
+ |
+ |
+ |
+ |
+ |
+/******************************************************************** |
+StrAllocString - allocates or reuses dynamic string memory and copies in an existing string |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+NOTE: cchSource does not have to equal the length of wzSource |
+NOTE: if cchSource == 0, length of wzSource is used instead |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrAllocString( |
+ __deref_out_ecount_z(cchSource+1) LPWSTR* ppwz, |
+ __in_z LPCWSTR wzSource, |
+ __in DWORD_PTR cchSource |
+ ) |
+{ |
+ Assert(ppwz && wzSource); // && *wzSource); |
+ |
+ HRESULT hr = S_OK; |
+ DWORD_PTR cch = 0; |
+ |
+ if (*ppwz) |
+ { |
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1) |
+ if (-1 == cch) |
+ { |
+ hr = E_INVALIDARG; |
+ ExitOnFailure(hr, "failed to get size of destination string"); |
+ } |
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters |
+ } |
+ |
+ if (0 == cchSource) |
+ { |
+ cchSource = lstrlenW(wzSource); |
+ } |
+ |
+ DWORD_PTR cchNeeded; |
+ hr = ::ULongPtrAdd(cchSource, 1, &cchNeeded); // add one for the null terminator |
+ ExitOnFailure(hr, "source string is too long"); |
+ |
+ if (cch < cchNeeded) |
+ { |
+ cch = cchNeeded; |
+ hr = StrAlloc(ppwz, cch); |
+ ExitOnFailure(hr, "failed to allocate string from string."); |
+ } |
+ |
+ // copy everything (the NULL terminator will be included) |
+ hr = ::StringCchCopyNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+ |
+ |
+ |
+/******************************************************************** |
+StrAllocConcat - allocates or reuses dynamic string memory and adds an existing string |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+NOTE: cchSource does not have to equal the length of wzSource |
+NOTE: if cchSource == 0, length of wzSource is used instead |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrAllocConcat( |
+ __deref_out_z LPWSTR* ppwz, |
+ __in_z LPCWSTR wzSource, |
+ __in DWORD_PTR cchSource |
+ ) |
+{ |
+ Assert(ppwz && wzSource); // && *wzSource); |
+ |
+ HRESULT hr = S_OK; |
+ DWORD_PTR cch = 0; |
+ DWORD_PTR cchLen = 0; |
+ |
+ if (*ppwz) |
+ { |
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1) |
+ if (-1 == cch) |
+ { |
+ hr = E_INVALIDARG; |
+ ExitOnFailure(hr, "failed to get size of destination string"); |
+ } |
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters |
+ |
+ hr = ::StringCchLengthW(*ppwz, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen)); |
+ ExitOnFailure(hr, "Failed to calculate length of string"); |
+ } |
+ |
+ Assert(cchLen <= cch); |
+ |
+ if (0 == cchSource) |
+ { |
+ hr = ::StringCchLengthW(wzSource, STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchSource)); |
+ ExitOnFailure(hr, "Failed to calculate length of string"); |
+ } |
+ |
+ if (cch - cchLen < cchSource + 1) |
+ { |
+ cch = (cchSource + cchLen + 1) * 2; |
+ hr = StrAlloc(ppwz, cch); |
+ ExitOnFailure1(hr, "failed to allocate string from string: %ls", wzSource); |
+ } |
+ |
+ if (*ppwz) |
+ { |
+ hr = ::StringCchCatNExW(*ppwz, cch, wzSource, cchSource, NULL, NULL, STRSAFE_FILL_BEHIND_NULL); |
+ } |
+ else |
+ { |
+ hr = E_UNEXPECTED; |
+ ExitOnFailure(hr, "for some reason our buffer is still null"); |
+ } |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+ |
+ |
+ |
+/******************************************************************** |
+StrAllocFormatted - allocates or reuses dynamic string memory and formats it |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrAllocFormatted( |
+ __deref_out_z LPWSTR* ppwz, |
+ __in __format_string LPCWSTR wzFormat, |
+ ... |
+ ) |
+{ |
+ Assert(ppwz && wzFormat && *wzFormat); |
+ |
+ HRESULT hr = S_OK; |
+ va_list args; |
+ |
+ va_start(args, wzFormat); |
+ hr = StrAllocFormattedArgs(ppwz, wzFormat, args); |
+ va_end(args); |
+ |
+ return hr; |
+} |
+ |
+ |
+ |
+ |
+/******************************************************************** |
+StrAllocFormattedArgs - allocates or reuses dynamic string memory |
+and formats it with the passed in args |
+ |
+NOTE: caller is responsible for freeing ppwz even if function fails |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrAllocFormattedArgs( |
+ __deref_out_z LPWSTR* ppwz, |
+ __in __format_string LPCWSTR wzFormat, |
+ __in va_list args |
+ ) |
+{ |
+ Assert(ppwz && wzFormat && *wzFormat); |
+ |
+ HRESULT hr = S_OK; |
+ DWORD_PTR cch = 0; |
+ LPWSTR pwzOriginal = NULL; |
+ DWORD_PTR cchOriginal = 0; |
+ |
+ if (*ppwz) |
+ { |
+ cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1) |
+ if (-1 == cch) |
+ { |
+ hr = E_INVALIDARG; |
+ ExitOnFailure(hr, "failed to get size of destination string"); |
+ } |
+ cch /= sizeof(WCHAR); //convert the count in bytes to count in characters |
+ |
+ cchOriginal = lstrlenW(*ppwz); |
+ } |
+ |
+ if (0 == cch) // if there is no space in the string buffer |
+ { |
+ cch = 256; |
+ hr = StrAlloc(ppwz, cch); |
+ ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFormat); |
+ } |
+ |
+ // format the message (grow until it fits or there is a failure) |
+ do |
+ { |
+ hr = ::StringCchVPrintfW(*ppwz, cch, wzFormat, args); |
+ if (STRSAFE_E_INSUFFICIENT_BUFFER == hr) |
+ { |
+ if (!pwzOriginal) |
+ { |
+ // this allows you to pass the original string as a formatting argument and not crash |
+ // save the original string and free it after the printf is complete |
+ pwzOriginal = *ppwz; |
+ *ppwz = NULL; |
+ // StringCchVPrintfW starts writing to the string... |
+ // NOTE: this hack only works with sprintf(&pwz, "%s ...", pwz, ...); |
+ pwzOriginal[cchOriginal] = 0; |
+ } |
+ cch *= 2; |
+ hr = StrAlloc(ppwz, cch); |
+ ExitOnFailure1(hr, "failed to allocate string to format: %ls", wzFormat); |
+ hr = S_FALSE; |
+ } |
+ } while (S_FALSE == hr); |
+ ExitOnFailure(hr, "failed to format string"); |
+ |
+LExit: |
+ ReleaseStr(pwzOriginal); |
+ |
+ return hr; |
+} |
+ |
+ |
+ |
+ |
+ |
+ |
+/******************************************************************** |
+StrMaxLength - returns maximum number of characters that can be stored in dynamic string p |
+ |
+NOTE: assumes Unicode string |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrMaxLength( |
+ __in LPCVOID p, |
+ __out DWORD_PTR* pcch |
+ ) |
+{ |
+ Assert(pcch); |
+ |
+ HRESULT hr = S_OK; |
+ |
+ if (p) |
+ { |
+ *pcch = MemSize(p); // get size of entire buffer |
+ if (-1 == *pcch) |
+ { |
+ ExitFunction1(hr = E_FAIL); |
+ } |
+ |
+ *pcch /= sizeof(WCHAR); // reduce to count of characters |
+ } |
+ else |
+ { |
+ *pcch = 0; |
+ } |
+ Assert(S_OK == hr); |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+/******************************************************************** |
+StrSize - returns count of bytes in dynamic string p |
+ |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrSize( |
+ __in LPCVOID p, |
+ __out DWORD_PTR* pcb |
+ ) |
+{ |
+ Assert(p && pcb); |
+ |
+ HRESULT hr = S_OK; |
+ |
+ *pcb = MemSize(p); |
+ if (-1 == *pcb) |
+ { |
+ hr = E_FAIL; |
+ } |
+ |
+ return hr; |
+} |
+ |
+/******************************************************************** |
+StrFree - releases dynamic string memory allocated by any StrAlloc*() functions |
+ |
+********************************************************************/ |
+extern "C" HRESULT DAPI StrFree( |
+ __in LPVOID p |
+ ) |
+{ |
+ Assert(p); |
+ |
+ HRESULT hr = MemFree(p); |
+ ExitOnFailure(hr, "failed to free string"); |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+ |
+/**************************************************************************** |
+wcsistr - case insensitive find a substring |
+ |
+****************************************************************************/ |
+extern "C" LPCWSTR wcsistr( |
+ __in_z LPCWSTR wzString, |
+ __in_z LPCWSTR wzCharSet |
+ ) |
+{ |
+ LPCWSTR wzSource = wzString; |
+ LPCWSTR wzSearch = NULL; |
+ DWORD_PTR cchSourceIndex = 0; |
+ |
+ // Walk through wzString (the source string) one character at a time |
+ while (*wzSource) |
+ { |
+ cchSourceIndex = 0; |
+ wzSearch = wzCharSet; |
+ |
+ // Look ahead in the source string until we get a full match or we hit the end of the source |
+ while (L'\0' != wzSource[cchSourceIndex] && L'\0' != *wzSearch && towlower(wzSource[cchSourceIndex]) == towlower(*wzSearch)) |
+ { |
+ ++cchSourceIndex; |
+ ++wzSearch; |
+ } |
+ |
+ // If we found it, return the point that we found it at |
+ if (L'\0' == *wzSearch) |
+ { |
+ return wzSource; |
+ } |
+ |
+ // Walk ahead one character |
+ ++wzSource; |
+ } |
+ |
+ return NULL; |
+} |
+ |
+/**************************************************************************** |
+StrStringToInt16 - converts a string to a signed 16-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToInt16( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out SHORT* psOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ LONGLONG ll = 0; |
+ |
+ hr = StrStringToInt64(wzIn, cchIn, &ll); |
+ ExitOnFailure(hr, "Failed to parse int64."); |
+ |
+ if (SHORT_MAX < ll || SHORT_MIN > ll) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ *psOut = (SHORT)ll; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToUInt16 - converts a string to an unsigned 16-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToUInt16( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out USHORT* pusOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ ULONGLONG ull = 0; |
+ |
+ hr = StrStringToUInt64(wzIn, cchIn, &ull); |
+ ExitOnFailure(hr, "Failed to parse uint64."); |
+ |
+ if (USHORT_MAX < ull) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ *pusOut = (USHORT)ull; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToInt32 - converts a string to a signed 32-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToInt32( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out INT* piOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ LONGLONG ll = 0; |
+ |
+ hr = StrStringToInt64(wzIn, cchIn, &ll); |
+ ExitOnFailure(hr, "Failed to parse int64."); |
+ |
+ if (INT_MAX < ll || INT_MIN > ll) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ *piOut = (INT)ll; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToUInt32 - converts a string to an unsigned 32-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToUInt32( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out UINT* puiOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ ULONGLONG ull = 0; |
+ |
+ hr = StrStringToUInt64(wzIn, cchIn, &ull); |
+ ExitOnFailure(hr, "Failed to parse uint64."); |
+ |
+ if (UINT_MAX < ull) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ *puiOut = (UINT)ull; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToInt64 - converts a string to a signed 64-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToInt64( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out LONGLONG* pllOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ DWORD i = 0; |
+ INT iSign = 1; |
+ INT nDigit = 0; |
+ LARGE_INTEGER liValue = { }; |
+ |
+ // get string length if not provided |
+ if (0 >= cchIn) |
+ { |
+ cchIn = lstrlenW(wzIn); |
+ if (0 >= cchIn) |
+ { |
+ ExitFunction1(hr = E_INVALIDARG); |
+ } |
+ } |
+ |
+ // check sign |
+ if (L'-' == wzIn[0]) |
+ { |
+ if (1 >= cchIn) |
+ { |
+ ExitFunction1(hr = E_INVALIDARG); |
+ } |
+ i = 1; |
+ iSign = -1; |
+ } |
+ |
+ // read digits |
+ while (i < cchIn) |
+ { |
+ nDigit = wzIn[i] - L'0'; |
+ if (0 > nDigit || 9 < nDigit) |
+ { |
+ ExitFunction1(hr = E_INVALIDARG); |
+ } |
+ liValue.QuadPart = liValue.QuadPart * 10 + nDigit * iSign; |
+ |
+ if ((liValue.HighPart ^ iSign) & INT_MIN) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ ++i; |
+ } |
+ |
+ *pllOut = liValue.QuadPart; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToUInt64 - converts a string to an unsigned 64-bit integer. |
+ |
+****************************************************************************/ |
+extern "C" HRESULT DAPI StrStringToUInt64( |
+ __in_z LPCWSTR wzIn, |
+ __in DWORD cchIn, |
+ __out ULONGLONG* pullOut |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ DWORD i = 0; |
+ DWORD nDigit = 0; |
+ ULONGLONG ullValue = 0; |
+ ULONGLONG ull = 0; |
+ |
+ // get string length if not provided |
+ if (0 >= cchIn) |
+ { |
+ cchIn = lstrlenW(wzIn); |
+ if (0 >= cchIn) |
+ { |
+ ExitFunction1(hr = E_INVALIDARG); |
+ } |
+ } |
+ |
+ // read digits |
+ while (i < cchIn) |
+ { |
+ nDigit = wzIn[i] - L'0'; |
+ if (9 < nDigit) |
+ { |
+ ExitFunction1(hr = E_INVALIDARG); |
+ } |
+ ull = (ULONGLONG)(ullValue * 10 + nDigit); |
+ |
+ if (ull < ullValue) |
+ { |
+ ExitFunction1(hr = DISP_E_OVERFLOW); |
+ } |
+ ullValue = ull; |
+ ++i; |
+ } |
+ |
+ *pullOut = ullValue; |
+ |
+LExit: |
+ return hr; |
+} |
+ |
+/**************************************************************************** |
+StrStringToUpper - alters the given string in-place to be entirely uppercase |
+ |
+****************************************************************************/ |
+void DAPI StrStringToUpper( |
+ __inout_z LPWSTR wzIn |
+ ) |
+{ |
+ ::CharUpperBuffW(wzIn, lstrlenW(wzIn)); |
+} |
+ |
+/**************************************************************************** |
+StrStringToLower - alters the given string in-place to be entirely lowercase |
+ |
+****************************************************************************/ |
+void DAPI StrStringToLower( |
+ __inout_z LPWSTR wzIn |
+ ) |
+{ |
+ ::CharLowerBuffW(wzIn, lstrlenW(wzIn)); |
+} |
+ |
+ |
+ |
+ |
+/**************************************************************************** |
+StrAllocStringMapInvariant - helper function for the ToUpper and ToLower. |
+ |
+Note: Assumes source and destination buffers will be the same. |
+****************************************************************************/ |
+static HRESULT StrAllocStringMapInvariant( |
+ __deref_out_z LPWSTR* pscz, |
+ __in_z LPCWSTR wzSource, |
+ __in int cchSource, |
+ __in DWORD dwMapFlags |
+ ) |
+{ |
+ HRESULT hr = S_OK; |
+ |
+ hr = StrAllocString(pscz, wzSource, cchSource); |
+ ExitOnFailure(hr, "Failed to allocate a copy of the source string."); |
+ |
+ if (0 == cchSource) |
+ { |
+ // Need the actual string size for LCMapString. This includes the null-terminator |
+ // but LCMapString doesn't care either way. |
+ hr = ::StringCchLengthW(*pscz, INT_MAX, reinterpret_cast<size_t*>(&cchSource)); |
+ ExitOnFailure(hr, "Failed to get the length of the string."); |
+ } |
+ |
+ // Convert the copy of the string to upper or lower case in-place. |
+ if (0 == ::LCMapStringW(LOCALE_INVARIANT, dwMapFlags, *pscz, cchSource, *pscz, cchSource)) |
+ { |
+ ExitWithLastError(hr, "Failed to convert the string case."); |
+ } |
+ |
+LExit: |
+ return hr; |
+} |