- Add support for CAtlString and all its supporting base classes.
- It doesn't do much more than assign wchat_t arrarys and call LoadString, but it's a full base to start adding more methods as people decide to.

svn path=/trunk/; revision=69332
This commit is contained in:
Ged Murphy 2015-09-23 20:05:31 +00:00
parent c43914c6a7
commit d3519a4284
4 changed files with 651 additions and 164 deletions

View file

@ -204,8 +204,99 @@ public:
{
return m_hInstResource;
}
HINSTANCE SetResourceInstance(HINSTANCE hInst)
{
return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst));
}
HINSTANCE GetHInstanceAt(int i);
};
extern CAtlBaseModule _AtlBaseModule;
///
// String Resource helper functions
//
#pragma warning(push)
#pragma warning(disable: 4200)
struct ATLSTRINGRESOURCEIMAGE
{
WORD nLength;
WCHAR achString[];
};
#pragma warning(pop)
inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage(
_In_ HINSTANCE hInstance,
_In_ HRSRC hResource,
_In_ UINT id)
{
const ATLSTRINGRESOURCEIMAGE* pImage;
const ATLSTRINGRESOURCEIMAGE* pImageEnd;
ULONG nResourceSize;
HGLOBAL hGlobal;
UINT iIndex;
hGlobal = ::LoadResource(hInstance, hResource);
if (hGlobal == NULL) return NULL;
pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource(hGlobal);
if (pImage == NULL) return NULL;
nResourceSize = ::SizeofResource(hInstance, hResource);
pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + nResourceSize);
iIndex = id & 0x000f;
while ((iIndex > 0) && (pImage < pImageEnd))
{
pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + (sizeof(ATLSTRINGRESOURCEIMAGE) + (pImage->nLength * sizeof(WCHAR))));
iIndex--;
}
if (pImage >= pImageEnd) return NULL;
if (pImage->nLength == 0) return NULL;
return pImage;
}
inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage(
_In_ HINSTANCE hInstance,
_In_ UINT id) throw()
{
HRSRC hResource;
hResource = ::FindResourceW(hInstance, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast<WORD>(~0))), (LPWSTR)RT_STRING);
if (hResource == NULL) return NULL;
return _AtlGetStringResourceImage(hInstance, hResource, id);
}
inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage(
_In_ HINSTANCE hInstance,
_In_ UINT id,
_In_ WORD wLanguage)
{
HRSRC hResource;
hResource = ::FindResourceExW(hInstance, (LPWSTR)RT_STRING, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast<WORD>(~0))), wLanguage);
if (hResource == NULL) return NULL;
return _AtlGetStringResourceImage(hInstance, hResource, id);
}
inline HINSTANCE AtlFindStringResourceInstance(
UINT nID,
WORD wLanguage = 0)
{
const ATLSTRINGRESOURCEIMAGE* strRes = NULL;
HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0);
for (int i = 1; hInst != NULL && strRes == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++))
{
strRes = AtlGetStringResourceImage(hInst, nID, wLanguage);
if (strRes != NULL) return hInst;
}
return NULL;
}
}; // namespace ATL

View file

@ -8,125 +8,388 @@
namespace ATL
{
struct CStringData;
struct CStringData;
__interface IAtlStringMgr
__interface IAtlStringMgr
{
public:
_Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
CStringData* Allocate(
_In_ int nAllocLength,
_In_ int nCharSize
);
void Free(
_Inout_ CStringData* pData
);
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
CStringData* Reallocate(
_Inout_ CStringData* pData,
_In_ int nAllocLength,
_In_ int nCharSize
);
CStringData* GetNilString(void);
IAtlStringMgr* Clone(void);
};
struct CStringData
{
IAtlStringMgr* pStringMgr;
int nAllocLength;
int nDataLength;
long nRefs;
void* data() throw()
{
public:
return (this + 1);
}
_Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
CStringData* Allocate(
_In_ int nAllocLength,
_In_ int nCharSize) throw();
void Free(_Inout_ CStringData* pData) throw();
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize)
CStringData* Reallocate(
_Inout_ CStringData* pData,
_In_ int nAllocLength,
_In_ int nCharSize) throw();
CStringData* GetNilString() throw();
IAtlStringMgr* Clone() throw();
};
struct CStringData
void AddRef() throw()
{
IAtlStringMgr* pStringMgr;
int nDataLength;
int nAllocLength;
long nRefs;
ATLASSERT(nRefs > 0);
_InterlockedIncrement(&nRefs);
}
void* data() throw()
void Release() throw()
{
ATLASSERT(nRefs != 0);
if (_InterlockedDecrement(&nRefs) <= 0)
{
return (this + 1);
pStringMgr->Free(this);
}
}
void AddRef() throw()
bool IsLocked() const throw()
{
return (nRefs < 0);
}
bool IsShared() const throw()
{
return (nRefs > 1);
}
};
class CNilStringData :
public CStringData
{
public:
CNilStringData() throw()
{
pStringMgr = NULL;
nRefs = 2;
nDataLength = 0;
nAllocLength = 0;
achNil[0] = 0;
achNil[1] = 0;
}
void SetManager(_In_ IAtlStringMgr* pMgr) throw()
{
ATLASSERT(pStringMgr == NULL);
pStringMgr = pMgr;
}
public:
wchar_t achNil[2];
};
template< typename BaseType = char >
class ChTraitsBase
{
public:
typedef char XCHAR;
typedef LPSTR PXSTR;
typedef LPCSTR PCXSTR;
typedef wchar_t YCHAR;
typedef LPWSTR PYSTR;
typedef LPCWSTR PCYSTR;
};
template<>
class ChTraitsBase< wchar_t >
{
public:
typedef wchar_t XCHAR;
typedef LPWSTR PXSTR;
typedef LPCWSTR PCXSTR;
typedef char YCHAR;
typedef LPSTR PYSTR;
typedef LPCSTR PCYSTR;
};
template< typename BaseType, bool t_bMFCDLL = false>
class CSimpleStringT
{
private:
LPWSTR m_pszData;
public:
typedef typename ChTraitsBase<BaseType>::XCHAR XCHAR;
typedef typename ChTraitsBase<BaseType>::PXSTR PXSTR;
typedef typename ChTraitsBase<BaseType>::PCXSTR PCXSTR;
typedef typename ChTraitsBase<BaseType>::YCHAR YCHAR;
typedef typename ChTraitsBase<BaseType>::PYSTR PYSTR;
typedef typename ChTraitsBase<BaseType>::PCYSTR PCYSTR;
public:
explicit CSimpleStringT(_Inout_ IAtlStringMgr* pStringMgr)
{
CStringData* pData = pStringMgr->GetNilString();
Attach(pData);
}
CSimpleStringT(_In_ const CSimpleStringT& strSrc)
{
CStringData* pSrcData = strSrc.GetData();
CStringData* pNewData = CloneData(pSrcData);
Attach(pNewData);
}
CSimpleStringT(_In_ const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc)
{
CStringData* pSrcData = strSrc.GetData();
CStringData* pNewData = CloneData(pSrcData);
Attach(pNewData);
}
CSimpleStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
{
SetString(pszSrc);
return *this;
}
operator PCXSTR() const throw()
{
return m_pszData;
}
void Empty() throw()
{
CStringData* pOldData = GetData();
IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
if (pOldData->nDataLength == 0) return;
if (pOldData->IsLocked())
{
ATLASSERT(nRefs > 0);
_InterlockedIncrement(&nRefs);
SetLength(0);
}
void Release() throw()
else
{
ATLASSERT(nRefs != 0);
pOldData->Release();
CStringData* pNewData = pStringMgr->GetNilString();
Attach(pNewData);
}
}
if (_InterlockedDecrement(&nRefs) <= 0)
void SetString(_In_opt_z_ PCXSTR pszSrc)
{
SetString(pszSrc, StringLength(pszSrc));
}
void SetString(_In_reads_opt_(nLength) PCXSTR pszSrc,
_In_ int nLength)
{
if (nLength == 0)
{
Empty();
}
else
{
UINT nOldLength = GetLength();
UINT_PTR nOffset = pszSrc - GetString();
PXSTR pszBuffer = GetBuffer(nLength);
if (nOffset <= nOldLength)
{
pStringMgr->Free(this);
CopyCharsOverlapped(pszBuffer, GetAllocLength(),
pszBuffer + nOffset, nLength);
}
else
{
CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength);
}
ReleaseBufferSetLength(nLength);
}
};
}
template< typename BaseType = char >
class ChTraitsBase
static int __cdecl StringLength(_In_opt_z_ const wchar_t* psz) throw()
{
public:
typedef char XCHAR;
typedef LPSTR PXSTR;
typedef LPCSTR PCXSTR;
typedef wchar_t YCHAR;
typedef LPWSTR PYSTR;
typedef LPCWSTR PCYSTR;
};
if (psz == NULL) return 0;
return (int)wcslen(psz);
}
template<>
class ChTraitsBase< wchar_t >
PXSTR GetBuffer()
{
public:
typedef wchar_t XCHAR;
typedef LPWSTR PXSTR;
typedef LPCWSTR PCXSTR;
typedef char YCHAR;
typedef LPSTR PYSTR;
typedef LPCSTR PCYSTR;
};
CStringData* pData = GetData();
if (pData->IsShared())
{
// We should fork here
Fork(pData->nDataLength);
}
return m_pszData;
}
template< typename BaseType, bool t_bMFCDLL = false>
class CSimpleStringT
int GetAllocLength() const throw()
{
public:
typedef typename ChTraitsBase<BaseType>::XCHAR XCHAR;
typedef typename ChTraitsBase<BaseType>::PXSTR PXSTR;
typedef typename ChTraitsBase<BaseType>::PCXSTR PCXSTR;
typedef typename ChTraitsBase<BaseType>::YCHAR YCHAR;
typedef typename ChTraitsBase<BaseType>::PYSTR PYSTR;
typedef typename ChTraitsBase<BaseType>::PCYSTR PCYSTR;
return GetData()->nAllocLength;
}
public:
explicit CSimpleStringT(_Inout_ IAtlStringMgr* pStringMgr)
int GetLength() const throw()
{
return GetData()->nDataLength;
}
PCXSTR GetString() const throw()
{
return m_pszData;
}
void ReleaseBufferSetLength(_In_ int nNewLength)
{
ATLASSERT(nNewLength >= 0);
SetLength(nNewLength);
}
bool IsEmpty() const throw()
{
return (GetLength() == 0);
}
_Ret_notnull_ _Post_writable_size_(nMinBufferLength + 1) PXSTR GetBuffer(_In_ int nMinBufferLength)
{
return PrepareWrite(nMinBufferLength);
}
CStringData* GetData() const throw()
{
return reinterpret_cast<CStringData*>(m_pszData) - 1;
}
static void __cdecl CopyChars(
_Out_writes_to_(nDestLen, nChars) XCHAR* pchDest,
_In_ size_t nDestLen,
_In_reads_opt_(nChars) const XCHAR* pchSrc,
_In_ int nChars) throw()
{
memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
}
static void __cdecl CopyCharsOverlapped(
_Out_writes_to_(nDestLen, nDestLen) XCHAR* pchDest,
_In_ size_t nDestLen,
_In_reads_(nChars) const XCHAR* pchSrc,
_In_ int nChars) throw()
{
memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
}
private:
void Attach(_Inout_ CStringData* pData) throw()
{
m_pszData = static_cast<PXSTR>(pData->data());
}
__declspec(noinline) void Fork(_In_ int nLength)
{
CStringData* pOldData = GetData();
int nOldLength = pOldData->nDataLength;
CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate(nLength, sizeof(XCHAR));
if (pNewData == NULL)
{
ATLENSURE(pStringMgr != NULL);
CStringData* pData = pStringMgr->GetNilString();
Attach(pData);
throw; // ThrowMemoryException();
}
int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength) + 1;
CopyChars(PXSTR(pNewData->data()), nCharsToCopy,
PCXSTR(pOldData->data()), nCharsToCopy);
pNewData->nDataLength = nOldLength;
pOldData->Release();
Attach(pNewData);
}
PXSTR PrepareWrite(_In_ int nLength)
{
CStringData* pOldData = GetData();
int nShared = 1 - pOldData->nRefs;
int nTooShort = pOldData->nAllocLength - nLength;
if ((nShared | nTooShort) < 0)
{
PrepareWrite2(nLength);
}
CSimpleStringT(_In_ const CSimpleStringT& strSrc)
return m_pszData;
}
void PrepareWrite2(_In_ int nLength)
{
CStringData* pOldData = GetData();
if (pOldData->nDataLength > nLength)
{
CStringData* pSrcData = strSrc.GetData();
CStringData* pNewData = CloneData(pSrcData);
Attach(pNewData);
nLength = pOldData->nDataLength;
}
CSimpleStringT(_In_ const CSimpleStringT<BaseType, !t_bMFCDLL>& strSrc)
if (pOldData->IsShared())
{
CStringData* pSrcData = strSrc.GetData();
CStringData* pNewData = CloneData(pSrcData);
Attach(pNewData);
Fork(nLength);
ATLASSERT(FALSE);
}
operator PCXSTR() const throw()
else if (pOldData->nAllocLength < nLength)
{
return m_pszData;
int nNewLength = pOldData->nAllocLength;
if (nNewLength > 1024 * 1024 * 1024)
{
nNewLength += 1024 * 1024;
}
else
{
nNewLength = nNewLength + nNewLength / 2;
}
if (nNewLength < nLength)
{
nNewLength = nLength;
}
Reallocate(nNewLength);
}
}
};
void Reallocate(_In_ int nLength)
{
CStringData* pOldData = GetData();
ATLASSERT(pOldData->nAllocLength < nLength);
IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
if (pOldData->nAllocLength >= nLength || nLength <= 0)
{
return;
}
CStringData* pNewData = pStringMgr->Reallocate(pOldData, nLength, sizeof(XCHAR));
if (pNewData == NULL) throw;
Attach(pNewData);
}
void SetLength(_In_ int nLength)
{
ATLASSERT(nLength >= 0);
ATLASSERT(nLength <= GetData()->nAllocLength);
if (nLength < 0 || nLength > GetData()->nAllocLength)
throw;
GetData()->nDataLength = nLength;
m_pszData[nLength] = 0;
}
};
}
#endif

View file

@ -2,42 +2,128 @@
#define __ATLSTR_H__
#pragma once
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#include <atlbase.h>
#include <cstringt.h>
namespace ATL
{
template< typename _BaseType = char, class StringIterator = ChTraitsOS<_BaseType>>
class StrTraitATL :
public StringIterator
class CAtlStringMgr : public IAtlStringMgr
{
protected:
IAtlMemMgr* m_MemMgr;
CNilStringData m_NilStrData;
public:
CAtlStringMgr(_In_opt_ IAtlMemMgr* MemMgr = NULL):
m_MemMgr(MemMgr)
{
public:
static HINSTANCE FindStringResourceInstance(_In_ UINT nID) throw()
{
return(AtlFindStringResourceInstance(nID));
}
m_NilStrData.SetManager(this);
}
static IAtlStringMgr* GetDefaultManager() throw()
{
return CAtlStringMgr::GetInstance();
}
};
template< typename _CharType = wchar_t>
class ChTraitsOS :
public ChTraitsBase<_CharType>
virtual ~CAtlStringMgr(void)
{
protected:
}
public:
static IAtlStringMgr* GetInstance(void)
{
static CWin32Heap Win32Heap(::GetProcessHeap());
static CAtlStringMgr StringMgr(&Win32Heap);
return &StringMgr;
}
};
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + NumChars * CharSize) CStringData* Allocate(
_In_ int NumChars,
_In_ int CharSize)
{
size_t SizeBytes;
CStringData* StrData;
SizeBytes = sizeof(CStringData) + ((NumChars + 1) * CharSize);
StrData = static_cast<CStringData*>(m_MemMgr->Allocate(SizeBytes));
if (StrData == NULL) return NULL;
StrData->pStringMgr = this;
StrData->nRefs = 1;
StrData->nAllocLength = NumChars;
StrData->nDataLength = 0;
return StrData;
}
virtual void Free(_In_ CStringData* StrData)
{
ATLASSERT(StrData->pStringMgr == this);
m_MemMgr->Free(StrData);
}
virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nChars*nCharSize) CStringData* Reallocate(
_Inout_ _Post_readable_byte_size_(sizeof(CStringData)) CStringData* StrData,
_In_ int nChars,
_In_ int nCharSize) throw()
{
ATLASSERT(StrData->pStringMgr == this);
CStringData* pNewData;
ULONG SizeBytes;
ULONG nDataBytes;
nChars++;
nDataBytes = nChars * nCharSize;
SizeBytes = sizeof(CStringData) + nDataBytes;
pNewData = static_cast< CStringData* >(m_MemMgr->Reallocate(StrData, SizeBytes));
if (pNewData == NULL) return NULL;
pNewData->nAllocLength = nChars - 1;
return pNewData;
}
virtual CStringData* GetNilString() throw()
{
m_NilStrData.AddRef();
return &m_NilStrData;
}
virtual IAtlStringMgr* Clone() throw()
{
return this;
}
private:
static bool StaticInitialize()
{
GetInstance();
return true;
}
};
template<typename _BaseType = char, class StringIterator = ChTraitsOS<_BaseType>>
class StrTraitATL :
public StringIterator
{
public:
static HINSTANCE FindStringResourceInstance(_In_ UINT nID) throw()
{
return AtlFindStringResourceInstance(nID);
}
static IAtlStringMgr* GetDefaultManager() throw()
{
return CAtlStringMgr::GetInstance();
}
};
template< typename _CharType = wchar_t>
class ChTraitsOS :
public ChTraitsBase<_CharType>
{
protected:
public:
};
#ifndef _ATL_CSTRING_NO_CRT
typedef CStringT<wchar_t, StrTraitATL<wchar_t, ChTraitsCRT<wchar_t>>> CAtlStringW;

View file

@ -2,75 +2,122 @@
#define __CSTRINGT_H__
#pragma once
#include <atlsimpstr.h>
#include <stddef.h>
#include <stdio.h>
#include <wchar.h>
#include <atlmem.h>
namespace ATL
{
template< typename _CharType = wchar_t>
class ChTraitsCRT :
public ChTraitsBase<_CharType>
inline UINT WINAPI _AtlGetConversionACP() throw()
{
#ifdef _CONVERSION_DONT_USE_THREAD_LOCALE
return CP_ACP;
#else
return CP_THREAD_ACP;
#endif
}
template<typename _CharType = wchar_t>
class ChTraitsCRT : public ChTraitsBase<_CharType>
{
public:
static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw()
{
public:
};
namespace _CSTRING_IMPL_
{
template <typename _CharType, class StringTraits>
struct _MFCDLLTraitsCheck
{
const static bool c_bIsMFCDLLTraits = false;
};
return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1;
}
template< typename BaseType, class StringTraits>
class CStringT :
public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
static int __cdecl GetBaseTypeLength(
_In_reads_(nLength) LPCWSTR pszSource,
_In_ int nLength) throw()
{
public:
typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
typedef StringTraits StrTraits;
typedef typename CThisSimpleString::XCHAR XCHAR;
typedef typename CThisSimpleString::PXSTR PXSTR;
typedef typename CThisSimpleString::PCXSTR PCXSTR;
typedef typename CThisSimpleString::YCHAR YCHAR;
typedef typename CThisSimpleString::PYSTR PYSTR;
typedef typename CThisSimpleString::PCYSTR PCYSTR;
return ::WideCharToMultiByte(CP_THREAD_ACP, 0, pszSource, nLength, NULL, 0, NULL, NULL);
}
public:
CStringT() throw() :
CThisSimpleString(StringTraits::GetDefaultManager())
{
}
explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
CThisSimpleString(pStringMgr)
{
}
static void __cdecl ConvertToBaseType(
_Out_writes_(nDestLength) LPWSTR pszDest,
_In_ int nDestLength,
_In_ LPCWSTR pszSrc,
_In_ int nSrcLength = -1)
{
if (nSrcLength == -1)
nSrcLength = 1 + GetBaseTypeLength(pszSrc);
CStringT(_In_ const VARIANT& varSrc);
CStringT(
_In_ const VARIANT& varSrc,
_In_ IAtlStringMgr* pStringMgr);
wmemcpy(pszDest, pszSrc, nSrcLength);
}
};
static void __cdecl Construct(_In_ CStringT* pString)
{
new(pString)CStringT;
}
CStringT(_In_ const CStringT& strSrc) :
CThisSimpleString(strSrc)
{
}
namespace _CSTRING_IMPL_
{
template <typename _CharType, class StringTraits>
struct _MFCDLLTraitsCheck
{
const static bool c_bIsMFCDLLTraits = false;
};
}
template <typename BaseType, class StringTraits>
class CStringT :
public CSimpleStringT <BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits>
{
public:
typedef CSimpleStringT<BaseType, _CSTRING_IMPL_::_MFCDLLTraitsCheck<BaseType, StringTraits>::c_bIsMFCDLLTraits> CThisSimpleString;
typedef StringTraits StrTraits;
typedef typename CThisSimpleString::XCHAR XCHAR;
typedef typename CThisSimpleString::PXSTR PXSTR;
typedef typename CThisSimpleString::PCXSTR PCXSTR;
typedef typename CThisSimpleString::YCHAR YCHAR;
typedef typename CThisSimpleString::PYSTR PYSTR;
typedef typename CThisSimpleString::PCYSTR PCYSTR;
public:
CStringT() throw() :
CThisSimpleString(StringTraits::GetDefaultManager())
{
}
explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() :
CThisSimpleString(pStringMgr)
{
}
static void __cdecl Construct(_In_ CStringT* pString)
{
new pString (CStringT);
}
CStringT(_In_ const CStringT& strSrc) :
CThisSimpleString(strSrc)
{
}
CStringT& operator=(_In_opt_z_ PCXSTR pszSrc)
{
CThisSimpleString::operator=(pszSrc);
return *this;
}
_Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance,
_In_ UINT nID)
{
const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID);
if (pImage == NULL) return FALSE;
int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength);
PXSTR pszBuffer = GetBuffer(nLength);
StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength);
ReleaseBufferSetLength(nLength);
return TRUE;
}
};
} //namespace ATL