337 lines
6.8 KiB
C
337 lines
6.8 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|
|||
|
|