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.

404 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. c_snadb.c
  5. Abstract:
  6. This file contains the main functions for this module.
  7. External Routines in this file:
  8. DllEntry
  9. NlsDllCodePageTranslation
  10. Revision History:
  11. 10-30-96 JulieB Created.
  12. --*/
  13. ////////////////////////////////////////////////////////////////////////////
  14. //
  15. // IBM EBCDIC DBCS from/to Unicode conversions for SNA
  16. //
  17. // CP# = Single Byte + Double Byte
  18. // ----- = ----------- + -----------
  19. // 50930 = 290 (Katakana Extended) + 300 (Japanese) calls 20930
  20. // 50931 = 037 (US/Canada) + 300 (Japanese) calls 20931
  21. // 50933 = 833 (Korean Extended) + 834 (Korean) calls 20933
  22. // 50935 = 836 (Simp-Chinese Ext.) + 837 (Simplified Chinese) calls 20935
  23. // 50937 = 037 (US/Canada) + 835 (Traditional Chinese) calls 20937
  24. // 50939 = 1027 (Latin Extended) + 300 (Japanese) calls 20939
  25. //
  26. ////////////////////////////////////////////////////////////////////////////
  27. //
  28. // Include Files.
  29. //
  30. #include <share.h>
  31. //
  32. // Constant Declarations.
  33. //
  34. #define SHIFTOUT 0x0e // from SBCS to DBCS
  35. #define SHIFTIN 0x0f // from DBCS to SBCS
  36. #define BOGUSLEADBYTE 0x3f // prefix SBC to make it DBC
  37. #define INTERNAL_CODEPAGE(cp) ((cp) - 30000)
  38. //-------------------------------------------------------------------------//
  39. // DLL ENTRY POINT //
  40. //-------------------------------------------------------------------------//
  41. ////////////////////////////////////////////////////////////////////////////
  42. //
  43. // DllEntry
  44. //
  45. // DLL Entry initialization procedure.
  46. //
  47. // 10-30-96 JulieB Created.
  48. ////////////////////////////////////////////////////////////////////////////
  49. BOOL DllEntry(
  50. HANDLE hModule,
  51. DWORD dwReason,
  52. LPVOID lpRes)
  53. {
  54. switch (dwReason)
  55. {
  56. case ( DLL_THREAD_ATTACH ) :
  57. {
  58. return (TRUE);
  59. }
  60. case ( DLL_THREAD_DETACH ) :
  61. {
  62. return (TRUE);
  63. }
  64. case ( DLL_PROCESS_ATTACH ) :
  65. {
  66. return (TRUE);
  67. }
  68. case ( DLL_PROCESS_DETACH ) :
  69. {
  70. return (TRUE);
  71. }
  72. }
  73. return (FALSE);
  74. hModule;
  75. lpRes;
  76. }
  77. //-------------------------------------------------------------------------//
  78. // EXTERNAL ROUTINES //
  79. //-------------------------------------------------------------------------//
  80. ////////////////////////////////////////////////////////////////////////////
  81. //
  82. // NlsDllCodePageTranslation
  83. //
  84. // This routine is the main exported procedure for the functionality in
  85. // this DLL. All calls to this DLL must go through this function.
  86. //
  87. // 10-30-96 JulieB Created.
  88. ////////////////////////////////////////////////////////////////////////////
  89. DWORD NlsDllCodePageTranslation(
  90. DWORD CodePage,
  91. DWORD dwFlags,
  92. LPSTR lpMultiByteStr,
  93. int cchMultiByte,
  94. LPWSTR lpWideCharStr,
  95. int cchWideChar,
  96. LPCPINFO lpCPInfo)
  97. {
  98. LPSTR lpMBNoEscStr;
  99. int cchMBEscStr = 0;
  100. int ctr, cchMBTemp, cchMBCount, cchWCCount;
  101. BOOL IsDBCS = FALSE;
  102. //
  103. // Error out if internally needed c_*.nls file is not installed.
  104. //
  105. if (!IsValidCodePage(INTERNAL_CODEPAGE(CodePage)))
  106. {
  107. SetLastError(ERROR_INVALID_PARAMETER);
  108. return (0);
  109. }
  110. switch (dwFlags)
  111. {
  112. case ( NLS_CP_CPINFO ) :
  113. {
  114. memset(lpCPInfo, 0, sizeof(CPINFO));
  115. lpCPInfo->MaxCharSize = 3;
  116. lpCPInfo->DefaultChar[0] = 0x3f;
  117. //
  118. // Lead byte does not apply here, leave them all NULL.
  119. //
  120. return (TRUE);
  121. }
  122. case ( NLS_CP_MBTOWC ) :
  123. {
  124. if (cchMultiByte == -1)
  125. {
  126. cchMultiByte = strlen(lpMultiByteStr) + 1;
  127. }
  128. //
  129. // Each single byte char becomes 2 bytes, so we need a
  130. // temporary buffer twice as big.
  131. //
  132. if ((lpMBNoEscStr = (LPSTR)NLS_ALLOC_MEM(cchMultiByte << 1)) == NULL)
  133. {
  134. SetLastError(ERROR_OUTOFMEMORY);
  135. return (0);
  136. }
  137. //
  138. // Remove all Shift-In & Shift-Out.
  139. //
  140. for (ctr = 0, cchMBTemp = 0; ctr < cchMultiByte; ctr++)
  141. {
  142. if (lpMultiByteStr[ctr] == SHIFTOUT)
  143. {
  144. IsDBCS = TRUE;
  145. }
  146. else if (lpMultiByteStr[ctr] == SHIFTIN)
  147. {
  148. IsDBCS = FALSE;
  149. }
  150. else
  151. {
  152. if (IsDBCS)
  153. {
  154. //
  155. // Double byte char.
  156. //
  157. if (ctr < (cchMultiByte - 1))
  158. {
  159. lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr++];
  160. lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr];
  161. }
  162. else
  163. {
  164. //
  165. // Last char is a lead-byte with no trail-byte,
  166. // so let MultiByteToWideChar take care of it.
  167. //
  168. break;
  169. }
  170. }
  171. else
  172. {
  173. //
  174. // Single byte char.
  175. // Prefix it with a bogus lead byte to make it a
  176. // double byte char. The internal table has been
  177. // arranged accordingly.
  178. //
  179. lpMBNoEscStr[cchMBTemp++] = BOGUSLEADBYTE;
  180. lpMBNoEscStr[cchMBTemp++] = lpMultiByteStr[ctr];
  181. }
  182. }
  183. }
  184. cchWCCount = MultiByteToWideChar( INTERNAL_CODEPAGE(CodePage),
  185. 0,
  186. lpMBNoEscStr,
  187. cchMBTemp,
  188. lpWideCharStr,
  189. cchWideChar );
  190. if (cchWCCount == 0)
  191. {
  192. SetLastError(ERROR_NO_UNICODE_TRANSLATION);
  193. }
  194. NLS_FREE_MEM(lpMBNoEscStr);
  195. return (cchWCCount);
  196. }
  197. case ( NLS_CP_WCTOMB ) :
  198. {
  199. if (cchWideChar == -1)
  200. {
  201. cchWideChar = wcslen(lpWideCharStr) + 1;
  202. }
  203. cchMBTemp = cchWideChar * sizeof(WCHAR);
  204. lpMBNoEscStr = (LPSTR)NLS_ALLOC_MEM(cchMBTemp);
  205. if (lpMBNoEscStr == NULL)
  206. {
  207. SetLastError(ERROR_OUTOFMEMORY);
  208. return (0);
  209. }
  210. //
  211. // Convert to an MB string without Shift-In/Out first.
  212. //
  213. cchMBCount = WideCharToMultiByte( INTERNAL_CODEPAGE(CodePage),
  214. WC_NO_BEST_FIT_CHARS,
  215. lpWideCharStr,
  216. cchWideChar,
  217. lpMBNoEscStr,
  218. cchMBTemp,
  219. NULL,
  220. NULL );
  221. /*
  222. what if (cchMBCount == 0) ?
  223. might need to add error checking later
  224. */
  225. //
  226. // Insert Shift-In and Shift-Out as needed and
  227. // remove BOGUSLEADBYTE.
  228. //
  229. ctr = 0;
  230. while (ctr < cchMBCount)
  231. {
  232. //
  233. // See if it's a single byte char.
  234. //
  235. if (lpMBNoEscStr[ctr] == BOGUSLEADBYTE)
  236. {
  237. //
  238. // It's a single byte char.
  239. //
  240. ctr++;
  241. if (IsDBCS)
  242. {
  243. if (cchMultiByte)
  244. {
  245. if (cchMBEscStr < cchMultiByte)
  246. {
  247. lpMultiByteStr[cchMBEscStr] = SHIFTIN;
  248. }
  249. else
  250. {
  251. //
  252. // Output buffer is too small.
  253. //
  254. break;
  255. }
  256. }
  257. cchMBEscStr++;
  258. IsDBCS = FALSE;
  259. }
  260. if (cchMultiByte)
  261. {
  262. if (cchMBEscStr < cchMultiByte)
  263. {
  264. lpMultiByteStr[cchMBEscStr] = lpMBNoEscStr[ctr];
  265. }
  266. else
  267. {
  268. //
  269. // Output buffer is too small.
  270. //
  271. break;
  272. }
  273. }
  274. cchMBEscStr++;
  275. ctr++;
  276. }
  277. else
  278. {
  279. //
  280. // It's a double byte char.
  281. //
  282. if (!IsDBCS)
  283. {
  284. if (cchMultiByte)
  285. {
  286. if (cchMBEscStr < cchMultiByte)
  287. {
  288. lpMultiByteStr[cchMBEscStr] = SHIFTOUT;
  289. }
  290. else
  291. {
  292. //
  293. // Output buffer is too small.
  294. //
  295. break;
  296. }
  297. }
  298. cchMBEscStr++;
  299. IsDBCS = TRUE;
  300. }
  301. if (ctr >= (cchMBCount - 1))
  302. {
  303. //
  304. // Missing trail byte.
  305. //
  306. break;
  307. }
  308. if (cchMultiByte)
  309. {
  310. if (cchMBEscStr < (cchMultiByte - 1))
  311. {
  312. lpMultiByteStr[cchMBEscStr] = lpMBNoEscStr[ctr];
  313. lpMultiByteStr[cchMBEscStr + 1] = lpMBNoEscStr[ctr + 1];
  314. }
  315. else
  316. {
  317. //
  318. // Output buffer is too small.
  319. //
  320. break;
  321. }
  322. }
  323. cchMBEscStr += 2;
  324. ctr += 2;
  325. }
  326. }
  327. NLS_FREE_MEM(lpMBNoEscStr);
  328. //
  329. // See if the output buffer is too small.
  330. //
  331. if ((cchMultiByte > 0) && (cchMBEscStr > cchMultiByte))
  332. {
  333. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  334. return (0);
  335. }
  336. return (cchMBEscStr);
  337. }
  338. }
  339. //
  340. // This shouldn't happen since this is called by the NLS APIs.
  341. //
  342. SetLastError(ERROR_INVALID_PARAMETER);
  343. return (0);
  344. }