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.

446 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. Chcp
  5. Abstract:
  6. Chcpo is a DOS5-Compatible codepage utility
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 01-May-1991
  9. Revision History:
  10. --*/
  11. #include "ulib.hxx"
  12. #include "arg.hxx"
  13. #include "stream.hxx"
  14. #include "smsg.hxx"
  15. #include "wstring.hxx"
  16. #include "rtmsg.h"
  17. #include "chcp.hxx"
  18. #include <winnlsp.h>
  19. VOID __cdecl
  20. main (
  21. )
  22. /*++
  23. Routine Description:
  24. Main function of the Chcp utility
  25. Arguments:
  26. None.
  27. Return Value:
  28. None.
  29. Notes:
  30. --*/
  31. {
  32. SetThreadUILanguage(0);
  33. //
  34. // Initialize stuff
  35. //
  36. DEFINE_CLASS_DESCRIPTOR( CHCP );
  37. {
  38. CHCP Chcp;
  39. if ( Chcp.Initialize() ) {
  40. Chcp.Chcp();
  41. }
  42. }
  43. }
  44. DEFINE_CONSTRUCTOR( CHCP, PROGRAM );
  45. CHCP::~CHCP (
  46. )
  47. /*++
  48. Routine Description:
  49. Destructs a CHCP object
  50. Arguments:
  51. None.
  52. Return Value:
  53. None.
  54. Notes:
  55. --*/
  56. {
  57. }
  58. BOOLEAN
  59. CHCP::Initialize (
  60. )
  61. /*++
  62. Routine Description:
  63. Initializes a CHCP object
  64. Arguments:
  65. None.
  66. Return Value:
  67. TRUE if initialized.
  68. Notes:
  69. --*/
  70. {
  71. //
  72. // Initialize program object
  73. //
  74. if ( PROGRAM::Initialize( MSG_CHCP_USAGE ) &&
  75. _Screen.Initialize( )
  76. ) {
  77. _SetCodePage = FALSE;
  78. _CodePage = 0;
  79. return TRUE;
  80. }
  81. return FALSE;
  82. }
  83. BOOLEAN
  84. CHCP::Chcp (
  85. )
  86. /*++
  87. Routine Description:
  88. Does the Chcp thing.
  89. Arguments:
  90. None.
  91. Return Value:
  92. TRUE.
  93. Notes:
  94. --*/
  95. {
  96. ValidateVersion();
  97. if ( ParseArguments() ) {
  98. if ( _SetCodePage ) {
  99. //
  100. // Set the code page
  101. //
  102. if ( !SetCodePage() ) {
  103. ExitProgram( EXIT_ERROR );
  104. }
  105. } else {
  106. //
  107. // Display current code page
  108. //
  109. if ( !DisplayCodePage() ) {
  110. ExitProgram( EXIT_ERROR );
  111. }
  112. }
  113. ExitProgram( EXIT_NORMAL );
  114. } else {
  115. ExitProgram( EXIT_ERROR );
  116. }
  117. return TRUE;
  118. }
  119. BOOLEAN
  120. CHCP::DisplayCodePage (
  121. )
  122. /*++
  123. Routine Description:
  124. Displays the active code page
  125. Arguments:
  126. None.
  127. Return Value:
  128. TRUE if success, FALSE if syntax error.
  129. Notes:
  130. --*/
  131. {
  132. DisplayMessage(
  133. MSG_CHCP_ACTIVE_CODEPAGE,
  134. NORMAL_MESSAGE, "%d",
  135. _Screen.QueryCodePage( )
  136. );
  137. return TRUE;
  138. }
  139. BOOLEAN
  140. CHCP::ParseArguments (
  141. )
  142. /*++
  143. Routine Description:
  144. Parses arguments
  145. Arguments:
  146. None.
  147. Return Value:
  148. TRUE if success, FALSE if syntax error.
  149. Notes:
  150. --*/
  151. {
  152. ARGUMENT_LEXEMIZER ArgLex;
  153. ARRAY LexArray;
  154. ARRAY ArgArray;
  155. STRING_ARGUMENT ProgramNameArgument;
  156. LONG_ARGUMENT CodePageArgument;
  157. FLAG_ARGUMENT UsageArgument;
  158. if ( !ArgArray.Initialize() ||
  159. !LexArray.Initialize() ||
  160. !ArgLex.Initialize( &LexArray )
  161. ) {
  162. DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE );
  163. ExitProgram( EXIT_ERROR );
  164. }
  165. if ( !ProgramNameArgument.Initialize( "*" ) ||
  166. !UsageArgument.Initialize( "/?" ) ||
  167. !CodePageArgument.Initialize( "*" )
  168. ) {
  169. DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE );
  170. ExitProgram( EXIT_ERROR );
  171. }
  172. if ( !ArgArray.Put( &ProgramNameArgument ) ||
  173. !ArgArray.Put( &UsageArgument ) ||
  174. !ArgArray.Put( &CodePageArgument )
  175. ) {
  176. DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE );
  177. ExitProgram( EXIT_ERROR );
  178. }
  179. //
  180. // Set up the defaults
  181. //
  182. ArgLex.PutSwitches( "/" );
  183. ArgLex.SetCaseSensitive( FALSE );
  184. if ( !ArgLex.PrepareToParse() ) {
  185. DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE );
  186. ExitProgram( EXIT_ERROR );
  187. }
  188. if ( !ArgLex.DoParsing( &ArgArray ) ) {
  189. DisplayMessage( MSG_CHCP_INVALID_PARAMETER, ERROR_MESSAGE, "%W", ArgLex.QueryInvalidArgument() );
  190. ExitProgram( EXIT_ERROR );
  191. }
  192. //
  193. // Display Help if requested
  194. //
  195. if ( UsageArgument.IsValueSet() ) {
  196. DisplayMessage( MSG_CHCP_USAGE, NORMAL_MESSAGE );
  197. ExitProgram( EXIT_NORMAL );
  198. }
  199. if ( CodePageArgument.IsValueSet() ) {
  200. _SetCodePage = TRUE;
  201. _CodePage = (DWORD)CodePageArgument.QueryLong();
  202. } else {
  203. _SetCodePage = FALSE;
  204. }
  205. return TRUE;
  206. }
  207. inline bool IsFarEastCodePage(UINT cp)
  208. {
  209. return cp == 932 || cp == 949 || cp == 936 || cp == 950;
  210. }
  211. inline bool IsFarEastLocale(LANGID langid)
  212. {
  213. // Accepts primay langid only
  214. return langid == LANG_JAPANESE || langid == LANG_KOREAN || langid == LANG_CHINESE;
  215. }
  216. inline bool IsFarEastSystemLocale()
  217. {
  218. return IsFarEastLocale(PRIMARYLANGID(GetSystemDefaultLangID()));
  219. }
  220. BOOLEAN
  221. CHCP::SetCodePage (
  222. )
  223. /*++
  224. Routine Description:
  225. Sets the active code page
  226. Arguments:
  227. None.
  228. Return Value:
  229. TRUE if success, FALSE if syntax error.
  230. Notes:
  231. --*/
  232. {
  233. UINT OldCP = _Screen.QueryCodePage( );
  234. if (IsFarEastSystemLocale() &&
  235. (IsFarEastCodePage(_CodePage) || IsFarEastCodePage(OldCP)) &&
  236. _CodePage != OldCP) {
  237. /*
  238. * This CLS function is needed only if it's FE.
  239. */
  240. _Screen.MoveCursorTo(0, 0);
  241. _Screen.EraseScreenAndResetAttribute();
  242. }
  243. if ( _Screen.SetOutputCodePage( _CodePage ) ) {
  244. if (_Screen.SetCodePage( _CodePage ) ) {
  245. /*
  246. // Comment from NT4J:
  247. // Since FormatMessage checks the current TEB's locale, and the Locale for
  248. // CHCP is initialized when the message class is initialized, the TEB has to
  249. // be updated after the code page is changed successfully. All other code
  250. // pages other than JP and US are ignored.
  251. if (IsFarEastSystemLocale()) {
  252. LANGID LangId;
  253. switch (_CodePage) {
  254. case 932:
  255. LangId = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT);
  256. break;
  257. case 949:
  258. LangId = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
  259. break;
  260. case 936:
  261. LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
  262. break;
  263. case 950:
  264. LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
  265. break;
  266. default:
  267. LangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  268. break;
  269. }
  270. SetThreadLocale(MAKELCID(LangId, SORT_DEFAULT));
  271. }
  272. */
  273. SetThreadUILanguage(0);
  274. return DisplayCodePage( );
  275. } else {
  276. // SetOutputCodePage failed.
  277. // Restore the privous input code page
  278. _Screen.SetOutputCodePage( OldCP );
  279. }
  280. }
  281. // Was unable to set the given code page
  282. DisplayMessage( MSG_CHCP_INVALID_CODEPAGE, ERROR_MESSAGE );
  283. return FALSE;
  284. }