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.

733 lines
22 KiB

  1. //============================================================================
  2. //
  3. // UNICODE and ANSI conversion functions
  4. //
  5. //============================================================================
  6. #include "priv.h"
  7. #include <mlang.h>
  8. /*
  9. * @doc INTERNAL
  10. *
  11. * @func int | SHAnsiToUnicodeNativeCP |
  12. *
  13. * Convert an ANSI string to a UNICODE string via the
  14. * specified Windows code page. If the source string is too large
  15. * for the destination buffer, then as many characters as
  16. * possible are copied.
  17. *
  18. * The resulting output string is always null-terminated.
  19. *
  20. * @parm UINT | uiCP |
  21. *
  22. * The code page in which to perform the conversion.
  23. * This must be a Windows code page.
  24. *
  25. * @parm LPCSTR | pszSrc |
  26. *
  27. * Source buffer containing ANSI string to be converted.
  28. *
  29. * @parm int | cchSrc |
  30. *
  31. * Source buffer length, including terminating null.
  32. *
  33. * @parm LPWSTR | pwszDst |
  34. *
  35. * Destination buffer to receive converted UNICODE string.
  36. *
  37. * @parm int | cwchBuf |
  38. *
  39. * Size of the destination buffer in <t WCHAR>s.
  40. *
  41. * @returns
  42. *
  43. * On success, the number of characters copied to the output
  44. * buffer is returned, including the terminating null.
  45. */
  46. int
  47. SHAnsiToUnicodeNativeCP(UINT uiCP,
  48. LPCSTR pszSrc, int cchSrc,
  49. LPWSTR pwszDst, int cwchBuf)
  50. {
  51. int cwchRc = 0; /* Assume failure */
  52. /*
  53. * Checks the caller should've made.
  54. */
  55. ASSERT(IS_VALID_STRING_PTRA(pszSrc, -1));
  56. ASSERT(cchSrc == lstrlenA(pszSrc) + 1);
  57. ASSERT(IS_VALID_WRITE_BUFFER(pwszDst, WCHAR, cwchBuf));
  58. ASSERT(pszSrc != NULL);
  59. ASSERT(uiCP != 1200 && uiCP != 65000 && uiCP != 50000 && uiCP != 65001);
  60. ASSERT(pwszDst);
  61. ASSERT(cwchBuf);
  62. cwchRc = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc, pwszDst, cwchBuf);
  63. if (cwchRc) {
  64. /*
  65. * The output buffer was big enough; no double-buffering
  66. * needed.
  67. */
  68. } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  69. /*
  70. * The output buffer wasn't big enough. Need to double-buffer.
  71. */
  72. int cwchNeeded = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc,
  73. NULL, 0);
  74. ASSERT(cwchRc == 0); /* In case we fail later */
  75. if (cwchNeeded) {
  76. LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED,
  77. cwchNeeded * SIZEOF(WCHAR));
  78. if (pwsz) {
  79. cwchRc = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc,
  80. pwsz, cwchNeeded);
  81. if (cwchRc) {
  82. StrCpyNW(pwszDst, pwsz, cwchBuf);
  83. cwchRc = cwchBuf;
  84. }
  85. LocalFree(pwsz);
  86. }
  87. }
  88. } else {
  89. /* Possibly unsupported code page */
  90. ASSERT(!"Unexpected error in MultiByteToWideChar");
  91. }
  92. return cwchRc;
  93. }
  94. /*
  95. * @doc INTERNAL
  96. *
  97. * @func int | SHAnsiToUnicodeInetCP |
  98. *
  99. * Convert an ANSI string to a UNICODE string via the
  100. * specified Internet code page. If the source string is too large
  101. * for the destination buffer, then as many characters as
  102. * possible are copied.
  103. *
  104. * The resulting output string is always null-terminated.
  105. *
  106. * @parm UINT | uiCP |
  107. *
  108. * The code page in which to perform the conversion.
  109. * This must be an Internet code page.
  110. *
  111. * @parm LPCSTR | pszSrc |
  112. *
  113. * Source buffer containing ANSI string to be converted.
  114. *
  115. * @parm int | cchSrc |
  116. *
  117. * Source buffer length, including terminating null.
  118. *
  119. * @parm LPWSTR | pwszDst |
  120. *
  121. * Destination buffer to receive converted UNICODE string.
  122. *
  123. * @parm int | cwchBuf |
  124. *
  125. * Size of the destination buffer in <t WCHAR>s.
  126. *
  127. * @returns
  128. *
  129. * On success, the number of characters copied to the output
  130. * buffer is returned, including the terminating null.
  131. */
  132. int
  133. SHAnsiToUnicodeInetCP(UINT uiCP,
  134. LPCSTR pszSrc, int cchSrc,
  135. LPWSTR pwszDst, int cwchBuf)
  136. {
  137. int cchSrcT, cwchNeeded;
  138. int cwchRc = 0; /* Assume failure */
  139. HRESULT hres;
  140. DWORD dwMode;
  141. /*
  142. * Checks the caller should've made.
  143. */
  144. ASSERT(IS_VALID_STRING_PTRA(pszSrc, -1));
  145. ASSERT(cchSrc == lstrlenA(pszSrc) + 1);
  146. ASSERT(IS_VALID_WRITE_BUFFER(pwszDst, WCHAR, cwchBuf));
  147. ASSERT(pszSrc != NULL);
  148. ASSERT(uiCP == 1200 || uiCP == 65000 || uiCP == 65001);
  149. ASSERT(pwszDst);
  150. ASSERT(cwchBuf);
  151. cchSrcT = cchSrc;
  152. cwchNeeded = cwchBuf;
  153. dwMode = 0;
  154. hres = ConvertINetMultiByteToUnicode(&dwMode, uiCP, pszSrc,
  155. &cchSrcT, pwszDst, &cwchNeeded);
  156. if (SUCCEEDED(hres)) {
  157. if (cchSrcT >= cchSrc) {
  158. /*
  159. * The output buffer was big enough; no double-buffering
  160. * needed.
  161. */
  162. cwchRc = cwchNeeded;
  163. } else {
  164. /*
  165. * The output buffer wasn't big enough. Need to double-buffer.
  166. */
  167. LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED,
  168. cwchNeeded * SIZEOF(WCHAR));
  169. if (pwsz) {
  170. dwMode = 0;
  171. hres = ConvertINetMultiByteToUnicode(&dwMode, uiCP, pszSrc,
  172. &cchSrc, pwsz, &cwchNeeded);
  173. if (SUCCEEDED(hres)) {
  174. StrCpyNW(pwszDst, pwsz, cwchBuf);
  175. cwchRc = cwchBuf;
  176. }
  177. LocalFree(pwsz);
  178. }
  179. }
  180. } else {
  181. /* Possibly unsupported code page */
  182. ASSERT(!"Unexpected error in ConvertInetMultiByteToUnicode");
  183. }
  184. return cwchRc;
  185. }
  186. /*
  187. * @doc EXTERNAL
  188. *
  189. * @func int | SHAnsiToUnicodeCP |
  190. *
  191. * Convert an ANSI string to a UNICODE string via the
  192. * specified code page, which can be either a native
  193. * Windows code page or an Internet code page.
  194. * If the source string is too large
  195. * for the destination buffer, then as many characters as
  196. * possible are copied.
  197. *
  198. * The resulting output string is always null-terminated.
  199. *
  200. * @parm UINT | uiCP |
  201. *
  202. * The code page in which to perform the conversion.
  203. *
  204. * @parm LPCSTR | pszSrc |
  205. *
  206. * Source buffer containing ANSI string to be converted.
  207. *
  208. * @parm LPWSTR | pwszDst |
  209. *
  210. * Destination buffer to receive converted UNICODE string.
  211. *
  212. * @parm int | cwchBuf |
  213. *
  214. * Size of the destination buffer in <t WCHAR>s.
  215. *
  216. * @returns
  217. *
  218. * On success, the number of characters copied to the output
  219. * buffer is returned, including the terminating null.
  220. */
  221. int
  222. SHAnsiToUnicodeCP(UINT uiCP, LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf)
  223. {
  224. int cwchRc = 0; /* Assume failure */
  225. RIPMSG(IS_VALID_STRING_PTRA(pszSrc, -1), "Caller of SHAnsiToUnicodeCP passed in a NULL pszSrc!");
  226. ASSERT(IS_VALID_WRITE_BUFFER(pwszDst, WCHAR, cwchBuf));
  227. /*
  228. * Sanity check - NULL source string is treated as a null string.
  229. */
  230. if (pszSrc == NULL) {
  231. pszSrc = "";
  232. }
  233. /*
  234. * Sanity check - Output buffer must be non-NULL and must be of
  235. * nonzero size.
  236. */
  237. if (pwszDst && cwchBuf) {
  238. int cchSrc;
  239. pwszDst[0] = 0; /* In case of error */
  240. cchSrc = lstrlenA(pszSrc) + 1;
  241. /*
  242. * Decide what kind of code page it is.
  243. */
  244. switch (uiCP) {
  245. case 1200: // UCS-2 (Unicode)
  246. uiCP = 65001;
  247. // Fall through
  248. case 50000: // "User Defined"
  249. case 65000: // UTF-7
  250. case 65001: // UTF-8
  251. cwchRc = SHAnsiToUnicodeInetCP(uiCP, pszSrc, cchSrc, pwszDst, cwchBuf);
  252. break;
  253. default:
  254. cwchRc = SHAnsiToUnicodeNativeCP(uiCP, pszSrc, cchSrc, pwszDst, cwchBuf);
  255. break;
  256. }
  257. }
  258. return cwchRc;
  259. }
  260. // This function exists to make sure SHAnsiToAnsi and SHUnicodeToAnsi
  261. // have the same return value. Callers use SHTCharToAnsi and don't know
  262. // when it callapses to SHAnsiToAnsi.
  263. int SHAnsiToAnsi(LPCSTR pszSrc, LPSTR pszDst, int cchBuf)
  264. {
  265. int cchRc = 0; /* Assume failure */
  266. if (cchBuf)
  267. {
  268. // APP COMPAT! WARNING! Sony PictureGear passes too-small buffers to
  269. // SHGetPathFromIDList (which uses SHAnsiToAnsi eventually), so we
  270. // must be careful to pass the actual buffer size to SHTruncateString
  271. // and not the theoretical maximum (rarely attained).
  272. LPSTR pszEnd = StrCpyNXA(pszDst, pszSrc, cchBuf);
  273. cchRc = (int)(pszEnd - pszDst) + 1;
  274. cchRc = SHTruncateString(pszDst, cchRc) + 1;
  275. }
  276. return cchRc;
  277. }
  278. // This function exists to make sure SHUnicodeToUnicode and SHUnicodeToAnsi
  279. // have the same return value. Callers use SHTCharToUnicode and don't know
  280. // when it callapses to SHUnicodeToUnicode.
  281. int SHUnicodeToUnicode(LPCWSTR pwzSrc, LPWSTR pwzDst, int cchBuf)
  282. {
  283. return (int) (StrCpyNXW(pwzDst, pwzSrc, cchBuf) - pwzDst + 1); // size including terminator
  284. }
  285. /*
  286. * @doc EXTERNAL
  287. *
  288. * @func int | SHAnsiToUnicode |
  289. *
  290. * Convert an ANSI string to a UNICODE string via the
  291. * <c CP_ACP> code page. If the source string is too large
  292. * for the destination buffer, then as many characters as
  293. * possible are copied.
  294. *
  295. * The resulting output string is always null-terminated.
  296. *
  297. * @parm LPCSTR | pszSrc |
  298. *
  299. * Source buffer containing ANSI string to be converted.
  300. *
  301. * @parm LPWSTR | pwszDst |
  302. *
  303. * Destination buffer to receive converted UNICODE string.
  304. *
  305. * @parm int | cwchBuf |
  306. *
  307. * Size of the destination buffer in <t WCHAR>s.
  308. *
  309. * @returns
  310. *
  311. * On success, the number of characters copied to the output
  312. * buffer is returned, including the terminating null.
  313. *
  314. */
  315. int
  316. SHAnsiToUnicode(LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf)
  317. {
  318. return SHAnsiToUnicodeCP(CP_ACP, pszSrc, pwszDst, cwchBuf);
  319. }
  320. /*
  321. * @doc INTERNAL
  322. *
  323. * @func int | SHUnicodeToAnsiNativeCP |
  324. *
  325. * Convert a UNICODE string to an ANSI string via the
  326. * specified Windows code page. If the source string is too large
  327. * for the destination buffer, then as many characters as
  328. * possible are copied. Care is taken not to break a double-byte
  329. * character.
  330. *
  331. * The resulting output string is always null-terminated.
  332. *
  333. * @parm UINT | uiCP |
  334. *
  335. * The code page in which to perform the conversion.
  336. * This must be a Windows code page.
  337. *
  338. * @parm LPCWSTR | pwszSrc |
  339. *
  340. * Source buffer containing UNICODE string to be converted.
  341. *
  342. * @parm int | cwchSrc |
  343. *
  344. * Number of characters in source buffer, including terminating
  345. * null.
  346. *
  347. * @parm LPSTR | pszDst |
  348. *
  349. * Destination buffer to receive converted ANSI string.
  350. *
  351. * @parm int | cchBuf |
  352. *
  353. * Size of the destination buffer in <t CHAR>s.
  354. *
  355. * @returns
  356. *
  357. * On success, the number of characters copied to the output
  358. * buffer is returned, including the terminating null.
  359. * (For the purpose of this function, a double-byte character
  360. * counts as two characters.)
  361. */
  362. int
  363. SHUnicodeToAnsiNativeCP(UINT uiCP,
  364. LPCWSTR pwszSrc, int cwchSrc,
  365. LPSTR pszDst, int cchBuf)
  366. {
  367. int cchRc = 0; /* Assume failure */
  368. #ifdef DEBUG
  369. BOOL fVerify = TRUE;
  370. BOOL fLossy;
  371. if (uiCP == CP_ACPNOVALIDATE) {
  372. // -1 means use CP_ACP, but do *not* verify
  373. // kind of a hack, but it's DEBUG and leaves 99% of callers unchanged
  374. uiCP = CP_ACP;
  375. fVerify = FALSE;
  376. }
  377. #define USUALLY_NULL (&fLossy)
  378. #else
  379. #define USUALLY_NULL NULL
  380. #endif
  381. /*
  382. * Checks the caller should've made.
  383. */
  384. ASSERT(IS_VALID_STRING_PTRW(pwszSrc, -1));
  385. ASSERT(cwchSrc == lstrlenW(pwszSrc) + 1);
  386. ASSERT(IS_VALID_WRITE_BUFFER(pszDst, CHAR, cchBuf));
  387. ASSERT(uiCP != 1200 && uiCP != 65000 && uiCP != 50000 && uiCP != 65001);
  388. ASSERT(pwszSrc);
  389. ASSERT(pszDst);
  390. ASSERT(cchBuf);
  391. cchRc = WideCharToMultiByte(uiCP, 0, pwszSrc, cwchSrc, pszDst, cchBuf,
  392. NULL, USUALLY_NULL);
  393. if (cchRc) {
  394. /*
  395. * The output buffer was big enough; no double-buffering
  396. * needed.
  397. */
  398. } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  399. /*
  400. * The output buffer wasn't big enough. Need to double-buffer.
  401. */
  402. int cchNeeded = WideCharToMultiByte(uiCP, 0, pwszSrc, cwchSrc,
  403. NULL, 0, NULL, NULL);
  404. ASSERT(cchRc == 0); /* In case we fail later */
  405. if (cchNeeded) {
  406. LPSTR psz = (LPSTR)LocalAlloc(LMEM_FIXED,
  407. cchNeeded * SIZEOF(CHAR));
  408. if (psz) {
  409. cchRc = WideCharToMultiByte(uiCP, 0, pwszSrc, cwchSrc,
  410. psz, cchNeeded, NULL, USUALLY_NULL);
  411. if (cchRc) {
  412. // lstrcpyn doesn't check if it's chopping a DBCS char
  413. // so we need to use SHTruncateString.
  414. //
  415. // Add 1 because SHTruncateString doesn't count
  416. // the trailing null but we do
  417. //
  418. // Assert that we meet the preconditions for
  419. // SHTruncateString to return a valid value.
  420. //
  421. ASSERT(cchRc > cchBuf);
  422. cchRc = SHTruncateString(psz, cchBuf) + 1;
  423. lstrcpynA(pszDst, psz, cchBuf);
  424. }
  425. LocalFree(psz);
  426. }
  427. }
  428. } else {
  429. /* Possibly unsupported code page */
  430. ASSERT(!"Unexpected error in WideCharToMultiByte");
  431. }
  432. #ifdef DEBUG
  433. TBOOL(!fVerify || !fLossy);
  434. #endif
  435. return cchRc;
  436. }
  437. /*
  438. * @doc INTERNAL
  439. *
  440. * @func int | SHUnicodeToAnsiInetCP |
  441. *
  442. * Convert a UNICODE string to an ANSI string via the
  443. * specified Internet code page. If the source string is too large
  444. * for the destination buffer, then as many characters as
  445. * possible are copied. Care is taken not to break a double-byte
  446. * character.
  447. *
  448. * The resulting output string is always null-terminated.
  449. *
  450. * @parm UINT | uiCP |
  451. *
  452. * The code page in which to perform the conversion.
  453. * This must be an Internet code page.
  454. *
  455. * @parm LPCWSTR | pwszSrc |
  456. *
  457. * Source buffer containing UNICODE string to be converted.
  458. *
  459. * @parm int | cwchSrc |
  460. *
  461. * Number of characters in source buffer, including terminating
  462. * null.
  463. *
  464. * @parm LPSTR | pszDst |
  465. *
  466. * Destination buffer to receive converted ANSI string.
  467. *
  468. * @parm int | cchBuf |
  469. *
  470. * Size of the destination buffer in <t CHAR>s.
  471. *
  472. * @returns
  473. *
  474. * On success, the number of characters copied to the output
  475. * buffer is returned, including the terminating null.
  476. * (For the purpose of this function, a double-byte character
  477. * counts as two characters.)
  478. */
  479. int
  480. SHUnicodeToAnsiInetCP(UINT uiCP,
  481. LPCWSTR pwszSrc, int cwchSrc,
  482. LPSTR pszDst, int cchBuf)
  483. {
  484. int cwchSrcT, cchNeeded;
  485. int cchRc = 0; /* Assume failure */
  486. DWORD dwMode;
  487. HRESULT hres;
  488. /*
  489. * Checks the caller should've made.
  490. */
  491. ASSERT(IS_VALID_STRING_PTRW(pwszSrc, -1));
  492. ASSERT(cwchSrc == lstrlenW(pwszSrc) + 1);
  493. ASSERT(IS_VALID_WRITE_BUFFER(pszDst, CHAR, cchBuf));
  494. ASSERT(uiCP == 1200 || uiCP == 65000 || uiCP == 65001);
  495. ASSERT(pwszSrc);
  496. ASSERT(pszDst);
  497. ASSERT(cchBuf);
  498. /*
  499. * Note that not all encodings translate a null terminator into a null
  500. * terminator, so we have to save the NUL for last.
  501. */
  502. cwchSrc--; /* Save the NUL for last */
  503. cwchSrcT = cwchSrc;
  504. cchNeeded = cchBuf - 1; /* Save the NUL for last */
  505. dwMode = 0; /* Start fresh */
  506. hres = ConvertINetUnicodeToMultiByte(&dwMode, uiCP, pwszSrc,
  507. &cwchSrcT, pszDst, &cchNeeded);
  508. if (SUCCEEDED(hres)) {
  509. if (cwchSrcT >= cwchSrc) {
  510. /*
  511. * The output buffer was big enough; no double-buffering
  512. * needed. Translate the NUL manually.
  513. */
  514. ASSERT(cchNeeded < cchBuf);
  515. pszDst[cchNeeded] = TEXT('\0');
  516. cchRc = cchNeeded + 1;
  517. } else {
  518. /*
  519. * The output buffer wasn't big enough. Need to double-buffer.
  520. */
  521. LPSTR psz = (LPSTR)LocalAlloc(LMEM_FIXED,
  522. cchNeeded * SIZEOF(CHAR));
  523. if (psz) {
  524. dwMode = 0; /* Start fresh */
  525. hres = ConvertINetUnicodeToMultiByte(&dwMode, uiCP, pwszSrc,
  526. &cwchSrc, psz, &cchNeeded);
  527. if (SUCCEEDED(hres)) {
  528. // lstrcpyn doesn't check if it's chopping a DBCS char
  529. // so we need to use SHTruncateString.
  530. //
  531. // Add 1 because SHTruncateString doesn't count
  532. // the trailing null but we do
  533. //
  534. // Assert that we meet the preconditions for
  535. // SHTruncateString to return a valid value.
  536. //
  537. ASSERT(cchNeeded > cchBuf);
  538. cchRc = SHTruncateString(psz, cchBuf) + 1;
  539. lstrcpynA(pszDst, psz, cchBuf);
  540. }
  541. LocalFree(psz);
  542. }
  543. }
  544. } else {
  545. /* Possibly unsupported code page */
  546. ASSERT(!"Unexpected error in ConvertInetUnicodeToMultiByte");
  547. }
  548. return cchRc;
  549. }
  550. /*
  551. * @doc EXTERNAL
  552. *
  553. * @func int | SHUnicodeToAnsiCP |
  554. *
  555. * Convert a UNICODE string to an ANSI string via the
  556. * specified code page, which can be either a native
  557. * Windows code page or an Internet code page.
  558. * If the source string is too large
  559. * for the destination buffer, then as many characters as
  560. * possible are copied. Care is taken not to break a double-byte
  561. * character.
  562. *
  563. * The resulting output string is always null-terminated.
  564. *
  565. * @parm UINT | uiCP |
  566. *
  567. * The code page in which to perform the conversion.
  568. *
  569. * @parm LPCWSTR | pwszSrc |
  570. *
  571. * Source buffer containing UNICODE string to be converted.
  572. *
  573. * @parm LPSTR | pszDst |
  574. *
  575. * Destination buffer to receive converted ANSI string.
  576. *
  577. * @parm int | cchBuf |
  578. *
  579. * Size of the destination buffer in <t CHAR>s.
  580. *
  581. * @returns
  582. *
  583. * On success, the number of characters copied to the output
  584. * buffer is returned, including the terminating null.
  585. * (For the purpose of this function, a double-byte character
  586. * counts as two characters.)
  587. *
  588. */
  589. int
  590. SHUnicodeToAnsiCP(UINT uiCP, LPCWSTR pwszSrc, LPSTR pszDst, int cchBuf)
  591. {
  592. int cchRc = 0; /* Assume failure */
  593. #ifdef DEBUG
  594. #define GET_CP(uiCP) (((uiCP) == CP_ACPNOVALIDATE) ? CP_ACP : (uiCP))
  595. #else
  596. #define GET_CP(uiCP) uiCP
  597. #endif
  598. RIPMSG(IS_VALID_STRING_PTRW(pwszSrc, -1), "Caller of SHUnicodeToAnsiCP passed in a NULL pwszSrc!");
  599. ASSERT(IS_VALID_WRITE_BUFFER(pszDst, CHAR, cchBuf));
  600. /*
  601. * Sanity check - NULL source string is treated as a null string.
  602. */
  603. if (pwszSrc == NULL) {
  604. pwszSrc = L"";
  605. }
  606. /*
  607. * Sanity check - Output buffer must be non-NULL and must be of
  608. * nonzero size.
  609. */
  610. if (pszDst && cchBuf) {
  611. int cwchSrc;
  612. pszDst[0] = 0; /* In case of error */
  613. cwchSrc = lstrlenW(pwszSrc) + 1; /* Yes, Win9x has lstrlenW */
  614. /*
  615. * Decide what kind of code page it is.
  616. */
  617. switch (GET_CP(uiCP)) {
  618. case 1200: // UCS-2 (Unicode)
  619. uiCP = 65001;
  620. // Fall through
  621. case 50000: // "User Defined"
  622. case 65000: // UTF-7
  623. case 65001: // UTF-8
  624. cchRc = SHUnicodeToAnsiInetCP(GET_CP(uiCP), pwszSrc, cwchSrc, pszDst, cchBuf);
  625. break;
  626. default:
  627. cchRc = SHUnicodeToAnsiNativeCP(uiCP, pwszSrc, cwchSrc, pszDst, cchBuf);
  628. break;
  629. }
  630. }
  631. return cchRc;
  632. }
  633. /*
  634. * @doc EXTERNAL
  635. *
  636. * @func int | SHUnicodeToAnsi |
  637. *
  638. * Convert a UNICODE string to an ANSI string via the
  639. * <c CP_ACP> code page. If the source string is too large
  640. * for the destination buffer, then as many characters as
  641. * possible are copied. Care is taken not to break a double-byte
  642. * character.
  643. *
  644. * The resulting output string is always null-terminated.
  645. *
  646. * @parm LPCWSTR | pwszSrc |
  647. *
  648. * Source buffer containing UNICODE string to be converted.
  649. *
  650. * @parm LPSTR | pszDst |
  651. *
  652. * Destination buffer to receive converted ANSI string.
  653. *
  654. * @parm int | cchBuf |
  655. *
  656. * Size of the destination buffer in <t CHAR>s.
  657. *
  658. * @returns
  659. *
  660. * On success, the number of characters copied to the output
  661. * buffer is returned, including the terminating null.
  662. * (For the purpose of this function, a double-byte character
  663. * counts as two characters.)
  664. *
  665. */
  666. int
  667. SHUnicodeToAnsi(LPCWSTR pwszSrc, LPSTR pszDst, int cchBuf)
  668. {
  669. return SHUnicodeToAnsiCP(CP_ACP, pwszSrc, pszDst, cchBuf);
  670. }