397 lines
13 KiB
C++
397 lines
13 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Module Name:
|
|
// Helpers.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of helpers used to format resource strings.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Pch.h"
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Finds a localized resource and returns a pointer to the constant string.
|
|
// This is adapted from a blog article published by Raymond Chen entitled
|
|
// "The format of string resources."
|
|
// http://blogs.msdn.com/oldnewthing/archive/2004/01/30/65013.aspx
|
|
//
|
|
// Parameters:
|
|
// hInstance - Handle to the module that contains the resource.
|
|
// uID - ID of the format string resource to be loaded.
|
|
// nLangID - Specifies the language of the resource.
|
|
// ppcstrResource - Pointer that recieves the resource string.
|
|
// pcch - Length of the resource string.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// S_FALSE - The requested string resource was empty.
|
|
// Other HRESULTs - Error returned by LoadResource or FindResourceEx.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT FindStringResourceEx(
|
|
__in HINSTANCE hInstance,
|
|
__in UINT uID,
|
|
__in UINT nLangID,
|
|
__deref_out_ecount(*pcch) const WCHAR **ppcstrResource,
|
|
__out size_t *pcch)
|
|
{
|
|
*ppcstrResource = NULL;
|
|
*pcch = 0;
|
|
|
|
// Convert the string ID into a bundle number
|
|
// Strings listed in .rc files are grouped together in
|
|
// bundles of 16, starting with bundle number 1.
|
|
HRSRC hrsrc = FindResourceEx(
|
|
hInstance,
|
|
RT_STRING,
|
|
MAKEINTRESOURCE(uID / 16 + 1),
|
|
(WORD) nLangID);
|
|
HRESULT hr = (hrsrc != NULL) ? S_OK : ResultFromKnownLastError();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Load the resource bundle into memory.
|
|
HGLOBAL hglob = LoadResource(hInstance, hrsrc);
|
|
hr = (hglob != NULL) ? S_OK : ResultFromKnownLastError();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Strings in the resource table are not null terminated.
|
|
// Treat a failure to lock the resource as an empty string, since
|
|
// LockResource() isn't documented to call SetLastError().
|
|
const WCHAR *pcstr = NULL;
|
|
pcstr = reinterpret_cast<const WCHAR *>(LockResource(hglob));
|
|
hr = (pcstr != NULL) ? S_OK : S_FALSE;
|
|
if (hr == S_OK)
|
|
{
|
|
// We have the string bundle we're looking for,
|
|
// let's traverse it and find the specific
|
|
// string entry we want.
|
|
for (UINT iResource = 0; iResource < (uID & 15); iResource++)
|
|
{
|
|
// The length of the string is stored as the
|
|
// first word in the entry.
|
|
pcstr += 1 + (UINT) *pcstr;
|
|
}
|
|
|
|
hr = S_FALSE;
|
|
|
|
// Get the length of our resource string
|
|
*pcch = (UINT) *pcstr;
|
|
|
|
// If we have a zero length string, pcstr + 1
|
|
// will point to the next string resource.
|
|
// We should only reassign *ppcstrResource if
|
|
// our length is greater than zero.
|
|
if (*pcch > 0)
|
|
{
|
|
hr = S_OK;
|
|
*ppcstrResource = pcstr + 1;
|
|
}
|
|
|
|
UnlockResource(pcstr);
|
|
} // if: resource locked successfully
|
|
|
|
FreeResource(hglob);
|
|
} // if: resource loaded successfully
|
|
} // if: string resource found
|
|
|
|
return hr;
|
|
|
|
} //*** FindStringResourceEx
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Finds a resource for the current language (for the current thread)
|
|
// and returns a pointer to the contant string.
|
|
//
|
|
// Parameters:
|
|
// hInstance - Handle to the module that contains the resource.
|
|
// uID - ID of the format string resource to be loaded.
|
|
// ppcstrResource - Pointer that recieves the resource string.
|
|
// pcch - Length of the resource string.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT FindStringResource(
|
|
__in HINSTANCE hInstance,
|
|
__in UINT uID,
|
|
__deref_out_ecount(*pcch) const WCHAR **ppcstrResource,
|
|
__out size_t *pcch)
|
|
{
|
|
return FindStringResourceEx(hInstance, uID, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), ppcstrResource, pcch);
|
|
|
|
} //*** FindStringResource
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Finds a resource string and returns an allocated copy of the string.
|
|
// The returned string should be freed using LocalFree().
|
|
//
|
|
// Parameters:
|
|
// hInstance - Handle to the module that contains the resource.
|
|
// uID - ID of the string to be loaded.
|
|
// ppwsz - Pointer to the allocated sstring.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT AllocStringFromResource(
|
|
__in HINSTANCE hInstance,
|
|
__in UINT uID,
|
|
__deref_out PWSTR *ppwsz)
|
|
{
|
|
*ppwsz = NULL;
|
|
|
|
// Retrieve a pointer to the string resource we are looking for.
|
|
// Resource strings are stored with their length as the first word
|
|
// followed by the actual string value.
|
|
const WCHAR *pcstrResource;
|
|
size_t cch;
|
|
HRESULT hr = FindStringResource(hInstance, uID, &pcstrResource, &cch);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Get the length of the resource string.
|
|
// Note that resource strings are not null terminated.
|
|
PWSTR pwsz = (PWSTR) LocalAlloc(LMEM_ZEROINIT, (cch + 1) * sizeof(WCHAR));
|
|
hr = (pwsz != NULL) ? S_OK : E_OUTOFMEMORY;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Copy the resource value out.
|
|
// If this resource points to an empty string (length zero),
|
|
// cch will be zero, and we will fill the resulting string
|
|
// with a single null terminator.
|
|
hr = StringCchCopyNExW(pwsz, cch + 1, pcstrResource, cch, NULL, NULL, STRSAFE_IGNORE_NULLS);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppwsz = pwsz;
|
|
}
|
|
}
|
|
} // if: found string resource
|
|
|
|
return hr;
|
|
|
|
} //*** AllocStringFromResource
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Format a resource string with the given optional parameters.
|
|
//
|
|
// Parameters:
|
|
// hInstance
|
|
// Handle to the module that contains the resource.
|
|
//
|
|
// uID
|
|
// ID of the format string resource to be loaded.
|
|
//
|
|
// ppwszOut
|
|
// Pointer to the string formatted from the string
|
|
// resource and the parameters. Caller must
|
|
// deallocate using LocalFree().
|
|
//
|
|
// ...
|
|
// Optional parameters to format into the string.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT FormatString(
|
|
__in HINSTANCE hInstance,
|
|
__in UINT uID,
|
|
__deref_out PWSTR *ppwszOut,
|
|
...)
|
|
{
|
|
*ppwszOut = NULL;
|
|
|
|
va_list vaParamList;
|
|
va_start(vaParamList, ppwszOut);
|
|
HRESULT hr = FormatStringVA(hInstance, uID, ppwszOut, vaParamList);
|
|
va_end(vaParamList);
|
|
|
|
return hr;
|
|
|
|
} //*** FormatString
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Format a given string with the given optional parameters.
|
|
//
|
|
// Parameters:
|
|
// pwszFormat
|
|
// Pointer to a string containing the format string
|
|
//
|
|
// ppwszOut
|
|
// Pointer which will receive the formatted string. Caller must
|
|
// deallocate with LocalFree().
|
|
//
|
|
// ...
|
|
// Optional parameters to format into the string.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT FormatString(__in PCWSTR pwszFormat, __deref_out PWSTR *ppwszOut, ...)
|
|
{
|
|
*ppwszOut = NULL;
|
|
|
|
va_list vaParamList;
|
|
va_start(vaParamList, ppwszOut);
|
|
HRESULT hr = FormatStringVA(pwszFormat, ppwszOut, vaParamList);
|
|
va_end(vaParamList);
|
|
|
|
return hr;
|
|
|
|
}//*** FormatString
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT FormatStringVA(__in PCWSTR pwszFormat, __deref_out PWSTR *ppwszOut, __in va_list vaParamList)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*ppwszOut = NULL;
|
|
|
|
if (FormatMessageW(
|
|
(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING),
|
|
pwszFormat,
|
|
0,
|
|
0,
|
|
(PWSTR) ppwszOut,
|
|
0,
|
|
&vaParamList) == 0)
|
|
{
|
|
hr = ResultFromKnownLastError();
|
|
}
|
|
|
|
return hr;
|
|
|
|
}//*** FormatStringVA
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Format a resource string with the given va list.
|
|
//
|
|
// Parameters:
|
|
// hInstance
|
|
// Handle to the module that contains the resource.
|
|
//
|
|
// uID
|
|
// ID of the format string resource to be loaded.
|
|
//
|
|
// ppwszOut
|
|
// Pointer to the formated resource string. Caller
|
|
// must deallocate using LocalFree().
|
|
//
|
|
// vaParamList
|
|
// Variable argument list.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT FormatStringVA(
|
|
__in HINSTANCE hInstance,
|
|
__in UINT uID,
|
|
__deref_out PWSTR *ppwszOut,
|
|
__in va_list vaParamList)
|
|
{
|
|
*ppwszOut = NULL;
|
|
|
|
// Retrieve the localized format string from the DLL.
|
|
PWSTR pwszFormat;
|
|
HRESULT hr = AllocStringFromResource(hInstance, uID, &pwszFormat);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (FormatMessageW(
|
|
(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
|
| FORMAT_MESSAGE_FROM_STRING),
|
|
pwszFormat,
|
|
0,
|
|
0,
|
|
(PWSTR) ppwszOut,
|
|
0,
|
|
&vaParamList) == 0)
|
|
{
|
|
hr = ResultFromKnownLastError();
|
|
}
|
|
|
|
LocalFree(pwszFormat);
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** FormatStringVA
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Compare two Sync Center IDs, e.g. two sync handler IDs or two sync
|
|
// item IDs. It is expected that both IDs are for the same type of
|
|
// object (e.g. sync handler or sync item). This routine should be used
|
|
// in all places the must compare for equality so that the correct
|
|
// comparison routine is used everywhere. Incorrect comparison routines
|
|
// include those that factor code page or locale into the comparison.
|
|
//
|
|
// Parameters:
|
|
// pszFirstID - First sync handler or sync item ID to compare.
|
|
// pszSecondID - Second sync handler or sync item ID to compare.
|
|
//
|
|
// Return Values:
|
|
// -1 - First ID sorts lexically before second ID.
|
|
// 0 - Both IDs are equivalent.
|
|
// 1 - First ID sorts lexically after second ID.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int CompareSyncMgrID(__in PCWSTR pszFirstID, __in PCWSTR pszSecondID)
|
|
{
|
|
int nCompareResult = CompareStringOrdinal(pszFirstID, -1 /*cchCount1*/, pszSecondID, -1 /*cchCount2*/, TRUE /*bIgnoreCase*/);
|
|
|
|
int nResult;
|
|
switch (nCompareResult)
|
|
{
|
|
case CSTR_EQUAL:
|
|
nResult = 0;
|
|
break;
|
|
case CSTR_GREATER_THAN:
|
|
nResult = 1;
|
|
break;
|
|
case CSTR_LESS_THAN:
|
|
nResult = -1;
|
|
break;
|
|
default:
|
|
// This should never happen. If it does, consider them different.
|
|
nResult = -1;
|
|
break;
|
|
}
|
|
|
|
return nResult;
|
|
|
|
} //*** CompareSyncMgrID
|
|
|