windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/srvsvc/server/cmdline.c

337 lines
6.8 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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