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.

575 lines
17 KiB

  1. //+------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: CodePageConvert.cpp
  6. //
  7. // Contents: Implementation of functions
  8. // HrCodePageConvert
  9. // HrCodePageConvert
  10. // HrCodePageConvertFree
  11. // HrCodePageConvertInternal
  12. //
  13. // History:
  14. // aszafer 2000/03/15 created
  15. //
  16. //-------------------------------------------------------------
  17. #include "CodePageConvert.h"
  18. #include "dbgtrace.h"
  19. //+------------------------------------------------------------
  20. //
  21. // Function: HrCodePageConvert
  22. //
  23. // Synopsis: Converts a zero terminated string to a different code page
  24. //
  25. // NOTES:
  26. // caller needs to provide buffer where target string is returned
  27. //
  28. // Arguments:
  29. // uiSourceCodePage Source Code Page
  30. // pszSourceString Source String
  31. // uiTargetCodePage Target Code Page
  32. // pszTargetString p to prealloc buffer where target string is returned
  33. // cbTargetStringBuffer cbytes of preallocated buffer for target string
  34. //
  35. // Returns:
  36. // S_OK: Success
  37. // E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
  38. // HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
  39. // HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) if
  40. // uiSourceCodePage = uiTargetCodePage and
  41. // cbTargetStringBuffer is too small
  42. //
  43. // History:
  44. // aszafer 2000/03/29 created
  45. //
  46. //-------------------------------------------------------------
  47. HRESULT HrCodePageConvert (
  48. IN UINT uiSourceCodePage, // Source code page
  49. IN LPSTR pszSourceString, // Source String
  50. IN UINT uiTargetCodePage, // Target code page
  51. OUT LPSTR pszTargetString, // p to buffer where target string is returned
  52. IN int cbTargetStringBuffer) // cbytes in buffer for target string
  53. {
  54. HRESULT hr = S_OK;
  55. TraceFunctEnter("HrCodePageConvert");
  56. _ASSERT(pszSourceString);
  57. _ASSERT(pszTargetString);
  58. _ASSERT(cbTargetStringBuffer);
  59. //
  60. // Take care of trivial cases first
  61. //
  62. if (uiTargetCodePage == uiSourceCodePage){
  63. if (pszTargetString == pszSourceString)
  64. goto CLEANUP ;
  65. if (lstrlen(pszSourceString) < cbTargetStringBuffer){
  66. lstrcpy(pszTargetString,pszSourceString);
  67. }else{
  68. DebugTrace(0,
  69. "Insufficient cbTargetStringBuffer = %08lx",cbTargetStringBuffer);
  70. hr = HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ;
  71. }
  72. goto CLEANUP ;
  73. }
  74. //
  75. // If case is not trivial, call into HrCodePageConvertInternal
  76. //
  77. hr = HrCodePageConvertInternal (
  78. uiSourceCodePage, // source code page
  79. pszSourceString, // source string
  80. uiTargetCodePage, // target code page
  81. pszTargetString, // target string or NULL
  82. cbTargetStringBuffer, // cb in target string or 0
  83. NULL ); // NULL or p to where target string is returned
  84. if (FAILED(hr))
  85. DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr);
  86. CLEANUP:
  87. DebugTrace(0,"returning %08lx", hr);
  88. TraceFunctLeave();
  89. return hr;
  90. }
  91. //+------------------------------------------------------------
  92. //
  93. // Function: HrCodePageConvert
  94. //
  95. // Synopsis: Converts a zero terminated string to a different code page
  96. //
  97. // NOTES:
  98. // 1. if the fucntion succeeds, the caller needs to call
  99. // HrCodePageConvertFree (*ppszTargetString) when done,
  100. // to free memory allocated inside this function
  101. // 2. if the function fails, it will internally free all allocated memory
  102. //
  103. // Arguments:
  104. // uiSourceCodePage Source Code Page
  105. // pszSourceString Source String
  106. // uiTargetCodePage Target Code Page
  107. // ppszTargetString p to where to return target string
  108. //
  109. // Returns:
  110. // S_OK: Success
  111. // E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
  112. // HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
  113. //
  114. // History:
  115. // aszafer 2000/03/29 created
  116. //
  117. //-------------------------------------------------------------
  118. HRESULT HrCodePageConvert (
  119. IN UINT uiSourceCodePage, // Source code page
  120. IN LPSTR pszSourceString, // Source string
  121. IN UINT uiTargetCodePage, // Target code page
  122. OUT LPSTR * ppszTargetString) // p to where target string is returned
  123. {
  124. HRESULT hr = S_OK;
  125. LPSTR pszTargetString = NULL;
  126. TraceFunctEnter("HrCodePageConvert");
  127. _ASSERT(pszSourceString);
  128. _ASSERT(ppszTargetString);
  129. //
  130. // Take care of trivial cases first
  131. //
  132. if (uiTargetCodePage == uiSourceCodePage){
  133. pszTargetString = new CHAR[lstrlen(pszSourceString) + 1];
  134. if (pszTargetString == NULL) {
  135. hr = E_OUTOFMEMORY ;
  136. DebugTrace(0,"alloc for pszTargetString failed hr = %08lx", hr);
  137. goto CLEANUP ;
  138. }
  139. lstrcpy(pszTargetString,pszSourceString);
  140. *ppszTargetString = pszTargetString;
  141. goto CLEANUP ;
  142. }
  143. //
  144. // If case is not trivial, call into HrCodePageConvertInternal
  145. //
  146. hr = HrCodePageConvertInternal (
  147. uiSourceCodePage, // source code page
  148. pszSourceString, // source string
  149. uiTargetCodePage, // target code page
  150. NULL, // target string or NULL
  151. 0, // cb in target string or 0
  152. ppszTargetString ); // NULL or p to where target string is returned
  153. if (FAILED(hr))
  154. DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr);
  155. CLEANUP:
  156. DebugTrace(0,"returning %08lx", hr);
  157. TraceFunctLeave();
  158. return hr;
  159. }
  160. //+------------------------------------------------------------
  161. //
  162. // Function: HrCodePageConvertInternal
  163. //
  164. // Synopsis: Converts a zero terminated string to a different code page
  165. //
  166. // NOTES:
  167. // pointers to Source and Target strings may be the same
  168. //
  169. // Arguments:
  170. // uiSourceCodePage Source Code Page
  171. // pszSourceString Source String
  172. // uiTargetCodePage Target Code Page
  173. //
  174. // either:
  175. // pszTargetString p to buffer prealloc by caller where target string
  176. // is returned
  177. // cbTargetStringBuffer cbytes in prealloc buffer for target string
  178. // ppszTargetString NULL,
  179. //
  180. // or:
  181. // pszTargetString NULL
  182. // cbTargetStringBuffer 0
  183. // ppszTargetString p to where target string is to be returned
  184. //
  185. // Returns:
  186. // S_OK: Success
  187. // E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
  188. // HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
  189. //
  190. // History:
  191. // aszafer 2000/03/29 created
  192. //
  193. //-------------------------------------------------------------
  194. HRESULT HrCodePageConvertInternal (
  195. IN UINT uiSourceCodePage, // source code page
  196. IN LPSTR pszSourceString, // source string
  197. IN UINT uiTargetCodePage, // target code page
  198. OUT LPSTR pszTargetString, // target string or NULL
  199. IN int cbTargetStringBuffer, // cb in target string or 0
  200. OUT LPSTR* ppszTargetString ) // NULL or p to where target string is returned
  201. {
  202. HRESULT hr = S_OK;
  203. WCHAR wsz[TEMPBUFFER_WCHARS] ;
  204. int cwch = sizeof(wsz)/sizeof(WCHAR) ;
  205. WCHAR* pwsz = wsz ;
  206. CHAR* psz ;
  207. int iSourceStringLengh ;
  208. int cch ;
  209. BOOL fAlloc1 = FALSE ;
  210. BOOL fAlloc2 = FALSE ;
  211. TraceFunctEnter("HrCodePageConvertInternal");
  212. _ASSERT(((pszTargetString != NULL) && (cbTargetStringBuffer != 0)) ||
  213. (ppszTargetString != NULL) );
  214. psz = pszTargetString;
  215. cch = cbTargetStringBuffer;
  216. //
  217. // If stack allocated temp buffer may not be sufficient
  218. // for unicode string, allocate from heap
  219. //
  220. iSourceStringLengh = lstrlen(pszSourceString) + 1 ; //includes terminator
  221. if (iSourceStringLengh > TEMPBUFFER_WCHARS){
  222. //
  223. // Here we assume that each character in the source code page
  224. // can be represented by a single unicode character
  225. //
  226. cwch = iSourceStringLengh ;
  227. pwsz = new WCHAR[iSourceStringLengh];
  228. if (pwsz == NULL) {
  229. hr = E_OUTOFMEMORY ;
  230. DebugTrace(0,"alloc for pwsz failed hr = %08lx", hr);
  231. goto CLEANUP ;
  232. }
  233. fAlloc1 = TRUE ;
  234. }
  235. //
  236. // Convert to unicode
  237. //
  238. cwch = MultiByteToWideChar(
  239. uiSourceCodePage, // code page
  240. 0, // dwFlags
  241. pszSourceString, // string to map
  242. -1 , // number of bytes in string
  243. pwsz, // wide-character buffer
  244. cwch ); // size of buffer
  245. if(cwch == 0) {
  246. hr = HRESULT_FROM_WIN32(GetLastError());
  247. DebugTrace(0,"MultiByteToWideChar2 failed hr = %08lx", hr);
  248. _ASSERT(FAILED(hr));
  249. goto CLEANUP ;
  250. }
  251. //
  252. // If cbTargetStringBuffer == 0, allocate space for target string
  253. //
  254. if (cbTargetStringBuffer == 0){
  255. cch = WideCharToMultiByte(
  256. uiTargetCodePage, // codepage
  257. 0, // dwFlags
  258. pwsz, // wide-character string
  259. cwch, // number of wchars in string
  260. NULL, // buffer for new string
  261. 0, // size of buffer
  262. NULL, // default for unmappable chars
  263. NULL); // set when default char used
  264. if(cch == 0) {
  265. hr = HRESULT_FROM_WIN32(GetLastError());
  266. DebugTrace(0,"WideCharToMultiByte1 failed hr = %08lx", hr);
  267. _ASSERT(FAILED(hr));
  268. goto CLEANUP ;
  269. }
  270. psz = new CHAR[cch];
  271. if (psz == NULL) {
  272. hr = E_OUTOFMEMORY ;
  273. DebugTrace(0,"alloc for psz failed hr = %08lx", hr);
  274. goto CLEANUP ;
  275. }
  276. fAlloc2 = TRUE ;
  277. }
  278. //
  279. // Convert to target code page
  280. //
  281. cch = WideCharToMultiByte(
  282. uiTargetCodePage, // codepage
  283. 0, // dwFlags
  284. pwsz, // wide-character string
  285. cwch, // number of wchars in string
  286. psz, // buffer for new string
  287. cch, // size of buffer
  288. NULL, // default for unmappable chars
  289. NULL); // set when default char used
  290. if(cch == 0) {
  291. hr = HRESULT_FROM_WIN32(GetLastError());
  292. DebugTrace(0,"WideCharToMultiByte2 failed hr = %08lx", hr);
  293. _ASSERT(FAILED(hr));
  294. goto CLEANUP ;
  295. }
  296. //
  297. // If target string had to be allocated, output pointer to it
  298. //
  299. if (cbTargetStringBuffer == 0)
  300. *ppszTargetString = psz ;
  301. CLEANUP:
  302. if (fAlloc1)
  303. delete[] pwsz ;
  304. if (FAILED(hr)){
  305. if (fAlloc2)
  306. delete[] psz ;
  307. }
  308. DebugTrace(0,"returning %08lx", hr);
  309. TraceFunctLeave();
  310. return hr;
  311. }
  312. //+------------------------------------------------------------
  313. //
  314. // Function: HrCodePageConvertFree
  315. //
  316. // Synopsis: Use to free memory if HrCodePageConvert or HrCodePageConvertInternal
  317. // allocate buffer for target string
  318. //
  319. // Arguments:
  320. // pszTargetString p to buffer to be freed
  321. //
  322. // History:
  323. // aszafer 2000/03/29 created
  324. //
  325. //-------------------------------------------------------------
  326. VOID HrCodePageConvertFree(LPSTR pszTargetString)
  327. {
  328. _ASSERT(pszTargetString);
  329. delete pszTargetString;
  330. }
  331. //+------------------------------------------------------------
  332. //
  333. // Function: wcsutf8cmpi
  334. //
  335. // Synopsis: Compare a Unicode string to a UTF8 string and see
  336. // if they are identical
  337. //
  338. // Arguments: pwszStr1 - Unicode string
  339. // pszStr2 - UTF8 string
  340. //
  341. // Returns: S_OK - identical
  342. // S_FALSE - different
  343. // E_* - error
  344. //
  345. //-------------------------------------------------------------
  346. HRESULT wcsutf8cmpi(LPWSTR pwszStr1, LPCSTR pszStr2) {
  347. int rc;
  348. HRESULT hr;
  349. WCHAR wszStr2[TEMPBUFFER_WCHARS];
  350. LPWSTR pwszStr2 = wszStr2;
  351. DWORD cStr2;
  352. // convert string 2 to wide
  353. cStr2 = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, 0);
  354. if (cStr2 > (sizeof(wszStr2) / sizeof(WCHAR)) ) {
  355. pwszStr2 = new WCHAR[cStr2 + 1];
  356. if (pwszStr2 == NULL) {
  357. hr = E_OUTOFMEMORY;
  358. goto Exit;
  359. }
  360. }
  361. rc = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, cStr2);
  362. if (rc == 0) {
  363. hr = HRESULT_FROM_WIN32(GetLastError());
  364. goto Exit;
  365. }
  366. // do the comparison
  367. rc = _wcsicmp(pwszStr1, pwszStr2);
  368. if (rc == 0) hr = S_OK; else hr = S_FALSE;
  369. Exit:
  370. if (pwszStr2 != wszStr2) {
  371. delete[] pwszStr2;
  372. }
  373. return hr;
  374. }
  375. //+------------------------------------------------------------
  376. //
  377. // Function: CodePageConvertFree
  378. //
  379. // Synopsis: Free memory allocated in CodePageConvert
  380. //
  381. // Arguments:
  382. // pwszTargetString: Memory to free
  383. //
  384. // Returns: NOTHING
  385. //
  386. // History:
  387. // jstamerj 2001/03/20 16:37:28: Created.
  388. //
  389. //-------------------------------------------------------------
  390. VOID CodePageConvertFree(
  391. IN LPWSTR pwszTargetString)
  392. {
  393. delete [] pwszTargetString;
  394. } // CodePageConvertFree
  395. //+------------------------------------------------------------
  396. //
  397. // Function: HrConvertToUnicodeWithAlloc
  398. //
  399. // Synopsis: Convet an MBCS string to unicode (And allocate the
  400. // unicode string buffer)
  401. //
  402. // Arguments:
  403. // uiSourceCodePage: Source code page
  404. // pszSourceString: Source string
  405. // ppwszTargetString: Out parameter -- will be set to pointer to
  406. // allocated buffer. This should be free'd with CodePageConvertFree
  407. //
  408. // Returns:
  409. // S_OK: Success
  410. // E_OUTOFMEMORY
  411. // or error from MultiByteToWideChar
  412. //
  413. // History:
  414. // jstamerj 2001/03/20 16:38:52: Created.
  415. //
  416. //-------------------------------------------------------------
  417. HRESULT HrConvertToUnicodeWithAlloc(
  418. IN UINT uiSourceCodePage,
  419. IN LPSTR pszSourceString,
  420. OUT LPWSTR* ppwszTargetString)
  421. {
  422. return HrConvertToUnicodeWithAlloc(
  423. uiSourceCodePage,
  424. lstrlen(pszSourceString),
  425. pszSourceString,
  426. ppwszTargetString);
  427. }
  428. HRESULT HrConvertToUnicodeWithAlloc(
  429. IN UINT uiSourceCodePage,
  430. IN DWORD dwcbSourceString,
  431. IN LPSTR pszSourceString,
  432. OUT LPWSTR* ppwszTargetString)
  433. {
  434. HRESULT hr = S_OK;
  435. int ich = 0;
  436. int ich2 = 0;
  437. LPWSTR pwszTmp = NULL;
  438. TraceFunctEnterEx((LPARAM)0, "HrConvertToUnicodeWithAlloc");
  439. ich = MultiByteToWideChar(
  440. uiSourceCodePage,
  441. 0,
  442. pszSourceString,
  443. dwcbSourceString,
  444. NULL,
  445. 0);
  446. if(ich == 0)
  447. {
  448. hr = HRESULT_FROM_WIN32(GetLastError());
  449. ErrorTrace((LPARAM)0, "MultiByteToWideChar failed hr %08lx", hr);
  450. goto CLEANUP;
  451. }
  452. pwszTmp = new WCHAR[ich + 1];
  453. if(pwszTmp == NULL)
  454. {
  455. hr = E_OUTOFMEMORY;
  456. goto CLEANUP;
  457. }
  458. ich2 = MultiByteToWideChar(
  459. uiSourceCodePage,
  460. 0,
  461. pszSourceString,
  462. dwcbSourceString,
  463. pwszTmp,
  464. ich);
  465. if(ich2 == 0)
  466. {
  467. hr = HRESULT_FROM_WIN32(GetLastError());
  468. ErrorTrace((LPARAM)0, "MultiByteToWideChar2 failed hr %08lx", hr);
  469. goto CLEANUP;
  470. }
  471. pwszTmp[ich] = '\0';
  472. //
  473. // Success!
  474. //
  475. *ppwszTargetString = pwszTmp;
  476. CLEANUP:
  477. if(FAILED(hr))
  478. {
  479. if(pwszTmp)
  480. delete [] pwszTmp;
  481. }
  482. DebugTrace((LPARAM)0, "returning %08lx", hr);
  483. TraceFunctLeaveEx((LPARAM)0);
  484. return hr;
  485. } // HrConvertToUnicodeWithAlloc