📄 sphelper.h
字号:
/*******************************************************************************
* SPHelper.h *
*------------*
* Description:
* This is the header file for core helper functions implementation.
*-------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*******************************************************************************/
#ifndef SPHelper_h
#define SPHelper_h
#ifndef _INC_MALLOC
#include <malloc.h>
#endif
#ifndef _INC_CRTDBG
#include <crtdbg.h>
#endif
#ifndef __sapi_h__
#include <sapi.h>
#endif
#ifndef __sapiddk_h__
#include <sapiddk.h>
#endif
#ifndef SPError_h
#include <SPError.h>
#endif
#ifndef SPDebug_h
#include <SPDebug.h>
#endif
#ifndef _INC_LIMITS
#include <limits.h>
#endif
#ifndef _INC_MMSYSTEM
#include <mmsystem.h>
#endif
#ifndef __comcat_h__
#include <comcat.h>
#endif
#ifndef _INC_MMREG
#include <mmreg.h>
#endif
#ifndef __ATLBASE_H__
#include <atlbase.h>
#endif
//=== Constants ==============================================================
#define sp_countof(x) ((sizeof(x) / sizeof(*(x))))
/*** CSpDynamicString helper class
*
*/
class CSpDynamicString
{
public:
WCHAR * m_psz;
CSpDynamicString()
{
m_psz = NULL;
}
CSpDynamicString(ULONG cchReserve)
{
m_psz = (WCHAR *)::CoTaskMemAlloc(cchReserve * sizeof(WCHAR));
}
WCHAR * operator=(const CSpDynamicString& src)
{
if (m_psz != src.m_psz)
{
::CoTaskMemFree(m_psz);
m_psz = src.Copy();
}
return m_psz;
}
WCHAR * operator=(const WCHAR * pSrc)
{
Clear();
if (pSrc)
{
ULONG cbNeeded = (wcslen(pSrc) + 1) * sizeof(WCHAR);
m_psz = (WCHAR *)::CoTaskMemAlloc(cbNeeded);
SPDBG_ASSERT(m_psz);
if (m_psz)
{
memcpy(m_psz, pSrc, cbNeeded);
}
}
return m_psz;
}
WCHAR * operator=(const char * pSrc)
{
Clear();
if (pSrc)
{
ULONG cbNeeded = (lstrlenA(pSrc) + 1) * sizeof(WCHAR);
m_psz = (WCHAR *)::CoTaskMemAlloc(cbNeeded);
SPDBG_ASSERT(m_psz);
if (m_psz)
{
::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, m_psz, cbNeeded/sizeof(WCHAR));
}
}
return m_psz;
}
WCHAR * operator=(REFGUID rguid)
{
Clear();
::StringFromCLSID(rguid, &m_psz);
return m_psz;
}
/*explicit*/ CSpDynamicString(const WCHAR * pSrc)
{
m_psz = NULL;
operator=(pSrc);
}
/*explicit*/ CSpDynamicString(const char * pSrc)
{
m_psz = NULL;
operator=(pSrc);
}
/*explicit*/ CSpDynamicString(const CSpDynamicString& src)
{
m_psz = src.Copy();
}
/*explicit*/ CSpDynamicString(REFGUID rguid)
{
::StringFromCLSID(rguid, &m_psz);
}
~CSpDynamicString()
{
::CoTaskMemFree(m_psz);
}
unsigned int Length() const
{
return (m_psz == NULL)? 0 : wcslen(m_psz);
}
operator WCHAR * () const
{
return m_psz;
}
//The assert on operator& usually indicates a bug. If this is really
//what is needed, however, take the address of the m_psz member explicitly.
WCHAR ** operator&()
{
SPDBG_ASSERT(m_psz == NULL);
return &m_psz;
}
WCHAR * Append(const WCHAR * pszSrc)
{
if (pszSrc)
{
ULONG lenSrc = wcslen(pszSrc);
if (lenSrc)
{
ULONG lenMe = Length();
WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc + 1) * sizeof(WCHAR));
if (pszNew)
{
if (m_psz) // Could append to an empty string so check...
{
if (lenMe)
{
memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
}
::CoTaskMemFree(m_psz);
}
memcpy(pszNew + lenMe, pszSrc, (lenSrc + 1) * sizeof(WCHAR));
m_psz = pszNew;
}
else
{
SPDBG_ASSERT(FALSE);
}
}
}
return m_psz;
}
WCHAR * Append(const WCHAR * pszSrc, const ULONG lenSrc)
{
if (pszSrc && lenSrc)
{
ULONG lenMe = Length();
WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc + 1) * sizeof(WCHAR));
if (pszNew)
{
if (m_psz) // Could append to an empty string so check...
{
if (lenMe)
{
memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
}
::CoTaskMemFree(m_psz);
}
memcpy(pszNew + lenMe, pszSrc, lenSrc * sizeof(WCHAR));
*(pszNew + lenMe + lenSrc) = L'\0';
m_psz = pszNew;
}
else
{
SPDBG_ASSERT(FALSE);
}
}
return m_psz;
}
WCHAR * Append2(const WCHAR * pszSrc1, const WCHAR * pszSrc2)
{
ULONG lenSrc1 = pszSrc1 ? wcslen(pszSrc1) : 0;
ULONG lenSrc2 = pszSrc2 ? wcslen(pszSrc2) : 0;
if (lenSrc1 || lenSrc2)
{
ULONG lenMe = Length();
WCHAR *pszNew = (WCHAR *)::CoTaskMemAlloc((lenMe + lenSrc1 + lenSrc2 + 1) * sizeof(WCHAR));
if (pszNew)
{
if (m_psz) // Could append to an empty string so check...
{
if (lenMe)
{
memcpy(pszNew, m_psz, lenMe * sizeof(WCHAR));
}
::CoTaskMemFree(m_psz);
}
// In both of these cases, we copy the trailing NULL so that we're sure it gets
// there (if lenSrc2 is 0 then we better copy it from pszSrc1).
if (lenSrc1)
{
memcpy(pszNew + lenMe, pszSrc1, (lenSrc1 + 1) * sizeof(WCHAR));
}
if (lenSrc2)
{
memcpy(pszNew + lenMe + lenSrc1, pszSrc2, (lenSrc2 + 1) * sizeof(WCHAR));
}
m_psz = pszNew;
}
else
{
SPDBG_ASSERT(FALSE);
}
}
return m_psz;
}
WCHAR * Copy() const
{
if (m_psz)
{
CSpDynamicString szNew(m_psz);
return szNew.Detach();
}
return NULL;
}
CHAR * CopyToChar() const
{
if (m_psz)
{
CHAR* psz;
ULONG cbNeeded = ::WideCharToMultiByte(CP_ACP, 0, m_psz, -1, NULL, NULL, NULL, NULL);
psz = (CHAR *)::CoTaskMemAlloc(cbNeeded);
SPDBG_ASSERT(psz);
if (psz)
{
::WideCharToMultiByte(CP_ACP, 0, m_psz, -1, psz, cbNeeded/sizeof(CHAR), NULL, NULL);
}
return psz;
}
return NULL;
}
void Attach(WCHAR * pszSrc)
{
SPDBG_ASSERT(m_psz == NULL);
m_psz = pszSrc;
}
WCHAR * Detach()
{
WCHAR * s = m_psz;
m_psz = NULL;
return s;
}
void Clear()
{
::CoTaskMemFree(m_psz);
m_psz = NULL;
}
bool operator!() const
{
return (m_psz == NULL);
}
HRESULT CopyToBSTR(BSTR * pbstr)
{
if (m_psz)
{
*pbstr = ::SysAllocString(m_psz);
if (*pbstr == NULL)
{
return E_OUTOFMEMORY;
}
}
else
{
*pbstr = NULL;
}
return S_OK;
}
void TrimToSize(ULONG ulNumChars)
{
if (m_psz && ulNumChars < Length())
{
m_psz[ulNumChars] = 0;
}
}
WCHAR * Compact()
{
if (m_psz)
{
ULONG cch = wcslen(m_psz);
m_psz = (WCHAR *)::CoTaskMemRealloc(m_psz, (cch + 1) * sizeof(WCHAR));
}
return m_psz;
}
WCHAR * ClearAndGrowTo(ULONG cch)
{
if (m_psz)
{
Clear();
}
m_psz = (WCHAR *)::CoTaskMemAlloc(cch * sizeof(WCHAR));
return m_psz;
}
WCHAR * LTrim()
{
if (m_psz)
{
WCHAR * pszRead = m_psz;
while (iswspace(*pszRead))
{
pszRead++;
}
if (pszRead != m_psz)
{
WCHAR * pszWrite = m_psz;
while (*pszRead)
{
*pszWrite++ = *pszRead++;
}
*pszWrite = '\0';
}
}
return m_psz;
}
WCHAR * RTrim()
{
if (m_psz)
{
WCHAR * pszTail = m_psz + wcslen(m_psz);
WCHAR * pszZeroTerm = pszTail;
while (pszZeroTerm > m_psz && iswspace(pszZeroTerm[-1]))
{
pszZeroTerm--;
}
if (pszZeroTerm != pszTail)
{
*pszZeroTerm = '\0';
}
}
return m_psz;
}
WCHAR * TrimBoth()
{
RTrim();
return LTrim();
}
};
//
// Simple inline function converts a ulong to a hex string.
//
inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
{
const static WCHAR szHexChars[] = L"0123456789ABCDEF";
if (ul == 0)
{
psz[0] = L'0';
psz[1] = 0;
}
else
{
ULONG ulChars = 1;
psz[0] = 0;
while (ul)
{
memmove(psz + 1, psz, ulChars * sizeof(WCHAR));
psz[0] = szHexChars[ul % 16];
ul /= 16;
ulChars++;
}
}
}
//=== Token helpers
inline HRESULT SpGetTokenFromId(
const WCHAR * pszTokenId,
ISpObjectToken ** ppToken,
BOOL fCreateIfNotExist = FALSE)
{
SPDBG_FUNC("SpGetTokenFromId");
HRESULT hr;
CComPtr<ISpObjectToken> cpToken;
hr = cpToken.CoCreateInstance(CLSID_SpObjectToken);
if (SUCCEEDED(hr))
{
hr = cpToken->SetId(NULL, pszTokenId, fCreateIfNotExist);
}
if (SUCCEEDED(hr))
{
*ppToken = cpToken.Detach();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -