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.

899 lines
17 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. text
  5. Abstract:
  6. This module provides the runtime code to support the CText class.
  7. Author:
  8. Doug Barlow (dbarlow) 11/7/1995
  9. Environment:
  10. Win32, C++ w/ Exceptions
  11. Notes:
  12. None
  13. --*/
  14. #ifndef WIN32_LEAN_AND_MEAN
  15. #define WIN32_LEAN_AND_MEAN
  16. #endif
  17. #include <windows.h>
  18. #include "cspUtils.h"
  19. /*++
  20. CText::Copy:
  21. This method makes a copy of the supplied string. Use this when the
  22. assigned target string is going to go away.
  23. Arguments:
  24. sz supples the new value as an LPCSTR object (ANSI).
  25. wsz supplies the new value as an LPCWSTR object (Unicode).
  26. Return Value:
  27. A reference to the CText object.
  28. Author:
  29. Doug Barlow (dbarlow) 12/9/1999
  30. --*/
  31. #undef __SUBROUTINE__
  32. #define __SUBROUTINE__ TEXT("CText::Copy")
  33. LPCSTR
  34. CText::Copy(
  35. LPCSTR sz)
  36. {
  37. ULONG length;
  38. //
  39. // Reset the ANSI buffer.
  40. //
  41. if (NULL != sz)
  42. {
  43. length = lstrlenA(sz) + 1;
  44. m_bfAnsi.Copy((LPBYTE)sz, length * sizeof(CHAR));
  45. }
  46. else
  47. m_bfAnsi.Empty();
  48. m_fFlags = fAnsiGood;
  49. return sz;
  50. }
  51. LPCWSTR
  52. CText::Copy(
  53. LPCWSTR wsz)
  54. {
  55. ULONG length;
  56. //
  57. // Reset the Unicode Buffer.
  58. //
  59. if (NULL != wsz)
  60. {
  61. length = lstrlenW(wsz) + 1;
  62. m_bfUnicode.Copy((LPBYTE)wsz, length * sizeof(WCHAR));
  63. }
  64. else
  65. m_bfUnicode.Empty();
  66. m_fFlags = fUnicodeGood;
  67. return wsz;
  68. }
  69. /*++
  70. CText::operator=:
  71. These methods set the CText object to the given value, properly
  72. adjusting the object to the type of text.
  73. Arguments:
  74. tz supplies the new value as a CText object.
  75. sz supples the new value as an LPCSTR object (ANSI).
  76. wsz supplies the new value as an LPCWSTR object (Unicode).
  77. Return Value:
  78. A reference to the CText object.
  79. Author:
  80. Doug Barlow (dbarlow) 10/5/1995
  81. --*/
  82. CText &
  83. CText::operator=(
  84. const CText &tz)
  85. {
  86. //
  87. // See what the other CText object has that's good, and copy it over
  88. // here.
  89. //
  90. switch (m_fFlags = tz.m_fFlags)
  91. {
  92. case fNoneGood:
  93. // Nothing's Good!?! ?Error?
  94. throw (ULONG)ERROR_INTERNAL_ERROR;
  95. break;
  96. case fAnsiGood:
  97. // The ANSI buffer is good.
  98. m_bfAnsi = tz.m_bfAnsi;
  99. break;
  100. case fUnicodeGood:
  101. // The Unicode buffer is good.
  102. m_bfUnicode = tz.m_bfUnicode;
  103. break;
  104. case fAllGood:
  105. // Everything is good.
  106. m_bfAnsi = tz.m_bfAnsi;
  107. m_bfUnicode = tz.m_bfUnicode;
  108. break;
  109. default:
  110. // Internal error.
  111. throw (ULONG)ERROR_INTERNAL_ERROR;
  112. break;
  113. }
  114. return *this;
  115. }
  116. LPCSTR
  117. CText::operator=(
  118. LPCSTR sz)
  119. {
  120. ULONG length;
  121. //
  122. // Reset the ANSI buffer.
  123. //
  124. if (NULL != sz)
  125. {
  126. length = lstrlenA(sz) + 1;
  127. m_bfAnsi.Set((LPBYTE)sz, length * sizeof(CHAR));
  128. }
  129. else
  130. m_bfAnsi.Empty();
  131. m_fFlags = fAnsiGood;
  132. return sz;
  133. }
  134. LPCWSTR
  135. CText::operator=(
  136. LPCWSTR wsz)
  137. {
  138. ULONG length;
  139. //
  140. // Reset the Unicode Buffer.
  141. //
  142. if (NULL != wsz)
  143. {
  144. length = lstrlenW(wsz) + 1;
  145. m_bfUnicode.Set((LPBYTE)wsz, length * sizeof(WCHAR));
  146. }
  147. else
  148. m_bfUnicode.Empty();
  149. m_fFlags = fUnicodeGood;
  150. return wsz;
  151. }
  152. /*++
  153. CText::operator+=:
  154. These methods append the given data to the existing CText object
  155. value, properly adjusting the object to the type of text.
  156. Arguments:
  157. tz supplies the new value as a CText object.
  158. sz supples the new value as an LPCSTR object (ANSI).
  159. wsz supplies the new value as an LPCWSTR object (Unicode).
  160. Return Value:
  161. A reference to the CText object.
  162. Author:
  163. Doug Barlow (dbarlow) 10/5/1995
  164. --*/
  165. CText &
  166. CText::operator+=(
  167. const CText &tz)
  168. {
  169. //
  170. // Append the other's good value to our value.
  171. //
  172. switch (tz.m_fFlags)
  173. {
  174. case fNoneGood:
  175. throw (ULONG)ERROR_INTERNAL_ERROR;
  176. break;
  177. case fAnsiGood:
  178. *this += (LPCSTR)tz.m_bfAnsi.Value();
  179. break;
  180. case fUnicodeGood:
  181. *this += (LPCWSTR)tz.m_bfUnicode.Value();
  182. break;
  183. case fAllGood:
  184. #ifdef UNICODE
  185. *this += (LPCWSTR)tz.m_bfUnicode.Access();
  186. #else
  187. *this += (LPCSTR)tz.m_bfAnsi.Value();
  188. #endif
  189. break;
  190. default:
  191. throw (ULONG)ERROR_INTERNAL_ERROR;
  192. break;
  193. }
  194. return *this;
  195. }
  196. LPCSTR
  197. CText::operator+=(
  198. LPCSTR sz)
  199. {
  200. ULONG length;
  201. //
  202. // Extend ourself as an ANSI string.
  203. //
  204. if (NULL != sz)
  205. {
  206. length = lstrlenA(sz);
  207. if (0 < length)
  208. {
  209. length += 1;
  210. length *= sizeof(CHAR);
  211. Ansi();
  212. if (0 < m_bfAnsi.Length())
  213. m_bfAnsi.Length(m_bfAnsi.Length() - sizeof(CHAR));
  214. m_bfAnsi.Append((LPBYTE)sz, length);
  215. m_fFlags = fAnsiGood;
  216. }
  217. }
  218. return (LPCSTR)m_bfAnsi.Value();
  219. }
  220. LPCWSTR
  221. CText::operator+=(
  222. LPCWSTR wsz)
  223. {
  224. ULONG length;
  225. //
  226. // Extend ourself as a Unicode string.
  227. //
  228. if (NULL != wsz)
  229. {
  230. length = lstrlenW(wsz);
  231. if (0 < length)
  232. {
  233. length += 1;
  234. length *= sizeof(WCHAR);
  235. Unicode();
  236. if (0 < m_bfUnicode.Length())
  237. m_bfUnicode.Length(m_bfUnicode.Length() - sizeof(WCHAR));
  238. m_bfUnicode.Append((LPBYTE)wsz, length);
  239. m_fFlags = fUnicodeGood;
  240. }
  241. }
  242. return (LPCWSTR)m_bfUnicode.Value();
  243. }
  244. /*++
  245. Unicode:
  246. This method returns the CText object as a Unicode string.
  247. Arguments:
  248. None
  249. Return Value:
  250. The value of the object expressed in Unicode.
  251. Author:
  252. Doug Barlow (dbarlow) 10/5/1995
  253. --*/
  254. LPCWSTR
  255. CText::Unicode(
  256. void)
  257. {
  258. int length;
  259. //
  260. // See what data we've got, and if any conversion is necessary.
  261. //
  262. switch (m_fFlags)
  263. {
  264. case fNoneGood:
  265. // No valid values. Report an error.
  266. throw (ULONG)ERROR_INTERNAL_ERROR;
  267. break;
  268. case fAnsiGood:
  269. // The ANSI value is good. Convert it to Unicode.
  270. if (0 < m_bfAnsi.Length())
  271. {
  272. length =
  273. MultiByteToWideChar(
  274. GetACP(),
  275. MB_PRECOMPOSED,
  276. (LPCSTR)m_bfAnsi.Value(),
  277. m_bfAnsi.Length() - sizeof(CHAR),
  278. NULL,
  279. 0);
  280. if (0 == length)
  281. throw GetLastError();
  282. m_bfUnicode.Space((length + 1) * sizeof(WCHAR));
  283. length =
  284. MultiByteToWideChar(
  285. GetACP(),
  286. MB_PRECOMPOSED,
  287. (LPCSTR)m_bfAnsi.Value(),
  288. m_bfAnsi.Length() - sizeof(CHAR),
  289. (LPWSTR)m_bfUnicode.Access(),
  290. length);
  291. if (0 == length)
  292. throw GetLastError();
  293. *(LPWSTR)m_bfUnicode.Access(length * sizeof(WCHAR)) = 0;
  294. m_bfUnicode.Length((length + 1) * sizeof(WCHAR));
  295. }
  296. else
  297. m_bfUnicode.Empty();
  298. m_fFlags = fAllGood;
  299. break;
  300. case fUnicodeGood:
  301. case fAllGood:
  302. // The Unicode value is good. Just return that.
  303. break;
  304. default:
  305. // Internal error.
  306. throw (ULONG)ERROR_INTERNAL_ERROR;
  307. break;
  308. }
  309. //
  310. // If we don't have any value, return a null string.
  311. //
  312. if (0 == m_bfUnicode.Length())
  313. return L"\000"; // Double NULLs to support Multistrings
  314. else
  315. return (LPCWSTR)m_bfUnicode.Value();
  316. }
  317. /*++
  318. CText::Ansi:
  319. This method returns the value of the object expressed in an ANSI string.
  320. Arguments:
  321. None
  322. Return Value:
  323. The value of the object expressed as an ANSI string.
  324. Author:
  325. Doug Barlow (dbarlow) 10/5/1995
  326. --*/
  327. LPCSTR
  328. CText::Ansi(
  329. void)
  330. {
  331. int length;
  332. //
  333. // See what data we've got, and if any conversion is necessary.
  334. //
  335. switch (m_fFlags)
  336. {
  337. case fNoneGood:
  338. // Nothing is good!?! Return an error.
  339. throw (ULONG)ERROR_INTERNAL_ERROR;
  340. break;
  341. case fUnicodeGood:
  342. // The Unicode buffer is good. Convert it to ANSI.
  343. if (0 < m_bfUnicode.Length())
  344. {
  345. length =
  346. WideCharToMultiByte(
  347. GetACP(),
  348. 0,
  349. (LPCWSTR)m_bfUnicode.Value(),
  350. (m_bfUnicode.Length() / sizeof(WCHAR)) - 1,
  351. NULL,
  352. 0,
  353. NULL,
  354. NULL);
  355. if (0 == length)
  356. throw GetLastError();
  357. m_bfAnsi.Space((length + 1) * sizeof(CHAR));
  358. length =
  359. WideCharToMultiByte(
  360. GetACP(),
  361. 0,
  362. (LPCWSTR)m_bfUnicode.Value(),
  363. (m_bfUnicode.Length() / sizeof(WCHAR)) - 1,
  364. (LPSTR)m_bfAnsi.Access(),
  365. length,
  366. NULL,
  367. NULL);
  368. if (0 == length)
  369. throw GetLastError();
  370. *(LPSTR)m_bfAnsi.Access(length * sizeof(CHAR)) = 0;
  371. m_bfAnsi.Length((length + 1) * sizeof(CHAR));
  372. }
  373. else
  374. m_bfAnsi.Empty();
  375. m_fFlags = fAllGood;
  376. break;
  377. case fAnsiGood:
  378. case fAllGood:
  379. // The ANSI buffer is good. We'll return that.
  380. break;
  381. default:
  382. // An internal error.
  383. throw (ULONG)ERROR_INTERNAL_ERROR;
  384. break;
  385. }
  386. //
  387. // If there's nothing in the ANSI buffer, return a null string.
  388. //
  389. if (0 == m_bfAnsi.Length())
  390. return "\000"; // Double NULLs to support Multistrings
  391. else
  392. return (LPCSTR)m_bfAnsi.Value();
  393. }
  394. /*++
  395. Compare:
  396. These methods compare the value of this object to another value, and return
  397. a comparative value.
  398. Arguments:
  399. tz supplies the value to be compared as a CText object.
  400. sz supplies the value to be compared as an ANSI string.
  401. wsz supplies the value to be compared as a Unicode string.
  402. Return Value:
  403. < 0 - The supplied value is less than this object.
  404. = 0 - The supplied value is equal to this object.
  405. > 0 - The supplies value is greater than this object.
  406. Author:
  407. Doug Barlow (dbarlow) 10/5/1995
  408. --*/
  409. int
  410. CText::Compare(
  411. const CText &tz)
  412. {
  413. int nResult;
  414. //
  415. // See what we've got to compare.
  416. //
  417. switch (tz.m_fFlags)
  418. {
  419. case fNoneGood:
  420. // Nothing!?! Complain.
  421. throw (ULONG)ERROR_INTERNAL_ERROR;
  422. break;
  423. case fAllGood:
  424. case fAnsiGood:
  425. // Use the ANSI version for fastest comparison.
  426. Ansi();
  427. nResult = CompareStringA(
  428. LOCALE_USER_DEFAULT,
  429. 0,
  430. (LPCSTR)m_bfAnsi.Value(),
  431. (m_bfAnsi.Length() / sizeof(CHAR)) - 1,
  432. (LPCSTR)tz.m_bfAnsi.Value(),
  433. (tz.m_bfAnsi.Length() / sizeof(CHAR)) - 1);
  434. break;
  435. case fUnicodeGood:
  436. // The Unicode version is good.
  437. Unicode();
  438. nResult = CompareStringW(
  439. LOCALE_USER_DEFAULT,
  440. 0,
  441. (LPCWSTR)m_bfUnicode.Value(),
  442. (m_bfUnicode.Length() / sizeof(WCHAR)) - 1,
  443. (LPCWSTR)tz.m_bfUnicode.Value(),
  444. (tz.m_bfUnicode.Length() / sizeof(WCHAR)) - 1);
  445. break;
  446. default:
  447. // Internal Error.
  448. throw (ULONG)ERROR_INTERNAL_ERROR;
  449. break;
  450. }
  451. return nResult;
  452. }
  453. int
  454. CText::Compare(
  455. LPCSTR sz)
  456. {
  457. int nResult;
  458. //
  459. // Make sure our ANSI version is good.
  460. //
  461. Ansi();
  462. //
  463. // Do an ANSI comparison.
  464. //
  465. nResult = CompareStringA(
  466. LOCALE_USER_DEFAULT,
  467. 0,
  468. (LPCSTR)m_bfAnsi.Value(),
  469. (m_bfAnsi.Length() / sizeof(CHAR)) - 1,
  470. sz,
  471. lstrlenA(sz));
  472. return nResult;
  473. }
  474. int
  475. CText::Compare(
  476. LPCWSTR wsz)
  477. {
  478. int nResult;
  479. //
  480. // Make sure our Unicode version is good.
  481. //
  482. Unicode();
  483. //
  484. // Do the comparison using Unicode.
  485. //
  486. nResult = CompareStringW(
  487. LOCALE_USER_DEFAULT,
  488. 0,
  489. (LPCWSTR)m_bfUnicode.Value(),
  490. (m_bfUnicode.Length() / sizeof(WCHAR)) - 1,
  491. wsz,
  492. lstrlenW(wsz));
  493. return nResult;
  494. }
  495. /*++
  496. Length:
  497. These routines return the length of strings, in Characters, not including
  498. any trailing null characters.
  499. Arguments:
  500. sz supplies the value whos length is to be returned as an ANSI string.
  501. wsz supplies the value whos length is to be returned as a Unicode string.
  502. Return Value:
  503. The length of the string, in characters, excluding the trailing null.
  504. Author:
  505. Doug Barlow (dbarlow) 2/17/1997
  506. --*/
  507. ULONG
  508. CText::Length(
  509. void)
  510. {
  511. ULONG length = 0;
  512. switch (m_fFlags)
  513. {
  514. case fNoneGood:
  515. // Nothing is good!?! Return an error.
  516. throw (ULONG)ERROR_INTERNAL_ERROR;
  517. break;
  518. case fAnsiGood:
  519. // The ANSI buffer is good. We'll return its length.
  520. if (0 < m_bfAnsi.Length())
  521. length = (m_bfAnsi.Length() / sizeof(CHAR)) - 1;
  522. break;
  523. case fUnicodeGood:
  524. // The Unicode buffer is good. Return it's length.
  525. if (0 < m_bfUnicode.Length())
  526. length = (m_bfUnicode.Length() / sizeof(WCHAR)) - 1;
  527. break;
  528. case fAllGood:
  529. #ifdef UNICODE
  530. // The Unicode buffer is good. Return it's length.
  531. if (0 < m_bfUnicode.Length())
  532. length = (m_bfUnicode.Length() / sizeof(WCHAR)) - 1;
  533. #else
  534. // The ANSI buffer is good. We'll return its length.
  535. if (0 < m_bfAnsi.Length())
  536. length = (m_bfAnsi.Length() / sizeof(CHAR)) - 1;
  537. #endif
  538. break;
  539. default:
  540. // An internal error.
  541. throw (ULONG)ERROR_INTERNAL_ERROR;
  542. break;
  543. }
  544. return length;
  545. }
  546. /*++
  547. Length:
  548. This routine manipulates the length of the contained string.
  549. Arguments:
  550. cchLen supplies the new length of the string, in characters.
  551. Return Value:
  552. None
  553. Throws:
  554. ?exceptions?
  555. Remarks:
  556. Using this routine assumes that the buffer was filled in externally.
  557. Author:
  558. Doug Barlow (dbarlow) 11/15/1999
  559. --*/
  560. #undef __SUBROUTINE__
  561. #define __SUBROUTINE__ TEXT("Length")
  562. void
  563. CText::LengthA(
  564. ULONG cchLen)
  565. {
  566. if ((ULONG)(-1) == cchLen)
  567. cchLen = lstrlenA((LPCSTR)m_bfAnsi.Access());
  568. ASSERT(m_bfAnsi.Space() > cchLen * sizeof(CHAR));
  569. if (m_bfAnsi.Space() > cchLen * sizeof(CHAR))
  570. {
  571. *(LPSTR)m_bfAnsi.Access(cchLen * sizeof(CHAR)) = 0;
  572. m_bfAnsi.Length((cchLen + 1) * sizeof(CHAR));
  573. m_fFlags = fAnsiGood;
  574. }
  575. }
  576. void
  577. CText::LengthW(
  578. ULONG cchLen)
  579. {
  580. if ((ULONG)(-1) == cchLen)
  581. cchLen = lstrlenW((LPCWSTR)m_bfUnicode.Access());
  582. ASSERT(m_bfUnicode.Space() > cchLen * sizeof(WCHAR));
  583. if (m_bfUnicode.Space() > cchLen * sizeof(WCHAR))
  584. {
  585. *(LPSTR)m_bfUnicode.Access(cchLen * sizeof(WCHAR)) = 0;
  586. m_bfUnicode.Length((cchLen + 1) * sizeof(WCHAR));
  587. m_fFlags = fUnicodeGood;
  588. }
  589. }
  590. /*++
  591. Space:
  592. These routines manipulate the size of the underlying storage buffer,
  593. so that it can receive data.
  594. Arguments:
  595. cchLen supplies the desired size of the buffer.
  596. Return Value:
  597. The actual size of the buffer.
  598. Throws:
  599. ?exceptions?
  600. Remarks:
  601. ?Remarks?
  602. Author:
  603. Doug Barlow (dbarlow) 11/15/1999
  604. --*/
  605. #undef __SUBROUTINE__
  606. #define __SUBROUTINE__ TEXT("Space")
  607. ULONG
  608. CText::SpaceA(
  609. void)
  610. {
  611. ULONG cch = m_bfAnsi.Space();
  612. if (0 < cch)
  613. cch = cch / sizeof(CHAR) - 1;
  614. return cch;
  615. }
  616. ULONG
  617. CText::SpaceW(
  618. void)
  619. {
  620. ULONG cch = m_bfUnicode.Space();
  621. if (0 < cch)
  622. cch = cch / sizeof(WCHAR) - 1;
  623. return cch;
  624. }
  625. void
  626. CText::SpaceA(
  627. ULONG cchLen)
  628. {
  629. m_bfAnsi.Space((cchLen + 1) * sizeof(CHAR));
  630. m_fFlags = fNoneGood;
  631. }
  632. void
  633. CText::SpaceW(
  634. ULONG cchLen)
  635. {
  636. m_bfUnicode.Space((cchLen + 1) * sizeof(WCHAR));
  637. m_fFlags = fNoneGood;
  638. }
  639. /*++
  640. Access:
  641. These routines provide direct access to the text buffer, so that it can
  642. be used to receive output from another routine.
  643. Arguments:
  644. cchOffset supplies an offset into the buffer.
  645. Return Value:
  646. The address of the buffer, plus any offset.
  647. Throws:
  648. ?exceptions?
  649. Remarks:
  650. ?Remarks?
  651. Author:
  652. Doug Barlow (dbarlow) 11/15/1999
  653. --*/
  654. #undef __SUBROUTINE__
  655. #define __SUBROUTINE__ TEXT("Access")
  656. LPSTR
  657. CText::AccessA(
  658. ULONG cchOffset)
  659. {
  660. m_fFlags = fNoneGood;
  661. return (LPSTR)m_bfAnsi.Access(cchOffset * sizeof(CHAR));
  662. }
  663. LPWSTR
  664. CText::AccessW(
  665. ULONG cchOffset)
  666. {
  667. m_fFlags = fNoneGood;
  668. return (LPWSTR)m_bfUnicode.Access(cchOffset * sizeof(WCHAR));
  669. }