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

  1. #pragma once
  2. #define CRT_ALLOC 0
  3. #define COM_ALLOC 1
  4. #include <windows.h>
  5. #include <shlwapi.h>
  6. #include <util.h>
  7. #include <objbase.h>
  8. #include <cstrings.h>
  9. //-----------------------------------------------------------------------------
  10. // Minimal string class
  11. //-----------------------------------------------------------------------------
  12. // ctor
  13. CString::CString()
  14. {
  15. _dwSig = 'NRTS';
  16. _pwz = NULL;
  17. _cc = 0;
  18. _ccBuf = 0;
  19. _eAlloc = CRT_Allocator;
  20. _hr = S_OK;
  21. }
  22. // ctor w/ allocator
  23. CString::CString(AllocFlags eAlloc)
  24. {
  25. _dwSig = 'NRTS';
  26. _pwz = NULL;
  27. _cc = 0;
  28. _ccBuf = 0;
  29. _eAlloc = eAlloc;
  30. _hr = S_OK;
  31. }
  32. // dtor
  33. CString::~CString()
  34. {
  35. FreeBuffer();
  36. }
  37. // Allocations
  38. HRESULT CString::ResizeBuffer(DWORD ccNew)
  39. {
  40. LPWSTR pwzNew = NULL;
  41. DWORD ccOriginal = 0;
  42. if (ccNew < _ccBuf)
  43. return (_hr = S_OK);
  44. if (_eAlloc == CRT_Allocator)
  45. pwzNew = new WCHAR[ccNew];
  46. else if (_eAlloc == COM_Allocator)
  47. pwzNew = (LPWSTR) CoTaskMemAlloc(ccNew * sizeof(WCHAR));
  48. if (!pwzNew)
  49. return (_hr = E_OUTOFMEMORY);
  50. if (_pwz && _cc)
  51. memcpy(pwzNew, _pwz, _cc * sizeof(WCHAR));
  52. ccOriginal = _cc;
  53. FreeBuffer();
  54. _pwz = pwzNew;
  55. _cc = ccOriginal;
  56. _ccBuf = ccNew;
  57. return _hr;
  58. }
  59. // Deallocations
  60. VOID CString::FreeBuffer()
  61. {
  62. if (_eAlloc == CRT_Allocator)
  63. {
  64. SAFEDELETEARRAY(_pwz);
  65. }
  66. else if (_eAlloc == COM_Allocator)
  67. {
  68. if (_pwz)
  69. CoTaskMemFree(_pwz);
  70. _pwz = NULL;
  71. }
  72. _cc = 0;
  73. _ccBuf = 0;
  74. }
  75. // assume control for a buffer.
  76. HRESULT CString::TakeOwnership(WCHAR* pwz, DWORD cc)
  77. {
  78. if (!pwz)
  79. return (_hr = E_INVALIDARG);
  80. FreeBuffer();
  81. _pwz = pwz;
  82. if (cc)
  83. _cc = _ccBuf = cc;
  84. else
  85. _cc = _ccBuf = lstrlen(_pwz) + 1;
  86. return S_OK;
  87. }
  88. HRESULT CString::TakeOwnership(LPWSTR pwz)
  89. {
  90. return TakeOwnership(pwz, 0);
  91. }
  92. // Release control.
  93. HRESULT CString::ReleaseOwnership()
  94. {
  95. _pwz = NULL;
  96. _cc = _ccBuf = 0;
  97. return S_OK;
  98. }
  99. // Direct copy assign from string.
  100. HRESULT CString::Assign(LPWSTR pwzSource)
  101. {
  102. if (!pwzSource)
  103. return(_hr = E_INVALIDARG);
  104. FreeBuffer();
  105. DWORD ccSource = lstrlen(pwzSource) + 1;
  106. if (FAILED(_hr = ResizeBuffer(ccSource)))
  107. return _hr;
  108. _cc = ccSource;
  109. memcpy(_pwz, pwzSource, _cc * sizeof(WCHAR));
  110. return _hr;
  111. }
  112. // Direct copy assign from CString
  113. HRESULT CString::Assign(CString& sSource)
  114. {
  115. return Assign(sSource._pwz);
  116. }
  117. // Append given wchar string.
  118. HRESULT CString::Append(LPWSTR pwzSource)
  119. {
  120. DWORD ccSource, ccRequired;
  121. if (!pwzSource)
  122. return (_hr = E_INVALIDARG);
  123. ccSource = lstrlen(pwzSource) + 1;
  124. ccRequired = _cc + ccSource;
  125. if (_cc)
  126. ccRequired--;
  127. if (FAILED(_hr = ResizeBuffer(ccRequired)))
  128. return _hr;
  129. memcpy(_pwz + (_cc ? _cc-1 : 0),
  130. pwzSource, ccSource * sizeof(WCHAR));
  131. _cc = ccRequired;
  132. return _hr;
  133. }
  134. // Append given CString
  135. HRESULT CString::Append(CString& sSource)
  136. {
  137. DWORD ccSource, ccRequired;
  138. if ((!sSource._pwz)
  139. || (!(sSource._eAlloc == _eAlloc)))
  140. return (_hr = E_INVALIDARG);
  141. ccRequired = _cc + sSource._cc;
  142. if (_cc)
  143. ccRequired--;
  144. if (FAILED(_hr = ResizeBuffer(ccRequired)))
  145. return _hr;
  146. memcpy(_pwz + (_cc ? _cc-1 : 0), sSource._pwz, sSource._cc * sizeof(WCHAR));
  147. _cc = ccRequired;
  148. return _hr;
  149. }
  150. // Return ith element.
  151. WCHAR& CString::operator [] (DWORD i)
  152. {
  153. return _pwz[i];
  154. }
  155. // last element as string
  156. HRESULT CString::LastElement(CString &sSource)
  157. {
  158. LPWSTR pwz = _pwz + _cc;
  159. while ((pwz != _pwz) && (*pwz != L'\\') && (*pwz != L'/'))
  160. pwz--;
  161. sSource.Assign(pwz+1);
  162. return S_OK;
  163. }
  164. // remove last element, also the L'\\' or L'/'
  165. HRESULT CString::RemoveLastElement()
  166. {
  167. LPWSTR pwz = _pwz + _cc;
  168. while ((pwz != _pwz) && (*pwz != L'\\') && (*pwz != L'/'))
  169. pwz--;
  170. *pwz = L'\0';
  171. _cc = lstrlen(_pwz) + 1;
  172. return S_OK;
  173. }
  174. // shlwapi either path- or url-combine
  175. HRESULT CString::Combine(LPWSTR pwzSource, BOOL fUrl)
  176. {
  177. LPWSTR pwzDir = NULL;
  178. DWORD ccSource = 0, ccCombined = 0, dwFlags = 0;
  179. ccSource = lstrlen(pwzSource) + 1;
  180. ccCombined = _cc + ccSource;
  181. if (FAILED(_hr = ResizeBuffer(ccCombined)))
  182. return _hr;
  183. pwzDir = WSTRDupDynamic(_pwz);
  184. if (fUrl)
  185. // see msdn on UrlCombine...
  186. ::UrlCombine(pwzDir, pwzSource, _pwz, &ccCombined, dwFlags);
  187. else
  188. ::PathCombine(_pwz, pwzDir, pwzSource);
  189. _cc = lstrlen(_pwz) + 1;
  190. SAFEDELETEARRAY(pwzDir);
  191. return S_OK;
  192. }
  193. HRESULT CString::PathCombine(LPWSTR pwzSource)
  194. {
  195. return Combine(pwzSource, FALSE);
  196. }
  197. HRESULT CString::PathCombine(CString &sSource)
  198. {
  199. return Combine(sSource._pwz, FALSE);
  200. }
  201. HRESULT CString::UrlCombine(LPWSTR pwzSource)
  202. {
  203. return Combine(pwzSource, TRUE);
  204. }
  205. HRESULT CString::UrlCombine(CString &sSource)
  206. {
  207. return Combine(sSource._pwz, TRUE);
  208. }
  209. HRESULT CString::PathFindFileName(LPWSTR *ppwz)
  210. {
  211. *ppwz = ::PathFindFileName(_pwz);
  212. return S_OK;
  213. }
  214. HRESULT CString::PathFindFileName(CString &sPath)
  215. {
  216. LPWSTR pwzFileName = NULL;
  217. pwzFileName = ::PathFindFileName(_pwz);
  218. sPath.Assign(pwzFileName);
  219. return S_OK;
  220. }
  221. HRESULT CString::PathPrefixMatch(LPWSTR pwzPrefix)
  222. {
  223. DWORD ccPrefix = lstrlen(pwzPrefix);
  224. if (!StrNCmpI(_pwz, pwzPrefix, ccPrefix))
  225. return S_OK;
  226. return S_FALSE;
  227. }
  228. // / -> \ in string
  229. VOID CString::PathNormalize()
  230. {
  231. LPWSTR ptr = _pwz;
  232. while (*ptr)
  233. {
  234. if (*ptr == L'/')
  235. *ptr = L'\\';
  236. ptr++;
  237. }
  238. }
  239. VOID CString::Get65599Hash(LPDWORD pdwHash, DWORD dwFlags)
  240. {
  241. ULONG TmpHashValue = 0;
  242. if (pdwHash != NULL)
  243. *pdwHash = 0;
  244. DWORD cc = _cc;
  245. LPWSTR pwz = _pwz;
  246. if (dwFlags == CaseSensitive)
  247. {
  248. while (cc-- != 0)
  249. {
  250. WCHAR Char = *pwz++;
  251. TmpHashValue = (TmpHashValue * 65599) + (WCHAR) ::CharUpperW((PWSTR) Char);
  252. }
  253. }
  254. else
  255. {
  256. while (cc-- != 0)
  257. TmpHashValue = (TmpHashValue * 65599) + *pwz++;
  258. }
  259. *pdwHash = TmpHashValue;
  260. }