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.

423 lines
11 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. #ifndef CHICAGO
  22. #include <ntrtl.h>
  23. #else
  24. #include <stdio.h>
  25. #endif
  26. #include <string.h>
  27. #include <stdlib.h>
  28. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  29. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  30. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  31. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  32. //--------------------------- PRIVATE CONSTANTS -----------------------------
  33. //--------------------------- PRIVATE STRUCTS -------------------------------
  34. //--------------------------- PRIVATE VARIABLES -----------------------------
  35. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  36. //--------------------------- PRIVATE PROCEDURES ----------------------------
  37. //--------------------------- PUBLIC PROCEDURES -----------------------------
  38. // The return code matches what Uni->Str uses
  39. LONG
  40. SNMP_FUNC_TYPE
  41. SnmpUtilUnicodeToAnsi(
  42. LPSTR *ansi_string,
  43. LPWSTR uni_string,
  44. BOOLEAN alloc_it)
  45. {
  46. int result;
  47. LPSTR new_string;
  48. unsigned short length;
  49. unsigned short maxlength;
  50. // initialize
  51. if (alloc_it) {
  52. *((UNALIGNED LPSTR *) ansi_string) = NULL;
  53. }
  54. length = (unsigned short)wcslen(uni_string);
  55. maxlength = length + 1;
  56. if (alloc_it) {
  57. new_string = SnmpUtilMemAlloc(maxlength * sizeof(CHAR));
  58. } else {
  59. new_string = *((UNALIGNED LPSTR *) ansi_string);
  60. }
  61. if (new_string == NULL) {
  62. return(-1);
  63. }
  64. if (length) {
  65. result = WideCharToMultiByte(
  66. CP_ACP,
  67. 0,
  68. uni_string,
  69. maxlength,
  70. new_string,
  71. maxlength,
  72. NULL,
  73. NULL
  74. );
  75. } else {
  76. *new_string = '\0';
  77. result = 1; // converted terminating character
  78. }
  79. if (alloc_it) {
  80. if (result) {
  81. *((UNALIGNED LPSTR *) ansi_string) = new_string;
  82. } else {
  83. SNMPDBG((
  84. SNMP_LOG_ERROR,
  85. "SNMP: API: WideCharToMultiByte returns 0x%08lx.\n",
  86. GetLastError()
  87. ));
  88. SnmpUtilMemFree(new_string);
  89. }
  90. }
  91. return (result > 0) ? 0 : -1;
  92. }
  93. // The return code matches what Uni->Str uses
  94. LONG
  95. SNMP_FUNC_TYPE
  96. SnmpUtilUnicodeToUTF8(
  97. LPSTR *pUtfString,
  98. LPWSTR wcsString,
  99. BOOLEAN bAllocBuffer)
  100. {
  101. int retCode;
  102. int nWcsStringLen;
  103. int nUtfStringLen;
  104. // Bug# 268748, lmmib2.dll uses this API and causes exception here on IA64 platform.
  105. // it is possible that pUtfString points to a pointer which is not aligned because the
  106. // pointer is embedded in a buffer allocated in lmmib2.dll.
  107. // Other functions in this file are fixed with this potential problem too.
  108. // make sure the parameters are valid
  109. if (wcsString == NULL || // the unicode string should be valid
  110. pUtfString == NULL || // the output parameter should be a valid pointer
  111. (!bAllocBuffer && *((UNALIGNED LPSTR *) pUtfString) == NULL)) // if we are not requested to allocate the buffer,
  112. // then the supplied one should be valid
  113. {
  114. SNMPDBG((
  115. SNMP_LOG_ERROR,
  116. "SNMP: LMMIB2: Invalid input to SnmpUtilUnicodeToUTF8.\n"));
  117. return (-1);
  118. }
  119. nWcsStringLen = wcslen(wcsString);
  120. nUtfStringLen = 3 * (nWcsStringLen + 1); // initialize the lenght of the output buffer with the
  121. // greatest value possible
  122. // if we are requested to alloc the output buffer..
  123. if (bAllocBuffer)
  124. {
  125. // ...pick up first the buffer length needed for translation.
  126. retCode = WideCharToMultiByte(
  127. CP_UTF8,
  128. 0,
  129. wcsString,
  130. nWcsStringLen + 1, // include the null terminator in the string
  131. NULL,
  132. 0,
  133. NULL,
  134. NULL);
  135. // at least we expect here the null terminator
  136. // if retCode is zero, something else went wrong.
  137. if (retCode == 0)
  138. {
  139. SNMPDBG((
  140. SNMP_LOG_ERROR,
  141. "SNMP: LMMIB2: First call to WideCharToMultiByte failed [%d].\n",
  142. GetLastError()));
  143. return -1;
  144. }
  145. // adjust the length of the utf8 string to the correct value
  146. // !!! it includes the null terminator !!!
  147. nUtfStringLen = retCode;
  148. // alloc here as many bytes as we need for the translation
  149. *((UNALIGNED LPSTR *) pUtfString) = SnmpUtilMemAlloc(nUtfStringLen);
  150. // at this point we should have a valid output buffer
  151. if (*((UNALIGNED LPSTR *) pUtfString) == NULL)
  152. {
  153. SNMPDBG((
  154. SNMP_LOG_ERROR,
  155. "SNMP: LMMIB2: Memory allocation failed in SnmpUtilUnicodeToUTF8 [%d].\n",
  156. GetLastError()));
  157. return -1;
  158. }
  159. }
  160. // if bAllocBuffer is false, we assume the buffer given
  161. // by the caller is sufficiently large to hold all the UTF8 string
  162. retCode = WideCharToMultiByte(
  163. CP_UTF8,
  164. 0,
  165. wcsString,
  166. nWcsStringLen + 1,
  167. *((UNALIGNED LPSTR *) pUtfString),
  168. nUtfStringLen,
  169. NULL,
  170. NULL);
  171. // nothing should go wrong here. However, if smth went wrong...
  172. if (retCode == 0)
  173. {
  174. SNMPDBG((
  175. SNMP_LOG_ERROR,
  176. "SNMP: LMMIB2: Second call to WideCharToMultiByte failed [%d].\n",
  177. GetLastError()));
  178. // ..we made it, we kill it
  179. if (bAllocBuffer)
  180. {
  181. SnmpUtilMemFree(*((UNALIGNED LPSTR *) pUtfString));
  182. *((UNALIGNED LPSTR *) pUtfString) = NULL;
  183. }
  184. // bail with error
  185. return -1;
  186. }
  187. // at this point, the call succeeded.
  188. return 0;
  189. }
  190. // The return code matches what Uni->Str uses
  191. LONG
  192. SNMP_FUNC_TYPE
  193. SnmpUtilAnsiToUnicode(
  194. LPWSTR *uni_string,
  195. LPSTR ansi_string,
  196. BOOLEAN alloc_it)
  197. {
  198. int result;
  199. LPWSTR new_string;
  200. unsigned short length;
  201. unsigned short maxlength;
  202. // initialize
  203. if (alloc_it) {
  204. *((UNALIGNED LPWSTR *) uni_string) = NULL;
  205. }
  206. length = (unsigned short) strlen(ansi_string);
  207. maxlength = length + 1;
  208. if (alloc_it) {
  209. new_string = SnmpUtilMemAlloc(maxlength * sizeof(WCHAR));
  210. } else {
  211. new_string = *((UNALIGNED LPWSTR *) uni_string);
  212. }
  213. if (new_string == NULL) {
  214. return(-1);
  215. }
  216. if (length) {
  217. result = MultiByteToWideChar(
  218. CP_ACP,
  219. MB_PRECOMPOSED,
  220. ansi_string,
  221. length,
  222. new_string,
  223. maxlength
  224. );
  225. } else {
  226. *new_string = L'\0';
  227. result = 1; // converted terminating character
  228. }
  229. if (alloc_it) {
  230. if (result) {
  231. *((UNALIGNED LPWSTR *) uni_string) = new_string;
  232. } else {
  233. SNMPDBG((
  234. SNMP_LOG_ERROR,
  235. "SNMP: API: MultiByteToWideChar returns 0x%08lx.\n",
  236. GetLastError()
  237. ));
  238. SnmpUtilMemFree(new_string);
  239. }
  240. }
  241. return (result > 0) ? 0 : -1;
  242. }
  243. // The return code matches what Uni->Str uses
  244. LONG
  245. SNMP_FUNC_TYPE
  246. SnmpUtilUTF8ToUnicode(
  247. LPWSTR *pWcsString,
  248. LPSTR utfString,
  249. BOOLEAN bAllocBuffer)
  250. {
  251. int retCode;
  252. int nUtfStringLen;
  253. int nWcsStringLen;
  254. // check the consistency of the parameters first
  255. if (utfString == NULL || // the input parameter must be valid
  256. pWcsString == NULL || // the pointer to the output parameter must be valid
  257. (!bAllocBuffer && *((UNALIGNED LPWSTR *) pWcsString) == NULL)) // if we are not required to allocate the output parameter
  258. // then the output buffer must be valid
  259. {
  260. SNMPDBG((
  261. SNMP_LOG_ERROR,
  262. "SNMP: LMMIB2: Invalid input to SnmpUtilUTF8ToUnicode.\n"));
  263. return -1;
  264. }
  265. nUtfStringLen = strlen(utfString); // the length of the input utf8 string
  266. nWcsStringLen = nUtfStringLen + 1; // greatest value possible
  267. if (bAllocBuffer)
  268. {
  269. retCode = MultiByteToWideChar(
  270. CP_UTF8,
  271. 0,
  272. utfString,
  273. nUtfStringLen + 1,
  274. NULL,
  275. 0);
  276. // at least we expect here the null terminator
  277. // if retCode is zero, something else went wrong.
  278. if (retCode == 0)
  279. {
  280. SNMPDBG((
  281. SNMP_LOG_ERROR,
  282. "SNMP: LMMIB2: First call to MultiByteToWideChar failed [%d].\n",
  283. GetLastError()));
  284. return -1;
  285. }
  286. // adjust the length of the utf8 string to the correct value
  287. nWcsStringLen = retCode;
  288. // alloc here as many bytes as we need for the translation
  289. // !!! it includes the null terminator !!!
  290. *((UNALIGNED LPWSTR *) pWcsString) = SnmpUtilMemAlloc(nWcsStringLen * sizeof(WCHAR));
  291. // at this point we should have a valid output buffer
  292. if (*((UNALIGNED LPWSTR *) pWcsString) == NULL)
  293. {
  294. SNMPDBG((
  295. SNMP_LOG_ERROR,
  296. "SNMP: LMMIB2: Memory allocation failed in SnmpUtilUTF8ToUnicode [%d].\n",
  297. GetLastError()));
  298. return -1;
  299. }
  300. }
  301. // if bAllocBuffer is false, we assume the buffer given
  302. // by the caller is sufficiently large to hold all the UTF8 string
  303. retCode = MultiByteToWideChar(
  304. CP_UTF8,
  305. 0,
  306. utfString,
  307. nUtfStringLen + 1,
  308. *((UNALIGNED LPWSTR *) pWcsString),
  309. nWcsStringLen);
  310. // nothing should go wrong here. However, if smth went wrong...
  311. if (retCode == 0)
  312. {
  313. SNMPDBG((
  314. SNMP_LOG_ERROR,
  315. "SNMP: LMMIB2: Second call to MultiByteToWideChar failed [%d].\n",
  316. GetLastError()));
  317. // ..we made it, we kill it
  318. if (bAllocBuffer)
  319. {
  320. SnmpUtilMemFree(*((UNALIGNED LPWSTR *) pWcsString));
  321. *((UNALIGNED LPWSTR *) pWcsString) = NULL;
  322. }
  323. // bail with error
  324. return -1;
  325. }
  326. // at this point, the call succeeded.
  327. return 0;
  328. }
  329. //-------------------------------- END --------------------------------------