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.

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