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.

567 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: charconv.hxx
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef __CHARCONV_HXX_
  11. #define __CHARCONV_HXX_
  12. #define INVALID_LENGTH ((unsigned short)-1)
  13. // #define NO_STACK_ALLOCS
  14. RPC_STATUS A2WAttachHelper(char *pszAnsi, WCHAR **ppUnicode);
  15. RPC_STATUS W2AAttachHelper(WCHAR *pUnicode, char **ppAnsi);
  16. inline
  17. void
  18. SimpleUnicodeToAnsi(WCHAR *in, char *out)
  19. /*++
  20. Routine Description:
  21. Converts a unicode string to an ansi string. It is assumed
  22. that the unicode string contains only ANSI characters (IP addresses,
  23. port numbers, DNS names, etc) and that the out buffer is large enough
  24. to hold the result.
  25. Arguments:
  26. in - Unicode string containing only ANSI characters.
  27. If any of the high bytes are used they will be lost.
  28. out - Buffer to put the result, assumed to be wcslen(in) + 1 bytes.
  29. Return Value:
  30. None
  31. --*/
  32. {
  33. while( *out++ = (CHAR)*in++)
  34. ;
  35. }
  36. inline
  37. void
  38. SimpleAnsiToUnicode(char *in, WCHAR *out)
  39. {
  40. while( *out++ = (USHORT)*in++)
  41. ;
  42. }
  43. inline void SimpleAnsiToPlatform(char *in, RPC_CHAR *out)
  44. {
  45. SimpleAnsiToUnicode(in, out);
  46. }
  47. inline void SimpleUnicodeToPlatform(WCHAR * in, RPC_CHAR *out)
  48. {
  49. wcscpy(out, in);
  50. }
  51. inline void SimplePlatformToAnsi(RPC_CHAR *in, char *out)
  52. {
  53. SimpleUnicodeToAnsi(in, out);
  54. }
  55. inline void SimplePlatformToUnicode(RPC_CHAR *in, WCHAR * out)
  56. {
  57. wcscpy(out, in);
  58. }
  59. inline void FullAnsiToUnicode(char *in, WCHAR * out)
  60. {
  61. int nLength = strlen(in) + 1;
  62. RtlMultiByteToUnicodeN(out, nLength * 2, NULL, in, nLength);
  63. }
  64. inline void FullUnicodeToAnsi(WCHAR * in, char *out)
  65. {
  66. int nLength = wcslen(in) + 1;
  67. RtlUnicodeToMultiByteN(out, nLength, NULL, in, nLength * 2);
  68. }
  69. inline void AnsiToPlatform(char *in, RPC_CHAR *out)
  70. {
  71. FullAnsiToUnicode(in, out);
  72. }
  73. inline void UnicodeToPlatform(WCHAR * in, RPC_CHAR *out)
  74. {
  75. wcscpy(out, in);
  76. }
  77. inline void PlatformToAnsi(RPC_CHAR *in, char *out)
  78. {
  79. FullUnicodeToAnsi(in, out);
  80. }
  81. inline void PlatformToUnicode(RPC_CHAR *in, WCHAR * out)
  82. {
  83. wcscpy(out, in);
  84. }
  85. class CNlUnicode
  86. {
  87. public:
  88. #ifdef DBG
  89. CNlUnicode(void)
  90. {
  91. m_pUnicodeString = NULL;
  92. }
  93. #endif
  94. operator WCHAR *(void)
  95. {
  96. return m_pUnicodeString;
  97. }
  98. RPC_STATUS Attach(char *pszAnsi)
  99. {
  100. return A2WAttachHelper(pszAnsi, &m_pUnicodeString);
  101. }
  102. RPC_STATUS Attach(unsigned char *pszAnsi)
  103. {
  104. return Attach((char *)pszAnsi);
  105. }
  106. RPC_STATUS AttachOptional(char *pszAnsi)
  107. {
  108. if (pszAnsi)
  109. return A2WAttachHelper(pszAnsi, &m_pUnicodeString);
  110. else
  111. {
  112. m_pUnicodeString = NULL;
  113. return RPC_S_OK;
  114. }
  115. }
  116. RPC_STATUS AttachOptional(unsigned char *pszAnsi)
  117. {
  118. return AttachOptional((char *)pszAnsi);
  119. }
  120. protected:
  121. WCHAR *m_pUnicodeString;
  122. };
  123. class CNlAnsi
  124. {
  125. public:
  126. #ifdef DBG
  127. CNlAnsi(void)
  128. {
  129. m_pAnsiString = NULL;
  130. }
  131. #endif
  132. operator char *(void)
  133. {
  134. return m_pAnsiString;
  135. }
  136. operator unsigned char *(void)
  137. {
  138. return (unsigned char *)m_pAnsiString;
  139. }
  140. RPC_STATUS Attach(WCHAR *pszUnicode)
  141. {
  142. return W2AAttachHelper(pszUnicode, &m_pAnsiString);
  143. }
  144. RPC_STATUS AttachOptional(WCHAR *pszUnicode)
  145. {
  146. if (pszUnicode)
  147. return W2AAttachHelper(pszUnicode, &m_pAnsiString);
  148. else
  149. {
  150. m_pAnsiString = NULL;
  151. return RPC_S_OK;
  152. }
  153. }
  154. char **GetPAnsiString(void)
  155. {
  156. return &m_pAnsiString;
  157. }
  158. protected:
  159. char *m_pAnsiString;
  160. };
  161. class CNlDelAnsiUnicode : public CNlUnicode
  162. {
  163. public:
  164. CNlDelAnsiUnicode(void)
  165. {
  166. m_pAnsiString = NULL;
  167. }
  168. ~CNlDelAnsiUnicode()
  169. {
  170. if (m_pAnsiString)
  171. delete m_pAnsiString;
  172. }
  173. operator char **(void)
  174. {
  175. return &m_pAnsiString;
  176. }
  177. operator unsigned char **(void)
  178. {
  179. return (unsigned char **)&m_pAnsiString;
  180. }
  181. RPC_STATUS Convert(void)
  182. {
  183. RPC_STATUS status;
  184. if (m_pAnsiString != NULL)
  185. {
  186. status = A2WAttachHelper(m_pAnsiString, &m_pUnicodeString);
  187. delete m_pAnsiString;
  188. m_pAnsiString = NULL;
  189. }
  190. else
  191. {
  192. status = RPC_S_OK;
  193. }
  194. return status;
  195. }
  196. RPC_STATUS ConvertOptional(void)
  197. {
  198. if (m_pAnsiString)
  199. return Convert();
  200. else
  201. {
  202. m_pUnicodeString = NULL;
  203. return RPC_S_OK;
  204. }
  205. }
  206. protected:
  207. char *m_pAnsiString;
  208. };
  209. class CNlDelUnicodeAnsi : public CNlAnsi
  210. {
  211. public:
  212. CNlDelUnicodeAnsi(void)
  213. {
  214. m_pUnicodeString = NULL;
  215. }
  216. ~CNlDelUnicodeAnsi()
  217. {
  218. if (m_pUnicodeString)
  219. delete m_pUnicodeString;
  220. }
  221. operator WCHAR **(void)
  222. {
  223. return &m_pUnicodeString;
  224. }
  225. RPC_STATUS Convert(void)
  226. {
  227. RPC_STATUS status;
  228. if (m_pUnicodeString != NULL)
  229. {
  230. status = W2AAttachHelper(m_pUnicodeString, &m_pAnsiString);
  231. delete m_pUnicodeString;
  232. m_pUnicodeString = NULL;
  233. }
  234. else
  235. {
  236. status = RPC_S_OK;
  237. }
  238. return status;
  239. }
  240. RPC_STATUS ConvertOptional(void)
  241. {
  242. if (m_pUnicodeString)
  243. return Convert();
  244. else
  245. {
  246. m_pAnsiString = NULL;
  247. return RPC_S_OK;
  248. }
  249. }
  250. protected:
  251. WCHAR *m_pUnicodeString;
  252. };
  253. class CHeapUnicode
  254. {
  255. public:
  256. CHeapUnicode(void)
  257. {
  258. m_UnicodeString.Length = INVALID_LENGTH;
  259. m_UnicodeString.Buffer = NULL;
  260. }
  261. ~CHeapUnicode()
  262. {
  263. if (m_UnicodeString.Length != INVALID_LENGTH)
  264. RtlFreeUnicodeString(&m_UnicodeString);
  265. }
  266. operator WCHAR *(void)
  267. {
  268. return m_UnicodeString.Buffer;
  269. }
  270. RPC_STATUS Attach(char *pszAnsi);
  271. RPC_STATUS Attach(unsigned char *pszAnsi)
  272. {
  273. return Attach((char *)pszAnsi);
  274. }
  275. RPC_STATUS AttachOptional(char *pszAnsi)
  276. {
  277. if (pszAnsi)
  278. return Attach(pszAnsi);
  279. else
  280. {
  281. m_UnicodeString.Buffer = 0;
  282. return RPC_S_OK;
  283. }
  284. }
  285. RPC_STATUS AttachOptional(unsigned char *pszAnsi)
  286. {
  287. return AttachOptional((char *)pszAnsi);
  288. }
  289. private:
  290. UNICODE_STRING m_UnicodeString;
  291. };
  292. class CHeapAnsi
  293. {
  294. public:
  295. CHeapAnsi(void)
  296. {
  297. m_AnsiString.Length = INVALID_LENGTH;
  298. m_AnsiString.Buffer = NULL;
  299. }
  300. ~CHeapAnsi()
  301. {
  302. if (m_AnsiString.Length != INVALID_LENGTH)
  303. RtlFreeAnsiString(&m_AnsiString);
  304. }
  305. operator char *(void)
  306. {
  307. return m_AnsiString.Buffer;
  308. }
  309. operator unsigned char *(void)
  310. {
  311. return (unsigned char *)(m_AnsiString.Buffer);
  312. }
  313. RPC_STATUS Attach(WCHAR *pszUnicode);
  314. RPC_STATUS AttachOptional(WCHAR *pszUnicode)
  315. {
  316. if (pszUnicode)
  317. return Attach(pszUnicode);
  318. else
  319. {
  320. m_AnsiString.Buffer = 0;
  321. return RPC_S_OK;
  322. }
  323. }
  324. private:
  325. ANSI_STRING m_AnsiString;
  326. };
  327. class CStackUnicode
  328. {
  329. public:
  330. #ifdef DBG
  331. CStackUnicode(void)
  332. {
  333. m_pUnicodeString = NULL;
  334. }
  335. #endif
  336. operator WCHAR *(void)
  337. {
  338. return m_pUnicodeString;
  339. }
  340. RPC_STATUS Attach(char *pszAnsi, int nLength)
  341. {
  342. RtlMultiByteToUnicodeN(m_pUnicodeString, nLength * 2, NULL, pszAnsi, nLength);
  343. return(RPC_S_OK);
  344. }
  345. RPC_STATUS Attach(unsigned char *pszAnsi, int nLength)
  346. {
  347. return Attach((char *)pszAnsi, nLength);
  348. }
  349. RPC_STATUS AttachOptional(char *pszAnsi, int nLength)
  350. {
  351. if (pszAnsi)
  352. return Attach(pszAnsi, nLength);
  353. else
  354. {
  355. m_pUnicodeString = NULL;
  356. return RPC_S_OK;
  357. }
  358. }
  359. RPC_STATUS AttachOptional(unsigned char *pszAnsi, int nLength)
  360. {
  361. return AttachOptional((char *)pszAnsi, nLength);
  362. }
  363. WCHAR **GetPUnicodeString(void)
  364. {
  365. return &m_pUnicodeString;
  366. }
  367. private:
  368. WCHAR *m_pUnicodeString;
  369. };
  370. class CStackAnsi
  371. {
  372. public:
  373. #ifdef DBG
  374. CStackAnsi(void)
  375. {
  376. m_pAnsiString = NULL;
  377. }
  378. #endif
  379. operator char *(void)
  380. {
  381. return m_pAnsiString;
  382. }
  383. operator unsigned char *(void)
  384. {
  385. return (unsigned char *)m_pAnsiString;
  386. }
  387. RPC_STATUS Attach(WCHAR *pszUnicode, int nAnsiLength, int nUnicodeLength)
  388. {
  389. RtlUnicodeToMultiByteN(m_pAnsiString, nAnsiLength, NULL, pszUnicode, nUnicodeLength);
  390. return(RPC_S_OK);
  391. }
  392. RPC_STATUS AttachOptional(WCHAR *pszUnicode, int nAnsiLength, int nUnicodeLength)
  393. {
  394. if (pszUnicode)
  395. return Attach(pszUnicode, nAnsiLength, nUnicodeLength);
  396. else
  397. {
  398. m_pAnsiString = NULL;
  399. return RPC_S_OK;
  400. }
  401. }
  402. char **GetPAnsiString(void)
  403. {
  404. return &m_pAnsiString;
  405. }
  406. private:
  407. char *m_pAnsiString;
  408. };
  409. #define USES_CONVERSION RPC_STATUS _convResult
  410. #define ATTEMPT_HEAP_A2W(o, a) \
  411. _convResult = o.Attach(a); \
  412. if (_convResult != RPC_S_OK) \
  413. return _convResult
  414. #define ATTEMPT_HEAP_W2A(o, w) \
  415. _convResult = o.Attach(w); \
  416. if (_convResult != RPC_S_OK) \
  417. return _convResult
  418. #define ATTEMPT_STACK_A2W(o, a) \
  419. _convResult = lstrlenA((const char *)a) + 1; \
  420. *(o.GetPUnicodeString()) = (WCHAR *)_alloca(_convResult * sizeof(WCHAR)); \
  421. _convResult = o.Attach((char *)a, _convResult); \
  422. if (_convResult != RPC_S_OK) \
  423. return _convResult
  424. #define ATTEMPT_STACK_W2A(o, w) \
  425. _convResult = ((lstrlenW(w) + 1) * 2); \
  426. *(o.GetPAnsiString()) = (char *)_alloca(_convResult); \
  427. _convResult = o.Attach(w, _convResult, _convResult); \
  428. if (_convResult != RPC_S_OK) \
  429. return _convResult
  430. #define ATTEMPT_NL_A2W(o, a) ATTEMPT_HEAP_A2W(o, a)
  431. #define ATTEMPT_NL_W2A(o, w) ATTEMPT_HEAP_W2A(o, w)
  432. #define ATTEMPT_CONVERT_A2W(o, w) \
  433. _convResult = o.Convert(); \
  434. if (_convResult != RPC_S_OK) \
  435. return _convResult; \
  436. *w = o
  437. #define ATTEMPT_CONVERT_W2A(o, a) \
  438. _convResult = o.Convert(); \
  439. if (_convResult != RPC_S_OK) \
  440. return _convResult; \
  441. *a = o
  442. // optional conversions
  443. #define ATTEMPT_HEAP_A2W_OPTIONAL(o, a) \
  444. _convResult = o.AttachOptional(a); \
  445. if (_convResult != RPC_S_OK) \
  446. return _convResult
  447. #define ATTEMPT_HEAP_W2A_OPTIONAL(o, w) \
  448. _convResult = o.AttachOptional(w); \
  449. if (_convResult != RPC_S_OK) \
  450. return _convResult
  451. #define ATTEMPT_STACK_A2W_OPTIONAL(o, a) \
  452. if (a) \
  453. { \
  454. ATTEMPT_STACK_A2W(o, a); \
  455. } \
  456. else \
  457. *(o.GetPUnicodeString()) = NULL
  458. #define ATTEMPT_STACK_W2A_OPTIONAL(o, w) \
  459. if (w) \
  460. { \
  461. ATTEMPT_STACK_W2A(o, w); \
  462. } \
  463. else \
  464. *(o.GetPAnsiString()) = NULL
  465. #define ATTEMPT_NL_A2W_OPTIONAL(o, a) ATTEMPT_HEAP_A2W_OPTIONAL(o, a)
  466. #define ATTEMPT_NL_W2A_OPTIONAL(o, w) ATTEMPT_HEAP_W2A_OPTIONAL(o, w)
  467. #define ATTEMPT_CONVERT_A2W_OPTIONAL(o, w) \
  468. _convResult = o.ConvertOptional(); \
  469. if (_convResult != RPC_S_OK) \
  470. return _convResult; \
  471. if (w) \
  472. *w = o
  473. #define ATTEMPT_CONVERT_W2A_OPTIONAL(o, a) \
  474. _convResult = o.ConvertOptional(); \
  475. if (_convResult != RPC_S_OK) \
  476. return _convResult; \
  477. if (a) \
  478. *a = o
  479. // generic thunking macros.
  480. #ifdef UNICODE
  481. // if unicode is defined, then inbound thunking is in the direction Ansi -> Unicode
  482. typedef unsigned char THUNK_CHAR;
  483. #define CHeapInThunk CHeapUnicode
  484. #define CStackInThunk CStackUnicode
  485. #define ATTEMPT_HEAP_IN_THUNK ATTEMPT_HEAP_A2W
  486. #define ATTEMPT_HEAP_IN_THUNK_OPTIONAL ATTEMPT_HEAP_A2W_OPTIONAL
  487. #define ATTEMPT_STACK_IN_THUNK ATTEMPT_STACK_A2W
  488. #define ATTEMPT_STACK_IN_THUNK_OPTIONAL ATTEMPT_STACK_A2W_OPTIONAL
  489. #define THUNK_FN(fn) fn##A
  490. // the outbound thunking is opposite to inbound - Unicode -> Ansi
  491. #define COutDelThunk CNlDelUnicodeAnsi
  492. #define ATTEMPT_OUT_THUNK ATTEMPT_CONVERT_W2A
  493. #define ATTEMPT_OUT_THUNK_OPTIONAL ATTEMPT_CONVERT_W2A_OPTIONAL
  494. #else
  495. typedef unsigned short THUNK_CHAR;
  496. #define CHeapInThunk CHeapAnsi
  497. #define CStackInThunk CStackAnsi
  498. #define ATTEMPT_HEAP_IN_THUNK ATTEMPT_HEAP_W2A
  499. #define ATTEMPT_HEAP_IN_THUNK_OPTIONAL ATTEMPT_HEAP_W2A_OPTIONAL
  500. #define ATTEMPT_STACK_IN_THUNK ATTEMPT_STACK_W2A
  501. #define ATTEMPT_STACK_IN_THUNK_OPTIONAL ATTEMPT_STACK_W2A_OPTIONAL
  502. #define THUNK_FN(fn) fn##W
  503. #define COutDelThunk CNlDelAnsiUnicode
  504. #define ATTEMPT_OUT_THUNK ATTEMPT_CONVERT_A2W
  505. #define ATTEMPT_OUT_THUNK_OPTIONAL ATTEMPT_CONVERT_A2W_OPTIONAL
  506. #endif
  507. #endif // #ifndef __CHARCONV_HXX_