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.

521 lines
13 KiB

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Filename : VarStr.h
  4. // Purpose : To hold definition for CVarString
  5. //
  6. // Project : Persistent Query
  7. // Component: Common
  8. //
  9. // Author : urib
  10. //
  11. // Log:
  12. // Feb 2 1997 urib Creation
  13. // Jun 19 1997 urib Add counted operators.
  14. // Jun 24 1997 urib Fix bad const declarations.
  15. // Dec 29 1997 urib Add includes.
  16. // Feb 2 1999 yairh fix bug in SetMinimalSize.
  17. // Feb 8 1999 urib Enable different built in sizes.
  18. // Feb 25 1999 urib Add SizedStringCopy.
  19. // Jul 5 1999 urib Fix SizedStringCopy..
  20. // May 1 2000 urib Cleanup.
  21. // Nov 23 2000 urib Fix a bug in counted copy and cat.
  22. //
  23. ////////////////////////////////////////////////////////////////////////////////
  24. #ifndef VARSTR_H
  25. #define VARSTR_H
  26. #pragma once
  27. #include "AutoPtr.h"
  28. #include "Excption.h"
  29. ////////////////////////////////////////////////////////////////////////////////
  30. //
  31. // CVarString class definition
  32. //
  33. ////////////////////////////////////////////////////////////////////////////////
  34. template <ULONG ulStackSize = 0x10>
  35. class TVarString
  36. {
  37. public:
  38. // Constructor - tips the implementation on the string size.
  39. TVarString(ULONG ulInitialSize = 0);
  40. // Constructor - copy this string.
  41. TVarString(PCWSTR);
  42. // Constructor - convert to UNICODE and copy this string.
  43. TVarString(const PSZ);
  44. // Copy Constructor
  45. TVarString(const TVarString&);
  46. ~TVarString();
  47. // Copy/Convert and copy the string.
  48. TVarString& Cpy(PCWSTR);
  49. TVarString& Cpy(const ULONG, PCWSTR);
  50. TVarString& Cpy(const PSZ);
  51. // Concatenate/Convert and concatenate the string to the existing string.
  52. TVarString& Cat(PCWSTR);
  53. TVarString& Cat(const ULONG, PCWSTR);
  54. TVarString& Cat(const PSZ);
  55. // Compare/Convert and compare the string to the existing string.
  56. int Cmp(PCWSTR) const;
  57. int Cmp(const PSZ) const;
  58. // Return the string length.
  59. ULONG Len() const;
  60. // Allow access to the string memory.
  61. operator PWSTR() const;
  62. // Hint the implementation about the string size.
  63. void SetMinimalSize(ULONG);
  64. // Set a specific character
  65. void SetCharacter(ULONG, WCHAR);
  66. // Appends a backslash to the string if the last character is not a
  67. // backslash.
  68. void AppendBackslash();
  69. // Appends a slash to the string if the last character is not a
  70. // slash.
  71. void AppendSlash();
  72. protected:
  73. // A predicate to see if memory is allocated or not.
  74. bool IsAllocated();
  75. // The allocation size
  76. ULONG m_ulSize;
  77. // This is the place for the standard string.
  78. WCHAR m_rwchNormalString[ulStackSize + 1];
  79. // If the string is becoming too big we will allocate space for it.
  80. WCHAR* m_pTheString;
  81. private:
  82. TVarString&
  83. operator=(const TVarString& vsOther)
  84. {
  85. Cpy(vsOther);
  86. return *this;
  87. }
  88. };
  89. template <ULONG ulStackSize>
  90. inline
  91. TVarString<ulStackSize>::TVarString(ULONG ulInitialSize)
  92. :m_pTheString(m_rwchNormalString)
  93. ,m_ulSize(ulStackSize)
  94. {
  95. SetMinimalSize(ulInitialSize);
  96. m_pTheString[0] = L'\0';
  97. }
  98. template <ULONG ulStackSize>
  99. inline
  100. TVarString<ulStackSize>::TVarString(PCWSTR pwsz)
  101. :m_pTheString(m_rwchNormalString)
  102. ,m_ulSize(ulStackSize)
  103. {
  104. Cpy(pwsz);
  105. }
  106. template <ULONG ulStackSize>
  107. inline
  108. TVarString<ulStackSize>::TVarString(const PSZ psz)
  109. :m_pTheString(m_rwchNormalString)
  110. ,m_ulSize(ulStackSize)
  111. {
  112. Cpy(psz);
  113. }
  114. template <ULONG ulStackSize>
  115. inline
  116. TVarString<ulStackSize>::TVarString(const TVarString<ulStackSize>& vsOther)
  117. :m_pTheString(m_rwchNormalString)
  118. ,m_ulSize(ulStackSize)
  119. {
  120. Cpy(vsOther);
  121. }
  122. template <ULONG ulStackSize>
  123. inline
  124. TVarString<ulStackSize>::~TVarString()
  125. {
  126. if (IsAllocated())
  127. {
  128. free(m_pTheString);
  129. }
  130. }
  131. template <ULONG ulStackSize>
  132. inline
  133. bool
  134. TVarString<ulStackSize>::IsAllocated()
  135. {
  136. return m_pTheString != m_rwchNormalString;
  137. }
  138. template <ULONG ulStackSize>
  139. inline
  140. void
  141. TVarString<ulStackSize>::SetMinimalSize(ULONG ulNewSize)
  142. {
  143. // We allocate a little more so if someone would like to add a slash
  144. // or something, it will not cause us to realocate.
  145. // On debug builds, I want to check for string overflows so I don't
  146. // want the extra memory. Activating the reallocation mechanism is also'
  147. // a good thing in debug builds.
  148. #if !(defined(DEBUG))
  149. ulNewSize++;
  150. #endif
  151. //
  152. // if the new size is smaller then what we have - bye bye
  153. //
  154. if (ulNewSize > m_ulSize)
  155. {
  156. //
  157. // We already allocated a string. Should change it's size
  158. //
  159. if (IsAllocated())
  160. {
  161. PWSTR pwszTemp = (PWSTR) realloc(
  162. m_pTheString,
  163. (ulNewSize + 1) * sizeof(WCHAR));
  164. if (NULL == pwszTemp)
  165. {
  166. THROW_MEMORY_EXCEPTION();
  167. }
  168. //
  169. // Save the new memory block.
  170. //
  171. m_pTheString = pwszTemp;
  172. }
  173. else
  174. {
  175. //
  176. // We move the string from the buffer to the allocation.
  177. // Note that this is dangerous if someone took the buffer address.
  178. // The user must always use the access method and never cache the
  179. // string pointer.
  180. //
  181. m_pTheString = (PWSTR) malloc(sizeof(WCHAR) * (ulNewSize + 1));
  182. if (NULL == m_pTheString)
  183. {
  184. THROW_MEMORY_EXCEPTION();
  185. }
  186. wcsncpy(m_pTheString, m_rwchNormalString, m_ulSize + 1);
  187. }
  188. m_ulSize = ulNewSize;
  189. }
  190. }
  191. template <ULONG ulStackSize>
  192. inline
  193. TVarString<ulStackSize>&
  194. TVarString<ulStackSize>::Cpy(PCWSTR pwsz)
  195. {
  196. return Cpy(wcslen(pwsz), pwsz);
  197. }
  198. template <ULONG ulStackSize>
  199. inline
  200. TVarString<ulStackSize>&
  201. TVarString<ulStackSize>::Cpy(const ULONG ulCount, PCWSTR pwsz)
  202. {
  203. SetMinimalSize(ulCount + 1);
  204. wcsncpy(m_pTheString, pwsz, ulCount);
  205. m_pTheString[ulCount] = L'\0';
  206. return *this;
  207. }
  208. template <ULONG ulStackSize>
  209. inline
  210. TVarString<ulStackSize>&
  211. TVarString<ulStackSize>::Cpy(const PSZ psz)
  212. {
  213. int iLen;
  214. iLen = MultiByteToWideChar(
  215. CP_ACP,
  216. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  217. psz,
  218. -1,
  219. NULL,
  220. 0);
  221. if (0 == iLen)
  222. {
  223. Assert(0 == iLen);
  224. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  225. }
  226. SetMinimalSize(iLen);
  227. iLen = MultiByteToWideChar(
  228. CP_ACP,
  229. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  230. psz,
  231. -1,
  232. m_pTheString,
  233. iLen);
  234. if (0 == iLen)
  235. {
  236. Assert(0 == iLen);
  237. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  238. }
  239. return *this;
  240. }
  241. template <ULONG ulStackSize>
  242. inline
  243. TVarString<ulStackSize>&
  244. TVarString<ulStackSize>::Cat(PCWSTR pwsz)
  245. {
  246. ULONG ulLength = wcslen(pwsz);
  247. return Cat(ulLength, pwsz);
  248. }
  249. template <ULONG ulStackSize>
  250. inline
  251. TVarString<ulStackSize>&
  252. TVarString<ulStackSize>::Cat(const ULONG ulLength, PCWSTR pwsz)
  253. {
  254. ULONG ulCurrentLength = Len();
  255. SetMinimalSize(ulCurrentLength + ulLength + 1);
  256. wcsncpy(m_pTheString + ulCurrentLength, pwsz, ulLength);
  257. m_pTheString[ulCurrentLength + ulLength] = L'\0';
  258. return *this;
  259. }
  260. template <ULONG ulStackSize>
  261. inline
  262. TVarString<ulStackSize>&
  263. TVarString<ulStackSize>::Cat(const PSZ psz)
  264. {
  265. ULONG ulCurrentLength = Len();
  266. int iLen;
  267. iLen = MultiByteToWideChar(
  268. CP_ACP,
  269. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  270. psz,
  271. -1,
  272. NULL,
  273. 0);
  274. if (0 == iLen)
  275. {
  276. Assert(0 == iLen);
  277. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  278. }
  279. SetMinimalSize(iLen + ulCurrentLength);
  280. iLen = MultiByteToWideChar(
  281. CP_ACP,
  282. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  283. psz,
  284. -1,
  285. m_pTheString + ulCurrentLength,
  286. iLen);
  287. if (0 == iLen)
  288. {
  289. Assert(0 == iLen);
  290. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  291. }
  292. return *this;
  293. }
  294. template <ULONG ulStackSize>
  295. inline
  296. int
  297. TVarString<ulStackSize>::Cmp(PCWSTR pwsz) const
  298. {
  299. return wcscmp(m_pTheString, pwsz);
  300. }
  301. template <ULONG ulStackSize>
  302. inline
  303. int
  304. TVarString<ulStackSize>::Cmp(const PSZ psz) const
  305. {
  306. int iLen;
  307. iLen = MultiByteToWideChar(
  308. CP_ACP,
  309. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  310. psz,
  311. -1,
  312. NULL,
  313. 0);
  314. if (0 == iLen)
  315. {
  316. Assert(0 == iLen);
  317. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  318. }
  319. CAutoMallocPointer<WCHAR> apBuffer = (PWSTR) malloc((iLen) * sizeof(WCHAR));
  320. iLen = MultiByteToWideChar(
  321. CP_ACP,
  322. MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
  323. psz,
  324. -1,
  325. apBuffer.Get(),
  326. iLen);
  327. if (0 == iLen)
  328. {
  329. Assert(0 == iLen);
  330. THROW_HRESULT_EXCEPTION(HRESULT_FROM_WIN32(GetLastError()));
  331. }
  332. return Cmp(apBuffer.Get());
  333. }
  334. template <ULONG ulStackSize>
  335. inline
  336. ULONG
  337. TVarString<ulStackSize>::Len() const
  338. {
  339. return wcslen(m_pTheString);
  340. }
  341. template <ULONG ulStackSize>
  342. inline
  343. TVarString<ulStackSize>::operator PWSTR() const
  344. {
  345. return m_pTheString;
  346. }
  347. template <ULONG ulStackSize>
  348. inline
  349. void
  350. TVarString<ulStackSize>::SetCharacter(ULONG ulIndex, WCHAR wch)
  351. {
  352. SetMinimalSize(ulIndex + 2); // index to size + null
  353. if (L'\0' == m_pTheString[ulIndex])
  354. {
  355. m_pTheString[ulIndex + 1] = L'\0';
  356. }
  357. else if (L'\0' == wch)
  358. {
  359. }
  360. m_pTheString[ulIndex] = wch;
  361. }
  362. template <ULONG ulStackSize>
  363. inline
  364. void
  365. TVarString<ulStackSize>::AppendSlash()
  366. {
  367. if (L'/' != m_pTheString[Len() - 1])
  368. Cat(L"/");
  369. }
  370. template <ULONG ulStackSize>
  371. inline
  372. void
  373. TVarString<ulStackSize>::AppendBackslash()
  374. {
  375. if (L'\\' != m_pTheString[Len() - 1])
  376. Cat(L"\\");
  377. }
  378. typedef TVarString<4> CShortVarString;
  379. typedef TVarString<16> CVarString;
  380. typedef TVarString<256> CLongVarString;
  381. typedef TVarString<1024> CHugeVarString;
  382. ////////////////////////////////////////////////////////////////////////////////
  383. //
  384. // String related utilities definition
  385. //
  386. ////////////////////////////////////////////////////////////////////////////////
  387. ////////////////////////////////////////////////////////////////////////////////
  388. //
  389. // Name : ::SizedStringCopy
  390. // Purpose : This function copies ulSize wide characters from the source
  391. // to the destination. It does not treat '\0' characters as
  392. // end of string and does not append the end of string mark
  393. // to the destination. Intended to be used instead of memcpy
  394. // when copying wide string characters.
  395. //
  396. // Parameters:
  397. // [in] PWSTR pwszTarget
  398. // [in] PCWSTR pwszSource
  399. // [in] ULONG ulSize
  400. //
  401. // Returns : PWSTR
  402. //
  403. // Log:
  404. // Jan 2 2001 urib Creation
  405. //
  406. ////////////////////////////////////////////////////////////////////////////////
  407. inline
  408. PWSTR
  409. SizedStringCopy(PWSTR pwszTarget, PCWSTR pwszSource, ULONG ulSize)
  410. {
  411. return (PWSTR) memcpy(
  412. (void*)pwszTarget,
  413. (void*)pwszSource,
  414. ulSize * sizeof(pwszSource[0]));
  415. }
  416. ////////////////////////////////////////////////////////////////////////////////
  417. //
  418. // Name : ::CoTaskDuplicateString
  419. // Purpose : strdup. Throwing though.
  420. //
  421. // Parameters:
  422. // [in] PCWSTR pwsz
  423. //
  424. // Returns : PWSTR
  425. //
  426. // Log:
  427. // Dec 25 2000 urib Creation
  428. //
  429. ////////////////////////////////////////////////////////////////////////////////
  430. inline
  431. PWSTR CoTaskDuplicateString(PCWSTR pwsz)
  432. {
  433. CAutoTaskPointer<WCHAR> apTempName =
  434. (PWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (1 + wcslen(pwsz)));
  435. if (!apTempName.IsValid())
  436. {
  437. THROW_MEMORY_EXCEPTION();
  438. }
  439. wcscpy(apTempName.Get(), pwsz);
  440. return apTempName.Detach();
  441. }
  442. #endif /* VARSTR_H */