Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

337 lines
6.2 KiB

#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;
}