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

  1. #pragma once
  2. // Two flavors of allocator.
  3. #define CRT_ALLOC 0
  4. #define COM_ALLOC 1
  5. // Buffer alloc chungks must be a power of 2.
  6. #define BUFFER_ALLOCATION_SIZE 0x40
  7. #define ROUNDUPTOPOWEROF2(bytesize, powerof2) (((bytesize) + (powerof2) - 1) & ~((powerof2) - 1))
  8. // MAXCHARCOUNT is nice for simple overflow calculations; it allows rollover checks only on the character
  9. // counts themselves and not also again on the underlying byte counts passed to memcpy.
  10. // Find the right include for this.
  11. #define ULONG_MAX 0xffffffff
  12. #define MAXCHARCOUNT (ULONG_MAX / sizeof(WCHAR))
  13. #define BADMATH HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)
  14. #define OVERFLOW_CHECK1(_x) do { if (_x > MAXCHARCOUNT) { _hr = BADMATH; ASSERT(PREDICATE); goto exit; } } while (0)
  15. #define OVERFLOW_CHECK2(_x, _y) do { if ((_y > MAXCHARCOUNT) || (_y < _x)) { _hr = BADMATH; ASSERT(PREDICATE); goto exit; } } while (0)
  16. #define DEFAULT_STACK_SIZE 32
  17. //////////////////////////////////////////////////////////////////////////////
  18. //
  19. // CBaseString
  20. //
  21. //////////////////////////////////////////////////////////////////////////////
  22. template <ULONG T> class CBaseString
  23. {
  24. public:
  25. enum AllocFlags
  26. {
  27. COM_Allocator = 0,
  28. CRT_Allocator
  29. };
  30. enum HashFlags
  31. {
  32. CaseInsensitive = 0,
  33. CaseSensitive
  34. };
  35. DWORD _dwSig;
  36. HRESULT _hr;
  37. WCHAR _wz[T];
  38. LPWSTR _pwz; // Str ptr.
  39. DWORD _cc; // String length
  40. DWORD _ccBuf; // Buffer length
  41. AllocFlags _eAlloc; // Allocator
  42. BOOL _fLocked; // Accessor lock
  43. // ctor
  44. CBaseString();
  45. // ctor w/ allocator
  46. CBaseString(AllocFlags eAlloc);
  47. // dtor
  48. ~CBaseString();
  49. operator LPCWSTR ( ) const;
  50. // Used by accessor.
  51. HRESULT Lock();
  52. HRESULT UnLock();
  53. // Allocations
  54. HRESULT ResizeBuffer(DWORD ccNew);
  55. // Deallocations
  56. VOID FreeBuffer();
  57. // Assume control for a buffer.
  58. HRESULT TakeOwnership(WCHAR* pwz, DWORD cc = 0);
  59. // Release control.
  60. HRESULT ReleaseOwnership(LPWSTR *ppwz);
  61. // Direct copy assign from string.
  62. HRESULT Assign(LPCWSTR pwzSource, DWORD ccSource = 0);
  63. // Direct copy assign from CBaseString
  64. HRESULT Assign(CBaseString& sSource);
  65. // Append given wchar string.
  66. HRESULT Append(LPCWSTR pwzSource, DWORD ccSource = 0);
  67. // Append given CBaseString
  68. HRESULT Append(CBaseString& sSource);
  69. // Append given number (DWORD)
  70. HRESULT Append(DWORD dwValue);
  71. // Compare to string
  72. HRESULT CompareString(CBaseString& s);
  73. HRESULT CompareString(LPCWSTR pwz);
  74. HRESULT LastElement(CBaseString &sSource);
  75. HRESULT RemoveLastElement();
  76. HRESULT SplitLastElement(WCHAR wcSeparator, CBaseString &sSource);
  77. HRESULT StartsWith(LPCWSTR pwzPrefix);
  78. HRESULT EndsWith(LPCWSTR pwzSuffix);
  79. DWORD ByteCount();
  80. DWORD CharCount();
  81. // / -> \ in string
  82. HRESULT PathNormalize();
  83. HRESULT GetHash(LPDWORD pdwhash, DWORD dwFlags);
  84. HRESULT Get65599Hash(LPDWORD pdwHash, DWORD dwFlags);
  85. };
  86. //-----------------------------------------------------------------------------
  87. // ctor
  88. //-----------------------------------------------------------------------------
  89. template<ULONG T> CBaseString<T>::CBaseString()
  90. {
  91. _dwSig = 'NRTS';
  92. _wz[0] = 'L\0';
  93. _pwz = NULL;
  94. _cc = 0;
  95. _ccBuf = 0;
  96. _eAlloc = CRT_Allocator;
  97. _hr = S_OK;
  98. _fLocked = FALSE;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // ctor w/ allocator
  102. //-----------------------------------------------------------------------------
  103. template<ULONG T> CBaseString<T>::CBaseString(AllocFlags eAlloc)
  104. {
  105. _dwSig = 'NRTS';
  106. _wz[0] = L'\0';
  107. _pwz = NULL;
  108. _cc = 0;
  109. _ccBuf = 0;
  110. _eAlloc = eAlloc;
  111. _hr = S_OK;
  112. _fLocked = FALSE;
  113. }
  114. //-----------------------------------------------------------------------------
  115. // dtor
  116. //-----------------------------------------------------------------------------
  117. template<ULONG T> CBaseString<T>::~CBaseString()
  118. {
  119. FreeBuffer();
  120. }
  121. //-----------------------------------------------------------------------------
  122. // operator LPCWSTR
  123. //-----------------------------------------------------------------------------
  124. template<ULONG T> CBaseString<T>::operator LPCWSTR () const
  125. {
  126. return _pwz;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Lock
  130. //-----------------------------------------------------------------------------
  131. template<ULONG T>HRESULT CBaseString<T>::Lock()
  132. {
  133. IF_FALSE_EXIT(_fLocked != TRUE, E_UNEXPECTED);
  134. _fLocked = TRUE;
  135. exit:
  136. return _hr;
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Lock
  140. //-----------------------------------------------------------------------------
  141. template<ULONG T> HRESULT CBaseString<T>::UnLock()
  142. {
  143. IF_FALSE_EXIT(_fLocked != FALSE, E_UNEXPECTED);
  144. _fLocked = FALSE;
  145. exit:
  146. return _hr;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // ResizeBuffer
  150. // NOTICE: Does not decrease buffer size.
  151. //-----------------------------------------------------------------------------
  152. template<ULONG T> HRESULT CBaseString<T>::ResizeBuffer(DWORD ccNew)
  153. {
  154. LPWSTR pwzNew = NULL;
  155. DWORD ccOriginal = 0;
  156. DWORD ccNewRoundUp = 0;
  157. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  158. IF_TRUE_EXIT((ccNew <= _ccBuf), S_OK);
  159. if (!_pwz && (ccNew <= T))
  160. {
  161. _pwz = _wz;
  162. _ccBuf = T;
  163. goto exit;
  164. }
  165. ccNewRoundUp = ROUNDUPTOPOWEROF2(ccNew, BUFFER_ALLOCATION_SIZE);
  166. OVERFLOW_CHECK2(ccNew, ccNewRoundUp);
  167. if (_eAlloc == CRT_Allocator)
  168. pwzNew = new WCHAR[ccNewRoundUp];
  169. else if (_eAlloc == COM_Allocator)
  170. pwzNew = (LPWSTR) CoTaskMemAlloc(ccNewRoundUp * sizeof(WCHAR));
  171. IF_ALLOC_FAILED_EXIT(pwzNew);
  172. if (_pwz && _cc)
  173. memcpy(pwzNew, _pwz, _cc * sizeof(WCHAR));
  174. ccOriginal = _cc;
  175. FreeBuffer();
  176. _pwz = pwzNew;
  177. _cc = ccOriginal;
  178. _ccBuf = ccNewRoundUp;
  179. exit:
  180. return _hr;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // FreeBuffer
  184. //-----------------------------------------------------------------------------
  185. template<ULONG T> VOID CBaseString<T>::FreeBuffer()
  186. {
  187. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  188. if (_pwz == _wz)
  189. goto exit;
  190. if (_eAlloc == CRT_Allocator)
  191. {
  192. SAFEDELETEARRAY(_pwz);
  193. }
  194. else if (_eAlloc == COM_Allocator)
  195. {
  196. if (_pwz)
  197. CoTaskMemFree(_pwz);
  198. }
  199. exit:
  200. _pwz = NULL;
  201. _cc = 0;
  202. _ccBuf = 0;
  203. return;
  204. }
  205. //-----------------------------------------------------------------------------
  206. // TakeOwnership
  207. //
  208. // Working assumption here is that incoming buffer size if not
  209. // specified is equal to strlen + 1. If it's bigger, that's fine but
  210. // we won't know about the extra.
  211. //-----------------------------------------------------------------------------
  212. template<ULONG T> HRESULT CBaseString<T>::TakeOwnership(WCHAR* pwz, DWORD cc)
  213. {
  214. DWORD ccNew = 0, ccLen = 0;
  215. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  216. IF_NULL_EXIT(pwz, E_INVALIDARG);
  217. OVERFLOW_CHECK1(cc);
  218. if (cc)
  219. {
  220. ccNew = cc;
  221. }
  222. else
  223. {
  224. ccLen = lstrlen(pwz);
  225. ccNew = ccLen+1;
  226. OVERFLOW_CHECK2(ccLen, ccNew);
  227. }
  228. FreeBuffer();
  229. _pwz = pwz;
  230. _cc = _ccBuf = ccNew;
  231. exit:
  232. return _hr;
  233. }
  234. //-----------------------------------------------------------------------------
  235. // ReleaseOwnership
  236. //-----------------------------------------------------------------------------
  237. template<ULONG T>HRESULT CBaseString<T>::ReleaseOwnership(LPWSTR *ppwz)
  238. {
  239. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  240. if (_pwz == _wz)
  241. {
  242. IF_ALLOC_FAILED_EXIT(*ppwz = new WCHAR[_ccBuf]);
  243. memcpy(*ppwz, _wz, _ccBuf * sizeof(WCHAR));
  244. }
  245. else
  246. *ppwz = _pwz;
  247. _pwz = NULL;
  248. _cc = 0;
  249. _ccBuf = 0;
  250. exit:
  251. return _hr;
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Assign
  255. //-----------------------------------------------------------------------------
  256. template<ULONG T> HRESULT CBaseString<T>::Assign(LPCWSTR pwzSource, DWORD ccSource)
  257. {
  258. DWORD ccSourceLen = 0;
  259. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  260. IF_NULL_EXIT(pwzSource, E_INVALIDARG);
  261. OVERFLOW_CHECK1(ccSource);
  262. if (!ccSource)
  263. {
  264. ccSourceLen = lstrlen(pwzSource);
  265. ccSource = ccSourceLen + 1;
  266. OVERFLOW_CHECK2(ccSourceLen, ccSource);
  267. }
  268. IF_FAILED_EXIT(ResizeBuffer(ccSource));
  269. _cc = ccSource;
  270. memcpy(_pwz, pwzSource, _cc * sizeof(WCHAR));
  271. exit:
  272. return _hr;
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Assign
  276. //-----------------------------------------------------------------------------
  277. template<ULONG T> HRESULT CBaseString<T>::Assign(CBaseString& sSource)
  278. {
  279. return Assign(sSource._pwz, sSource._cc);
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Append
  283. //-----------------------------------------------------------------------------
  284. template<ULONG T> HRESULT CBaseString<T>::Append(LPCWSTR pwzSource, DWORD ccSource)
  285. {
  286. DWORD ccRequired = 0, ccSourceLen = 0;
  287. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  288. IF_NULL_EXIT(pwzSource, E_INVALIDARG);
  289. OVERFLOW_CHECK1(ccSource);
  290. if (!ccSource)
  291. {
  292. ccSourceLen = lstrlen(pwzSource);
  293. ccSource = ccSourceLen + 1;
  294. OVERFLOW_CHECK2(ccSourceLen, ccSource);
  295. }
  296. if (_cc)
  297. {
  298. ccRequired = _cc -1 + ccSource;
  299. OVERFLOW_CHECK2(ccSource, ccRequired);
  300. }
  301. else
  302. {
  303. ccRequired = ccSource;
  304. }
  305. IF_FAILED_EXIT(ResizeBuffer(ccRequired));
  306. memcpy(_pwz + (_cc ? _cc-1 : 0),
  307. pwzSource, ccSource * sizeof(WCHAR));
  308. _cc = ccRequired;
  309. exit:
  310. return _hr;
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Append
  314. //-----------------------------------------------------------------------------
  315. template<ULONG T> HRESULT CBaseString<T>::Append(CBaseString& sSource)
  316. {
  317. IF_NULL_EXIT(sSource._pwz, E_INVALIDARG);
  318. IF_FAILED_EXIT(Append(sSource._pwz, sSource._cc));
  319. exit:
  320. return _hr;
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Append
  324. //-----------------------------------------------------------------------------
  325. template<ULONG T> HRESULT CBaseString<T>::Append(DWORD dwValue)
  326. {
  327. LPWSTR pwzBuf = NULL;
  328. // ISSUE-05/31/02-felixybc optimize by using internal buffer if not currently used
  329. // 2^32 has 10 digits(base 10) + sign + '\0' = 12 WCHAR
  330. IF_ALLOC_FAILED_EXIT(pwzBuf = new WCHAR[12]);
  331. pwzBuf[0] = L'\0';
  332. // ISSUE- check error?
  333. _ultow(dwValue, pwzBuf, 10);
  334. IF_FAILED_EXIT(Append(pwzBuf));
  335. exit:
  336. SAFEDELETEARRAY(pwzBuf);
  337. return _hr;
  338. }
  339. //-----------------------------------------------------------------------------
  340. // CompareString
  341. //-----------------------------------------------------------------------------
  342. template<ULONG T> HRESULT CBaseString<T>::CompareString(CBaseString& s)
  343. {
  344. return CompareString(s._pwz);
  345. }
  346. //-----------------------------------------------------------------------------
  347. // CompareString
  348. //-----------------------------------------------------------------------------
  349. template<ULONG T> HRESULT CBaseString<T>::CompareString(LPCWSTR pwz)
  350. {
  351. DWORD iCompare = 0;
  352. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  353. iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
  354. _pwz, -1, pwz, -1);
  355. IF_WIN32_FALSE_EXIT(iCompare);
  356. _hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
  357. exit:
  358. return _hr;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // LastElement
  362. //-----------------------------------------------------------------------------
  363. template<ULONG T> HRESULT CBaseString<T>::LastElement(CBaseString<T> &sSource)
  364. {
  365. LPWSTR pwz = NULL;
  366. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  367. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  368. pwz = _pwz + _cc - 1;
  369. while (1)
  370. {
  371. pwz = CharPrev(_pwz, pwz);
  372. if (*pwz == L'\\' || *pwz == L'/')
  373. break;
  374. IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
  375. }
  376. sSource.Assign(pwz+1);
  377. exit:
  378. return _hr;
  379. }
  380. //-----------------------------------------------------------------------------
  381. // RemoveLastElement
  382. // remove last element, also the L'\\' or L'/'
  383. //-----------------------------------------------------------------------------
  384. template<ULONG T> HRESULT CBaseString<T>::RemoveLastElement()
  385. {
  386. DWORD cc = 0;
  387. LPWSTR pwz = NULL;
  388. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  389. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  390. pwz = _pwz + _cc - 1;
  391. while (1)
  392. {
  393. pwz = CharPrev(_pwz, pwz);
  394. cc++;
  395. if (*pwz == L'\\' || *pwz == L'/' || (pwz == _pwz) )
  396. break;
  397. // IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
  398. }
  399. *pwz = L'\0';
  400. _cc -= cc;
  401. exit:
  402. return _hr;
  403. }
  404. //-----------------------------------------------------------------------------
  405. // SplitLastElement
  406. // remove last element, also the separator
  407. //-----------------------------------------------------------------------------
  408. template<ULONG T> HRESULT CBaseString<T>::SplitLastElement(WCHAR wcSeparator, CBaseString &sSource)
  409. {
  410. DWORD cc = 0;
  411. LPWSTR pwz = NULL;
  412. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  413. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  414. pwz = _pwz + _cc - 1;
  415. while (1)
  416. {
  417. pwz = CharPrev(_pwz, pwz);
  418. cc++;
  419. if (*pwz == wcSeparator)
  420. break;
  421. IF_FALSE_EXIT((pwz != _pwz), E_FAIL);
  422. }
  423. sSource.Assign(pwz+1);
  424. *pwz = L'\0';
  425. _cc -= cc;
  426. exit:
  427. return _hr;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // ByteCount
  431. //-----------------------------------------------------------------------------
  432. template<ULONG T> DWORD CBaseString<T>::ByteCount()
  433. {
  434. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  435. exit:
  436. return (_cc * sizeof(WCHAR));
  437. }
  438. //-----------------------------------------------------------------------------
  439. // CharCount
  440. //-----------------------------------------------------------------------------
  441. template<ULONG T> DWORD CBaseString<T>::CharCount()
  442. {
  443. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  444. exit:
  445. return _cc;
  446. }
  447. //-----------------------------------------------------------------------------
  448. // StartsWith
  449. //-----------------------------------------------------------------------------
  450. template<ULONG T> HRESULT CBaseString<T>::StartsWith(LPCWSTR pwzPrefix)
  451. {
  452. DWORD ccPrefixLen = 0, iCompare = 0;
  453. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  454. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  455. IF_NULL_EXIT(pwzPrefix, E_INVALIDARG);
  456. ccPrefixLen = lstrlen(pwzPrefix);
  457. IF_FALSE_EXIT((ccPrefixLen < _cc-1), E_INVALIDARG);
  458. iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
  459. _pwz, ccPrefixLen, pwzPrefix, ccPrefixLen);
  460. IF_WIN32_FALSE_EXIT(iCompare);
  461. _hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
  462. exit:
  463. return _hr;
  464. }
  465. //-----------------------------------------------------------------------------
  466. // EndsWith
  467. //-----------------------------------------------------------------------------
  468. template<ULONG T> HRESULT CBaseString<T>::EndsWith(LPCWSTR pwzSuffix)
  469. {
  470. DWORD ccSuffixLen = 0, iCompare = 0;
  471. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  472. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  473. IF_NULL_EXIT(pwzSuffix, E_INVALIDARG);
  474. ccSuffixLen = lstrlen(pwzSuffix);
  475. IF_FALSE_EXIT((ccSuffixLen < _cc-1), E_INVALIDARG);
  476. iCompare = ::CompareString(LOCALE_USER_DEFAULT, 0,
  477. _pwz+_cc-ccSuffixLen, ccSuffixLen, pwzSuffix, ccSuffixLen);
  478. IF_WIN32_FALSE_EXIT(iCompare);
  479. _hr = (iCompare == CSTR_EQUAL) ? S_OK : S_FALSE;
  480. exit:
  481. return _hr;
  482. }
  483. //-----------------------------------------------------------------------------
  484. // PathNormalize
  485. // / -> \ in string
  486. //-----------------------------------------------------------------------------
  487. template<ULONG T> HRESULT CBaseString<T>::PathNormalize()
  488. {
  489. LPWSTR pwz = NULL;
  490. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  491. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  492. pwz = _pwz;
  493. if (*pwz == L'/')
  494. *pwz = L'\\';
  495. while ((pwz = CharNext(pwz)) && *pwz)
  496. {
  497. if (*pwz == L'/')
  498. *pwz = L'\\';
  499. }
  500. exit:
  501. return _hr;
  502. }
  503. //-----------------------------------------------------------------------------
  504. // GetHash
  505. //-----------------------------------------------------------------------------
  506. template<ULONG T> HRESULT CBaseString<T>::GetHash(LPDWORD pdwHash, DWORD dwFlags)
  507. {
  508. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  509. _hr = Get65599Hash(pdwHash, dwFlags);
  510. exit:
  511. return _hr;
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Get65599Hash
  515. //-----------------------------------------------------------------------------
  516. template<ULONG T> HRESULT CBaseString<T>::Get65599Hash(LPDWORD pdwHash, DWORD dwFlags)
  517. {
  518. ULONG TmpHashValue = 0;
  519. DWORD cc = 0;
  520. LPWSTR pwz = 0;
  521. IF_FALSE_EXIT(!_fLocked, E_UNEXPECTED);
  522. IF_FALSE_EXIT((_pwz && _cc), E_UNEXPECTED);
  523. if (pdwHash != NULL)
  524. *pdwHash = 0;
  525. cc = _cc;
  526. pwz = _pwz;
  527. if (dwFlags == CaseSensitive)
  528. {
  529. while (cc-- != 0)
  530. {
  531. WCHAR Char = *pwz++;
  532. TmpHashValue = (TmpHashValue * 65599) + (WCHAR) ::CharUpperW((PWSTR) Char);
  533. }
  534. }
  535. else
  536. {
  537. while (cc-- != 0)
  538. TmpHashValue = (TmpHashValue * 65599) + *pwz++;
  539. }
  540. *pdwHash = TmpHashValue;
  541. exit:
  542. return _hr;
  543. }
  544. //////////////////////////////////////////////////////////////////////////////
  545. //
  546. // CString
  547. //
  548. //////////////////////////////////////////////////////////////////////////////
  549. class CString : public CBaseString<DEFAULT_STACK_SIZE>
  550. {
  551. public:
  552. CString() : CBaseString<DEFAULT_STACK_SIZE> (){}
  553. CString(AllocFlags eAllocFlags) : CBaseString<DEFAULT_STACK_SIZE>(eAllocFlags) {}
  554. };
  555. //////////////////////////////////////////////////////////////////////////////
  556. //
  557. // CStringAccessor
  558. //
  559. //////////////////////////////////////////////////////////////////////////////
  560. template<class T> class CStringAccessor
  561. {
  562. private:
  563. HRESULT _hr;
  564. T* _ps;
  565. public:
  566. CStringAccessor();
  567. ~CStringAccessor();
  568. HRESULT Attach(T& s);
  569. HRESULT Detach(DWORD cc = 0);
  570. LPWSTR* operator &();
  571. LPWSTR GetBuf();
  572. };
  573. //-----------------------------------------------------------------------------
  574. // ctor
  575. //-----------------------------------------------------------------------------
  576. template<class T> CStringAccessor<T>::CStringAccessor()
  577. : _ps(NULL), _hr(S_OK)
  578. {}
  579. //-----------------------------------------------------------------------------
  580. // dtor
  581. //-----------------------------------------------------------------------------
  582. template<class T> CStringAccessor<T>::~CStringAccessor()
  583. {}
  584. //-----------------------------------------------------------------------------
  585. // Attach
  586. //-----------------------------------------------------------------------------
  587. template<class T> HRESULT CStringAccessor<T>::Attach(T &s)
  588. {
  589. _ps = &s;
  590. IF_FAILED_EXIT(_ps->Lock());
  591. exit:
  592. return _hr;
  593. }
  594. //-----------------------------------------------------------------------------
  595. // Detach
  596. //-----------------------------------------------------------------------------
  597. template<class T> HRESULT CStringAccessor<T>::Detach(DWORD cc)
  598. {
  599. DWORD ccLen = 0;
  600. IF_NULL_EXIT(_ps, E_UNEXPECTED);
  601. IF_NULL_EXIT(_ps->_pwz, E_UNEXPECTED);
  602. if (!cc)
  603. {
  604. ccLen = lstrlen(_ps->_pwz);
  605. cc = ccLen+1;
  606. OVERFLOW_CHECK2(ccLen, cc);
  607. }
  608. else
  609. {
  610. IF_FALSE_EXIT((*(_ps->_pwz + cc - 1) == L'\0'), E_INVALIDARG);
  611. }
  612. _ps->_cc = _ps->_ccBuf = cc;
  613. IF_FAILED_EXIT(_ps->UnLock());
  614. exit:
  615. return _hr;
  616. }
  617. //-----------------------------------------------------------------------------
  618. // operator &
  619. //-----------------------------------------------------------------------------
  620. template<class T> LPWSTR* CStringAccessor<T>::operator &()
  621. {
  622. if (!_ps)
  623. {
  624. ASSERT(FALSE);
  625. }
  626. return (_ps ? &(_ps->_pwz) : NULL);
  627. }
  628. //-----------------------------------------------------------------------------
  629. // GetBuf
  630. //-----------------------------------------------------------------------------
  631. template<class T> LPWSTR CStringAccessor<T>::GetBuf()
  632. {
  633. if (!_ps)
  634. {
  635. ASSERT(FALSE);
  636. }
  637. return (_ps ? (_ps->_pwz) : NULL);
  638. }