Leaked source code of windows server 2003
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.
 
 
 
 
 
 

846 lines
21 KiB

#pragma once
// Two flavors of allocator.
#define CRT_ALLOC 0
#define COM_ALLOC 1
// Buffer alloc chungks must be a power of 2.
#define BUFFER_ALLOCATION_SIZE 0x40
#define ROUNDUPTOPOWEROF2(bytesize, powerof2) (((bytesize) + (powerof2) - 1) & ~((powerof2) - 1))
// MAXCHARCOUNT is nice for simple overflow calculations; it allows rollover checks only on the character
// counts themselves and not also again on the underlying byte counts passed to memcpy.
// Find the right include for this.
#define ULONG_MAX 0xffffffff
#define MAXCHARCOUNT (ULONG_MAX / sizeof(WCHAR))
#define BADMATH HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)
#define OVERFLOW_CHECK1(_x) do { if (_x > MAXCHARCOUNT) { _hr = BADMATH; ASSERT(PREDICATE); goto exit; } } while (0)
#define OVERFLOW_CHECK2(_x, _y) do { if ((_y > MAXCHARCOUNT) || (_y < _x)) { _hr = BADMATH; ASSERT(PREDICATE); goto exit; } } while (0)
#define DEFAULT_STACK_SIZE 32
//////////////////////////////////////////////////////////////////////////////
//
// CBaseString
//
//////////////////////////////////////////////////////////////////////////////
template <ULONG T> class CBaseString
{
public:
enum AllocFlags
{
COM_Allocator = 0,
CRT_Allocator
};
enum HashFlags
{
CaseInsensitive = 0,
CaseSensitive
};
DWORD _dwSig;
HRESULT _hr;
WCHAR _wz[T];
LPWSTR _pwz; // Str ptr.
DWORD _cc; // String length
DWORD _ccBuf; // Buffer length
AllocFlags _eAlloc; // Allocator
BOOL _fLocked; // Accessor lock
// ctor
CBaseString();
// ctor w/ allocator
CBaseString(AllocFlags eAlloc);
// dtor
~CBaseString();
operator LPCWSTR ( ) const;
// Used by accessor.
HRESULT Lock();
HRESULT UnLock();
// Allocations
HRESULT ResizeBuffer(DWORD ccNew);
// Deallocations
VOID FreeBuffer();
// Assume control for a buffer.
HRESULT TakeOwnership(WCHAR* pwz, DWORD cc = 0);
// Release control.
HRESULT ReleaseOwnership(LPWSTR *ppwz);
// Direct copy assign from string.
HRESULT Assign(LPCWSTR pwzSource, DWORD ccSource = 0);
// Direct copy assign from CBaseString
HRESULT Assign(CBaseString& sSource);
// Append given wchar string.
HRESULT Append(LPCWSTR pwzSource, DWORD ccSource = 0);
// Append given CBaseString
HRESULT Append(CBaseString& sSource);
// Append given number (DWORD)
HRESULT Append(DWORD dwValue);
// Compare to string
HRESULT CompareString(CBaseString& s);
HRESULT CompareString(LPCWSTR pwz);
HRESULT LastElement(CBaseString &sSource);
HRESULT RemoveLastElement();
HRESULT SplitLastElement(WCHAR wcSeparator, CBaseString &sSource);
HRESULT StartsWith(LPCWSTR pwzPrefix);
HRESULT EndsWith(LPCWSTR pwzSuffix);
DWORD ByteCount();
DWORD CharCount();
// / -> \ in string
HRESULT PathNormalize();
HRESULT GetHash(LPDWORD pdwhash, DWORD dwFlags);
HRESULT Get65599Hash(LPDWORD pdwHash, DWORD dwFlags);
};
//-----------------------------------------------------------------------------
// ctor
//-----------------------------------------------------------------------------
template<ULONG T> CBaseString<T>::CBaseString()
{
_dwSig = 'NRTS';
_wz[0] = 'L\0';
_pwz = NULL;
_cc = 0;
_ccBuf = 0;
_eAlloc = CRT_Allocator;
_hr = S_OK;
_fLocked = FALSE;
}
//-----------------------------------------------------------------------------
// ctor w/ allocator
//-----------------------------------------------------------------------------
template<ULONG T> CBaseString<T>::CBaseString(AllocFlags eAlloc)
{
_dwSig = 'NRTS';
_wz[0] = L'\0';
_pwz = NULL;
_cc = 0;
_ccBuf = 0;
_eAlloc = eAlloc;
_hr = S_OK;
_fLocked = FALSE;
}
//-----------------------------------------------------------------------------
// dtor
//-----------------------------------------------------------------------------
template<ULONG T> CBaseString<T>::~CBaseString()
{
FreeBuffer();
}
//-----------------------------------------------------------------------------
// operator LPCWSTR
//-----------------------------------------------------------------------------
template<ULONG T> CBaseString<T>::operator LPCWSTR () const
{
return _pwz;
}
//-----------------------------------------------------------------------------
// Lock
//-----------------------------------------------------------------------------
template<ULONG T>HRESULT CBaseString<T>::Lock()
{
IF_FALSE_EXIT(_fLocked != TRUE, E_UNEXPECTED);
_fLocked = TRUE;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Lock
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::UnLock()
{
IF_FALSE_EXIT(_fLocked != FALSE, E_UNEXPECTED);
_fLocked = FALSE;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// ResizeBuffer
// NOTICE: Does not decrease buffer size.
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::ResizeBuffer(DWORD ccNew)
{
LPWSTR pwzNew = NULL;
DWORD ccOriginal = 0;
DWORD ccNewRoundUp = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_TRUE_EXIT((ccNew <= _ccBuf), S_OK);
if (!_pwz && (ccNew <= T))
{
_pwz = _wz;
_ccBuf = T;
goto exit;
}
ccNewRoundUp = ROUNDUPTOPOWEROF2(ccNew, BUFFER_ALLOCATION_SIZE);
OVERFLOW_CHECK2(ccNew, ccNewRoundUp);
if (_eAlloc == CRT_Allocator)
pwzNew = new WCHAR[ccNewRoundUp];
else if (_eAlloc == COM_Allocator)
pwzNew = (LPWSTR) CoTaskMemAlloc(ccNewRoundUp * sizeof(WCHAR));
IF_ALLOC_FAILED_EXIT(pwzNew);
if (_pwz && _cc)
memcpy(pwzNew, _pwz, _cc * sizeof(WCHAR));
ccOriginal = _cc;
FreeBuffer();
_pwz = pwzNew;
_cc = ccOriginal;
_ccBuf = ccNewRoundUp;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// FreeBuffer
//-----------------------------------------------------------------------------
template<ULONG T> VOID CBaseString<T>::FreeBuffer()
{
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
if (_pwz == _wz)
goto exit;
if (_eAlloc == CRT_Allocator)
{
SAFEDELETEARRAY(_pwz);
}
else if (_eAlloc == COM_Allocator)
{
if (_pwz)
CoTaskMemFree(_pwz);
}
exit:
_pwz = NULL;
_cc = 0;
_ccBuf = 0;
return;
}
//-----------------------------------------------------------------------------
// TakeOwnership
//
// Working assumption here is that incoming buffer size if not
// specified is equal to strlen + 1. If it's bigger, that's fine but
// we won't know about the extra.
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::TakeOwnership(WCHAR* pwz, DWORD cc)
{
DWORD ccNew = 0, ccLen = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_NULL_EXIT(pwz, E_INVALIDARG);
OVERFLOW_CHECK1(cc);
if (cc)
{
ccNew = cc;
}
else
{
ccLen = lstrlen(pwz);
ccNew = ccLen+1;
OVERFLOW_CHECK2(ccLen, ccNew);
}
FreeBuffer();
_pwz = pwz;
_cc = _ccBuf = ccNew;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// ReleaseOwnership
//-----------------------------------------------------------------------------
template<ULONG T>HRESULT CBaseString<T>::ReleaseOwnership(LPWSTR *ppwz)
{
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
if (_pwz == _wz)
{
IF_ALLOC_FAILED_EXIT(*ppwz = new WCHAR[_ccBuf]);
memcpy(*ppwz, _wz, _ccBuf * sizeof(WCHAR));
}
else
*ppwz = _pwz;
_pwz = NULL;
_cc = 0;
_ccBuf = 0;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Assign
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Assign(LPCWSTR pwzSource, DWORD ccSource)
{
DWORD ccSourceLen = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_NULL_EXIT(pwzSource, E_INVALIDARG);
OVERFLOW_CHECK1(ccSource);
if (!ccSource)
{
ccSourceLen = lstrlen(pwzSource);
ccSource = ccSourceLen + 1;
OVERFLOW_CHECK2(ccSourceLen, ccSource);
}
IF_FAILED_EXIT(ResizeBuffer(ccSource));
_cc = ccSource;
memcpy(_pwz, pwzSource, _cc * sizeof(WCHAR));
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Assign
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Assign(CBaseString& sSource)
{
return Assign(sSource._pwz, sSource._cc);
}
//-----------------------------------------------------------------------------
// Append
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Append(LPCWSTR pwzSource, DWORD ccSource)
{
DWORD ccRequired = 0, ccSourceLen = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_NULL_EXIT(pwzSource, E_INVALIDARG);
OVERFLOW_CHECK1(ccSource);
if (!ccSource)
{
ccSourceLen = lstrlen(pwzSource);
ccSource = ccSourceLen + 1;
OVERFLOW_CHECK2(ccSourceLen, ccSource);
}
if (_cc)
{
ccRequired = _cc -1 + ccSource;
OVERFLOW_CHECK2(ccSource, ccRequired);
}
else
{
ccRequired = ccSource;
}
IF_FAILED_EXIT(ResizeBuffer(ccRequired));
memcpy(_pwz + (_cc ? _cc-1 : 0),
pwzSource, ccSource * sizeof(WCHAR));
_cc = ccRequired;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Append
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Append(CBaseString& sSource)
{
IF_NULL_EXIT(sSource._pwz, E_INVALIDARG);
IF_FAILED_EXIT(Append(sSource._pwz, sSource._cc));
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Append
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Append(DWORD dwValue)
{
LPWSTR pwzBuf = NULL;
// ISSUE-05/31/02-felixybc optimize by using internal buffer if not currently used
// 2^32 has 10 digits(base 10) + sign + '\0' = 12 WCHAR
IF_ALLOC_FAILED_EXIT(pwzBuf = new WCHAR[12]);
pwzBuf[0] = L'\0';
// ISSUE- check error?
_ultow(dwValue, pwzBuf, 10);
IF_FAILED_EXIT(Append(pwzBuf));
exit:
SAFEDELETEARRAY(pwzBuf);
return _hr;
}
//-----------------------------------------------------------------------------
// CompareString
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::CompareString(CBaseString& s)
{
return CompareString(s._pwz);
}
//-----------------------------------------------------------------------------
// CompareString
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::CompareString(LPCWSTR pwz)
{
DWORD iCompare = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
_pwz, -1, pwz, -1);
IF_WIN32_FALSE_EXIT(iCompare);
_hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// LastElement
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::LastElement(CBaseString<T> &sSource)
{
LPWSTR pwz = NULL;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
pwz = _pwz + _cc - 1;
while (1)
{
pwz = CharPrev(_pwz, pwz);
if (*pwz == L'\\' || *pwz == L'/')
break;
IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
}
sSource.Assign(pwz+1);
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// RemoveLastElement
// remove last element, also the L'\\' or L'/'
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::RemoveLastElement()
{
DWORD cc = 0;
LPWSTR pwz = NULL;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
pwz = _pwz + _cc - 1;
while (1)
{
pwz = CharPrev(_pwz, pwz);
cc++;
if (*pwz == L'\\' || *pwz == L'/' || (pwz == _pwz) )
break;
// IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
}
*pwz = L'\0';
_cc -= cc;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// SplitLastElement
// remove last element, also the separator
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::SplitLastElement(WCHAR wcSeparator, CBaseString &sSource)
{
DWORD cc = 0;
LPWSTR pwz = NULL;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
pwz = _pwz + _cc - 1;
while (1)
{
pwz = CharPrev(_pwz, pwz);
cc++;
if (*pwz == wcSeparator)
break;
IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
}
sSource.Assign(pwz+1);
*pwz = L'\0';
_cc -= cc;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// ByteCount
//-----------------------------------------------------------------------------
template<ULONG T> DWORD CBaseString<T>::ByteCount()
{
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
exit:
return (_cc * sizeof(WCHAR));
}
//-----------------------------------------------------------------------------
// CharCount
//-----------------------------------------------------------------------------
template<ULONG T> DWORD CBaseString<T>::CharCount()
{
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
exit:
return _cc;
}
//-----------------------------------------------------------------------------
// StartsWith
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::StartsWith(LPCWSTR pwzPrefix)
{
DWORD ccPrefixLen = 0, iCompare = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
IF_NULL_EXIT(pwzPrefix, E_INVALIDARG);
ccPrefixLen = lstrlen(pwzPrefix);
IF_FALSE_EXIT((ccPrefixLen < _cc-1), E_INVALIDARG);
iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
_pwz, ccPrefixLen, pwzPrefix, ccPrefixLen);
IF_WIN32_FALSE_EXIT(iCompare);
_hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// EndsWith
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::EndsWith(LPCWSTR pwzSuffix)
{
DWORD ccSuffixLen = 0, iCompare = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
IF_NULL_EXIT(pwzSuffix, E_INVALIDARG);
ccSuffixLen = lstrlen(pwzSuffix);
IF_FALSE_EXIT((ccSuffixLen < _cc-1), E_INVALIDARG);
iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
_pwz+_cc-ccSuffixLen, ccSuffixLen, pwzSuffix, ccSuffixLen);
IF_WIN32_FALSE_EXIT(iCompare);
_hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// PathNormalize
// / -> \ in string
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::PathNormalize()
{
LPWSTR pwz = NULL;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
pwz = _pwz;
if (*pwz == L'/')
*pwz = L'\\';
while ((pwz = CharNext(pwz)) && *pwz)
{
if (*pwz == L'/')
*pwz = L'\\';
}
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// GetHash
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::GetHash(LPDWORD pdwHash, DWORD dwFlags)
{
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
_hr = Get65599Hash(pdwHash, dwFlags);
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Get65599Hash
//-----------------------------------------------------------------------------
template<ULONG T> HRESULT CBaseString<T>::Get65599Hash(LPDWORD pdwHash, DWORD dwFlags)
{
ULONG TmpHashValue = 0;
DWORD cc = 0;
LPWSTR pwz = 0;
IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
if (pdwHash != NULL)
*pdwHash = 0;
cc = _cc;
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;
exit:
return _hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CString
//
//////////////////////////////////////////////////////////////////////////////
class CString : public CBaseString<DEFAULT_STACK_SIZE>
{
public:
CString() : CBaseString<DEFAULT_STACK_SIZE> (){}
CString(AllocFlags eAllocFlags) : CBaseString<DEFAULT_STACK_SIZE>(eAllocFlags) {}
};
//////////////////////////////////////////////////////////////////////////////
//
// CStringAccessor
//
//////////////////////////////////////////////////////////////////////////////
template<class T> class CStringAccessor
{
private:
HRESULT _hr;
T* _ps;
public:
CStringAccessor();
~CStringAccessor();
HRESULT Attach(T& s);
HRESULT Detach(DWORD cc = 0);
LPWSTR* operator &();
LPWSTR GetBuf();
};
//-----------------------------------------------------------------------------
// ctor
//-----------------------------------------------------------------------------
template<class T> CStringAccessor<T>::CStringAccessor()
: _ps(NULL), _hr(S_OK)
{}
//-----------------------------------------------------------------------------
// dtor
//-----------------------------------------------------------------------------
template<class T> CStringAccessor<T>::~CStringAccessor()
{}
//-----------------------------------------------------------------------------
// Attach
//-----------------------------------------------------------------------------
template<class T> HRESULT CStringAccessor<T>::Attach(T &s)
{
_ps = &s;
IF_FAILED_EXIT(_ps->Lock());
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// Detach
//-----------------------------------------------------------------------------
template<class T> HRESULT CStringAccessor<T>::Detach(DWORD cc)
{
DWORD ccLen = 0;
IF_NULL_EXIT(_ps, E_UNEXPECTED);
IF_NULL_EXIT(_ps->_pwz, E_UNEXPECTED);
if (!cc)
{
ccLen = lstrlen(_ps->_pwz);
cc = ccLen+1;
OVERFLOW_CHECK2(ccLen, cc);
}
else
{
IF_FALSE_EXIT((*(_ps->_pwz + cc - 1) == L'\0'), E_INVALIDARG);
}
_ps->_cc = _ps->_ccBuf = cc;
IF_FAILED_EXIT(_ps->UnLock());
exit:
return _hr;
}
//-----------------------------------------------------------------------------
// operator &
//-----------------------------------------------------------------------------
template<class T> LPWSTR* CStringAccessor<T>::operator &()
{
if (!_ps)
{
ASSERT(FALSE);
}
return (_ps ? &(_ps->_pwz) : NULL);
}
//-----------------------------------------------------------------------------
// GetBuf
//-----------------------------------------------------------------------------
template<class T> LPWSTR CStringAccessor<T>::GetBuf()
{
if (!_ps)
{
ASSERT(FALSE);
}
return (_ps ? (_ps->_pwz) : NULL);
}