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.

491 lines
16 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. uniconv.c
  5. Abstract:
  6. Routine to convert UNICODE to ASCII.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 10-May-1996 DonRyan
  11. Removed banner from Technology Dynamics, Inc.
  12. --*/
  13. //--------------------------- WINDOWS DEPENDENCIES --------------------------
  14. #include <nt.h>
  15. #include <ntdef.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <snmp.h>
  20. #include <snmputil.h>
  21. #include <ntrtl.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  25. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  26. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  27. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  28. //--------------------------- PRIVATE CONSTANTS -----------------------------
  29. //--------------------------- PRIVATE STRUCTS -------------------------------
  30. //--------------------------- PRIVATE VARIABLES -----------------------------
  31. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  32. //--------------------------- PRIVATE PROCEDURES ----------------------------
  33. //--------------------------- PUBLIC PROCEDURES -----------------------------
  34. // The return code matches what Uni->Str uses
  35. LONG
  36. SNMP_FUNC_TYPE
  37. SnmpUtilUnicodeToAnsi(
  38. LPSTR *ppSzString,
  39. LPWSTR pWcsString,
  40. BOOLEAN bAllocBuffer)
  41. {
  42. int retCode;
  43. int nAnsiStringLen;
  44. int nUniStringLen;
  45. // make sure the parameters are valid
  46. if (pWcsString == NULL || // the unicode string should be valid
  47. ppSzString == NULL || // the output parameter should be a valid pointer
  48. (!bAllocBuffer && *((UNALIGNED LPSTR *) ppSzString) == NULL)) // if we are not requested to allocate the buffer,
  49. // then the supplied one should be valid
  50. {
  51. SNMPDBG((
  52. SNMP_LOG_ERROR,
  53. "SNMP: SNMPAPI: Invalid input to SnmpUtilUnicodeToAnsi.\n"));
  54. SetLastError(ERROR_INVALID_PARAMETER);
  55. return (-1);
  56. }
  57. nUniStringLen = wcslen(pWcsString);
  58. nAnsiStringLen = nUniStringLen + 1; // greatest value possible
  59. // if we are requested to alloc the output buffer..
  60. if (bAllocBuffer)
  61. {
  62. // ...pick up first the buffer length needed for translation.
  63. retCode = WideCharToMultiByte(
  64. CP_ACP,
  65. 0,
  66. pWcsString,
  67. nUniStringLen + 1, // include the null terminator in the string
  68. NULL,
  69. 0, // the function returns the number of bytes required for the buffer
  70. NULL,
  71. NULL);
  72. // at least we expect here the null terminator
  73. // if retCode is zero, something else went wrong.
  74. if (retCode == 0)
  75. {
  76. SNMPDBG((
  77. SNMP_LOG_ERROR,
  78. "SNMP: SNMPAPI: First call to WideCharToMultiByte failed [%d].\n",
  79. GetLastError()));
  80. return -1;
  81. }
  82. // adjust the length of the ANSI string to the correct value
  83. // !!! it includes the null terminator !!!
  84. nAnsiStringLen = retCode;
  85. // alloc here as many bytes as we need for the translation
  86. *((UNALIGNED LPSTR *) ppSzString) = SnmpUtilMemAlloc(nAnsiStringLen);
  87. // at this point we should have a valid output buffer
  88. if (*((UNALIGNED LPSTR *) ppSzString) == NULL)
  89. {
  90. SNMPDBG((
  91. SNMP_LOG_ERROR,
  92. "SNMP: SNMPAPI: Memory allocation failed in SnmpUtilUnicodeToAnsi [%d].\n",
  93. GetLastError()));
  94. SetLastError(SNMP_MEM_ALLOC_ERROR);
  95. return -1;
  96. }
  97. }
  98. // if bAllocBuffer is false, we assume the buffer given
  99. // by the caller is sufficiently large to hold all the ANSI string
  100. retCode = WideCharToMultiByte(
  101. CP_ACP,
  102. 0,
  103. pWcsString,
  104. nUniStringLen + 1,
  105. *((UNALIGNED LPSTR *) ppSzString),
  106. nAnsiStringLen,
  107. NULL,
  108. NULL);
  109. // nothing should go wrong here. However, if something went wrong...
  110. if (retCode == 0)
  111. {
  112. SNMPDBG((
  113. SNMP_LOG_ERROR,
  114. "SNMP: SNMPAPI: Second call to WideCharToMultiByte failed [%d].\n",
  115. GetLastError()));
  116. // ..we made it, we kill it
  117. if (bAllocBuffer)
  118. {
  119. SnmpUtilMemFree(*((UNALIGNED LPSTR *) ppSzString));
  120. *((UNALIGNED LPSTR *) ppSzString) = NULL;
  121. }
  122. // bail with error
  123. return -1;
  124. }
  125. // at this point, the call succeeded.
  126. return 0;
  127. }
  128. // The return code matches what Uni->Str uses
  129. LONG
  130. SNMP_FUNC_TYPE
  131. SnmpUtilUnicodeToUTF8(
  132. LPSTR *pUtfString,
  133. LPWSTR wcsString,
  134. BOOLEAN bAllocBuffer)
  135. {
  136. int retCode;
  137. int nWcsStringLen;
  138. int nUtfStringLen;
  139. // Bug# 268748, lmmib2.dll uses this API and causes exception here on IA64 platform.
  140. // it is possible that pUtfString points to a pointer which is not aligned because the
  141. // pointer is embedded in a buffer allocated in lmmib2.dll.
  142. // Other functions in this file are fixed with this potential problem too.
  143. // make sure the parameters are valid
  144. if (wcsString == NULL || // the unicode string should be valid
  145. pUtfString == NULL || // the output parameter should be a valid pointer
  146. (!bAllocBuffer && *((UNALIGNED LPSTR *) pUtfString) == NULL)) // if we are not requested to allocate the buffer,
  147. // then the supplied one should be valid
  148. {
  149. SNMPDBG((
  150. SNMP_LOG_ERROR,
  151. "SNMP: SNMPAPI: Invalid input to SnmpUtilUnicodeToUTF8.\n"));
  152. SetLastError(ERROR_INVALID_PARAMETER);
  153. return (-1);
  154. }
  155. nWcsStringLen = wcslen(wcsString);
  156. nUtfStringLen = 3 * (nWcsStringLen + 1); // initialize the lenght of the output buffer with the
  157. // greatest value possible
  158. // if we are requested to alloc the output buffer..
  159. if (bAllocBuffer)
  160. {
  161. // ...pick up first the buffer length needed for translation.
  162. retCode = WideCharToMultiByte(
  163. CP_UTF8,
  164. 0,
  165. wcsString,
  166. nWcsStringLen + 1, // include the null terminator in the string
  167. NULL,
  168. 0,
  169. NULL,
  170. NULL);
  171. // at least we expect here the null terminator
  172. // if retCode is zero, something else went wrong.
  173. if (retCode == 0)
  174. {
  175. SNMPDBG((
  176. SNMP_LOG_ERROR,
  177. "SNMP: SNMPAPI: First call to WideCharToMultiByte failed [%d].\n",
  178. GetLastError()));
  179. return -1;
  180. }
  181. // adjust the length of the utf8 string to the correct value
  182. // !!! it includes the null terminator !!!
  183. nUtfStringLen = retCode;
  184. // alloc here as many bytes as we need for the translation
  185. *((UNALIGNED LPSTR *) pUtfString) = SnmpUtilMemAlloc(nUtfStringLen);
  186. // at this point we should have a valid output buffer
  187. if (*((UNALIGNED LPSTR *) pUtfString) == NULL)
  188. {
  189. SNMPDBG((
  190. SNMP_LOG_ERROR,
  191. "SNMP: SNMPAPI: Memory allocation failed in SnmpUtilUnicodeToUTF8 [%d].\n",
  192. GetLastError()));
  193. SetLastError(SNMP_MEM_ALLOC_ERROR);
  194. return -1;
  195. }
  196. }
  197. // if bAllocBuffer is false, we assume the buffer given
  198. // by the caller is sufficiently large to hold all the UTF8 string
  199. retCode = WideCharToMultiByte(
  200. CP_UTF8,
  201. 0,
  202. wcsString,
  203. nWcsStringLen + 1,
  204. *((UNALIGNED LPSTR *) pUtfString),
  205. nUtfStringLen,
  206. NULL,
  207. NULL);
  208. // nothing should go wrong here. However, if smth went wrong...
  209. if (retCode == 0)
  210. {
  211. SNMPDBG((
  212. SNMP_LOG_ERROR,
  213. "SNMP: SNMPAPI: Second call to WideCharToMultiByte failed [%d].\n",
  214. GetLastError()));
  215. // ..we made it, we kill it
  216. if (bAllocBuffer)
  217. {
  218. SnmpUtilMemFree(*((UNALIGNED LPSTR *) pUtfString));
  219. *((UNALIGNED LPSTR *) pUtfString) = NULL;
  220. }
  221. // bail with error
  222. return -1;
  223. }
  224. // at this point, the call succeeded.
  225. return 0;
  226. }
  227. // The return code matches what Uni->Str uses
  228. LONG
  229. SNMP_FUNC_TYPE
  230. SnmpUtilAnsiToUnicode(
  231. LPWSTR *ppWcsString,
  232. LPSTR pSzString,
  233. BOOLEAN bAllocBuffer)
  234. {
  235. int retCode;
  236. int nAnsiStringLen;
  237. int nWcsStringLen;
  238. // check the consistency of the parameters first
  239. if (pSzString == NULL || // the input parameter must be valid
  240. ppWcsString == NULL || // the pointer to the output parameter must be valid
  241. (!bAllocBuffer && *((UNALIGNED LPWSTR *) ppWcsString) == NULL)) // if we are not required to allocate the output parameter
  242. // then the output buffer must be valid
  243. {
  244. SNMPDBG((
  245. SNMP_LOG_ERROR,
  246. "SNMP: SNMPAPI: Invalid input to SnmpUtilAnsiToUnicode.\n"));
  247. SetLastError(ERROR_INVALID_PARAMETER);
  248. return -1;
  249. }
  250. nAnsiStringLen = strlen(pSzString); // the length of the input ANSI string
  251. nWcsStringLen = nAnsiStringLen + 1; // greatest value possible
  252. if (bAllocBuffer)
  253. {
  254. retCode = MultiByteToWideChar(
  255. CP_ACP,
  256. MB_PRECOMPOSED,
  257. pSzString,
  258. nAnsiStringLen + 1, // including the null terminator
  259. NULL,
  260. 0); // the function returns the required buffer size, in wide characters
  261. // at least we expect here the null terminator
  262. // if retCode is zero, something else went wrong.
  263. if (retCode == 0)
  264. {
  265. SNMPDBG((
  266. SNMP_LOG_ERROR,
  267. "SNMP: SNMPAPI: First call to MultiByteToWideChar failed [%d].\n",
  268. GetLastError()));
  269. return -1;
  270. }
  271. // adjust the length of the Uincode string to the correct value
  272. nWcsStringLen = retCode;
  273. // alloc here as many bytes as we need for the translation
  274. // !!! it includes the null terminator !!!
  275. *((UNALIGNED LPWSTR *) ppWcsString) = SnmpUtilMemAlloc(nWcsStringLen * sizeof(WCHAR));
  276. // at this point we should have a valid output buffer
  277. if (*((UNALIGNED LPWSTR *) ppWcsString) == NULL)
  278. {
  279. SNMPDBG((
  280. SNMP_LOG_ERROR,
  281. "SNMP: SNMPAPI: Memory allocation failed in SnmpUtilAnsiToUnicode [%d].\n",
  282. GetLastError()));
  283. SetLastError(SNMP_MEM_ALLOC_ERROR);
  284. return -1;
  285. }
  286. }
  287. // if bAllocBuffer is false, we assume the buffer given
  288. // by the caller is sufficiently large to hold all the Unicode string
  289. retCode = MultiByteToWideChar(
  290. CP_ACP,
  291. MB_PRECOMPOSED,
  292. pSzString,
  293. nAnsiStringLen + 1,
  294. *((UNALIGNED LPWSTR *) ppWcsString),
  295. nWcsStringLen);
  296. // nothing should go wrong here. However, if something went wrong...
  297. if (retCode == 0)
  298. {
  299. SNMPDBG((
  300. SNMP_LOG_ERROR,
  301. "SNMP: SNMPAPI: Second call to MultiByteToWideChar failed [%d].\n",
  302. GetLastError()));
  303. // ..we made it, we kill it
  304. if (bAllocBuffer)
  305. {
  306. SnmpUtilMemFree(*((UNALIGNED LPWSTR *) ppWcsString));
  307. *((UNALIGNED LPWSTR *) ppWcsString) = NULL;
  308. }
  309. // bail with error
  310. return -1;
  311. }
  312. // at this point, the call succeeded.
  313. return 0;
  314. }
  315. // The return code matches what Uni->Str uses
  316. LONG
  317. SNMP_FUNC_TYPE
  318. SnmpUtilUTF8ToUnicode(
  319. LPWSTR *pWcsString,
  320. LPSTR utfString,
  321. BOOLEAN bAllocBuffer)
  322. {
  323. int retCode;
  324. int nUtfStringLen;
  325. int nWcsStringLen;
  326. // check the consistency of the parameters first
  327. if (utfString == NULL || // the input parameter must be valid
  328. pWcsString == NULL || // the pointer to the output parameter must be valid
  329. (!bAllocBuffer && *((UNALIGNED LPWSTR *) pWcsString) == NULL)) // if we are not required to allocate the output parameter
  330. // then the output buffer must be valid
  331. {
  332. SNMPDBG((
  333. SNMP_LOG_ERROR,
  334. "SNMP: SNMPAPI: Invalid input to SnmpUtilUTF8ToUnicode.\n"));
  335. SetLastError(ERROR_INVALID_PARAMETER);
  336. return -1;
  337. }
  338. nUtfStringLen = strlen(utfString); // the length of the input utf8 string
  339. nWcsStringLen = nUtfStringLen + 1; // greatest value possible
  340. if (bAllocBuffer)
  341. {
  342. retCode = MultiByteToWideChar(
  343. CP_UTF8,
  344. 0,
  345. utfString,
  346. nUtfStringLen + 1,
  347. NULL,
  348. 0);
  349. // at least we expect here the null terminator
  350. // if retCode is zero, something else went wrong.
  351. if (retCode == 0)
  352. {
  353. SNMPDBG((
  354. SNMP_LOG_ERROR,
  355. "SNMP: SNMPAPI: First call to MultiByteToWideChar failed [%d].\n",
  356. GetLastError()));
  357. return -1;
  358. }
  359. // adjust the length of the utf8 string to the correct value
  360. nWcsStringLen = retCode;
  361. // alloc here as many bytes as we need for the translation
  362. // !!! it includes the null terminator !!!
  363. *((UNALIGNED LPWSTR *) pWcsString) = SnmpUtilMemAlloc(nWcsStringLen * sizeof(WCHAR));
  364. // at this point we should have a valid output buffer
  365. if (*((UNALIGNED LPWSTR *) pWcsString) == NULL)
  366. {
  367. SNMPDBG((
  368. SNMP_LOG_ERROR,
  369. "SNMP: SNMPAPI: Memory allocation failed in SnmpUtilUTF8ToUnicode [%d].\n",
  370. GetLastError()));
  371. SetLastError(SNMP_MEM_ALLOC_ERROR);
  372. return -1;
  373. }
  374. }
  375. // if bAllocBuffer is false, we assume the buffer given
  376. // by the caller is sufficiently large to hold all the UTF8 string
  377. retCode = MultiByteToWideChar(
  378. CP_UTF8,
  379. 0,
  380. utfString,
  381. nUtfStringLen + 1,
  382. *((UNALIGNED LPWSTR *) pWcsString),
  383. nWcsStringLen);
  384. // nothing should go wrong here. However, if smth went wrong...
  385. if (retCode == 0)
  386. {
  387. SNMPDBG((
  388. SNMP_LOG_ERROR,
  389. "SNMP: SNMPAPI: Second call to MultiByteToWideChar failed [%d].\n",
  390. GetLastError()));
  391. // ..we made it, we kill it
  392. if (bAllocBuffer)
  393. {
  394. SnmpUtilMemFree(*((UNALIGNED LPWSTR *) pWcsString));
  395. *((UNALIGNED LPWSTR *) pWcsString) = NULL;
  396. }
  397. // bail with error
  398. return -1;
  399. }
  400. // at this point, the call succeeded.
  401. return 0;
  402. }
  403. //-------------------------------- END --------------------------------------