|
|
/*++
Copyright (c) 1991-1992 Microsoft Corporation
Module Name:
CmdLine.c
Abstract:
This module contains support routines for processing server service command-line arguments.
Author:
David Treadwell (davidtr) 10-Mar-1991
Revision History:
--*/
#include "srvsvcp.h"
#include <netlibnt.h>
#include <tstr.h>
//
// Forward declarations.
//
PFIELD_DESCRIPTOR FindSwitchMatch ( IN LPWCH Argument, IN BOOLEAN Starting );
NET_API_STATUS SetField ( IN PFIELD_DESCRIPTOR SwitchDesc, IN LPWCH Argument );
NET_API_STATUS SsParseCommandLine ( IN DWORD argc, IN LPWSTR argv[], IN BOOLEAN Starting )
/*++
Routine Description:
This routine sets server parameters using a command line. It parses the command line, changing one parameter at a time as it comes up.
Arguments:
argc - the number of command-line arguments.
argv - an arrray of pointers to the arguments.
Starting - TRUE if the command line is from server startup, i.e. net start server. This is needed because some fields may only be set at startup.
Return Value:
NET_API_STATUS - 0 or reason for failure.
--*/
{ NET_API_STATUS error; DWORD i; PFIELD_DESCRIPTOR switchDesc; PSERVER_SERVICE_DATA saveSsData;
//
// Save the service data in case there is an invalid param and we have
// to back out.
//
saveSsData = MIDL_user_allocate( sizeof(SERVER_SERVICE_DATA) ); if ( saveSsData == NULL ) { return ERROR_NOT_ENOUGH_MEMORY; }
RtlCopyMemory( saveSsData, &SsData, sizeof(SERVER_SERVICE_DATA) );
//
// Loop through the command-line arguments, setting as we go.
//
for ( i = 0; i < argc; i++ ) {
LPWCH arg;
arg = argv[i];
//
// A hack to aid debugging.
//
if ( _wcsnicmp( L"/debug", arg, 6 ) == 0 ) { continue; }
//
// Try to match the switch against the legal switches.
//
switchDesc = FindSwitchMatch( arg, Starting ); if ( switchDesc == NULL ) { error = ERROR_INVALID_PARAMETER; goto err_exit; }
//
// Set the value in the field.
//
error = SetField( switchDesc, arg ); if ( error != NO_ERROR ) { IF_DEBUG(INITIALIZATION_ERRORS) { SS_PRINT(( "SsParseCommandLine: SetField failed for switch " "\"%ws\": %ld\n", arg, error )); } goto err_exit; } }
error = NO_ERROR; goto normal_exit;
err_exit:
//
// Restore the original server settings.
//
RtlCopyMemory( &SsData, saveSsData, sizeof(SERVER_SERVICE_DATA) );
normal_exit:
MIDL_user_free( saveSsData );
return error;
} // SsParseCommandLine
PFIELD_DESCRIPTOR FindSwitchMatch ( IN LPWCH Argument, IN BOOLEAN Starting )
/*++
Routine Description:
This routine tries to match a given switch against the possible switch values.
Arguments:
Argument - a pointer to the text argument.
Starting - TRUE if the command line is from server startup, i.e. net start server. This is needed because some fields may only be set at startup.
Return Value:
A pointer to a FIELD_DESCRIPTOR field from SsServerInfoFields[], or NULL if no valid match could be found.
--*/
{ SHORT i; PFIELD_DESCRIPTOR foundSwitch = NULL; ULONG switchLength; LPWCH s;
//
// Ignore the leading /.
//
if ( *Argument != '/' ) { SS_PRINT(( "Invalid switch: %ws\n", Argument )); return NULL; }
Argument++;
//
// Find out how long the passed-in switch is.
//
for ( s = Argument, switchLength = 0; *s != ':' && *s != '\0'; s++, switchLength++ );
//
// Compare at most that many bytes. We allow a minimal matching--
// as long as the specified switch uniquely identifies a switch, then
// is is usable.
//
for ( i = 0; SsServerInfoFields[i].FieldName != NULL; i++ ) {
if ( _wcsnicmp( Argument, SsServerInfoFields[i].FieldName, switchLength ) == 0 ) {
if ( SsServerInfoFields[i].Settable == NOT_SETTABLE || ( !Starting && SsServerInfoFields[i].Settable == SET_ON_STARTUP ) ) {
SS_PRINT(( "Cannot set field %ws at this time.\n", SsServerInfoFields[i].FieldName ));
return NULL; }
if ( foundSwitch != NULL ) { SS_PRINT(( "Ambiguous switch name: %ws (matches %ws and %ws)\n", Argument-1, foundSwitch->FieldName, SsServerInfoFields[i].FieldName )); return NULL; }
foundSwitch = &SsServerInfoFields[i]; } }
if ( foundSwitch == NULL ) { SS_PRINT(( "Unknown argument: %ws\n", Argument-1 )); }
return foundSwitch;
} // FindSwitchMatch
NET_API_STATUS SetField ( IN PFIELD_DESCRIPTOR Field, IN LPWCH Argument )
/*++
Routine Description:
This routine sets the value of a server info parameter.
Arguments:
Field - a pointer to the appropriate FIELD_DESCRIPTOR field from SsServerInfoFields[].
Argument - a pointer to the text argument. It should be of the form "/switch:value".
Return Value:
NET_API_STATUS - NO_ERROR or reason for failure.
--*/
{ LPWCH valueStart; DWORD_PTR value;
//
// Find out where the ':' is in the argument.
//
valueStart = wcschr( Argument, L':' );
if ( valueStart == NULL && Field->FieldType != BOOLEAN_FIELD ) { SS_PRINT(( "Invalid argument: %s\n", Argument )); }
switch ( Field->FieldType ) {
case BOOLEAN_FIELD:
//
// If the first character of the value is Y or there is no
// value specified, set the field to TRUE, otherwise set it
// to FALSE.
//
if ( valueStart == NULL || *(valueStart+1) == L'y' || *(valueStart+1) == L'Y' ) { value = TRUE; } else if ( *(valueStart+1) == L'n' || *(valueStart+1) == L'N' ) { value = FALSE; } else { return ERROR_INVALID_PARAMETER; }
break;
case DWORD_FIELD: { NTSTATUS status; UNICODE_STRING unicodeString; DWORD intValue;
RtlInitUnicodeString( &unicodeString, valueStart + 1 ); status = RtlUnicodeStringToInteger( &unicodeString, 0, &intValue ); if ( !NT_SUCCESS(status) ) { return ERROR_INVALID_PARAMETER; } value = intValue;
break; } case LPSTR_FIELD:
value = (DWORD_PTR)( valueStart + 1 ); break; }
//
// Call SsSetField to actually set the field.
//
return SsSetField( Field, &value, TRUE, NULL );
} // SetField
|