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.

408 lines
7.8 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. WideCharToMultiByte( GetConsoleOutputCP( ),
  60. 0,
  61. String,
  62. -1,
  63. SingleByteString,
  64. Count,
  65. 0,
  66. 0 );
  67. RetValue = WriteFile( OutputHandle, SingleByteString, Count - 1, &BytesWritten, 0 );
  68. free( SingleByteString );
  69. return RetValue;
  70. }
  71. }
  72. PWCHAR
  73. GetMsg(
  74. ULONG MsgNum,
  75. ...
  76. )
  77. /*++
  78. Routine Description:
  79. Retrieve, format, and return a message string with all args substituted
  80. Arguments:
  81. MsgNum - the message number to retrieve
  82. Optional arguments can be supplied
  83. Return Value:
  84. NULL if the message retrieval/formatting failed
  85. Otherwise pointer to the formatted string.
  86. --*/
  87. {
  88. PTCHAR Buffer = NULL;
  89. ULONG msglen;
  90. va_list arglist;
  91. va_start( arglist, MsgNum );
  92. msglen = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE
  93. | FORMAT_MESSAGE_FROM_SYSTEM
  94. | FORMAT_MESSAGE_ALLOCATE_BUFFER ,
  95. NULL,
  96. MsgNum,
  97. 0,
  98. (LPTSTR) &Buffer,
  99. 0,
  100. &arglist
  101. );
  102. va_end(arglist);
  103. return msglen == 0 ? NULL : Buffer;
  104. }
  105. void
  106. DisplayMessageError(
  107. ULONG MsgNum
  108. )
  109. /*++
  110. Routine Description:
  111. Displays a message if we cannot retrieve a message
  112. Arguments:
  113. MsgNum
  114. Message number to display
  115. Return Value:
  116. None.
  117. --*/
  118. {
  119. WCHAR Buffer[32];
  120. PWCHAR MessageString;
  121. _ultow( MsgNum, Buffer, 16 );
  122. MessageString = GetMsg( ERROR_MR_MID_NOT_FOUND, Buffer, L"Application" );
  123. if (MessageString == NULL) {
  124. PrintString( L"Unable to get Message-Not-Found message\n" );
  125. } else {
  126. PrintString( MessageString );
  127. LocalFree( MessageString );
  128. }
  129. }
  130. BOOL
  131. DisplayFullHelp(
  132. void
  133. )
  134. /*++
  135. Routine Description:
  136. Display the full help set. This assumes all messages in the message
  137. file are in the correct order
  138. Arguments:
  139. None.
  140. Return Value:
  141. TRUE if all messages were correctly output
  142. FALSE otherwise
  143. --*/
  144. {
  145. ULONG Message;
  146. BOOL RetValue = TRUE;
  147. for (Message = HELP_FIRST_HELP_MESSAGE; RetValue && Message <= HELP_LAST_HELP_MESSAGE; Message++) {
  148. PWCHAR MessageString = GetMsg( Message );
  149. if (MessageString == NULL) {
  150. DisplayMessageError( Message );
  151. RetValue = FALSE;
  152. } else {
  153. RetValue = PrintString( MessageString );
  154. LocalFree( MessageString );
  155. }
  156. }
  157. return RetValue;
  158. }
  159. BOOL
  160. DisplaySingleHelp(
  161. PWCHAR Command
  162. )
  163. /*++
  164. Routine Description:
  165. Display the help appropriate to the specific command
  166. Arguments:
  167. Command
  168. NUL-terminated UNICODE string for command
  169. Return Value:
  170. TRUE if help was correctly output
  171. FALSE otherwise
  172. --*/
  173. {
  174. ULONG Message;
  175. ULONG Count = wcslen( Command );
  176. PWCHAR MessageString;
  177. //
  178. // Walk through the messages one by one and determine which
  179. // one has the specified command as the prefix.
  180. //
  181. for (Message = HELP_FIRST_COMMAND_HELP_MESSAGE;
  182. Message <= HELP_LAST_HELP_MESSAGE;
  183. Message++) {
  184. MessageString = GetMsg( Message );
  185. if (MessageString == NULL) {
  186. DisplayMessageError( Message );
  187. return FALSE;
  188. } else {
  189. if (!_wcsnicmp( Command, MessageString, Count ) &&
  190. MessageString[Count] == L' ') {
  191. //
  192. // We've found a match. Let the command
  193. // display it's own help
  194. //
  195. WCHAR CommandString[MAX_PATH];
  196. wcscpy( CommandString, Command );
  197. wcscat( CommandString, L" /?" );
  198. _wsystem( CommandString );
  199. LocalFree( MessageString );
  200. return TRUE;
  201. }
  202. LocalFree( MessageString );
  203. }
  204. }
  205. MessageString = GetMsg( HELP_NOT_FOUND_MESSAGE, Command );
  206. if (MessageString == NULL) {
  207. DisplayMessageError( Message );
  208. return FALSE;
  209. }
  210. PrintString( MessageString );
  211. LocalFree( MessageString );
  212. return FALSE;
  213. }
  214. //
  215. // HELP with no arguments will display a series of one-line help summaries
  216. // for a variety of tools.
  217. //
  218. // HELP with a single argument will walk through the list of tools it knows
  219. // about and attempt to match the tool against the argument. If one is found,
  220. // the tool is executed with the /? switch and then the tool displays more
  221. // detailed help.
  222. //
  223. INT
  224. __cdecl wmain(
  225. INT argc,
  226. PWSTR argv[]
  227. )
  228. /*++
  229. Routine Description:
  230. Source entry point for the
  231. Arguments:
  232. argc - The argument count.
  233. argv - string arguments, the first being the name of the executable and the
  234. remainder being parameters, only a single one is allowed.
  235. Return Value:
  236. INT - Return Status:
  237. 0 if help was successfully displayed
  238. 1 otherwise
  239. --*/
  240. {
  241. PWSTR ProgramName = argv[0];
  242. PWSTR HelpString;
  243. BOOL RetValue;
  244. //
  245. // Set up all the various international stuff
  246. //
  247. setlocale( LC_ALL, ".OCP" ) ;
  248. SetThreadUILanguage( 0 );
  249. //
  250. // Get past the name of the program
  251. //
  252. SHIFT( argc, argv );
  253. //
  254. // No arguments means a quick blurt of all the messages
  255. //
  256. if (argc == 0) {
  257. return DisplayFullHelp( );
  258. }
  259. //
  260. // A single argument is looked up in the message set and
  261. // that command is executed
  262. //
  263. if (argc == 1 && wcscmp( argv[0], L"/?" )) {
  264. return DisplaySingleHelp( argv[0] );
  265. }
  266. //
  267. // More than one argument was supplied. This is an error
  268. //
  269. HelpString = GetMsg( HELP_USAGE_MESSAGE, ProgramName );
  270. if (HelpString == NULL) {
  271. PrintString( L"Unable to display usage message\n" );
  272. return 1;
  273. }
  274. RetValue = PrintString( HelpString );
  275. LocalFree( HelpString );
  276. return RetValue;
  277. }