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.

336 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. CmdLine.c
  5. Abstract:
  6. This module contains support routines for processing server service
  7. command-line arguments.
  8. Author:
  9. David Treadwell (davidtr) 10-Mar-1991
  10. Revision History:
  11. --*/
  12. #include "srvsvcp.h"
  13. #include <netlibnt.h>
  14. #include <tstr.h>
  15. //
  16. // Forward declarations.
  17. //
  18. PFIELD_DESCRIPTOR
  19. FindSwitchMatch (
  20. IN LPWCH Argument,
  21. IN BOOLEAN Starting
  22. );
  23. NET_API_STATUS
  24. SetField (
  25. IN PFIELD_DESCRIPTOR SwitchDesc,
  26. IN LPWCH Argument
  27. );
  28. NET_API_STATUS
  29. SsParseCommandLine (
  30. IN DWORD argc,
  31. IN LPWSTR argv[],
  32. IN BOOLEAN Starting
  33. )
  34. /*++
  35. Routine Description:
  36. This routine sets server parameters using a command line. It parses
  37. the command line, changing one parameter at a time as it comes up.
  38. Arguments:
  39. argc - the number of command-line arguments.
  40. argv - an arrray of pointers to the arguments.
  41. Starting - TRUE if the command line is from server startup, i.e.
  42. net start server. This is needed because some fields may only
  43. be set at startup.
  44. Return Value:
  45. NET_API_STATUS - 0 or reason for failure.
  46. --*/
  47. {
  48. NET_API_STATUS error;
  49. DWORD i;
  50. PFIELD_DESCRIPTOR switchDesc;
  51. PSERVER_SERVICE_DATA saveSsData;
  52. //
  53. // Save the service data in case there is an invalid param and we have
  54. // to back out.
  55. //
  56. saveSsData = MIDL_user_allocate( sizeof(SERVER_SERVICE_DATA) );
  57. if ( saveSsData == NULL ) {
  58. return ERROR_NOT_ENOUGH_MEMORY;
  59. }
  60. RtlCopyMemory( saveSsData, &SsData, sizeof(SERVER_SERVICE_DATA) );
  61. //
  62. // Loop through the command-line arguments, setting as we go.
  63. //
  64. for ( i = 0; i < argc; i++ ) {
  65. LPWCH arg;
  66. arg = argv[i];
  67. //
  68. // A hack to aid debugging.
  69. //
  70. if ( _wcsnicmp( L"/debug", arg, 6 ) == 0 ) {
  71. continue;
  72. }
  73. //
  74. // Try to match the switch against the legal switches.
  75. //
  76. switchDesc = FindSwitchMatch( arg, Starting );
  77. if ( switchDesc == NULL ) {
  78. error = ERROR_INVALID_PARAMETER;
  79. goto err_exit;
  80. }
  81. //
  82. // Set the value in the field.
  83. //
  84. error = SetField( switchDesc, arg );
  85. if ( error != NO_ERROR ) {
  86. IF_DEBUG(INITIALIZATION_ERRORS) {
  87. SS_PRINT(( "SsParseCommandLine: SetField failed for switch "
  88. "\"%ws\": %ld\n", arg, error ));
  89. }
  90. goto err_exit;
  91. }
  92. }
  93. error = NO_ERROR;
  94. goto normal_exit;
  95. err_exit:
  96. //
  97. // Restore the original server settings.
  98. //
  99. RtlCopyMemory( &SsData, saveSsData, sizeof(SERVER_SERVICE_DATA) );
  100. normal_exit:
  101. MIDL_user_free( saveSsData );
  102. return error;
  103. } // SsParseCommandLine
  104. PFIELD_DESCRIPTOR
  105. FindSwitchMatch (
  106. IN LPWCH Argument,
  107. IN BOOLEAN Starting
  108. )
  109. /*++
  110. Routine Description:
  111. This routine tries to match a given switch against the possible
  112. switch values.
  113. Arguments:
  114. Argument - a pointer to the text argument.
  115. Starting - TRUE if the command line is from server startup, i.e.
  116. net start server. This is needed because some fields may only
  117. be set at startup.
  118. Return Value:
  119. A pointer to a FIELD_DESCRIPTOR field from SsServerInfoFields[], or NULL if
  120. no valid match could be found.
  121. --*/
  122. {
  123. SHORT i;
  124. PFIELD_DESCRIPTOR foundSwitch = NULL;
  125. ULONG switchLength;
  126. LPWCH s;
  127. //
  128. // Ignore the leading /.
  129. //
  130. if ( *Argument != '/' ) {
  131. SS_PRINT(( "Invalid switch: %ws\n", Argument ));
  132. return NULL;
  133. }
  134. Argument++;
  135. //
  136. // Find out how long the passed-in switch is.
  137. //
  138. for ( s = Argument, switchLength = 0;
  139. *s != ':' && *s != '\0';
  140. s++, switchLength++ );
  141. //
  142. // Compare at most that many bytes. We allow a minimal matching--
  143. // as long as the specified switch uniquely identifies a switch, then
  144. // is is usable.
  145. //
  146. for ( i = 0; SsServerInfoFields[i].FieldName != NULL; i++ ) {
  147. if ( _wcsnicmp( Argument, SsServerInfoFields[i].FieldName, switchLength ) == 0 ) {
  148. if ( SsServerInfoFields[i].Settable == NOT_SETTABLE ||
  149. ( !Starting && SsServerInfoFields[i].Settable == SET_ON_STARTUP ) ) {
  150. SS_PRINT(( "Cannot set field %ws at this time.\n",
  151. SsServerInfoFields[i].FieldName ));
  152. return NULL;
  153. }
  154. if ( foundSwitch != NULL ) {
  155. SS_PRINT(( "Ambiguous switch name: %ws (matches %ws and %ws)\n",
  156. Argument-1, foundSwitch->FieldName,
  157. SsServerInfoFields[i].FieldName ));
  158. return NULL;
  159. }
  160. foundSwitch = &SsServerInfoFields[i];
  161. }
  162. }
  163. if ( foundSwitch == NULL ) {
  164. SS_PRINT(( "Unknown argument: %ws\n", Argument-1 ));
  165. }
  166. return foundSwitch;
  167. } // FindSwitchMatch
  168. NET_API_STATUS
  169. SetField (
  170. IN PFIELD_DESCRIPTOR Field,
  171. IN LPWCH Argument
  172. )
  173. /*++
  174. Routine Description:
  175. This routine sets the value of a server info parameter.
  176. Arguments:
  177. Field - a pointer to the appropriate FIELD_DESCRIPTOR field
  178. from SsServerInfoFields[].
  179. Argument - a pointer to the text argument. It should be of the form
  180. "/switch:value".
  181. Return Value:
  182. NET_API_STATUS - NO_ERROR or reason for failure.
  183. --*/
  184. {
  185. LPWCH valueStart;
  186. DWORD_PTR value;
  187. //
  188. // Find out where the ':' is in the argument.
  189. //
  190. valueStart = wcschr( Argument, L':' );
  191. if ( valueStart == NULL && Field->FieldType != BOOLEAN_FIELD ) {
  192. SS_PRINT(( "Invalid argument: %s\n", Argument ));
  193. }
  194. switch ( Field->FieldType ) {
  195. case BOOLEAN_FIELD:
  196. //
  197. // If the first character of the value is Y or there is no
  198. // value specified, set the field to TRUE, otherwise set it
  199. // to FALSE.
  200. //
  201. if ( valueStart == NULL || *(valueStart+1) == L'y' ||
  202. *(valueStart+1) == L'Y' ) {
  203. value = TRUE;
  204. } else if ( *(valueStart+1) == L'n' || *(valueStart+1) == L'N' ) {
  205. value = FALSE;
  206. } else {
  207. return ERROR_INVALID_PARAMETER;
  208. }
  209. break;
  210. case DWORD_FIELD:
  211. {
  212. NTSTATUS status;
  213. UNICODE_STRING unicodeString;
  214. DWORD intValue;
  215. RtlInitUnicodeString( &unicodeString, valueStart + 1 );
  216. status = RtlUnicodeStringToInteger( &unicodeString, 0, &intValue );
  217. if ( !NT_SUCCESS(status) ) {
  218. return ERROR_INVALID_PARAMETER;
  219. }
  220. value = intValue;
  221. break;
  222. }
  223. case LPSTR_FIELD:
  224. value = (DWORD_PTR)( valueStart + 1 );
  225. break;
  226. }
  227. //
  228. // Call SsSetField to actually set the field.
  229. //
  230. return SsSetField( Field, &value, TRUE, NULL );
  231. } // SetField