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.

412 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. Help.c
  5. Abstract:
  6. Simple minded utility that prints one-line help or spawns other
  7. utilities for their help.
  8. Author:
  9. Mark Zbikowski 5/18/2001
  10. Environment:
  11. User Mode
  12. --*/
  13. #include <windows.h>
  14. #include <winnlsp.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <locale.h>
  19. #include "msg.h"
  20. #ifndef SHIFT
  21. #define SHIFT(c,v) {(c)--; (v)++;}
  22. #endif //SHIFT
  23. BOOL
  24. PrintString(
  25. PWCHAR String
  26. )
  27. /*++
  28. Routine Description:
  29. Output a unicode string to the standard output handling
  30. redirection
  31. Arguments:
  32. String
  33. NUL-terminated UNICODE string for display
  34. Return Value:
  35. TRUE if string was successfully output to STD_OUTPUT_HANDLE
  36. FALSE otherwise
  37. --*/
  38. {
  39. DWORD BytesWritten;
  40. DWORD Mode;
  41. HANDLE OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  42. //
  43. // If the output handle is for the console
  44. //
  45. if ((GetFileType( OutputHandle ) & FILE_TYPE_CHAR) &&
  46. GetConsoleMode( OutputHandle, &Mode) ) {
  47. return WriteConsoleW( OutputHandle, String, wcslen( String ), &BytesWritten, 0);
  48. } else {
  49. BOOL RetValue;
  50. int Count = WideCharToMultiByte( GetConsoleOutputCP(),
  51. 0,
  52. String,
  53. -1,
  54. 0,
  55. 0,
  56. 0,
  57. 0 );
  58. PCHAR SingleByteString = (PCHAR) malloc( Count );
  59. if (SingleByteString == NULL) {
  60. RetValue = FALSE;
  61. } else {
  62. WideCharToMultiByte( GetConsoleOutputCP( ),
  63. 0,
  64. String,
  65. -1,
  66. SingleByteString,
  67. Count,
  68. 0,
  69. 0 );
  70. RetValue = WriteFile( OutputHandle, SingleByteString, Count - 1, &BytesWritten, 0 );
  71. free( SingleByteString );
  72. }
  73. return RetValue;
  74. }
  75. }
  76. PWCHAR
  77. GetMsg(
  78. ULONG MsgNum,
  79. ...
  80. )
  81. /*++
  82. Routine Description:
  83. Retrieve, format, and return a message string with all args substituted
  84. Arguments:
  85. MsgNum - the message number to retrieve
  86. Optional arguments can be supplied
  87. Return Value:
  88. NULL if the message retrieval/formatting failed
  89. Otherwise pointer to the formatted string.
  90. --*/
  91. {
  92. PTCHAR Buffer = NULL;
  93. ULONG msglen;
  94. va_list arglist;
  95. va_start( arglist, MsgNum );
  96. msglen = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE
  97. | FORMAT_MESSAGE_FROM_SYSTEM
  98. | FORMAT_MESSAGE_ALLOCATE_BUFFER ,
  99. NULL,
  100. MsgNum,
  101. 0,
  102. (LPTSTR) &Buffer,
  103. 0,
  104. &arglist
  105. );
  106. va_end(arglist);
  107. return msglen == 0 ? NULL : Buffer;
  108. }
  109. void
  110. DisplayMessageError(
  111. ULONG MsgNum
  112. )
  113. /*++
  114. Routine Description:
  115. Displays a message if we cannot retrieve a message
  116. Arguments:
  117. MsgNum
  118. Message number to display
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. WCHAR Buffer[40]; // This is from #define LONG_SIZE_LENGTH 40 in base\crts\crtw32\convert\xtow.c
  124. PWCHAR MessageString;
  125. _ultow( MsgNum, Buffer, 16 );
  126. MessageString = GetMsg( ERROR_MR_MID_NOT_FOUND, Buffer, L"Application" );
  127. if (MessageString == NULL) {
  128. PrintString( L"Unable to get Message-Not-Found message\n" );
  129. } else {
  130. PrintString( MessageString );
  131. LocalFree( MessageString );
  132. }
  133. }
  134. BOOL
  135. DisplayFullHelp(
  136. void
  137. )
  138. /*++
  139. Routine Description:
  140. Display the full help set. This assumes all messages in the message
  141. file are in the correct order
  142. Arguments:
  143. None.
  144. Return Value:
  145. TRUE if all messages were correctly output
  146. FALSE otherwise
  147. --*/
  148. {
  149. ULONG Message;
  150. BOOL RetValue = TRUE;
  151. for (Message = HELP_FIRST_HELP_MESSAGE; RetValue && Message <= HELP_LAST_HELP_MESSAGE; Message++) {
  152. PWCHAR MessageString = GetMsg( Message );
  153. if (MessageString == NULL) {
  154. DisplayMessageError( Message );
  155. RetValue = FALSE;
  156. } else {
  157. RetValue = PrintString( MessageString );
  158. LocalFree( MessageString );
  159. }
  160. }
  161. return RetValue;
  162. }
  163. BOOL
  164. DisplaySingleHelp(
  165. PWCHAR Command
  166. )
  167. /*++
  168. Routine Description:
  169. Display the help appropriate to the specific command
  170. Arguments:
  171. Command
  172. NUL-terminated UNICODE string for command
  173. Return Value:
  174. TRUE if help was correctly output
  175. FALSE otherwise
  176. --*/
  177. {
  178. ULONG Message;
  179. ULONG Count = wcslen( Command );
  180. PWCHAR MessageString;
  181. //
  182. // Walk through the messages one by one and determine which
  183. // one has the specified command as the prefix.
  184. //
  185. for (Message = HELP_FIRST_COMMAND_HELP_MESSAGE;
  186. Message <= HELP_LAST_HELP_MESSAGE;
  187. Message++) {
  188. MessageString = GetMsg( Message );
  189. if (MessageString == NULL) {
  190. DisplayMessageError( Message );
  191. return FALSE;
  192. } else {
  193. if (!_wcsnicmp( Command, MessageString, Count ) &&
  194. MessageString[Count] == L' ') {
  195. //
  196. // We've found a match. Let the command
  197. // display it's own help
  198. //
  199. WCHAR CommandString[MAX_PATH];
  200. wcscpy( CommandString, Command );
  201. wcscat( CommandString, L" /?" );
  202. _wsystem( CommandString );
  203. LocalFree( MessageString );
  204. return TRUE;
  205. }
  206. LocalFree( MessageString );
  207. }
  208. }
  209. MessageString = GetMsg( HELP_NOT_FOUND_MESSAGE, Command );
  210. if (MessageString == NULL) {
  211. DisplayMessageError( Message );
  212. return FALSE;
  213. }
  214. PrintString( MessageString );
  215. LocalFree( MessageString );
  216. return FALSE;
  217. }
  218. //
  219. // HELP with no arguments will display a series of one-line help summaries
  220. // for a variety of tools.
  221. //
  222. // HELP with a single argument will walk through the list of tools it knows
  223. // about and attempt to match the tool against the argument. If one is found,
  224. // the tool is executed with the /? switch and then the tool displays more
  225. // detailed help.
  226. //
  227. INT
  228. __cdecl wmain(
  229. INT argc,
  230. PWSTR argv[]
  231. )
  232. /*++
  233. Routine Description:
  234. Source entry point for the
  235. Arguments:
  236. argc - The argument count.
  237. argv - string arguments, the first being the name of the executable and the
  238. remainder being parameters, only a single one is allowed.
  239. Return Value:
  240. INT - Return Status:
  241. 0 if help was successfully displayed
  242. 1 otherwise
  243. --*/
  244. {
  245. PWSTR ProgramName = argv[0];
  246. PWSTR HelpString;
  247. BOOL RetValue;
  248. //
  249. // Set up all the various international stuff
  250. //
  251. setlocale( LC_ALL, ".OCP" ) ;
  252. SetThreadUILanguage( 0 );
  253. //
  254. // Get past the name of the program
  255. //
  256. SHIFT( argc, argv );
  257. //
  258. // No arguments means a quick blurt of all the messages
  259. //
  260. if (argc == 0) {
  261. return DisplayFullHelp( );
  262. }
  263. //
  264. // A single argument is looked up in the message set and
  265. // that command is executed
  266. //
  267. if (argc == 1 && wcscmp( argv[0], L"/?" )) {
  268. return DisplaySingleHelp( argv[0] );
  269. }
  270. //
  271. // More than one argument was supplied. This is an error
  272. //
  273. HelpString = GetMsg( HELP_USAGE_MESSAGE, ProgramName );
  274. if (HelpString == NULL) {
  275. PrintString( L"Unable to display usage message\n" );
  276. return 1;
  277. }
  278. RetValue = PrintString( HelpString );
  279. LocalFree( HelpString );
  280. return RetValue;
  281. }