/*++ Copyright (c) 1990 Microsoft Corporation Module Name: Argument Abstract: Argument processing for the Mode utility. After parsing the arguments off the command line, a minimum verification is done and a request packet is formed and returned. The request packet is eventually routed to the handler for a specific device, which performs further verification and takes proper action. Author: Ramon Juan San Andres (ramonsa) 26-Jun-1991 Notes: BUGBUG ramonsa 7/9/91 The number of stop bits can be 1, 1.5 or 2, Currently the library will not support floating point operations, so there are no floating-point-number arguments. We use a flag argument to handle the 1.5 case. This should be fixed whenever the library supports floating point. The mode command-line can take any of the following forms: MODE [/?] MODE [device] [/STATUS] MODE device CP PREPARE=string MODE device CP REFRESH MODE device CP SELECT=codepage MODE device CP [/STATUS] MODE LPTn[:] [COLS=c] [LINES=l] [RETRY=r] MODE LPTn[:] = COMm[:] MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] [RETRY=r] MODE CON[:] [COLS=c] [LINES=l] MODE CON[:] [RATE=r DELAY=d] Revision History: --*/ #include "mode.hxx" #include "arg.hxx" #include "array.hxx" #include "common.hxx" #include "lpt.hxx" #include "com.hxx" #include "con.hxx" // // BUGBUG all variables here should be static // PWSTRING LptPattern = NULL; PWSTRING LptColonPattern = NULL; PWSTRING ComPattern = NULL; PWSTRING ComColonPattern = NULL; PWSTRING ConPattern = NULL; PWSTRING ConColonPattern = NULL; PWSTRING StatusPattern = NULL; PWSTRING ColPattern = NULL; PWSTRING LinesPattern = NULL; PWSTRING CpPattern = NULL; PWSTRING PreparePattern = NULL; PWSTRING RetryPattern = NULL; PWSTRING EqualPattern = NULL; PWSTRING BaudPattern = NULL; PWSTRING ParityPattern = NULL; PWSTRING DataPattern = NULL; PWSTRING StopPattern = NULL; PWSTRING Stop15Pattern = NULL; PWSTRING SelectPattern = NULL; PWSTRING RefreshPattern = NULL; PWSTRING RatePattern = NULL; PWSTRING DelayPattern = NULL; PWSTRING HelpPattern = NULL; // // Parsing preferences // PWSTRING Switches = NULL; // // Arguments // PPATH_ARGUMENT ProgramNameArg; PLONG_ARGUMENT LptArg; PLONG_ARGUMENT LptColonArg; PLONG_ARGUMENT ComArg; PLONG_ARGUMENT ComColonArg; PFLAG_ARGUMENT ConArg; PFLAG_ARGUMENT ConColonArg; PSTRING_ARGUMENT StatusArg; PLONG_ARGUMENT ColArg; PLONG_ARGUMENT LinesArg; PFLAG_ARGUMENT CpArg; PSTRING_ARGUMENT PrepareArg; PSTRING_ARGUMENT RetryArg; PFLAG_ARGUMENT EqualArg; PLONG_ARGUMENT BaudArg; PSTRING_ARGUMENT ParityArg; PLONG_ARGUMENT DataArg; PLONG_ARGUMENT StopArg; PFLAG_ARGUMENT Stop15Arg; PLONG_ARGUMENT SelectArg; PFLAG_ARGUMENT RefreshArg; PLONG_ARGUMENT RateArg; PLONG_ARGUMENT DelayArg; PFLAG_ARGUMENT HelpArg; // // The Argument lexemizer and lexeme array. // PARGUMENT_LEXEMIZER ArgLex; PARRAY LexArray; // // Some device information so we don't have to be querying the arguments // all the time. // BOOLEAN LptSet; ULONG LptNumber; BOOLEAN ComSet; ULONG ComNumber; BOOLEAN ConSet; VOID AllocateStuff( ); VOID DeallocateStuff( ); PARRAY GetArgumentArray( ); VOID ParseArguments( IN PARRAY ArgArray ); PREQUEST_HEADER MakeRequest( ); PREQUEST_HEADER MakeStatusRequest( ); PREQUEST_HEADER MakeCodePageRequest( ); PREQUEST_HEADER MakeLptRequest( ); PREQUEST_HEADER MakeComRequest( ); PREQUEST_HEADER MakeConRequest( ); PREQUEST_HEADER GetRequest( ) /*++ Routine Description: Forms a device request based on the command line arguments. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PARRAY ArgArray; PREQUEST_HEADER Request; // // Get strings from resource messages // AllocateStuff(); // // Get array of arguments // ArgArray = GetArgumentArray(); DbgPtrAssert( ArgArray); // // Parse the arguments // ParseArguments( ArgArray ); // // Verify the arguments and form a request packet // Request = MakeRequest(); DbgPtrAssert( Request ); // // Deallocate resources // DELETE( ArgArray ); DeallocateStuff(); return Request; } VOID AllocateStuff( ) /*++ Routine Description: Obtains all necessary strings (e.g. argument patterns, switches) from message. Arguments: None. Return Value: None Notes: --*/ { // // Get strings from resource // if ( !( ( LptPattern = QueryMessageString( MODE_PATTERN_LPT )) && ( LptColonPattern = QueryMessageString( MODE_PATTERN_LPTCOLON )) && ( ComPattern = QueryMessageString( MODE_PATTERN_COM )) && ( ComColonPattern = QueryMessageString( MODE_PATTERN_COMCOLON )) && ( ConPattern = QueryMessageString( MODE_PATTERN_CON )) && ( ConColonPattern = QueryMessageString( MODE_PATTERN_CONCOLON )) && ( StatusPattern = QueryMessageString( MODE_PATTERN_STATUS )) && ( ColPattern = QueryMessageString( MODE_PATTERN_COLUMNS )) && ( LinesPattern = QueryMessageString( MODE_PATTERN_LINES )) && ( CpPattern = QueryMessageString( MODE_PATTERN_CODEPAGE )) && ( PreparePattern = QueryMessageString( MODE_PATTERN_PREPARE )) && ( RetryPattern = QueryMessageString( MODE_PATTERN_RETRY )) && ( EqualPattern = QueryMessageString( MODE_PATTERN_EQUAL )) && ( BaudPattern = QueryMessageString( MODE_PATTERN_BAUD )) && ( ParityPattern = QueryMessageString( MODE_PATTERN_PARITY )) && ( DataPattern = QueryMessageString( MODE_PATTERN_DATA )) && ( StopPattern = QueryMessageString( MODE_PATTERN_STOP )) && ( Stop15Pattern = QueryMessageString( MODE_PATTERN_STOP_15 )) && ( SelectPattern = QueryMessageString( MODE_PATTERN_SELECT )) && ( RefreshPattern = QueryMessageString( MODE_PATTERN_REFRESH )) && ( RatePattern = QueryMessageString( MODE_PATTERN_RATE )) && ( DelayPattern = QueryMessageString( MODE_PATTERN_DELAY )) && ( HelpPattern = QueryMessageString( MODE_PATTERN_HELP )) && ( Switches = QueryMessageString( MODE_SWITCHES )) )) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } // // Get argument objects. These are not global because the Create // method would not be called on them. // if ( !( ProgramNameArg = NEW PATH_ARGUMENT) || !( LptArg = NEW LONG_ARGUMENT) || !( LptColonArg = NEW LONG_ARGUMENT) || !( ComArg = NEW LONG_ARGUMENT) || !( ComColonArg = NEW LONG_ARGUMENT) || !( ConArg = NEW FLAG_ARGUMENT) || !( ConColonArg = NEW FLAG_ARGUMENT) || !( StatusArg = NEW STRING_ARGUMENT) || !( ColArg = NEW LONG_ARGUMENT) || !( LinesArg = NEW LONG_ARGUMENT) || !( CpArg = NEW FLAG_ARGUMENT) || !( PrepareArg = NEW STRING_ARGUMENT) || !( RetryArg = NEW STRING_ARGUMENT) || !( EqualArg = NEW FLAG_ARGUMENT) || !( BaudArg = NEW LONG_ARGUMENT) || !( ParityArg = NEW STRING_ARGUMENT) || !( DataArg = NEW LONG_ARGUMENT) || !( StopArg = NEW LONG_ARGUMENT) || !( Stop15Arg = NEW FLAG_ARGUMENT) || !( SelectArg = NEW LONG_ARGUMENT) || !( RefreshArg = NEW FLAG_ARGUMENT) || !( RateArg = NEW LONG_ARGUMENT) || !( DelayArg = NEW LONG_ARGUMENT) || !( HelpArg = NEW FLAG_ARGUMENT) ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } // // Lexemizer stuff // if ( !( ArgLex = NEW ARGUMENT_LEXEMIZER) || !( LexArray = NEW ARRAY) ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } } VOID DeallocateStuff( ) /*++ Routine Description: Deletes all the allocated strings. Arguments: None. Return Value: None Notes: --*/ { // // The string from the resource // DELETE( LptPattern ); DELETE( LptColonPattern ); DELETE( ComPattern ); DELETE( ComColonPattern ); DELETE( ConPattern ); DELETE( ConColonPattern ); DELETE( StatusPattern ); DELETE( ColPattern ); DELETE( LinesPattern ); DELETE( CpPattern ); DELETE( PreparePattern ); DELETE( RetryPattern ); DELETE( EqualPattern ); DELETE( BaudPattern ); DELETE( ParityPattern ); DELETE( DataPattern ); DELETE( StopPattern ); DELETE( SelectPattern ); DELETE( RefreshPattern ); DELETE( RatePattern ); DELETE( DelayPattern ); DELETE( HelpPattern ); DELETE( Switches ); // // The arguments // DELETE( ProgramNameArg ); DELETE( ProgramNameArg ); DELETE( LptArg ); DELETE( LptColonArg ); DELETE( ComArg ); DELETE( ComColonArg ); DELETE( ConArg ); DELETE( ConColonArg ); DELETE( StatusArg ); DELETE( ColArg ); DELETE( LinesArg ); DELETE( CpArg ); DELETE( PrepareArg ); DELETE( RetryArg ); DELETE( EqualArg ); DELETE( BaudArg ); DELETE( ParityArg ); DELETE( DataArg ); DELETE( StopArg ); DELETE( Stop15Arg ); DELETE( SelectArg ); DELETE( RefreshArg ); DELETE( RateArg ); DELETE( DelayArg ); DELETE( HelpArg ); // // The lexemizer stuff // DELETE( ArgLex ); DELETE( LexArray ); } PARRAY GetArgumentArray( ) /*++ Routine Description: Initializes all the arguments Arguments: None. Return Value: None Notes: --*/ { PARRAY ArgArray; if ( !( ( ArgArray = NEW ARRAY ) && ( ArgArray->Initialize( 22, 22, 0) ) && ( ProgramNameArg->Initialize( "*" )) && ( LptArg->Initialize( LptPattern )) && ( LptColonArg->Initialize( LptColonPattern )) && ( ComArg->Initialize( ComPattern )) && ( ComColonArg->Initialize( ComColonPattern )) && ( ConArg->Initialize( ConPattern )) && ( ConColonArg->Initialize( ConColonPattern )) && ( StatusArg->Initialize( StatusPattern )) && ( ColArg->Initialize( ColPattern )) && ( LinesArg->Initialize( LinesPattern )) && ( CpArg->Initialize( CpPattern )) && ( PrepareArg->Initialize( PreparePattern )) && ( RetryArg->Initialize( RetryPattern )) && ( EqualArg->Initialize( EqualPattern )) && ( BaudArg->Initialize( BaudPattern )) && ( ParityArg->Initialize( ParityPattern )) && ( DataArg->Initialize( DataPattern )) && ( StopArg->Initialize( StopPattern )) && ( Stop15Arg->Initialize( Stop15Pattern )) && ( SelectArg->Initialize( SelectPattern )) && ( RefreshArg->Initialize( RefreshPattern )) && ( RateArg->Initialize( RatePattern )) && ( DelayArg->Initialize( DelayPattern )) && ( HelpArg->Initialize( HelpPattern )) )) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } if ( !( ( ArgArray->Put( ProgramNameArg ) ) && ( ArgArray->Put( LptColonArg ) ) && ( ArgArray->Put( LptArg ) ) && ( ArgArray->Put( ComColonArg ) ) && ( ArgArray->Put( ComArg ) ) && ( ArgArray->Put( ConColonArg ) ) && ( ArgArray->Put( ConArg ) ) && ( ArgArray->Put( StatusArg ) ) && ( ArgArray->Put( ColArg ) ) && ( ArgArray->Put( LinesArg ) ) && ( ArgArray->Put( CpArg ) ) && ( ArgArray->Put( PrepareArg ) ) && ( ArgArray->Put( RetryArg ) ) && ( ArgArray->Put( EqualArg ) ) && ( ArgArray->Put( BaudArg ) ) && ( ArgArray->Put( ParityArg ) ) && ( ArgArray->Put( DataArg ) ) && ( ArgArray->Put( Stop15Arg ) ) && ( ArgArray->Put( StopArg ) ) && ( ArgArray->Put( SelectArg ) ) && ( ArgArray->Put( RefreshArg ) ) && ( ArgArray->Put( RateArg ) ) && ( ArgArray->Put( DelayArg ) ) && ( ArgArray->Put( HelpArg ) ) ) ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } return ArgArray; } VOID ParseArguments( IN PARRAY ArgArray ) /*++ Routine Description: Parses the command line Arguments: ArgArray - Supplies pointer to array of arguments Return Value: none Notes: --*/ { WSTRING CmdLine; // // Initialize the argument lexemizer // if ( !( CmdLine.Initialize( GetCommandLine() ) && LexArray->Initialize( 8, 8, 0) && ArgLex->Initialize( LexArray ) ) ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } // // Set our parsing preferences // ArgLex->PutSeparators( "," ); ArgLex->PutSwitches( Switches ); ArgLex->SetCaseSensitive( FALSE ); // // Parse the arguments // if ( !(ArgLex->PrepareToParse( &CmdLine ))) { DisplayMessageAndExit( MODE_ERROR_PARSE, NULL, EXIT_ERROR ); } if ( !ArgLex->DoParsing( ArgArray ) ) { DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, ArgLex->QueryInvalidArgument(), EXIT_ERROR ); } } PREQUEST_HEADER MakeRequest( ) /*++ Routine Description: Verifies the parameters and forms a device request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { // // See if Help requested // // MODE [/?] // if ( HelpArg->QueryFlag() ) { DisplayMessageAndExit( MODE_MESSAGE_HELP, NULL, EXIT_ERROR ); } // // We cannot have LPT1 and LPT1: at the same time // if ( ( LptArg->IsValueSet() && LptColonArg->IsValueSet() ) || ( ComArg->IsValueSet() && ComColonArg->IsValueSet() ) || ( ConArg->IsValueSet() && ConColonArg->IsValueSet() ) ) { DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } // // Set the global device info. so we don't have to query the // arguments all the time. // if ( LptArg->IsValueSet() ) { LptSet = TRUE; LptNumber = (ULONG)LptArg->QueryLong(); } if ( LptColonArg->IsValueSet() ) { LptSet = TRUE; LptNumber = (ULONG)LptColonArg->QueryLong(); } if ( ComArg->IsValueSet() ) { ComSet = TRUE; ComNumber = (ULONG)ComArg->QueryLong(); } if ( ComColonArg->IsValueSet() ) { ComSet = TRUE; ComNumber = (ULONG)ComColonArg->QueryLong(); } ConSet = (BOOLEAN)(ConArg->IsValueSet() || ConColonArg->IsValueSet()); // // See if codepage stuff requested // // MODE device CP [/STATUS] // MODE device CP PREPARE=string // MODE device CP REFRESH // MODE device CP SELECT=codepage // if ( CpArg->QueryFlag() ) { return MakeCodePageRequest(); } // // See if Status requested // // MODE [device] [/STATUS] // if ( ( ArgLex->QueryConsumedCount() == 1 ) || StatusArg->IsValueSet() ) { return MakeStatusRequest(); } // // See if LPT request // // MODE LPTn[:] [COLS=c] [LINES=l] [RETRY=r] // MODE LPTn[:] = COMm[:] // if ( LptSet ) { return MakeLptRequest(); } // // See if COM request // // MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] [RETRY=r] // if ( ComSet ) { return MakeComRequest(); } // // See if CON request // // MODE CON[:] [COLS=c] [LINES=l] // // MODE CON[:] [RATE=r DELAY=d] // if ( ConSet ) { return MakeConRequest(); } // // The request is incorrect // DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); // // To keep the compiler happy // return NULL; } PREQUEST_HEADER MakeStatusRequest( ) /*++ Routine Description: Verifies the parameters and forms a status request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PREQUEST_HEADER Request; // // The maximum number of parameters is 3: // // MODE [device] /STATUS // if ( ArgLex->QueryConsumedCount() > 3 ) { DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } // // Allocate the request header // Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } // // Now initialzie the request according to the device type // Request->RequestType = REQUEST_TYPE_STATUS; if ( LptSet ) { // // LPT Status request // Request->DeviceType = DEVICE_TYPE_LPT; Request->DeviceNumber = LptNumber; } else if ( ComSet ) { // // COM Status request // Request->DeviceType = DEVICE_TYPE_COM; Request->DeviceNumber = ComNumber; } else if ( ConSet ) { // // CON Status request // Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; } else { // // Everybody's status request // Request->DeviceType = DEVICE_TYPE_ALL; Request->DeviceNumber = ALL_DEVICES; } return Request; } PREQUEST_HEADER MakeCodePageRequest( ) /*++ Routine Description: Verifies the parameters and forms a codepage request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PREQUEST_HEADER Request; PCON_REQUEST ConRequest; // // Only CON accepts codepage requests. // if ( LptSet || ComSet ) { DisplayMessageAndExit( MODE_ERROR_CODEPAGE_OPERATION_NOT_SUPPORTED, NULL, EXIT_ERROR ); } if ( !ConSet ) { DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); } // // Form the request depending on the Codepage option // if ( RefreshArg->IsValueSet() || PrepareArg->IsValueSet() ) { // // REFRESH - This is a NO-OP // PREPARE - This is a NO-OP // if ( ArgLex->QueryConsumedCount() != 4 ) { // // Must have 4 arguments: // // MODE CON: CP REFRESH // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request->RequestType = REQUEST_TYPE_NULL; Request->DeviceType = DEVICE_TYPE_ALL; } else if ( SelectArg->IsValueSet() ) { // // SELECT // if ( ArgLex->QueryConsumedCount() != 4 ) { // // Must have 4 arguments: // // MODE CON: CP Select=codepage // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) ); DbgPtrAssert( ConRequest ); if ( !ConRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(ConRequest->Header); Request->RequestType = REQUEST_TYPE_CODEPAGE_SELECT; Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; ConRequest->Data.CpSelect.Codepage = (ULONG)SelectArg->QueryLong(); } else { // // STATUS // if ( ArgLex->QueryConsumedCount() != (ULONG)(StatusArg->IsValueSet() ? 4 : 3) ) { // Must have 3 or 4 arguments: // // MODE CON: CP [ /STATUS] // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request->RequestType = REQUEST_TYPE_CODEPAGE_STATUS; Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; } return Request; } PREQUEST_HEADER MakeLptRequest( ) /*++ Routine Description: Verifies the parameters and forms an LPT request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PREQUEST_HEADER Request; PLPT_REQUEST LptRequest; ULONG ArgCnt; // // Form the request depending on the argument line // if ( ArgLex->QueryConsumedCount() == 2 ) { // // STATUS // Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request->RequestType = REQUEST_TYPE_STATUS; Request->DeviceType = DEVICE_TYPE_LPT; Request->DeviceNumber = LptNumber; } else if ( EqualArg->IsValueSet() ) { // // REDIRECTION // // MODE LPTn[:] = COMm[:] if ( ArgLex->QueryConsumedCount() != 4 ) { // // Must have 4 arguments: // // MODE LPT1 = COM1 // // BUGBUG What happens line is "LPT1=COM1" ? // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } // // Can only redirect to COM // if ( !ComSet ) { DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); } LptRequest = (PLPT_REQUEST)MALLOC( sizeof( LPT_REQUEST ) ); DbgPtrAssert( LptRequest ); if ( !LptRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(LptRequest->Header); Request->RequestType = REQUEST_TYPE_LPT_REDIRECT; Request->DeviceType = DEVICE_TYPE_LPT; Request->DeviceNumber = LptNumber; LptRequest->Data.Redirect.DeviceType = DEVICE_TYPE_COM; LptRequest->Data.Redirect.DeviceNumber = ComNumber; } else if ( (ArgCnt = ( ColArg->IsValueSet() ? 1 : 0 ) + ( LinesArg->IsValueSet() ? 1 : 0 ) + ( RetryArg->IsValueSet() ? 1 : 0 )) > 0 ) { // // SET Lines & Columns // if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) { // // Must have 2 + ArgCnt arguments: // // MODE LPT1: [COLS=c] [LINES=l] [RETRY=r] // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } LptRequest = (PLPT_REQUEST)MALLOC( sizeof( LPT_REQUEST ) ); DbgPtrAssert( LptRequest ); if ( !LptRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(LptRequest->Header); Request->RequestType = REQUEST_TYPE_LPT_SETUP; Request->DeviceType = DEVICE_TYPE_LPT; Request->DeviceNumber = LptNumber; LptRequest->Data.Setup.SetCol = FALSE; LptRequest->Data.Setup.SetLines = FALSE; LptRequest->Data.Setup.SetRetry = FALSE; if ( ColArg->IsValueSet() ) { LptRequest->Data.Setup.SetCol = TRUE; LptRequest->Data.Setup.Col = ColArg->QueryLong(); } if ( LinesArg->IsValueSet() ) { LptRequest->Data.Setup.SetLines = TRUE; LptRequest->Data.Setup.Lines = LinesArg->QueryLong(); } if ( RetryArg->IsValueSet() ) { LptRequest->Data.Setup.SetRetry = TRUE; LptRequest->Data.Setup.Retry = 0; } } else { // // Invalid request // DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); } return Request; } PREQUEST_HEADER MakeComRequest( ) /*++ Routine Description: Verifies the parameters and forms a COM request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PREQUEST_HEADER Request; PCOM_REQUEST ComRequest; ULONG ArgCnt; if ( ArgLex->QueryConsumedCount() == 2 ) { // // Status request // Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request->RequestType = REQUEST_TYPE_STATUS; Request->DeviceType = DEVICE_TYPE_COM; Request->DeviceNumber = ComNumber; } else if ( (ArgCnt = ( BaudArg->IsValueSet() ? 1 : 0 ) + ( ParityArg->IsValueSet() ? 1 : 0 ) + ( DataArg->IsValueSet() ? 1 : 0 ) + ( Stop15Arg->IsValueSet() ? 1 : 0 ) + ( StopArg->IsValueSet() ? 1 : 0 ) + ( RetryArg->IsValueSet() ? 1 : 0 )) > 0 ) { // // Set COM Configuration // if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) { // // Must have 2 + ArgCnt arguments: // // MODE COM1: [ all options ] // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } ComRequest = (PCOM_REQUEST)MALLOC( sizeof( COM_REQUEST ) ); DbgPtrAssert( ComRequest ); if ( !ComRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(ComRequest->Header); Request->RequestType = REQUEST_TYPE_COM_SET; Request->DeviceType = DEVICE_TYPE_COM; Request->DeviceNumber = ComNumber; ComRequest->Data.Set.SetBaud = FALSE; ComRequest->Data.Set.SetDataBits = FALSE; ComRequest->Data.Set.SetStopBits = FALSE; ComRequest->Data.Set.SetParity = FALSE; ComRequest->Data.Set.SetRetry = FALSE; if ( BaudArg->IsValueSet() ) { ComRequest->Data.Set.SetBaud = TRUE; ComRequest->Data.Set.Baud = ConvertBaudRate( BaudArg->QueryLong(), ArgLex->GetLexemeAt( BaudArg->GetLexemeIndex()) ); } if ( DataArg->IsValueSet() ) { ComRequest->Data.Set.SetDataBits = TRUE; ComRequest->Data.Set.DataBits = ConvertDataBits( DataArg->QueryLong(), ArgLex->GetLexemeAt( DataArg->GetLexemeIndex()) ); } if ( Stop15Arg->IsValueSet() ) { ComRequest->Data.Set.SetStopBits = TRUE; ComRequest->Data.Set.StopBits = STOPBITS_15; } else if ( StopArg->IsValueSet() ) { ComRequest->Data.Set.SetStopBits = TRUE; ComRequest->Data.Set.StopBits = ConvertStopBits( StopArg->QueryLong(), ArgLex->GetLexemeAt( StopArg->GetLexemeIndex()) ); } if ( ParityArg->IsValueSet() ) { ComRequest->Data.Set.SetParity = TRUE; ComRequest->Data.Set.Parity = ConvertParity( ParityArg->GetString(), ArgLex->GetLexemeAt( ParityArg->GetLexemeIndex()) ); } if ( RetryArg->IsValueSet() ) { ComRequest->Data.Set.SetRetry = TRUE; ComRequest->Data.Set.Retry = ConvertRetry( RetryArg->GetString(), ArgLex->GetLexemeAt( RetryArg->GetLexemeIndex()) ); } } else { // // Invalid request // DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); } return Request; } PREQUEST_HEADER MakeConRequest( ) /*++ Routine Description: Verifies the parameters and forms a CON request. Arguments: None. Return Value: Pointer to the device request. Notes: --*/ { PREQUEST_HEADER Request; PCON_REQUEST ConRequest; ULONG ArgCnt; if ( ArgLex->QueryConsumedCount() == 2 ) { // // Status request // Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) ); DbgPtrAssert( Request ); if ( !Request ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request->RequestType = REQUEST_TYPE_STATUS; Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; } else if ( (ArgCnt = ( ColArg->IsValueSet() ? 1 : 0 ) + ( LinesArg->IsValueSet() ? 1 : 0 )) > 0 ) { // // Set Lines and Columns // if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) { // // Must have 2 + ArgCnt arguments: // // MODE CON: [COLS=c] [ LINES=l] // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) ); DbgPtrAssert( ConRequest ); if ( !ConRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(ConRequest->Header); Request->RequestType = REQUEST_TYPE_CON_SET_ROWCOL; Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; ConRequest->Data.RowCol.SetCol = FALSE; ConRequest->Data.RowCol.SetLines = FALSE; if ( ColArg->IsValueSet() ) { ConRequest->Data.RowCol.SetCol = TRUE; ConRequest->Data.RowCol.Col = ColArg->QueryLong(); } if ( LinesArg->IsValueSet() ) { ConRequest->Data.RowCol.SetLines = TRUE; ConRequest->Data.RowCol.Lines = LinesArg->QueryLong(); } } else if ( (ArgCnt = ( RateArg->IsValueSet() ? 1 : 0 ) + ( DelayArg->IsValueSet() ? 1 : 0 )) > 0 ) { // // Set Typematic rate // if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) { // // Must have 2 + ArgCnt arguments: // // MODE CON: [RATE=r] [DELAY=d] // DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS, NULL, EXIT_ERROR ); } ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) ); DbgPtrAssert( ConRequest ); if ( !ConRequest ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, EXIT_ERROR ); } Request = &(ConRequest->Header); Request->RequestType = REQUEST_TYPE_CON_SET_TYPEMATIC; Request->DeviceType = DEVICE_TYPE_CON; Request->DeviceNumber = 0; ConRequest->Data.Typematic.SetRate = FALSE; ConRequest->Data.Typematic.SetDelay = FALSE; if ( RateArg->IsValueSet() ) { ConRequest->Data.Typematic.SetRate = TRUE; ConRequest->Data.Typematic.Rate = RateArg->QueryLong(); } if ( DelayArg->IsValueSet() ) { ConRequest->Data.Typematic.SetDelay = TRUE; ConRequest->Data.Typematic.Delay = DelayArg->QueryLong(); } } else { // // Invalid request // DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER, (PWSTRING)(LexArray->GetAt( 1 )), EXIT_ERROR ); } return Request; } PREQUEST_HEADER MakeRequest( ) /*++ Routine Description: Makes a request and initializes its header Arguments: None. Return Value: Pointer to the device request. Notes: --*/ {