#pragma once #define CRT_ALLOC 0 #define COM_ALLOC 1 #include #include #include #include #include //----------------------------------------------------------------------------- // 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; }