338 lines
6.2 KiB
C++
338 lines
6.2 KiB
C++
|
#pragma once
|
||
|
|
||
|
#define CRT_ALLOC 0
|
||
|
#define COM_ALLOC 1
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <shlwapi.h>
|
||
|
#include <util.h>
|
||
|
#include <objbase.h>
|
||
|
#include <cstrings.h>
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Minimal string class
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
// ctor
|
||
|
CString::CString()
|
||
|
{
|
||
|
_dwSig = 'NRTS';
|
||
|
_pwz = NULL;
|
||
|
_cc = 0;
|
||
|
_ccBuf = 0;
|
||
|
_eAlloc = CRT_Allocator;
|
||
|
_hr = S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ctor w/ allocator
|
||
|
CString::CString(AllocFlags eAlloc)
|
||
|
{
|
||
|
_dwSig = 'NRTS';
|
||
|
_pwz = NULL;
|
||
|
_cc = 0;
|
||
|
_ccBuf = 0;
|
||
|
_eAlloc = eAlloc;
|
||
|
_hr = S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// dtor
|
||
|
CString::~CString()
|
||
|
{
|
||
|
FreeBuffer();
|
||
|
}
|
||
|
|
||
|
// Allocations
|
||
|
HRESULT CString::ResizeBuffer(DWORD ccNew)
|
||
|
{
|
||
|
LPWSTR pwzNew = NULL;
|
||
|
DWORD ccOriginal = 0;
|
||
|
|
||
|
if (ccNew < _ccBuf)
|
||
|
return (_hr = S_OK);
|
||
|
|
||
|
if (_eAlloc == CRT_Allocator)
|
||
|
pwzNew = new WCHAR[ccNew];
|
||
|
else if (_eAlloc == COM_Allocator)
|
||
|
pwzNew = (LPWSTR) CoTaskMemAlloc(ccNew * sizeof(WCHAR));
|
||
|
|
||
|
if (!pwzNew)
|
||
|
return (_hr = E_OUTOFMEMORY);
|
||
|
|
||
|
if (_pwz && _cc)
|
||
|
memcpy(pwzNew, _pwz, _cc * sizeof(WCHAR));
|
||
|
|
||
|
ccOriginal = _cc;
|
||
|
|
||
|
FreeBuffer();
|
||
|
|
||
|
_pwz = pwzNew;
|
||
|
_cc = ccOriginal;
|
||
|
_ccBuf = ccNew;
|
||
|
|
||
|
return _hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Deallocations
|
||
|
VOID CString::FreeBuffer()
|
||
|
{
|
||
|
if (_eAlloc == CRT_Allocator)
|
||
|
{
|
||
|
SAFEDELETEARRAY(_pwz);
|
||
|
}
|
||
|
else if (_eAlloc == COM_Allocator)
|
||
|
{
|
||
|
if (_pwz)
|
||
|
CoTaskMemFree(_pwz);
|
||
|
_pwz = NULL;
|
||
|
}
|
||
|
_cc = 0;
|
||
|
_ccBuf = 0;
|
||
|
}
|
||
|
|
||
|
// assume control for a buffer.
|
||
|
HRESULT CString::TakeOwnership(WCHAR* pwz, DWORD cc)
|
||
|
{
|
||
|
if (!pwz)
|
||
|
return (_hr = E_INVALIDARG);
|
||
|
|
||
|
FreeBuffer();
|
||
|
_pwz = pwz;
|
||
|
|
||
|
if (cc)
|
||
|
_cc = _ccBuf = cc;
|
||
|
else
|
||
|
_cc = _ccBuf = lstrlen(_pwz) + 1;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CString::TakeOwnership(LPWSTR pwz)
|
||
|
{
|
||
|
return TakeOwnership(pwz, 0);
|
||
|
}
|
||
|
|
||
|
// Release control.
|
||
|
HRESULT CString::ReleaseOwnership()
|
||
|
{
|
||
|
_pwz = NULL;
|
||
|
_cc = _ccBuf = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// Direct copy assign from string.
|
||
|
HRESULT CString::Assign(LPWSTR pwzSource)
|
||
|
{
|
||
|
if (!pwzSource)
|
||
|
return(_hr = E_INVALIDARG);
|
||
|
|
||
|
FreeBuffer();
|
||
|
|
||
|
DWORD ccSource = lstrlen(pwzSource) + 1;
|
||
|
if (FAILED(_hr = ResizeBuffer(ccSource)))
|
||
|
return _hr;
|
||
|
|
||
|
_cc = ccSource;
|
||
|
memcpy(_pwz, pwzSource, _cc * sizeof(WCHAR));
|
||
|
return _hr;
|
||
|
}
|
||
|
|
||
|
// Direct copy assign from CString
|
||
|
HRESULT CString::Assign(CString& sSource)
|
||
|
{
|
||
|
return Assign(sSource._pwz);
|
||
|
}
|
||
|
|
||
|
// Append given wchar string.
|
||
|
HRESULT CString::Append(LPWSTR pwzSource)
|
||
|
{
|
||
|
DWORD ccSource, ccRequired;
|
||
|
|
||
|
if (!pwzSource)
|
||
|
return (_hr = E_INVALIDARG);
|
||
|
|
||
|
ccSource = lstrlen(pwzSource) + 1;
|
||
|
ccRequired = _cc + ccSource;
|
||
|
if (_cc)
|
||
|
ccRequired--;
|
||
|
|
||
|
if (FAILED(_hr = ResizeBuffer(ccRequired)))
|
||
|
return _hr;
|
||
|
|
||
|
memcpy(_pwz + (_cc ? _cc-1 : 0),
|
||
|
pwzSource, ccSource * sizeof(WCHAR));
|
||
|
|
||
|
_cc = ccRequired;
|
||
|
|
||
|
return _hr;
|
||
|
}
|
||
|
|
||
|
// Append given CString
|
||
|
HRESULT CString::Append(CString& sSource)
|
||
|
{
|
||
|
DWORD ccSource, ccRequired;
|
||
|
|
||
|
if ((!sSource._pwz)
|
||
|
|| (!(sSource._eAlloc == _eAlloc)))
|
||
|
return (_hr = E_INVALIDARG);
|
||
|
|
||
|
ccRequired = _cc + sSource._cc;
|
||
|
if (_cc)
|
||
|
ccRequired--;
|
||
|
|
||
|
if (FAILED(_hr = ResizeBuffer(ccRequired)))
|
||
|
return _hr;
|
||
|
|
||
|
memcpy(_pwz + (_cc ? _cc-1 : 0), sSource._pwz, sSource._cc * sizeof(WCHAR));
|
||
|
|
||
|
_cc = ccRequired;
|
||
|
return _hr;
|
||
|
}
|
||
|
|
||
|
// Return ith element.
|
||
|
WCHAR& CString::operator [] (DWORD i)
|
||
|
{
|
||
|
return _pwz[i];
|
||
|
}
|
||
|
|
||
|
|
||
|
// last element as string
|
||
|
HRESULT CString::LastElement(CString &sSource)
|
||
|
{
|
||
|
LPWSTR pwz = _pwz + _cc;
|
||
|
while ((pwz != _pwz) && (*pwz != L'\\') && (*pwz != L'/'))
|
||
|
pwz--;
|
||
|
|
||
|
sSource.Assign(pwz+1);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
// remove last element, also the L'\\' or L'/'
|
||
|
HRESULT CString::RemoveLastElement()
|
||
|
{
|
||
|
LPWSTR pwz = _pwz + _cc;
|
||
|
while ((pwz != _pwz) && (*pwz != L'\\') && (*pwz != L'/'))
|
||
|
pwz--;
|
||
|
|
||
|
*pwz = L'\0';
|
||
|
_cc = lstrlen(_pwz) + 1;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// shlwapi either path- or url-combine
|
||
|
HRESULT CString::Combine(LPWSTR pwzSource, BOOL fUrl)
|
||
|
{
|
||
|
LPWSTR pwzDir = NULL;
|
||
|
DWORD ccSource = 0, ccCombined = 0, dwFlags = 0;
|
||
|
ccSource = lstrlen(pwzSource) + 1;
|
||
|
ccCombined = _cc + ccSource;
|
||
|
|
||
|
if (FAILED(_hr = ResizeBuffer(ccCombined)))
|
||
|
return _hr;
|
||
|
|
||
|
pwzDir = WSTRDupDynamic(_pwz);
|
||
|
if (fUrl)
|
||
|
// see msdn on UrlCombine...
|
||
|
::UrlCombine(pwzDir, pwzSource, _pwz, &ccCombined, dwFlags);
|
||
|
else
|
||
|
::PathCombine(_pwz, pwzDir, pwzSource);
|
||
|
|
||
|
_cc = lstrlen(_pwz) + 1;
|
||
|
SAFEDELETEARRAY(pwzDir);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CString::PathCombine(LPWSTR pwzSource)
|
||
|
{
|
||
|
return Combine(pwzSource, FALSE);
|
||
|
}
|
||
|
|
||
|
HRESULT CString::PathCombine(CString &sSource)
|
||
|
{
|
||
|
return Combine(sSource._pwz, FALSE);
|
||
|
}
|
||
|
|
||
|
HRESULT CString::UrlCombine(LPWSTR pwzSource)
|
||
|
{
|
||
|
return Combine(pwzSource, TRUE);
|
||
|
}
|
||
|
|
||
|
HRESULT CString::UrlCombine(CString &sSource)
|
||
|
{
|
||
|
return Combine(sSource._pwz, TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CString::PathFindFileName(LPWSTR *ppwz)
|
||
|
{
|
||
|
*ppwz = ::PathFindFileName(_pwz);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CString::PathFindFileName(CString &sPath)
|
||
|
{
|
||
|
LPWSTR pwzFileName = NULL;
|
||
|
pwzFileName = ::PathFindFileName(_pwz);
|
||
|
sPath.Assign(pwzFileName);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CString::PathPrefixMatch(LPWSTR pwzPrefix)
|
||
|
{
|
||
|
DWORD ccPrefix = lstrlen(pwzPrefix);
|
||
|
if (!StrNCmpI(_pwz, pwzPrefix, ccPrefix))
|
||
|
return S_OK;
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
// / -> \ in string
|
||
|
VOID CString::PathNormalize()
|
||
|
{
|
||
|
LPWSTR ptr = _pwz;
|
||
|
|
||
|
while (*ptr)
|
||
|
{
|
||
|
if (*ptr == L'/')
|
||
|
*ptr = L'\\';
|
||
|
ptr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID CString::Get65599Hash(LPDWORD pdwHash, DWORD dwFlags)
|
||
|
{
|
||
|
ULONG TmpHashValue = 0;
|
||
|
|
||
|
if (pdwHash != NULL)
|
||
|
*pdwHash = 0;
|
||
|
|
||
|
DWORD cc = _cc;
|
||
|
LPWSTR pwz = _pwz;
|
||
|
|
||
|
if (dwFlags == CaseSensitive)
|
||
|
{
|
||
|
while (cc-- != 0)
|
||
|
{
|
||
|
WCHAR Char = *pwz++;
|
||
|
TmpHashValue = (TmpHashValue * 65599) + (WCHAR) ::CharUpperW((PWSTR) Char);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (cc-- != 0)
|
||
|
TmpHashValue = (TmpHashValue * 65599) + *pwz++;
|
||
|
}
|
||
|
|
||
|
*pdwHash = TmpHashValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|