mirror of https://github.com/lianthony/NT4.0
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.
4160 lines
142 KiB
4160 lines
142 KiB
// --------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 1991 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// cmd.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
//
|
|
//
|
|
// Author:
|
|
//
|
|
// Tom Adams (tomad) 11-May-1991
|
|
//
|
|
// Revision History:
|
|
//
|
|
// 11-May-1991 tomad
|
|
//
|
|
// Created
|
|
//
|
|
//
|
|
// Sanjeev Katariya (sanjeevk) 4-6-1993
|
|
// Bug# 5203: The routine TpctlCopyAdapterAddress() needed modification to support
|
|
// the offset introduced by the Media type being returned on an Adapter Open.
|
|
// This was done in order to be able to correctly set the OID based on the
|
|
// medium
|
|
//
|
|
// Added support for commands DISABLE, ENABLE, SHELL, RECORDINGENABLE, RECORDINGDISABLE,
|
|
// Tpctl Options w,c and ?, fixed multicast address accounting
|
|
//
|
|
// Tim Wynsma (timothyw) 4-27-94
|
|
// Added performance testing
|
|
// 5-18-94
|
|
// Added setglobal command; cleanup
|
|
// 6-08-94
|
|
// Chgd perf test to client/server model
|
|
//
|
|
// ---------------------------------------------------------------------
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "tpctl.h"
|
|
#include "parse.h"
|
|
|
|
|
|
extern CMD_CODE CommandCode[] = {
|
|
|
|
{ CMD_ERR, "Unknown", "U" },
|
|
{ VERBOSE, "Verbose", "V" },
|
|
{ SETENV, "SetEnvironment", "SE" },
|
|
{ READSCRIPT, "ReadScript", "RS" },
|
|
{ BEGINLOGGING, "BeginLogging", "BL" },
|
|
{ ENDLOGGING, "EndLogging", "EL" },
|
|
{ WAIT, "Wait", "W" },
|
|
{ GO, "Go", "G" },
|
|
{ PAUSE, "Pause", "P" },
|
|
{ LOAD, "Load", "L" },
|
|
{ UNLOAD, "Unload", "U" },
|
|
{ OPEN, "Open", "O" },
|
|
{ CLOSE, "Close", "C" },
|
|
{ SETPF, "SetPacketFilter", "SP" },
|
|
{ SETLA, "SetLookAheadSize", "LA" },
|
|
{ ADDMA, "AddMulticastAddress", "AM" },
|
|
{ DELMA, "DeleteMulticastAddress", "DM" },
|
|
{ SETFA, "SetFunctionalAddress", "SF" },
|
|
{ SETGA, "SetGroupAddress", "SG" },
|
|
{ QUERYINFO, "QueryInformation", "QI" },
|
|
{ QUERYSTATS, "QueryStatistics", "QS" },
|
|
{ SETINFO, "SetInformation", "SI" },
|
|
{ RESET, "Reset", "R" },
|
|
{ SEND, "Send", "S" },
|
|
{ STOPSEND, "StopSend", "SS" },
|
|
{ WAITSEND, "WaitSend", "WT" },
|
|
{ RECEIVE, "Receive", "RC" },
|
|
{ STOPREC, "StopReceive", "SR" },
|
|
{ GETEVENTS, "GetEvents", "GE" },
|
|
{ STRESS, "Stress", "ST" },
|
|
{ STRESSSERVER, "StressServer", "SV" },
|
|
{ ENDSTRESS, "EndStress", "ES" },
|
|
{ WAITSTRESS, "WaitStress", "WS" },
|
|
{ CHECKSTRESS, "CheckStress", "CS" },
|
|
{ BREAKPOINT, "BreakPoint", "BP" },
|
|
{ QUIT, "Quit", "Q" },
|
|
{ HELP, "Help", "H" },
|
|
{ SHELL, "Shell", "SH" },
|
|
{ RECORDINGENABLE, "RecordingEnable", "RE" },
|
|
{ RECORDINGDISABLE,"RecordingDisable", "RD" },
|
|
{ DISABLE, "Disable", "DI" },
|
|
{ ENABLE, "Enable", "EN" },
|
|
{ REGISTRY, "Registry", "RG" },
|
|
{ PERFSERVER, "PerformServer", "PS" },
|
|
{ PERFCLIENT, "PerformClient", "PC" },
|
|
{ SETGLOBAL, "SetGlobalVar", "SET"}
|
|
};
|
|
|
|
|
|
extern BOOL WriteThrough;
|
|
extern BOOL ContinueOnError;
|
|
|
|
|
|
DWORD
|
|
TpctlParseCommandLine(
|
|
IN WORD argc,
|
|
IN LPSTR argv[]
|
|
)
|
|
|
|
// -----------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine parses the command line arguments. If there is a
|
|
// script file and or log file they are loaded, and will be read from
|
|
// when that test actually starts. If there is an adapter to be loaded
|
|
// it is written to the global var AdapterName and will be loaded
|
|
// by a later routine.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// argc - the number of arguments passed in at startup.
|
|
//
|
|
// argv - the argument vector containing the arguments passed in
|
|
// from the command line.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// DWORD - NO_ERROR if all the arguments are valid, and the
|
|
// script and log file are opened and loaded correctly.
|
|
// ERROR_INVALID_PARAMETER otherwise.
|
|
//
|
|
// --------------------
|
|
|
|
{
|
|
DWORD Status;
|
|
CHAR *TmpArgv[4];
|
|
CHAR *TmpOptions = "/N";
|
|
INT i;
|
|
|
|
//
|
|
// Parameter validations
|
|
//
|
|
if ( ( argc < 1 ) || ( argc > 4 ) )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Invalid Command Line Argument(s).\n",NULL);
|
|
TpctlUsage();
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Read the command line arguments into the global command buffer.
|
|
// We are going to temporarily "fake" that we are reading commands
|
|
// from a script so the parse agruments routine will not prompt
|
|
// the user for any additional info if all the arguments are not
|
|
// given. This will be disabled immediately following the call.
|
|
//
|
|
|
|
ScriptIndex++;
|
|
|
|
//
|
|
// This is very specific to this routine. The current method of parsing
|
|
// does not lead itself well to optionals
|
|
//
|
|
TmpArgv[0] = TmpArgv[1] = TmpArgv[2] = TmpArgv[3] = NULL;
|
|
for( i = 0; i < argc; i++ )
|
|
{
|
|
TmpArgv[i] = argv[i];
|
|
}
|
|
|
|
if ( ( argc >= 2 ) && ( argv[1][0] != '/' ) )
|
|
{
|
|
if ( argc == 4 )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Invalid Command Line Argument(s).\n",NULL);
|
|
TpctlUsage();
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We now shift things around. At this point we now that argc must be three
|
|
//
|
|
argc++;
|
|
TmpArgv[1] = TmpOptions;
|
|
TmpArgv[2] = argv[1];
|
|
TmpArgv[3] = argv[2];
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( (argc >=2 ) && (argv[1][0] == '/') &&
|
|
(strlen( argv[1] ) > (TPCTL_OPTION_SIZE-1)) )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Invalid Command Line Argument(s).\n",NULL);
|
|
TpctlUsage();
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
|
|
if ( TpctlParseArguments( CommandLineOptions,
|
|
Num_CommandLine_Params,
|
|
argc,
|
|
TmpArgv ) == -1 )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Invalid Command Line Argument(s)\n",NULL);
|
|
TpctlUsage();
|
|
ScriptIndex--;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
ScriptIndex--;
|
|
|
|
//
|
|
// Check the options
|
|
//
|
|
|
|
_strupr( GlobalCmdArgs.TpctlOptions );
|
|
|
|
if ( strchr( GlobalCmdArgs.TpctlOptions, '?' ) != NULL )
|
|
{
|
|
TpctlUsage();
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ( strchr( GlobalCmdArgs.TpctlOptions, 'W' ) != NULL )
|
|
{
|
|
WriteThrough = FALSE;
|
|
}
|
|
|
|
if ( strchr( GlobalCmdArgs.TpctlOptions, 'C' ) != NULL )
|
|
{
|
|
ContinueOnError = TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// If there is a script file to be opened.
|
|
//
|
|
|
|
if ( GlobalCmdArgs.ARGS.FILES.ScriptFile[0] != '\0' )
|
|
{
|
|
//
|
|
// Then open it and the log file if it exists.
|
|
//
|
|
|
|
Status = TpctlLoadFiles( GlobalCmdArgs.ARGS.FILES.ScriptFile,
|
|
GlobalCmdArgs.ARGS.FILES.LogFile );
|
|
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
TpctlUsage();
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Otherwise if there is only a logfile name with no script file
|
|
// name print the usage message and return an error.
|
|
//
|
|
|
|
}
|
|
else if ( GlobalCmdArgs.ARGS.FILES.LogFile[0] != '\0' )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Invalid Command Line Argument(s).\n",NULL);
|
|
TpctlUsage();
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlUsage (
|
|
VOID
|
|
)
|
|
|
|
// ------------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine prints out a usage statement.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// -- -------------
|
|
|
|
{
|
|
printf("\n\tUSAGE: TPCTL [/[?|W|C]] [SCRIPT_FILE_NAME [LOG_FILE_NAME]]\n\n");
|
|
|
|
printf("\tWhere:\n\n");
|
|
|
|
printf("\tSCRIPT_FILE_NAME - is an OPTIONAL script file containing test\n");
|
|
printf("\t commands.\n\n");
|
|
|
|
printf("\tLOG_FILE_NAME - is an OPTIONAL log file for logging test results.\n");
|
|
printf("\t Defaults to TESTPROT.LOG. A SCRIPT_FILE_NAME must\n");
|
|
printf("\t precede a LOG_FILE_NAME.\n\n");
|
|
|
|
printf("\tOPTIONS:\n\n");
|
|
printf("\t W - Disables write through which speeds up TPCTL as\n");
|
|
printf("\t writes to the log files are now cached. Note that\n");
|
|
printf("\t this exposes the risk of the log file not being\n");
|
|
printf("\t updated should the system crash during a test.\n");
|
|
printf("\t WRITE_THROUGH is enabled by default.\n\n");
|
|
|
|
printf("\t C - Enables TPCTL to continue on errors encountered during\n");
|
|
printf("\t script testing. TPCTL will stop script processing on\n");
|
|
printf("\t script errors by default.\n\n");
|
|
|
|
printf("\t ? - Access command online help.\n\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
TpctlHelp(
|
|
LPSTR Command
|
|
)
|
|
|
|
// ------------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine prints out help statements for each of the supported
|
|
// commands.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Command - The command to give the help information for. If no command
|
|
// is given then a list of all the commands that are supported
|
|
// will be printed.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// -----------------
|
|
|
|
{
|
|
DWORD CmdCode;
|
|
|
|
if ( GlobalCmdArgs.ARGS.CmdName[0] == '\0' )
|
|
{
|
|
CmdCode = HELP;
|
|
}
|
|
else
|
|
{
|
|
CmdCode = TpctlGetCommandCode( Command );
|
|
}
|
|
|
|
printf("\n\tThe syntax of this command is:\n\n");
|
|
|
|
switch ( CmdCode )
|
|
{
|
|
case HELP:
|
|
printf("\tHELP [command]\n\n");
|
|
printf("\tHelp is available on the following FUNCTIONAL commands:\n\n");
|
|
printf("\t (AM) AddMulticastAddress (C) Close\n");
|
|
printf("\t (DM) DeleteMulticastAddress (GE) GetEvents\n");
|
|
printf("\t (O) Open (QI) QueryInformation\n");
|
|
printf("\t (QS) QueryStatistics (RC) Receive\n");
|
|
printf("\t (R) Reset (S) Send\n");
|
|
printf("\t (SF) SetFunctionalAddress (SG) SetGroupAddress\n");
|
|
printf("\t (SI) SetInformation (LA) SetLookAheadSize\n");
|
|
printf("\t (SP) SetPacketFilter (SR) StopReceive\n");
|
|
printf("\t (SS) StopSend (WT) WaitSend\n\n");
|
|
printf("\tHelp is available on the following STRESS commands:\n\n");
|
|
printf("\t (CS) CheckStress (ES) EndStress\n");
|
|
printf("\t (ST) Stress (SV) StressServer\n");
|
|
printf("\t (WS) WaitStress\n\n");
|
|
printf("\tHelp is available on the following test control commands:\n\n");
|
|
printf("\t (BL) BeginLogging (BP) BreakPoint\n");
|
|
printf("\t (EL) EndLogging (G) Go\n");
|
|
printf("\t (H) Help (P) Pause\n");
|
|
printf("\t (Q) Quit (RS) ReadScript\n");
|
|
printf("\t (SE) SetEnvirnoment (V) Verbose\n");
|
|
printf("\t (W) Wait (RE) RecordingEnable\n");
|
|
printf("\t (RD) RecordingDisable (SH) CommandShell\n");
|
|
printf("\t (DI) Disable (EN) Enable\n");
|
|
printf("\t (RG) Registry\n\n");
|
|
printf("\tThe command may be entered in either the short form or\n");
|
|
printf("\tthe long form. The short form is described by the letter\n");
|
|
printf("\tor letters in the parentheses, while the long form is the\n");
|
|
printf("\tword or phrase following.\n\n");
|
|
break;
|
|
|
|
case VERBOSE:
|
|
printf("\tVERBOSE\n\n");
|
|
printf("\tVerbose enables and disables the output of each command and its\n");
|
|
printf("\tresults to the screen. Errors will be printed to the screen\n");
|
|
printf("\tregardless of the state of the Verbose flag.\n\n");
|
|
printf("\t\"V\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETENV:
|
|
printf("\tSETENVIRONMENT [Open_Instance] [Environment_Variable]\n\n");
|
|
printf("\tSetEnvironment allows the user to customize environment\n");
|
|
printf("\tvariables that effect the running of tests.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to set the environment variable\n");
|
|
printf("\t on. The default value is 1.\n\n");
|
|
printf("\tEnvironment_Variable - the variable(s) to set for a given call.\n\n");
|
|
printf("\t All variables are set back to their defaults\n");
|
|
printf("\t on each call unless otherwise specified.\n\n");
|
|
printf("\tEnvironment Variable values that may be set are:\n\n");
|
|
printf("\tWindowSize - the number of packets in the windows buffer of the\n");
|
|
printf("\t windowing algorithm. The default is 10 packets.\n\n");
|
|
printf("\tRandomBuffer - the maximum value passed to the rand routine to\n");
|
|
printf("\t determine the number of buffers in RAND_MAKEUP packets.\n");
|
|
printf("\t The default value is 5 which generates an average\n");
|
|
printf("\t buffer size of 1/5 of the packet size.\n\n");
|
|
printf("\tStressAddress - the multicast or functional address that will be\n");
|
|
printf("\t used to initialize a stress test. All machines in\n");
|
|
printf("\t a given stress test must use the same StressAddress.\n\n");
|
|
printf("\tStressDelay - the standard number of seconds to delay ecah loopp\n");
|
|
printf("\t through a stress test. The default is 1/1000 seconds.\n\n");
|
|
printf("\tUpForAirDelay - the number of seconds to delay on the loop through\n");
|
|
printf("\t a stress test after DelayInterval iterations have\n");
|
|
printf("\t occurred. The default is 1/100 seconds.\n");
|
|
printf("\tDelayInterval - the number of StressDelays between each UpForAirDelay\n");
|
|
printf("\t during a stress test. The default is 10 iterations.\n\n");
|
|
printf("\t\"SE\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case READSCRIPT:
|
|
printf("\tREADSCRIPT [Script_File] [Log_File]\n\n");
|
|
printf("\tReadScript reads test commands from a script file, executes\n");
|
|
printf("\tthe commands and logs the results of the command to a log file.\n\n");
|
|
printf("\tScript_File - the name of the file containing the test\n");
|
|
printf("\t commands to execute. The default script file name is\n");
|
|
printf("\t \"TESTPROT.TPS\".\n\n");
|
|
printf("\tLog_File - the name of the file to log commands and results to. If\n");
|
|
printf("\t this file exists, it will be overwritten. The default\n");
|
|
printf("\t log file name is \"TESTPROT.LOG\".\n\n");
|
|
printf("\t\"RS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case BEGINLOGGING:
|
|
printf("\tBEGINLOGGING [Log_File]\n\n");
|
|
printf("\tBeginLogging enables the logging of commands and their results.\n");
|
|
printf("\tOnce logging is started any commands entered from the command line\n");
|
|
printf("\tare written to the Log_File. If commands are being read from\n");
|
|
printf("\ta script this function is disabled. (see also ENDLOGGING)\n\n");
|
|
printf("\tLog_File - the name of the file to log the commands and results to.\n");
|
|
printf("\t If this file exists, it will be overwritten. The default\n");
|
|
printf("\t log file name is \"CMDLINE.LOG\".\n\n");
|
|
printf("\t\"BL\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case ENDLOGGING:
|
|
printf("\tENDLOGGING\n\n");
|
|
printf("\tEndLogging disables the logging of commands and their results.\n");
|
|
printf("\t(see also BEGINLOGGING)\n\n");
|
|
printf("\t\"EL\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case RECORDINGENABLE:
|
|
printf("\tRECORDINGENABLE [ScriptFile]\n\n");
|
|
printf("\tRecordingEnable enables the recording of commands.\n");
|
|
printf("\tOnce recording is started any commands entered from the command line\n");
|
|
printf("\tare written to the ScriptFile. If commands are being read from\n");
|
|
printf("\ta script this function is disabled. (see also RECORDINGDISABLE)\n\n");
|
|
printf("\tScriptFile - the name of the file to record the commands and results to.\n");
|
|
printf("\t If this file exists, it will be overwritten. The default\n");
|
|
printf("\t script file name is \"CMDLINE.TPS\".\n\n");
|
|
printf("\t\"RE\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case RECORDINGDISABLE:
|
|
printf("\tRECORDINGDISABLE\n\n");
|
|
printf("\tRecordingDisable disables the recording of commands.\n");
|
|
printf("\t(see also RECORDINGENABLE)\n\n");
|
|
printf("\t\"RD\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SHELL:
|
|
printf("\tSHELL [Argument_1 Argument2 ... Argument_N]\n\n");
|
|
printf("\tSHELL will from spawn a command shell from within TPCTL or execute\n");
|
|
printf("\tthe command arguments Argument_1 through Argument_N and return back\n");
|
|
printf("\tto the TPCTL command prompt. If using SHELL by itself, to return to\n");
|
|
printf("\tthe TPCTL prompt simply EXIT the command shell.\n\n");
|
|
printf("\t\"SH\" - the short form of the command.\n");
|
|
break;
|
|
|
|
|
|
case WAIT:
|
|
printf("\tWAIT [Wait_Time]\n\n");
|
|
printf("\tWait allows a script file to wait a given number of seconds prior\n");
|
|
printf("\tto continuing with the next command.\n\n");
|
|
printf("\tWait_Time - the time in seconds the call will wait before\n");
|
|
printf("\t returning control to command processing.\n\n");
|
|
printf("\t\"W\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case GO:
|
|
printf("\tGO [Open_Instance] [Remote_Address] [Test_Signature]\n\n");
|
|
printf("\tGo sends a TP_GO packet to the Remote Address signalling\n");
|
|
printf("\ta Paused instance of the driver to continue processing its\n");
|
|
printf("\ttest script. Go continuously resends the packet, and will\n");
|
|
printf("\twait, retrying, until it is acknowledged or stopped with\n");
|
|
printf("\t<Ctrl-C>. (see also PAUSE)\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver and\n");
|
|
printf("\t the MAC adapter that will send the TP_GO Packet.\n");
|
|
printf("\t The default value is 1.\n\n");
|
|
printf("\tRemote_Address - the address of a remote machine to send the TP_GO\n");
|
|
printf("\t packet to.\n\n");
|
|
printf("\tTest_Signature - a unique test signature used by both machines to\n");
|
|
printf("\t determine if the correct packets have been sent and\n");
|
|
printf("\t acknowledged. This value must match the Test\n");
|
|
printf("\t Signature value on the PAUSED machine.\n\n");
|
|
printf("\t\"G\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case PAUSE:
|
|
printf("\tPAUSE [Open_Instance] [Remote_Address] [Test_Signature]\n\n");
|
|
printf("\tPause waits for the receipt of a TP_GO packet wit ha matching test\n");
|
|
printf("\tsignature and then acknowledges it6 by sending a TP_GO_ACKL packet.\n");
|
|
printf("\tPause will wait for the receipt of the TP_GO packlet until it arrives,\n");
|
|
printf("\tor the command is cancelled by <Ctrl-c>.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver and\n");
|
|
printf("\t the MAC adapter that will wait for the TP_GO Packet.\n");
|
|
printf("\t The default value is 1.\n\n");
|
|
printf("\tRemote_Address - the address of a remote machine to send the TP_GO_ACK\n");
|
|
printf("\t packet to.\n\n");
|
|
printf("\tTest_Signature - a unique test signature used by both machines to\n");
|
|
printf("\t determine if the correct packets have been sent and\n");
|
|
printf("\t acknowledged. This value must match the Test\n");
|
|
printf("\t Signature value on the machine sending the TP_GO\n");
|
|
printf("\t packet\n\n");
|
|
printf("\t\"P\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case LOAD:
|
|
printf("\tLOAD [MAC_Driver_Name]\n\n");
|
|
printf("\tLoad issues a call to NtLoadDriver to unload the driver for\n");
|
|
printf("\tthe MAC adapter \"Adapter_Name\".\n\n");
|
|
printf("\tMAC_Driver_Name - the MAC adapter to be loaded. There is no default\n");
|
|
printf("\t value.\n\n");
|
|
printf("\t\"L\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case UNLOAD:
|
|
printf("\tUNLOAD [MAC_Driver_Name]\n\n");
|
|
printf("\tUnload issues a call to NtUnloadDriver to unload the driver for\n");
|
|
printf("\tthe MAC adapter \"Adapter_Name\".\n\n");
|
|
printf("\tMAC_Driver_Name - the MAC adapter to be unloaded. There is no default\n");
|
|
printf("\t value.\n\n");
|
|
printf("\t\"U\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case OPEN:
|
|
printf("\tOPEN [Open_Instance] [Adapter_Name]\n\n");
|
|
printf("\tOpen issues a call to NdisOpenAdapter to open the MAC adapter\n");
|
|
printf("\tAdapter_Name, and associates it with the given Open_Instance.\n");
|
|
printf("\tSubsequent calls to the Open_Instance will be directed to\n");
|
|
printf("\tthis adapter.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter this open will be associated\n");
|
|
printf("\t with. The default value is 1.\n\n");
|
|
printf("\tAdapter_Name - the MAC adapter to be unloaded. There is no default\n");
|
|
printf("\t value.\n\n");
|
|
printf("\t\"O\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case CLOSE:
|
|
printf("\tCLOSE [Open_Instance]\n\n");
|
|
printf("\tClose issues a call to NdisCloseAdapter to close the MAC adapter\n");
|
|
printf("\tassociated with the given Open_Instance.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to be closed. The default\n");
|
|
printf("\t value is 1.\n\n");
|
|
printf("\t\"C\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETPF:
|
|
printf("\tSETPACKETFILTER [Open_Instance] [Packet_Filter]\n\n");
|
|
printf("\tSetPacketFilter issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto set the card's packet filter to a given value.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tPacket_Filter - the packet filter value to set on the MAC adapter.\n");
|
|
printf("\t Multiple filter values may be entered by seperating\n");
|
|
printf("\t each with the \"|\" character. Valid values for\n");
|
|
printf("\t Packet_Filter are:\n\n");
|
|
printf("\t Directed\n");
|
|
printf("\t Multicast\n");
|
|
printf("\t AllMulticast\n");
|
|
printf("\t Broadcast\n");
|
|
printf("\t SourceRouting\n");
|
|
printf("\t Promiscuous\n");
|
|
printf("\t Mac_Frame\n");
|
|
printf("\t Functional\n");
|
|
printf("\t AllFunctional\n");
|
|
printf("\t Group\n");
|
|
printf("\t None\n\n");
|
|
printf("\t The default value is \"Directed\".\n\n");
|
|
printf("\t\"SP\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETLA:
|
|
printf("\tSETLOOKAHEADSIZE [Open_Instance] [LookAhead_Size]\n\n");
|
|
printf("\tSetLookAheadSize issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto set the card's lookahead buffer to a given size.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tLookAhead_Size - the new size of the card's lookahead buffer. The\n");
|
|
printf("\t default value is 100 bytes.\n\n");
|
|
printf("\t\"LA\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case ADDMA:
|
|
printf("\tADDMULTICASTADDRESS [Open_Instance] [Multicast_Address]\n\n");
|
|
printf("\tAddMulticastAddress issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto add a multicast address to the list of multicast addresses\n");
|
|
printf("\tcurrently set on the card.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tMulticast_Address - the multicast address to add to the list.\n\n");
|
|
printf("\t\"AM\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case DELMA:
|
|
printf("\tDELETEMULTICASTADDRESS [Open_Instance] [Multicast_Address]\n\n");
|
|
printf("\tDeleteMulticastAddress issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto delete a multicast address from the list of multicast\n");
|
|
printf("\taddresses currently set on the card.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tMulticast_Address - the multicast address to delete from the list.\n\n");
|
|
printf("\t\"DM\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETFA:
|
|
printf("\tSETFUNCTIONALADDRESS [Open_Instance] [Functional_Address]\n\n");
|
|
printf("\tSetFunctionalAddress issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto set a functional address on the card.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tFunctional_Address - the functional address to set on the card.\n\n");
|
|
printf("\t\"SF\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETGA:
|
|
printf("\tSETGROUPADDRESS [Open_Instance] [Group_Address]\n\n");
|
|
printf("\tSetGroupAddress issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto set a group address on the card.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tGroup_Address - the group address to set on the card.\n\n");
|
|
printf("\t\"SG\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case QUERYINFO:
|
|
printf("\tQUERYINFORMATION [Open_Instance] [OID_Request]\n\n");
|
|
printf("\tQueryInformation issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto query a given class of information from the MAC.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tOID_Request - the information type to query. The default value\n");
|
|
printf("\t is \"SupportedOidList\".\n");
|
|
printf("\t\"QI\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case QUERYSTATS:
|
|
printf("\tQUERYSTATISTICS [Device_Name] [OID_Request]\n\n");
|
|
printf("\tDevice_Name - the name of the device to issue the request\n");
|
|
printf("\t to. There is no default value.\n\n");
|
|
printf("\tOID_Request - the statistics type to query. The default value\n");
|
|
printf("\t is \"SupportedOidList\".\n");
|
|
printf("\t\"QS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SETINFO:
|
|
printf("\tSETINFORMATION [Open_Instance] [OID_Request] [Type_Specific]\n\n");
|
|
printf("\tSetInformation issues a call to the MAC using NdisRequest\n");
|
|
printf("\tto set a given class of information in the MAC.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tOID_Request - the information type to set. Valid values for\n");
|
|
printf("\t OID_Request are:\n\n");
|
|
printf("\t CurrentPacketFilter\n");
|
|
printf("\t CurrentLookAhead\n");
|
|
printf("\t CurrentMulticastList\n");
|
|
printf("\t CurrentFunctionalAddress\n");
|
|
printf("\t CurrentGroupAddress\n");
|
|
printf("\t The default value is \"CurrentPacketFilter\".\n");
|
|
printf("\tType_Specific - the information to set for a given OID_Request\n");
|
|
printf("\t\"SI\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case RESET:
|
|
printf("\tRESET [Open_Instance]\n\n");
|
|
printf("\tReset issues a call to the MAC using NdisReset to reset the MAC.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\t\"R\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case SEND:
|
|
printf("\tSEND [Open_Instance] [Destination_Address] [Packet_Size] [Number]\n");
|
|
printf("\t [Resend_Address]\n\n");
|
|
printf("\tSend issues a call to the MAC using NdisSend to send packets on the\n");
|
|
printf("\tnetwork. Sending more then one packet causes the command to return\n");
|
|
printf("\tasynchronously. If a Resend_Address argument is specified, then\n");
|
|
printf("\teach packet sent will contain a \"resend\" packet in the data field\n");
|
|
printf("\tthat is extracted from the packet by any receiving test and\n");
|
|
printf("\tresent to the address specified. (see also RECEIVE, STOPSEND and\n");
|
|
printf("\tWAITSEND)\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to issue the request(s) to. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tDestination_Address - the network address the packet(s) will be sent\n");
|
|
printf("\t to.\n\n");
|
|
printf("\tPacket_Size - the size of the packet(s) to send.\n\n");
|
|
printf("\tNumber - the number of packets to send. A value of \"-1\" will\n");
|
|
printf("\t cause the test to send packets continuously until\n");
|
|
printf("\t stopped by a call to STOPSEND.\n\n");
|
|
printf("\tResend_Address - OPTIONAL: the address that will be placed in the\n");
|
|
printf("\t destination address of the \"resend\" packet.\n\n");
|
|
printf("\t\"S\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case STOPSEND:
|
|
printf("\tSTOPSEND [Open_Instance]\n\n");
|
|
printf("\tStopSend stops a previously started SEND command if it is still\n");
|
|
printf("\trunning, and prints the SEND command's results.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to stop the SEND command on.\n");
|
|
printf("\t The default value is 1.\n\n");
|
|
printf("\t\"SS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case WAITSEND:
|
|
printf("\tWAITSEND [Open_Instance]\n\n");
|
|
printf("\tWaitSend waits for a send test to end, and then displays the\n");
|
|
printf("\tsend test results. This command may be cancelled by entering\n");
|
|
printf("\tCtrl-C.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to wait for the send test to\n");
|
|
printf("\t end on. The default value is 1.\n\n");
|
|
printf("\t\"WT\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case RECEIVE:
|
|
printf("\tRECEIVE [Open_Instance]\n\n");
|
|
printf("\tReceive sets the test up in a mode to \"expect\" to receive\n");
|
|
printf("\tpackets from other tests. Each packet will be inspected, and\n");
|
|
printf("\tcounted. If a test packet received contains a \"resend\"\n");
|
|
printf("\tpacket, the \"resend\" packet will be extracted from the packet,\n");
|
|
printf("\tand sent to the address contained within. (see also SEND and STOPRECEIVE)\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to set up to expect packets.\n");
|
|
printf("\t The default value is 1.\n\n");
|
|
printf("\t\"RC\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case STOPREC:
|
|
printf("\tSTOPRECEIVE [Open_Instance]\n\n");
|
|
printf("\tStopReceive resets a test which has previously had a\n");
|
|
printf("\tRECEIVE commmand issued to it, to no longer \"expect\" packets.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to reset. The default value\n");
|
|
printf("\t is 1.\n\n");
|
|
printf("\t\"SR\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case GETEVENTS:
|
|
printf("\tGETEVENTS [Open_Instance]\n\n");
|
|
printf("\tGetEvents queries the test for information about \"unexpected\"\n");
|
|
printf("\tindications and completions.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to query the events from. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\t\"GE\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case STRESS:
|
|
printf("\tSTRESS [Open_Instance] [Member_Type] [Packets] [Iterations]\n");
|
|
printf("\t [Packet_Type] [Packet_Size] [Packet_MakeUp] [Response_Type]\n");
|
|
printf("\t [Delay_Type] [Delay_Length] [Windowing] [Data_Checking]\n");
|
|
printf("\t [PacketsFromPool]\n\n");
|
|
printf("\tStress sets the test up to run a stress test. If the test\n");
|
|
printf("\tis started successfully the command will complete asynchronously.\n");
|
|
printf("\tThe test will run until finished or until stopped manually. (see also\n");
|
|
printf("\tENDSTRESS, STOPSTRESS, WAITSTRESS, and CHECKSTRESS)\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to start a stress test on. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\tMember_Type - how the protocol will perform in the stress test; as\n");
|
|
printf("\t a client (CLIENT) or as a client and server (BOTH).\n");
|
|
printf("\t The default value is BOTH.\n\n");
|
|
printf("\tPackets - the number of packets that will be sent to each server prior\n");
|
|
printf("\t to the test completing. A value of -1 causes the test to\n");
|
|
printf("\t run forever unless a value is entered for Iterations. The\n");
|
|
printf("\t default value for packets is -1.\n\n");
|
|
printf("\tIterations - the number of iterations this test will run. A value\n");
|
|
printf("\t of -1 causes the test to run forever unless a value is\n");
|
|
printf("\t entered for Packet. The default value for Iterations\n");
|
|
printf("\t is -1.\n\n");
|
|
printf("\tPacket_Type - the type of packet size algorithm used to create the\n");
|
|
printf("\t packets for the test; FIXEDSIZE, RANDOMSIZE or CYCLICAL.\n");
|
|
printf("\t The default type is FIXED.\n\n");
|
|
printf("\tPacket_Size - with the Packet_Type value determines the size of packets\n");
|
|
printf("\t in the test. The default is 512 bytes.\n\n");
|
|
printf("\tPacket_MakeUp - the number and size of the buffers that makeup each\n");
|
|
printf("\t packet; RAND, SMALL, ZEROS, ONES and KNOWN. The\n");
|
|
printf("\t default makeup is RAND.\n\n");
|
|
printf("\tResponse_Type - the method the server will use when responding to test\n");
|
|
printf("\t packets; NO_RESPONSE, FULL_RESPONSE, ACK_EVERY,\n");
|
|
printf("\t or ACK_10_TIMES. The default value is FULL_RESPONSE.\n\n");
|
|
printf("\tDelay_Type - the method used to determine the next interpacket\n");
|
|
printf("\t delay; FIXEDDELAY or RANDOMDELAY. The default value\n");
|
|
printf("\t is FIXEDDELAY.\n\n");
|
|
printf("\tDelay_Length - the minimum number of iterations between two\n");
|
|
printf("\t consecutive sends to the same server in a test.\n");
|
|
printf("\t The default value is 0 iterations.\n\n");
|
|
printf("\tWindowing - a boolean used to determine whether a simple windowing\n");
|
|
printf("\t algorithm will be used between the client and each server.\n");
|
|
printf("\t the default value is TRUE.\n\n");
|
|
printf("\tData_Checking - a boolean used to determine whether data checking\n");
|
|
printf("\t will be performed on each packet received. The\n");
|
|
printf("\t default value is TRUE.\n\n");
|
|
printf("\tPacketsFromPool - a boolean used to determine whether a pool of\n");
|
|
printf("\t packets will be created prior to the test. The\n");
|
|
printf("\t default value is TRUE.\n\n");
|
|
printf("\t\"ST\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case STRESSSERVER:
|
|
printf("\tSTRESSSERVER [Open_Instance]\n\n");
|
|
printf("\tStressServer sets the test up to participate in a stress\n");
|
|
printf("\ttest as a server receiving and responding to stress packets from\n");
|
|
printf("\tany clients running a stress test.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to start a stress server on. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\t\"SV\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case ENDSTRESS:
|
|
printf("\tENDSTRESS [Open_Instance]\n\n");
|
|
printf("\tEndStress issues a command to the test to stop a currently\n");
|
|
printf("\trunning stress test, whether the protocol is acting as a client or\n");
|
|
printf("\tserver. If the protocol is acting as a client, once the test has\n");
|
|
printf("\tended, the result will be displayed.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to end the stress test on. The\n");
|
|
printf("\t default value is 1.\n\n");
|
|
printf("\t\"ES\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case WAITSTRESS:
|
|
printf("\tWAITSTRESS [Open_Instance]\n\n");
|
|
printf("\tWaitStress waits for a stress test to end, and then displays the\n");
|
|
printf("\tstress test results. This command may be cancelled by entering\n");
|
|
printf("\tCtrl-C.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to wait for the stress test to\n");
|
|
printf("\t end on. The default value is 1.\n\n");
|
|
printf("\t\"WS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case CHECKSTRESS:
|
|
printf("\tCHECKSTRESS [Open_Instance]\n\n");
|
|
printf("\tCheckStress checks to see if a stress test has ended, and if so\n");
|
|
printf("\tdisplays the stress test results.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver\n");
|
|
printf("\t and the MAC adapter to check for the results of a\n");
|
|
printf("\t stress test on. The default value is 1.\n\n");
|
|
printf("\t\"CS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case BREAKPOINT:
|
|
printf("\tBREAKPOINT\n\n");
|
|
printf("\tBreakPoint causes an interrupt to break into the debugger.\n\n");
|
|
printf("\t\"BP\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case QUIT:
|
|
printf("\tQUIT\n\n");
|
|
printf("\tQuit exits the control application. Any tests currently\n");
|
|
printf("\trunning are stopped and any opens to MACs are subsequently\n");
|
|
printf("\tclosed.\n\n");
|
|
printf("\t\"Q\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case DISABLE:
|
|
printf("\tDISABLE [ENV_VAR_1] [ENV_VAR_2]...[ENV_VAR_N]\n\n");
|
|
printf("\tDisable will prevent the test tool from executing any commands\n");
|
|
printf("\tfollowing it UNLESS all the environment variables passed to it have\n");
|
|
printf("\tbeen declared OR if it encounters the special command ENABLE.\n");
|
|
printf("\tIn that event that all environments variables are set and passed as\n");
|
|
printf("\targuments to DISABLE, the command is ignored and TPCTL remains\n");
|
|
printf("\tactive. Disable by itself will also disable the tool\n\n");
|
|
printf("\t\"DI\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case ENABLE:
|
|
printf("\tENABLE\n\n");
|
|
printf("\tEnable will enable the tool to accept commands\n\n");
|
|
printf("\t\"EN\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case REGISTRY :
|
|
printf("\tREGISTRY [Operation_Type] [Key_DataBase] [SubKey] [SubKey_Class]\n");
|
|
printf("\t [SubKey_Value_Name] [SubKey_Value_Type] [SubKey_Value]\n\n");
|
|
printf("\tRegistry is responsible for adding, deleting, modifying and querying\n");
|
|
printf("\texisting registry key entries.\n\n");
|
|
printf("\tOperation_Type - The type of operation to be performed on the registry\n");
|
|
printf("\t key\n");
|
|
printf("\t Types : ADD_KEY, DELETE_KEY, QUERY_KEY, ADD_VALUE,\n");
|
|
printf("\t CHANGE_VALUE, DELETE_VALUE, QUERY_VALUE\n");
|
|
printf("\t Default: QUERY_KEY\n\n");
|
|
printf("\tKey_DataBase - The key database to be interacted with\n");
|
|
printf("\t Databases: CLASSES_ROOT, CURRENT_USER, LOCAL_MACHINE,\n");
|
|
printf("\t USER\n");
|
|
printf("\t Default : LOCAL_MACHINE\n\n");
|
|
printf("\tSubKey - The string value(name) of the subkey being interacted\n");
|
|
printf("\t with\n");
|
|
printf("\t Default:\n");
|
|
printf("\t \"System\\CurrenControlSet\\Services\\Elnkii01\\Parameters\"\n");
|
|
printf("\t NOTE : String values must be contained within double\n");
|
|
printf("\t quotes\n\n");
|
|
printf("\tSubKey_Class - The string value(class) to be associated with this\n");
|
|
printf("\t subkey\n");
|
|
printf("\t Default: \"Network Drivers\"\n");
|
|
printf("\t NOTE : String values must be contained within double\n");
|
|
printf("\t quotes\n\n");
|
|
printf("\tSubKey_Value_Name - The string value(ValueName) to be associated with\n");
|
|
printf("\t this subkey\n");
|
|
printf("\t Default: \"NetworkAddress\"\n");
|
|
printf("\t NOTE : String values must be contained within\n");
|
|
printf("\t double quotes\n\n");
|
|
printf("\tSubKey_Value_Type - The type of value being provided\n");
|
|
printf("\t Types : BINARY, DWORD_REGULAR,\n");
|
|
printf("\t DWORD_LITTLE_ENDIAN, DWORD_BIG_ENDIAN,\n");
|
|
printf("\t EXPAND_SZ, LINK, MULTI_SZ, NONE,\n");
|
|
printf("\t RESOURCE_LIST, SZ\n");
|
|
printf("\t Default: DWORD_REGULAR\n\n");
|
|
printf("\tSubKey_Value - The provided value to set the sub key to\n");
|
|
printf("\t NOTE : Multiple strings must be seperated by\n");
|
|
printf("\t commas. Hex values should be preceeded by 0x.\n");
|
|
printf("\t Octal values are preceded by 0. Decimal values\n");
|
|
printf("\t do not have a leading 0.By default the base\n");
|
|
printf("\t radix is 10\n\n");
|
|
printf("\t\"RG\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case PERFSERVER:
|
|
printf("\tPERFORMSERVER [Open_Instance] \n\n");
|
|
printf("\tPerfServer starts a server to participate with the specified client in a\n");
|
|
printf("\tperformance test. This command always returns synchronously.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver and the MAC\n");
|
|
printf("\t adapter to issue the request to. Default value is 1.\n\n");
|
|
printf("\t\"PS\" - the short form of the command.\n");
|
|
break;
|
|
|
|
case PERFCLIENT:
|
|
printf("\tPERFORMRECEIVE [Open_Instance] [Server_Address] [Send_Address] ");
|
|
printf(" [Packet_Size] [Num_Packets] [Delay] [Mode] \n\n");
|
|
printf("\tPerfClient starts a client to participate with the specified server in a\n");
|
|
printf("\tperformance test. The specific test is indicated by the mode.\n");
|
|
printf("\tThis command always returns synchronously.\n\n");
|
|
printf("\tOpen_Instance - the open instance between the test driver and the MAC\n");
|
|
printf("\t adapter to issue the request to. Default value is 1.\n\n");
|
|
printf("\tServer_Address - the network address of the server card\n\n");
|
|
printf("\tSend_Address - the network address to which the server sends messages.\n\n");
|
|
printf("\tPacket_Size - total size of the test packets to be sent\n\n");
|
|
printf("\tNum_Packets - total number of test packets to be sent\n\n");
|
|
printf("\tDelay - how much to delay between sends\n\n");
|
|
printf("\tMode - which performance test to use:\n");
|
|
printf("\t 0 = client sends to any address (performance send test)\n");
|
|
printf("\t 1 = client sends to server (performance send test)\n");
|
|
printf("\t 2 = client sends to server, with server ACKs\n");
|
|
printf("\t 3 = two-way sends\n");
|
|
printf("\t 4 = server sends to client (performance receive test)\n");
|
|
printf("\t 5 = client sends REQ to server, server responds with sends\n");
|
|
printf("\t other = shut down server\n\n");
|
|
printf("\t\"PC\" - the short form of the command.\n");
|
|
break;
|
|
|
|
default:
|
|
printf("\tHELP [ ADDMULTICASTADDRESS | BEGINLOGGING | BREAKPOINT | CHECKSTRESS |\n");
|
|
printf("\t CLOSE | DELETEMULTICASTADDRESS | ENDLOGGING | ENDSTRESS |\n");
|
|
printf("\t GETEVENTS | GO | HELP | LOAD | OPEN | PAUSE | QUERYINFORMATION |\n");
|
|
printf("\t QUERYSTATISTICS | QUIT | READSCRIPT | RECEIVE | RESET | SEND |\n");
|
|
printf("\t SETENVIRONMENT | SETFUNCTIONALADDRESS | SETGROUPADDRESS |\n");
|
|
printf("\t SETINFORMATION | SETLOOKAHEADSIZE | SETPACKETFILTER |\n");
|
|
printf("\t STOPRECEIVE | STOPSEND | STRESS | STRESSSERVER | UNLOAD |\n");
|
|
printf("\t VERBOSE | WAIT | WAITSEND | WAITSTRESS | SHELL |\n");
|
|
printf("\t RECORDINGENABLE | RECORDINGDISABLE | REGISTRY |\n");
|
|
printf("\t PERFSERVER | PERFCLIENT\n\n");
|
|
printf("\tThe command \"%s\" is unknown.\n", _strupr( Command ));
|
|
break;
|
|
|
|
} // switch()
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
TpctlLoadFiles(
|
|
LPSTR ScriptFile,
|
|
LPSTR LogFile
|
|
)
|
|
|
|
// ---------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine loads a script file into a buffer, and opens a log
|
|
// file for logging commands and results to.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// IN LPSTR ScriptFile - the name of the script file to open and read.
|
|
// IN LPSTR LogFile - the name of the log file to open.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// DWORD - NO_ERROR if the script and log files are opened and
|
|
// processed correctly, otherwise the error returned on the
|
|
// failure from the win32 api that failed.
|
|
//
|
|
// NOTE: if this routine returns an error, then TpctlUnLoadFiles
|
|
// MUST be called next to reset the script structures
|
|
// correctly, and deallocate any resources that were
|
|
// allocated during this routine.
|
|
//
|
|
// ---------------
|
|
|
|
|
|
{
|
|
DWORD NextScriptIndex;
|
|
HANDLE FileHandle;
|
|
DWORD Status;
|
|
DWORD FileSize;
|
|
|
|
NextScriptIndex = ScriptIndex+1;
|
|
|
|
//
|
|
// First set the lowest level flag(s) in the scripts field to
|
|
// delineate which script is the lowest VALID script and should be
|
|
// unloaded. (necessary in case the next call to load files fails we
|
|
// will know where the high water mark is.)
|
|
//
|
|
|
|
if ( ScriptIndex >= 0 )
|
|
{
|
|
//
|
|
// if this is the first script we must ignore the reset of the
|
|
// "previous" script.
|
|
//
|
|
|
|
Scripts[ScriptIndex].IsLowestLevel = FALSE;
|
|
}
|
|
|
|
Scripts[NextScriptIndex].IsLowestLevel = TRUE;
|
|
|
|
//
|
|
// We have a script file, so increment the script index, and set the
|
|
// the index into the script buffer to zero. Make sure that we have
|
|
// not passed the maximum number of recursion in reading scripts.
|
|
//
|
|
|
|
if ( NextScriptIndex == TPCTL_MAX_SCRIPT_LEVELS )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Too many levels of script reading recursion; level 0x%lx\n",
|
|
(PVOID)(NextScriptIndex+1));
|
|
return (DWORD)STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// First we allocate the memory to store the script file name in.
|
|
//
|
|
|
|
Scripts[NextScriptIndex].ScriptFile = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,
|
|
TPCTL_MAX_PATHNAME_SIZE );
|
|
|
|
if ( Scripts[NextScriptIndex].ScriptFile == NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlLoadFiles: failed to alloc Script file name storage, returned 0x%lx.\n", (PVOID)Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Then determine what filename to write to it.
|
|
//
|
|
|
|
if ( ScriptFile[0] == '\0' )
|
|
{
|
|
//
|
|
// If no script file name was passed, then open the default
|
|
// script file TESTPROT.TPS.
|
|
//
|
|
|
|
strcpy( Scripts[NextScriptIndex].ScriptFile,TPCTL_SCRIPTFILE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Otherwise copy the filename passed into place.
|
|
//
|
|
|
|
strcpy( Scripts[NextScriptIndex].ScriptFile,ScriptFile );
|
|
}
|
|
|
|
//
|
|
// Open the script file, if it does not exist fail with an error msg.
|
|
//
|
|
|
|
FileHandle = CreateFile(Scripts[NextScriptIndex].ScriptFile,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
|
|
if ( FileHandle == (HANDLE)-1 )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: failed to open script file \"%s\", ",
|
|
(PVOID)Scripts[NextScriptIndex].ScriptFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// and find its size.
|
|
//
|
|
|
|
FileSize = GetFileSize( FileHandle,NULL );
|
|
|
|
if ( FileSize == -1 )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: failed find file size - returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// If necessary allocate memory for the Buffer.
|
|
//
|
|
|
|
if ( Scripts[NextScriptIndex].Buffer == NULL )
|
|
{
|
|
Scripts[NextScriptIndex].Buffer = (LPBYTE)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,
|
|
FileSize );
|
|
|
|
if ( Scripts[NextScriptIndex].Buffer == NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlLoadFiles: failed to alloc script buffer, returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
CloseHandle( FileHandle );
|
|
return Status;
|
|
}
|
|
|
|
}
|
|
else if ( FileSize > Scripts[NextScriptIndex].Length )
|
|
{
|
|
Scripts[NextScriptIndex].Buffer =
|
|
(LPBYTE)GlobalReAlloc( (HANDLE)Scripts[NextScriptIndex].Buffer,
|
|
FileSize,
|
|
GMEM_ZEROINIT | GMEM_MOVEABLE );
|
|
|
|
if ( Scripts[NextScriptIndex].Buffer == NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlLoadFiles: failed to ReAlloc script buffer, returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
CloseHandle( FileHandle );
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// And read the script file into it.
|
|
//
|
|
|
|
Status = ReadFile( FileHandle,
|
|
Scripts[NextScriptIndex].Buffer,
|
|
FileSize,
|
|
&Scripts[NextScriptIndex].Length,
|
|
NULL );
|
|
|
|
if ( Status != TRUE )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlLoadFiles: failed to read script file \"%s\", ",(PVOID)ScriptFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
CloseHandle( FileHandle );
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// We are done with script file now, so close it.
|
|
//
|
|
|
|
if (!CloseHandle(FileHandle))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlLoadFiles: failed to close Script file \"%s\", ",(PVOID)ScriptFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
}
|
|
|
|
//
|
|
// Now handle the log file. If we are not given a log file we need
|
|
// to determine the name of the log file we should use.
|
|
// First we allocate the memory to store the log file name in.
|
|
//
|
|
|
|
Scripts[NextScriptIndex].LogFile = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,
|
|
TPCTL_MAX_PATHNAME_SIZE );
|
|
|
|
if ( Scripts[NextScriptIndex].LogFile == NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog(
|
|
"\n\tTpctlLoadFiles: failed to alloc Log file name storage, returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Then determine what filename to write to it.
|
|
//
|
|
|
|
if (( LogFile == NULL ) || ( LogFile[0] == '\0' ))
|
|
{
|
|
if ( NextScriptIndex == 0 )
|
|
{
|
|
//
|
|
// If this is the first script file and no log file name was
|
|
// given, then use the default log file name.
|
|
//
|
|
|
|
strcpy( Scripts[NextScriptIndex].LogFile,TPCTL_LOGFILE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Otherwise, since no new log file name was given, and we are
|
|
// recursively reading script files we will use the log file
|
|
// used by the last level of script files.
|
|
//
|
|
|
|
strcpy( Scripts[NextScriptIndex].LogFile,Scripts[ScriptIndex].LogFile );
|
|
Scripts[NextScriptIndex].LogHandle = Scripts[ScriptIndex].LogHandle;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We have a log file name so copy it into the scripts structure.
|
|
//
|
|
|
|
strcpy(Scripts[NextScriptIndex].LogFile,LogFile);
|
|
}
|
|
|
|
//
|
|
// Now, if the log file has not already been opened, then we must open
|
|
// it. If the logfile already exists it WILL be truncated on the open.
|
|
//
|
|
|
|
if (( LogFile != NULL ) && ( LogFile[0] != '\0' ) ||
|
|
( NextScriptIndex == 0 ))
|
|
{
|
|
if ( WriteThrough )
|
|
{
|
|
Scripts[NextScriptIndex].LogHandle =
|
|
CreateFile( Scripts[NextScriptIndex].LogFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
Scripts[NextScriptIndex].LogHandle =
|
|
CreateFile( Scripts[NextScriptIndex].LogFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
}
|
|
|
|
if ( Scripts[NextScriptIndex].LogHandle == (HANDLE)-1 )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: failed to open log file \"%s\", ",
|
|
(PVOID)Scripts[NextScriptIndex].LogFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We have successfully opened the script and log files, and are now
|
|
// ready to read commands from the script buffer, set the flag stating
|
|
// that the commands are coming from the script file, and increment the
|
|
// scriptindex to point to the newly create script info.
|
|
//
|
|
|
|
CommandsFromScript = TRUE;
|
|
|
|
ScriptIndex = NextScriptIndex;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlFreeFileBuffers(
|
|
VOID
|
|
)
|
|
|
|
// ---------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// --------------
|
|
|
|
{
|
|
DWORD si = 0;
|
|
HANDLE tmpHandle;
|
|
DWORD Status;
|
|
|
|
for (si=0;si<TPCTL_MAX_SCRIPT_LEVELS;si++)
|
|
{
|
|
if ( Scripts[si].Buffer != NULL )
|
|
{
|
|
tmpHandle = GlobalFree( (HANDLE)Scripts[si].Buffer );
|
|
|
|
if ( tmpHandle != NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlFreeFileBuffers: GlobalFree failed: returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
}
|
|
}
|
|
|
|
Scripts[si].Buffer = NULL;
|
|
Scripts[si].Length = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlUnLoadFiles(
|
|
VOID
|
|
)
|
|
|
|
// ---------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// --------------
|
|
|
|
{
|
|
DWORD si;
|
|
HANDLE tmpHandle;
|
|
DWORD Status;
|
|
|
|
//
|
|
// TpctlUnloadFiles may be called to unload a file that is no longer
|
|
// needed, or a file that was not successfully loaded by TpctlLoadFiles.
|
|
// If the file to be unloaded is one that failed to load during the load
|
|
// files routine, then the ScriptIndex does not point to the correct
|
|
// field in the script array, so we must adjust the index pointer
|
|
// to the next field, otherwise just unload the file pointed by the
|
|
// ScriptIndex.
|
|
//
|
|
|
|
si = ScriptIndex;
|
|
|
|
if (( ScriptIndex < 0 ) || ( Scripts[si].IsLowestLevel == FALSE ))
|
|
{
|
|
si++;
|
|
}
|
|
|
|
//
|
|
// Free up the memory used to store the file names, and the
|
|
// script file commands.
|
|
//
|
|
|
|
if ( Scripts[si].ScriptFile != NULL )
|
|
{
|
|
tmpHandle = GlobalFree( Scripts[si].ScriptFile );
|
|
|
|
if ( tmpHandle != NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlUnLoadFiles: GlobalFree failed: returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
}
|
|
}
|
|
|
|
if ( Scripts[si].LogFile != NULL )
|
|
{
|
|
tmpHandle = GlobalFree( Scripts[si].LogFile );
|
|
|
|
if ( tmpHandle != NULL )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlUnLoadFiles: GlobalFree failed: returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Do we have a unique log file, or was the log file opened by a higher
|
|
// order recursion of the TpctlLoadFiles routine?
|
|
//
|
|
|
|
if (( Scripts[si].LogHandle != (HANDLE)-1 ) && // log handle exists
|
|
(( si == 0 ) || // first level of recursion
|
|
( Scripts[si].LogHandle != Scripts[si-1].LogHandle )))
|
|
{
|
|
|
|
//
|
|
// This level of the ReadScript command opened the log file, so
|
|
// we must close it now.
|
|
//
|
|
|
|
CloseHandle( Scripts[si].LogHandle );
|
|
}
|
|
|
|
//
|
|
// Now set all the fields to their intial state.
|
|
//
|
|
|
|
Scripts[si].ScriptFile = NULL;
|
|
Scripts[si].BufIndex = 0;
|
|
Scripts[si].LogHandle = (HANDLE)-1;
|
|
Scripts[si].LogFile = NULL;
|
|
Scripts[si].IsLowestLevel = FALSE;
|
|
|
|
//
|
|
// If we are simply unloading a script that we are finished with
|
|
// then decrement the index into the Scripts array to reference the
|
|
// next higher level, if it exists, in the ReadScript recursion.
|
|
// If we are unloading the highest level script file then reset
|
|
// the commandsfromscript flag to state that we no longer are
|
|
// reading the commands from a script file.
|
|
//
|
|
|
|
if ( si == ScriptIndex )
|
|
{
|
|
if ( --ScriptIndex == -1 )
|
|
{
|
|
CommandsFromScript = FALSE;
|
|
TpctlFreeFileBuffers();
|
|
}
|
|
}
|
|
|
|
if ( si != 0 )
|
|
{
|
|
Scripts[si-1].IsLowestLevel = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
HANDLE
|
|
TpctlOpenLogFile(
|
|
VOID
|
|
)
|
|
|
|
// -------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// ------------
|
|
|
|
{
|
|
HANDLE LogHandle;
|
|
DWORD Status;
|
|
|
|
if ( WriteThrough )
|
|
{
|
|
LogHandle = CreateFile( GlobalCmdArgs.ARGS.FILES.LogFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
LogHandle = CreateFile( GlobalCmdArgs.ARGS.FILES.LogFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
}
|
|
|
|
|
|
if ( LogHandle == (HANDLE)-1 )
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: failed to open log file\"%s\", ",
|
|
(PVOID)GlobalCmdArgs.ARGS.FILES.LogFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
}
|
|
|
|
return LogHandle;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlCloseLogFile(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
DWORD Status;
|
|
|
|
if (!CloseHandle( CommandLineLogHandle ))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctlCloseLogFile: failed to close Log file; returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
HANDLE
|
|
TpctlOpenScriptFile(
|
|
VOID
|
|
)
|
|
|
|
// ----------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Created Sanjeevk 7-1-93
|
|
//
|
|
// This is a new function defined for the purpose of opening up a file
|
|
// to which commands will be written
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Global Arguments effected:
|
|
//
|
|
// RecordScriptName
|
|
//
|
|
// Return Value:
|
|
//
|
|
// A HANDLE to the script file or NULL
|
|
//
|
|
// ---------------
|
|
|
|
{
|
|
HANDLE ScriptHandle;
|
|
DWORD Status;
|
|
|
|
|
|
//
|
|
// 1. Clear the global variable and copy in the name of the file
|
|
// to be opened
|
|
//
|
|
|
|
memset( RecordScriptName, 0, (TPCTL_MAX_PATHNAME_SIZE*sizeof(CHAR)) );
|
|
strcpy( RecordScriptName, GlobalCmdArgs.ARGS.RECORD.ScriptFile );
|
|
|
|
if ( WriteThrough )
|
|
{
|
|
ScriptHandle = CreateFile( GlobalCmdArgs.ARGS.RECORD.ScriptFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
ScriptHandle = CreateFile( GlobalCmdArgs.ARGS.RECORD.ScriptFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
}
|
|
|
|
|
|
if ( ScriptHandle == (HANDLE)-1 )
|
|
{
|
|
Status = GetLastError();
|
|
ZeroMemory( RecordScriptName, (TPCTL_MAX_PATHNAME_SIZE*sizeof(CHAR)) );
|
|
TpctlErrorLog("\n\tTpctl: failed to open script recording file\"%s\", ",
|
|
(PVOID)GlobalCmdArgs.ARGS.RECORD.ScriptFile);
|
|
TpctlErrorLog("returned 0x%lx.\n",(PVOID)Status);
|
|
}
|
|
|
|
return ScriptHandle;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlCloseScriptFile(
|
|
VOID
|
|
)
|
|
|
|
// ---------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Created Sanjeevk 7-1-93
|
|
//
|
|
// This is a new function defined for the purpose of closing a file
|
|
// to which commands were being written
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Global Arguments effected:
|
|
//
|
|
// RecordScriptName
|
|
// ScriptRecordHandle
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// ---------------
|
|
|
|
{
|
|
DWORD Status;
|
|
|
|
ZeroMemory( RecordScriptName, (TPCTL_MAX_PATHNAME_SIZE*sizeof(CHAR)) );
|
|
|
|
if (!CloseHandle( ScriptRecordHandle ))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog(
|
|
"\n\tTpctlCloseScriptFile: failed to close script record file; returned 0x%lx.\n",
|
|
(PVOID)Status);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
TpctlReadCommand(
|
|
IN LPSTR Prompt,
|
|
OUT LPSTR Buffer,
|
|
IN DWORD MaximumResponse
|
|
)
|
|
|
|
// --------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine reads from the debug port or the command file one command.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// IN LPSTR Prompt,
|
|
// OUT LPSTR Buffer,
|
|
// IN DWORD MaximumResponse,
|
|
//
|
|
// Return Value:
|
|
//
|
|
// DWORD - NO_ERROR
|
|
//
|
|
// -------------
|
|
|
|
{
|
|
DWORD Status = NO_ERROR;
|
|
LPSTR CmdBufPtr = Buffer;
|
|
DWORD i, j, k;
|
|
BYTE LineBuf[TPCTL_CMDLINE_SIZE];
|
|
BYTE TmpBuf[TPCTL_CMDLINE_SIZE];
|
|
LPBYTE EndOfCmd;
|
|
LPBYTE SBuf;
|
|
BOOL ContinueCommand = FALSE;
|
|
BOOL InitialCommand = TRUE;
|
|
BOOL FoundEnvVar;
|
|
LPSTR EnvVar;
|
|
|
|
//
|
|
// If the ScriptIndex equals -1 we are reading commands from the
|
|
// command line, so we will prompt the user to enter commands.
|
|
//
|
|
|
|
if ( ScriptIndex == -1 )
|
|
{
|
|
TpctlPrompt( Prompt,LineBuf,MaximumResponse );
|
|
|
|
i = 0; // LineBuf index
|
|
k = 0; // Buffer index
|
|
|
|
while (( i < TPCTL_CMDLINE_SIZE ) &&
|
|
(( LineBuf[i] != '\n' ) &&
|
|
( LineBuf[i] != '\r' )))
|
|
{
|
|
//
|
|
// If we have found the beginning of an Environment
|
|
// Variable argument
|
|
//
|
|
|
|
if ( LineBuf[i] == '%' )
|
|
{
|
|
j = (DWORD)-1;
|
|
FoundEnvVar = FALSE;
|
|
i++;
|
|
|
|
//
|
|
// Copy it into a temp buffer.
|
|
//
|
|
|
|
while (( LineBuf[i] != '\n' ) &&
|
|
(( LineBuf[i] != ' ' ) &&
|
|
(( LineBuf[i] != '\t' ) &&
|
|
( LineBuf[i] != '\r' ))))
|
|
{
|
|
TmpBuf[++j] = LineBuf[i++];
|
|
|
|
if ( TmpBuf[j] == '%')
|
|
{
|
|
TmpBuf[j] = '\0';
|
|
FoundEnvVar = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TmpBuf[j] = '\0';
|
|
|
|
//
|
|
// And find its true value in the process environment.
|
|
//
|
|
|
|
if ( FoundEnvVar == TRUE )
|
|
{
|
|
EnvVar = getenv( _strupr( TmpBuf ));
|
|
|
|
if ( EnvVar == NULL )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Undefined Environment Variable \"%%%s%%\".\n",
|
|
TmpBuf);
|
|
return ERROR_ENVVAR_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// and copy the value to the line buffer.
|
|
//
|
|
|
|
do
|
|
{
|
|
Buffer[k++] = *EnvVar++;
|
|
} while ( *EnvVar != '\0' );
|
|
|
|
}
|
|
else
|
|
{
|
|
TmpBuf[++j] = '\0';
|
|
TpctlErrorLog("\n\tTpctl: Invalid Environment Variable Format \"%%%s\".\n",
|
|
TmpBuf);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Otherwise just copy the next character to the line buffer.
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
Buffer[k++] = LineBuf[i++];
|
|
}
|
|
}
|
|
|
|
//
|
|
// and then print the commands to the log file if necessary.
|
|
//
|
|
|
|
TpctlCmdLneLog(" %s\n", Buffer);
|
|
|
|
//
|
|
// Otherwise we are reading commands from a script file, so return
|
|
// the next command in the file.
|
|
//
|
|
|
|
}
|
|
else if ( Scripts[ScriptIndex].BufIndex >= Scripts[ScriptIndex].Length )
|
|
{
|
|
//
|
|
// We are at the end of this script file, clean up the script
|
|
// and log files.
|
|
//
|
|
|
|
TpctlUnLoadFiles();
|
|
|
|
//
|
|
// Set the return value in Buffer to null indicating that
|
|
// there was no command.
|
|
//
|
|
|
|
*Buffer = 0x0;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Null out the Buffer buffer so that we don't use any garbage
|
|
// laying around from the last command.
|
|
//
|
|
|
|
ZeroMemory(Buffer, TPCTL_CMDLINE_SIZE);
|
|
|
|
SBuf = Scripts[ScriptIndex].Buffer;
|
|
|
|
while ((DWORD)(CmdBufPtr - Buffer) < MaximumResponse )
|
|
{
|
|
//
|
|
// and null out the temporary command buffer.
|
|
//
|
|
|
|
ZeroMemory(LineBuf, TPCTL_CMDLINE_SIZE);
|
|
|
|
//
|
|
// Read the next command line from the script file.
|
|
//
|
|
|
|
i = (DWORD)-1;
|
|
|
|
while ( Scripts[ScriptIndex].BufIndex <
|
|
Scripts[ScriptIndex].Length )
|
|
{
|
|
//
|
|
// If we have found the beginning of an Environment
|
|
// Variable argument...
|
|
//
|
|
|
|
if ( SBuf[Scripts[ScriptIndex].BufIndex] == '%' )
|
|
{
|
|
j = (DWORD)-1;
|
|
FoundEnvVar = FALSE;
|
|
Scripts[ScriptIndex].BufIndex++;
|
|
|
|
//
|
|
// Copy it into a temp buffer.
|
|
//
|
|
|
|
while (( SBuf[Scripts[ScriptIndex].BufIndex] != '\n' ) &&
|
|
(( SBuf[Scripts[ScriptIndex].BufIndex] != ' ' ) &&
|
|
(( SBuf[Scripts[ScriptIndex].BufIndex] != '\t' ) &&
|
|
( SBuf[Scripts[ScriptIndex].BufIndex] != '\r' ))))
|
|
{
|
|
TmpBuf[++j] = SBuf[Scripts[ScriptIndex].BufIndex++];
|
|
|
|
if ( TmpBuf[j] == '%')
|
|
{
|
|
TmpBuf[j] = '\0';
|
|
FoundEnvVar = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// And find its true value in the process environment.
|
|
//
|
|
|
|
if ( FoundEnvVar == TRUE )
|
|
{
|
|
EnvVar = getenv( _strupr( TmpBuf ));
|
|
|
|
if ( EnvVar == NULL )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Undefined Environment Variable \"%%%s%%\".\n",
|
|
TmpBuf);
|
|
return ERROR_ENVVAR_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// and copy the value to the line buffer.
|
|
//
|
|
|
|
do
|
|
{
|
|
LineBuf[++i] = *EnvVar++;
|
|
} while ( *EnvVar != '\0' );
|
|
|
|
}
|
|
else
|
|
{
|
|
TmpBuf[++j] = '\0';
|
|
TpctlErrorLog("\n\tTpctl: Invalid Environment Variable Format \"%%%s\".\n",
|
|
TmpBuf);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Otherwise just copy the next character to the line buffer.
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
LineBuf[++i] = SBuf[Scripts[ScriptIndex].BufIndex++];
|
|
}
|
|
|
|
if ( LineBuf[i] == '\n' )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
LineBuf[i] = '\0';
|
|
|
|
if ( InitialCommand == TRUE )
|
|
{
|
|
TpctlLog("%s ",Prompt);
|
|
InitialCommand = FALSE;
|
|
}
|
|
else
|
|
{
|
|
TpctlLog("\t ",NULL );
|
|
}
|
|
|
|
TpctlLog("%s\n",LineBuf);
|
|
|
|
if ( !Verbose )
|
|
{
|
|
if ( strstr( LineBuf,"TITLE:" ) != NULL )
|
|
{
|
|
TpctlErrorLog("\n%s ",Prompt);
|
|
TpctlErrorLog("%s\n\n",LineBuf);
|
|
}
|
|
}
|
|
|
|
// check for comment ending line
|
|
|
|
ContinueCommand = FALSE;
|
|
if ( (EndOfCmd = strchr( LineBuf, '#')) != NULL)
|
|
{
|
|
//
|
|
// We just have a comment, set the command continue
|
|
// flag to exit the command parsing, and null the
|
|
// command section of the string.
|
|
//
|
|
EndOfCmd[0] = '\0';
|
|
}
|
|
|
|
// check for a closing parenthesis on line. This is the end of any SETGLOBALS
|
|
// command that contains an expression. No other command uses parenthesis
|
|
|
|
if ( (EndOfCmd = strchr( LineBuf, ')' )) != NULL)
|
|
{
|
|
EndOfCmd[1] = '\0'; // closing parenthese is last thing on line
|
|
}
|
|
else if ( (EndOfCmd = strchr( LineBuf, '+' )) != NULL)
|
|
{
|
|
//
|
|
// This is a Cmd Continuation, set the flag to continue
|
|
// the while loop, and ignore the rest of the line.
|
|
//
|
|
ContinueCommand = TRUE;
|
|
EndOfCmd[0] = '\0';
|
|
}
|
|
|
|
i=0;
|
|
|
|
while ( LineBuf[i] != '\0' )
|
|
{
|
|
if ((( LineBuf[i] == ' ' ) ||
|
|
( LineBuf[i] == '\t' )) ||
|
|
( LineBuf[i] == '\r' ))
|
|
{
|
|
*CmdBufPtr++ = ' ';
|
|
|
|
while ((( LineBuf[i] == ' ' ) ||
|
|
( LineBuf[i] == '\t' )) ||
|
|
( LineBuf[i] == '\r' ))
|
|
{
|
|
i++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
*CmdBufPtr++ = LineBuf[i++];
|
|
}
|
|
}
|
|
|
|
if ( ContinueCommand == FALSE )
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
TpctlParseCommand(
|
|
IN LPSTR CommandLine,
|
|
OUT LPSTR Argv[],
|
|
OUT PDWORD Argc,
|
|
IN DWORD MaxArgc
|
|
)
|
|
{
|
|
LPSTR cl = CommandLine;
|
|
DWORD ac = 0;
|
|
BOOL DoubleQuotesDetected, DetectedEndOfString, StartOfString;
|
|
|
|
while ( *cl && (ac < MaxArgc) )
|
|
{
|
|
//
|
|
// Skip to get to the lvalue
|
|
//
|
|
while ( *cl && (*cl <= ' ') ) // ignore leading blanks
|
|
{
|
|
cl++;
|
|
}
|
|
|
|
if ( !*cl )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Argument detected. Initialize the Argv and increment the counter
|
|
//
|
|
|
|
*Argv++ = cl;
|
|
++ac;
|
|
|
|
DoubleQuotesDetected = DetectedEndOfString = FALSE;
|
|
StartOfString = TRUE;
|
|
|
|
while( !DetectedEndOfString )
|
|
{
|
|
while ( *cl > ' ')
|
|
{
|
|
if ( StartOfString && (*cl == '"') && (*(cl-1) == '=') )
|
|
{
|
|
DoubleQuotesDetected = TRUE;
|
|
StartOfString = FALSE;
|
|
}
|
|
cl++;
|
|
}
|
|
|
|
if ( DoubleQuotesDetected )
|
|
{
|
|
if ( ((*(cl-1) == '"') && (*(cl-2) != '\\')) ||
|
|
( *cl != ' ' ) )
|
|
{
|
|
DetectedEndOfString = TRUE;
|
|
}
|
|
else
|
|
{
|
|
cl++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DetectedEndOfString = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( *cl )
|
|
{
|
|
*cl++ = '\0';
|
|
}
|
|
|
|
}
|
|
|
|
if ( ac < MaxArgc )
|
|
{
|
|
*Argv++ = NULL;
|
|
}
|
|
else if ( *cl )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: Too many tokens in command; \"%s\".\n",(PVOID)cl);
|
|
return FALSE;
|
|
}
|
|
|
|
*Argc = ac;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlPrompt(
|
|
LPSTR Prompt,
|
|
LPSTR Buffer,
|
|
DWORD BufferSize
|
|
)
|
|
|
|
// -----------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Prompt -
|
|
// Buffer -
|
|
// BufferSize -
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// ----------
|
|
|
|
{
|
|
LPSTR NewLine;
|
|
DWORD ReadAmount;
|
|
|
|
//
|
|
// print out the prompt command, and then read the user's input.
|
|
// We are using the TpctlErrorLog routine to print it to the
|
|
// screen and the log files because we know that verbose mode
|
|
//
|
|
|
|
TpctlErrorLog("%s ",Prompt);
|
|
|
|
ReadFile( GetStdHandle(STD_INPUT_HANDLE),
|
|
(LPVOID )Buffer,
|
|
BufferSize,
|
|
&ReadAmount,
|
|
NULL );
|
|
|
|
//
|
|
// If the user typed <CR>, then the buffer contains a single
|
|
// <CR> character. We want to remove this character, and replace it with
|
|
// a nul character.
|
|
//
|
|
|
|
if ( (NewLine = strchr(Buffer, '\r')) != NULL )
|
|
{
|
|
*NewLine = '\0';
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlLoadLastEnvironmentVariables(
|
|
DWORD OpenInstance
|
|
)
|
|
|
|
// --------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// -------------
|
|
|
|
{
|
|
GlobalCmdArgs.ARGS.ENV.WindowSize =
|
|
Open[OpenInstance].EnvVars->WindowSize;
|
|
|
|
GlobalCmdArgs.ARGS.ENV.RandomBufferNumber =
|
|
Open[OpenInstance].EnvVars->RandomBufferNumber;
|
|
|
|
GlobalCmdArgs.ARGS.ENV.StressDelayInterval =
|
|
Open[OpenInstance].EnvVars->StressDelayInterval;
|
|
|
|
GlobalCmdArgs.ARGS.ENV.UpForAirDelay =
|
|
Open[OpenInstance].EnvVars->UpForAirDelay;
|
|
|
|
GlobalCmdArgs.ARGS.ENV.StandardDelay =
|
|
Open[OpenInstance].EnvVars->StandardDelay;
|
|
|
|
strcpy( GlobalCmdArgs.ARGS.ENV.StressAddress,
|
|
Open[OpenInstance].EnvVars->StressAddress );
|
|
|
|
strcpy( GlobalCmdArgs.ARGS.ENV.ResendAddress,
|
|
Open[OpenInstance].EnvVars->ResendAddress );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlSaveNewEnvironmentVariables(
|
|
DWORD OpenInstance
|
|
)
|
|
|
|
// ---------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
// -------------
|
|
|
|
{
|
|
Open[OpenInstance].EnvVars->WindowSize =
|
|
GlobalCmdArgs.ARGS.ENV.WindowSize;
|
|
|
|
Open[OpenInstance].EnvVars->WindowSize =
|
|
GlobalCmdArgs.ARGS.ENV.RandomBufferNumber;
|
|
|
|
Open[OpenInstance].EnvVars->StressDelayInterval =
|
|
GlobalCmdArgs.ARGS.ENV.StressDelayInterval;
|
|
|
|
Open[OpenInstance].EnvVars->UpForAirDelay =
|
|
GlobalCmdArgs.ARGS.ENV.UpForAirDelay;
|
|
|
|
Open[OpenInstance].EnvVars->StandardDelay =
|
|
GlobalCmdArgs.ARGS.ENV.StandardDelay;
|
|
|
|
strcpy( Open[OpenInstance].EnvVars->StressAddress,
|
|
GlobalCmdArgs.ARGS.ENV.StressAddress );
|
|
|
|
strcpy( Open[OpenInstance].EnvVars->ResendAddress,
|
|
GlobalCmdArgs.ARGS.ENV.ResendAddress );
|
|
}
|
|
|
|
|
|
// !!check calls here for WIN32!!
|
|
|
|
VOID
|
|
TpctlPerformRegistryOperation(
|
|
IN PCMD_ARGS CmdArgs
|
|
)
|
|
{
|
|
DWORD Status,ValueType,ValueSize ;
|
|
DWORD ReadValueType, ReadValueSize;
|
|
DWORD Disposition , BytesWritten ;
|
|
PUCHAR ReadValue = NULL ;
|
|
UCHAR PrintStringBuffer[10], TmpChar;
|
|
HKEY DbaseHKey, KeyHandle ;
|
|
REGSAM SamDesired ;
|
|
LPSTR TmpBuf = GlobalBuf, StopString ;
|
|
LPSTR SubKeyName = &CmdArgs->ARGS.REGISTRY_ENTRY.SubKey[1] ;
|
|
LPSTR ValueName = &CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyValueName[1];
|
|
LPSTR Value = CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyValue ;
|
|
LPSTR DbaseName = KeyDbaseTable[CmdArgs->ARGS.REGISTRY_ENTRY.OperationType].FieldName;
|
|
LPSTR ClassName = &CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyClass[1] ;
|
|
LPSTR Tmp = NULL;
|
|
BOOL CompleteQueryStatus;
|
|
INT i,j,k,Radix = 16,CopyLength = 2;
|
|
|
|
|
|
TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCommandCode = %s\n",
|
|
TpctlGetCmdCode( CmdArgs->CmdCode ));
|
|
|
|
//
|
|
// Initialize and allocate resources
|
|
//
|
|
|
|
if ( (ReadValue = calloc( 2, MAX_VALUE_LENGTH )) == NULL )
|
|
{
|
|
TpctlErrorLog( "\n\tTpctl: TpctlPeformRegistryOperation: Unable to allocate memory resources\n", NULL );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Clear and write the buffer responsible for extracting the values
|
|
//
|
|
|
|
ZeroMemory ( PrintStringBuffer, sizeof( PrintStringBuffer ) );
|
|
sprintf( PrintStringBuffer, "%%%d.%dx", sizeof(DWORD), sizeof(DWORD) );
|
|
|
|
//
|
|
// Set the appropriate DataBase key
|
|
//
|
|
|
|
switch( CmdArgs->ARGS.REGISTRY_ENTRY.KeyDatabase )
|
|
{
|
|
case CLASSES_ROOT :
|
|
DbaseHKey = HKEY_CLASSES_ROOT;
|
|
break;
|
|
|
|
case CURRENT_USER :
|
|
DbaseHKey = HKEY_CURRENT_USER;
|
|
break;
|
|
|
|
case LOCAL_MACHINE:
|
|
DbaseHKey = HKEY_LOCAL_MACHINE;
|
|
break;
|
|
|
|
case USERS:
|
|
DbaseHKey = HKEY_USERS;
|
|
break;
|
|
|
|
default:
|
|
TpctlErrorLog("\n\tTpctl: %d not a valid Key DataBase",
|
|
(PVOID)CmdArgs->ARGS.REGISTRY_ENTRY.KeyDatabase );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// The SubKey Name
|
|
// The Value name
|
|
// The Class Name
|
|
//
|
|
if ( (Tmp = strrchr( SubKeyName, '"' )) != NULL )
|
|
{
|
|
*Tmp = '\0';
|
|
}
|
|
if ( (Tmp = strrchr( ValueName, '"' )) != NULL )
|
|
{
|
|
*Tmp = '\0';
|
|
}
|
|
if ( (Tmp = strrchr( ClassName, '"' )) != NULL )
|
|
{
|
|
*Tmp = '\0';
|
|
}
|
|
|
|
//
|
|
// The value type and the associated value
|
|
//
|
|
|
|
switch( CmdArgs->ARGS.REGISTRY_ENTRY.ValueType )
|
|
{
|
|
case BINARY :
|
|
ValueType = REG_BINARY;
|
|
i = 0;
|
|
j = 0; // Default begin extraction from String[j=0]:Value buffer starting point
|
|
k = 0; // Default:Input Value is in hex or binary - designator.
|
|
// 0 is HEX, 1 is BINARY
|
|
ValueSize = strlen( Value );
|
|
if( ValueSize >= 2 )
|
|
{
|
|
if ( toupper( Value[1] ) == 'B' )
|
|
{
|
|
j = 2;
|
|
k = 1;
|
|
Radix = 2;
|
|
CopyLength = 8;
|
|
}
|
|
}
|
|
{
|
|
UCHAR BitStream[9];
|
|
PUCHAR PTmpChar;
|
|
DWORD BytesToCopy;
|
|
|
|
while( j < (INT)ValueSize )
|
|
{
|
|
memset( BitStream, '\0', sizeof( BitStream ) );
|
|
memset( BitStream, '0' , sizeof(UCHAR)*CopyLength );
|
|
BytesToCopy = min( strlen( &Value[j] ), (DWORD)CopyLength );
|
|
memcpy( BitStream, &Value[j], BytesToCopy );
|
|
Value[i] = (UCHAR)strtoul( BitStream,&PTmpChar, Radix );
|
|
i++;
|
|
j += BytesToCopy;
|
|
}
|
|
ValueSize = i;
|
|
}
|
|
break;
|
|
|
|
case DWORD_REGULAR :
|
|
ValueType = REG_DWORD;
|
|
ValueSize = sizeof( DWORD );
|
|
*(LPDWORD)Value = strtoul( Value, &StopString, 0 );
|
|
break;
|
|
|
|
case DWORD_LITTLE_ENDIAN :
|
|
ValueType = REG_DWORD_LITTLE_ENDIAN;
|
|
ValueSize = sizeof( DWORD );
|
|
{
|
|
DWORD TmpValue = strtoul( Value, &StopString, 0 );
|
|
sprintf( Value, PrintStringBuffer, TmpValue );
|
|
}
|
|
// Reverse the array since this is Big Endian
|
|
|
|
for( i = 0, j = ValueSize-1; i < (INT)ValueSize; i++,j-- )
|
|
{
|
|
Value[i] -= '0';
|
|
Value[j] -= '0';
|
|
TmpChar = Value[i];
|
|
Value[i] = Value[j];
|
|
Value[j] = TmpChar;
|
|
}
|
|
break;
|
|
|
|
case DWORD_BIG_ENDIAN :
|
|
ValueType = REG_DWORD_BIG_ENDIAN;
|
|
ValueSize = sizeof( DWORD );
|
|
{
|
|
DWORD TmpValue = strtoul( Value, &StopString, 0 );
|
|
sprintf( Value, PrintStringBuffer, TmpValue );
|
|
}
|
|
break;
|
|
|
|
case EXPAND_SZ :
|
|
ValueType = REG_EXPAND_SZ;
|
|
ValueSize = strlen( Value );
|
|
break;
|
|
|
|
case LINK :
|
|
ValueType = REG_LINK;
|
|
ValueSize = strlen( Value );
|
|
break;
|
|
|
|
case MULTI_SZ :
|
|
ValueType = REG_MULTI_SZ;
|
|
|
|
//
|
|
// The string Value needs to be readjusted. Use ReadValue as a temporary
|
|
// buffer
|
|
|
|
memset( ReadValue, 0, 2*MAX_VALUE_LENGTH );
|
|
{
|
|
UCHAR CanCopy = 0x0;
|
|
BOOL IgnoreNext = FALSE;
|
|
|
|
for( i = 0, j = 0 ; i < (INT)strlen( Value ); i++ )
|
|
{
|
|
if ( ( Value[i] == '"' ) && ( IgnoreNext == FALSE ) )
|
|
{
|
|
CanCopy = ~CanCopy;
|
|
if ( !CanCopy )
|
|
{
|
|
ReadValue[j++] = '\0';
|
|
}
|
|
}
|
|
if ( Value[i] == '\\' )
|
|
{
|
|
IgnoreNext = TRUE;
|
|
}
|
|
else
|
|
{
|
|
IgnoreNext = FALSE;
|
|
}
|
|
if ( CanCopy )
|
|
{
|
|
ReadValue[j++] = Value[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fill the 2 nulls at the end of the array
|
|
//
|
|
|
|
ReadValue[j++] = '\0';ReadValue[j++] = '\0';
|
|
ValueSize = j;
|
|
memcpy( Value, ReadValue, j );
|
|
memset( ReadValue, 0, 2*MAX_VALUE_LENGTH );
|
|
break;
|
|
|
|
case NONE :
|
|
ValueType = REG_NONE;
|
|
ValueSize = strlen( Value );
|
|
break;
|
|
|
|
case RESOURCE_LIST :
|
|
ValueType = REG_RESOURCE_LIST;
|
|
ValueSize = strlen( Value );
|
|
break;
|
|
|
|
case SZ :
|
|
ValueType = REG_SZ;
|
|
ValueSize = strlen( Value );
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Switch to the demanded operation
|
|
//
|
|
|
|
switch ( CmdArgs->ARGS.REGISTRY_ENTRY.OperationType )
|
|
{
|
|
case ADD_KEY:
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = ADD_KEY\n" );
|
|
|
|
SamDesired = KEY_ALL_ACCESS;
|
|
|
|
Status = RegCreateKeyEx( DbaseHKey, SubKeyName, (DWORD)0,
|
|
ClassName, REG_OPTION_NON_VOLATILE,
|
|
SamDesired, NULL, &KeyHandle, &Disposition );
|
|
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to create\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = SUCCESS\n" );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tDisposition = " );
|
|
|
|
if ( Disposition == REG_CREATED_NEW_KEY )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "CREATED A NEW KEY\n" );
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "KEY ALREADY EXISTS\n" );
|
|
}
|
|
break;
|
|
|
|
case DELETE_KEY:
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = DELETE_KEY\n" );
|
|
|
|
Status = RegDeleteKey( DbaseHKey, SubKeyName );
|
|
if ( Status != ERROR_SUCCESS ) {
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to delete\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = SUCCESS\n" );
|
|
break;
|
|
|
|
|
|
case QUERY_KEY:
|
|
|
|
CompleteQueryStatus = TRUE;
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = QUERY_KEY\n" );
|
|
|
|
//
|
|
// Open the Registry Key
|
|
//
|
|
|
|
SamDesired = KEY_READ;
|
|
|
|
Status = RegOpenKeyEx( DbaseHKey, SubKeyName, (DWORD)0, SamDesired, &KeyHandle );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to open\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
{
|
|
LPSTR TmpKeyClassName = NULL, TmpSubKeyName = NULL, TmpValueName = NULL;
|
|
DWORD NumberOfSubKeys, NumberOfValues, TmpValueType, ClassNameSize;
|
|
DWORD TmpDwordVar, LongestSubKeyNameSize, LongestSubKeyClassNameSize;
|
|
DWORD LongestValueNameSize;
|
|
FILETIME LastWriteTime;
|
|
SYSTEMTIME SystemTime;
|
|
CHAR *DayOfWeek[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
|
"Friday", "Saturday" };
|
|
|
|
if ( (TmpKeyClassName = calloc( 1, MAX_PATH+1 )) == NULL )
|
|
{
|
|
TpctlErrorLog(
|
|
"\n\tTpctl: TpctlPeformRegistryOperation: QueryKey unable to allocate memory resources\n",
|
|
NULL );
|
|
return;
|
|
}
|
|
|
|
ClassNameSize = MAX_PATH+1;
|
|
Status = RegQueryInfoKey( KeyHandle, TmpKeyClassName, &ClassNameSize,
|
|
NULL, &NumberOfSubKeys, &LongestSubKeyNameSize,
|
|
&LongestSubKeyClassNameSize, &NumberOfValues,
|
|
&LongestValueNameSize,
|
|
&TmpDwordVar, &TmpDwordVar, &LastWriteTime );
|
|
|
|
if ( (Status == ERROR_MORE_DATA) || (Status == ERROR_INSUFFICIENT_BUFFER) )
|
|
{
|
|
free( TmpKeyClassName );
|
|
if ( (TmpKeyClassName = calloc( 1, ClassNameSize+2 )) == NULL )
|
|
{
|
|
TpctlErrorLog( "\n\tTpctl: TpctlPeformRegistryOperation: QueryKey unable to allocate memory resources\n", NULL );
|
|
return;
|
|
}
|
|
Status = RegQueryInfoKey( KeyHandle, TmpKeyClassName, &ClassNameSize,
|
|
NULL, &NumberOfSubKeys, &LongestSubKeyNameSize,
|
|
&LongestSubKeyClassNameSize, &NumberOfValues,
|
|
&LongestValueNameSize,
|
|
&TmpDwordVar, &TmpDwordVar, &LastWriteTime );
|
|
}
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to QueryInfo on\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
}
|
|
|
|
TmpBuf += sprintf( TmpBuf,
|
|
"\tKey Class Name = %s\n\tNumber Of SubKeys = %ld\n\tNumber of Values = %ld\n",
|
|
TmpKeyClassName, NumberOfSubKeys, NumberOfValues );
|
|
|
|
if ( FileTimeToSystemTime( &LastWriteTime, &SystemTime ) )
|
|
{
|
|
TmpBuf += sprintf( TmpBuf,
|
|
"\tLast Write Time = %s %2.2d-%2.2d-%4.4d at %2.2d:%2.2d:%2.2d %s\n",
|
|
DayOfWeek[SystemTime.wDayOfWeek],
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wYear,
|
|
((SystemTime.wHour > 12) ? (SystemTime.wHour-12)
|
|
: SystemTime.wHour),
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond,
|
|
((SystemTime.wHour > 12) ? "AM" : "PM") );
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "\tLast Write Time = Undefined\n" );
|
|
}
|
|
|
|
free( TmpKeyClassName );
|
|
|
|
if ( (TmpSubKeyName = calloc( 1, LongestSubKeyNameSize+2 )) == NULL )
|
|
{
|
|
TpctlErrorLog( "\n\tTpctl: TpctlPeformRegistryOperation: QueryKey unable to allocate memory resources\n", NULL );
|
|
return;
|
|
}
|
|
|
|
TmpBuf += sprintf( TmpBuf, "\tSub Key Name(s)\n" );
|
|
|
|
for( i = 0; i < (INT)NumberOfSubKeys; i++ )
|
|
{
|
|
memset( TmpSubKeyName, 0, LongestSubKeyNameSize+2 );
|
|
Status = RegEnumKey( KeyHandle, i, TmpSubKeyName, LongestSubKeyNameSize+2 );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to Enumerate Key Index %d from\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
i, SubKeyName, ClassName, DbaseName );
|
|
CompleteQueryStatus = FALSE;
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "\t%2d.\t%s\n", i, TmpSubKeyName );
|
|
}
|
|
}
|
|
|
|
free( TmpSubKeyName );
|
|
|
|
if ( (TmpValueName = calloc( 1, LongestValueNameSize+2 )) == NULL )
|
|
{
|
|
TpctlErrorLog( "\n\tTpctl: TpctlPeformRegistryOperation: QueryKey unable to allocate memory resources\n", NULL );
|
|
return;
|
|
}
|
|
|
|
TmpBuf += sprintf( TmpBuf, "\tSub Key Value Name(s) and Associated Type(s)\n" );
|
|
|
|
for( i = 0; i < (INT)NumberOfValues; i++ )
|
|
{
|
|
memset( TmpValueName, 0, LongestValueNameSize+2 );
|
|
TmpDwordVar = LongestValueNameSize+2;
|
|
Status = RegEnumValue( KeyHandle, i, TmpValueName, &TmpDwordVar, NULL,
|
|
&TmpValueType, NULL, NULL );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to Enumerate Value Index %d from\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
i, SubKeyName, ClassName, DbaseName );
|
|
CompleteQueryStatus = FALSE;
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += sprintf( TmpBuf,
|
|
"\t%2d.\t%-30s%-15s\n", i, TmpValueName, TpctlGetValueType( TmpValueType ) );
|
|
|
|
}
|
|
}
|
|
|
|
free( TmpValueName );
|
|
|
|
}
|
|
|
|
if ( CompleteQueryStatus )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tComplete Query Status = SUCCESS\n" );
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tComplete Query Status = FAILURE\n" );
|
|
}
|
|
break;
|
|
|
|
case ADD_VALUE:
|
|
case CHANGE_VALUE:
|
|
if ( CmdArgs->ARGS.REGISTRY_ENTRY.OperationType == CHANGE_VALUE )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = CHANGE_VALUE\n" );
|
|
SamDesired = KEY_WRITE|KEY_READ;
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = ADD_VALUE\n" );
|
|
SamDesired = KEY_ALL_ACCESS;
|
|
}
|
|
|
|
|
|
Status = RegOpenKeyEx( DbaseHKey, SubKeyName, (DWORD)0, SamDesired, &KeyHandle );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to open\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// If this is a request to change a value, make sure that the value exists
|
|
//
|
|
|
|
if ( CmdArgs->ARGS.REGISTRY_ENTRY.OperationType == CHANGE_VALUE )
|
|
{
|
|
//
|
|
// Make sure the ValueName exist since this is a change request
|
|
//
|
|
ReadValueSize = 2*MAX_VALUE_LENGTH;
|
|
ReadValueType = ValueType;
|
|
Status = RegQueryValueEx( KeyHandle, ValueName, (DWORD)0, &ReadValueType,
|
|
ReadValue, &ReadValueSize );
|
|
if ( (Status != ERROR_SUCCESS) &&
|
|
(Status != ERROR_MORE_DATA) &&
|
|
(Status != ERROR_INSUFFICIENT_BUFFER) )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to access\n\tValue : %s\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
ValueName, SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now set the values as expected
|
|
//
|
|
Status = RegSetValueEx( KeyHandle, ValueName, (DWORD)0, ValueType, Value, ValueSize );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to change\n\tValue : %s\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
ValueName, SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = SUCCESS\n" );
|
|
break;
|
|
|
|
|
|
case DELETE_VALUE:
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = DELETE_VALUE\n" );
|
|
|
|
//
|
|
// Open the Registry Key
|
|
//
|
|
SamDesired = KEY_SET_VALUE;
|
|
|
|
Status = RegOpenKeyEx( DbaseHKey, SubKeyName, (DWORD)0, SamDesired, &KeyHandle );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to open\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
Status = RegDeleteValue( KeyHandle, ValueName );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to delete\n\tValue : %s\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
ValueName, SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = SUCCESS\n" );
|
|
break;
|
|
|
|
case QUERY_VALUE:
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tSubCommandCode = QUERY_VALUE\n" );
|
|
|
|
//
|
|
// Open the Registry Key
|
|
//
|
|
SamDesired = KEY_QUERY_VALUE;
|
|
|
|
Status = RegOpenKeyEx( DbaseHKey, SubKeyName, (DWORD)0, SamDesired, &KeyHandle );
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to open\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure the ValueName exist since this is a change request
|
|
//
|
|
|
|
ReadValueSize = 2*MAX_VALUE_LENGTH;
|
|
Status = RegQueryValueEx( KeyHandle, ValueName, (DWORD)0, &ReadValueType,
|
|
ReadValue, &ReadValueSize );
|
|
|
|
if ( (Status == ERROR_MORE_DATA) || (Status == ERROR_INSUFFICIENT_BUFFER) )
|
|
{
|
|
free( ReadValue );
|
|
ReadValue = NULL;
|
|
ReadValue = calloc( 1, ReadValueSize+1 );
|
|
if ( ReadValue == NULL )
|
|
{
|
|
TpctlErrorLog(
|
|
"\n\tTpctl: TpctlPeformRegistryOperation: QueryValue unable to allocate memory resources\n",
|
|
NULL );
|
|
return;
|
|
}
|
|
Status = RegQueryValueEx( KeyHandle, ValueName, (DWORD)0, &ReadValueType,
|
|
ReadValue, &ReadValueSize );
|
|
}
|
|
|
|
if ( Status != ERROR_SUCCESS )
|
|
{
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,"\tStatus = %ldL\n", Status );
|
|
TmpBuf += (BYTE)sprintf( TmpBuf,
|
|
"\n\tTpctl: Unable to access\n\tValue : %s\n\tSubkey : %s\n\tClassName: %s\n\tDatabase : %s\n",
|
|
ValueName, SubKeyName, ClassName, DbaseName );
|
|
break;
|
|
|
|
}
|
|
|
|
TmpBuf += (BYTE)sprintf( TmpBuf, "\tStatus = SUCCESS\n" );
|
|
TmpBuf = TpctlEnumerateRegistryInfo( TmpBuf, DbaseName, SubKeyName, ValueName,
|
|
ReadValueType, ReadValue, ReadValueSize );
|
|
break;
|
|
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Close any open keys and deallocate any allocated resources
|
|
//
|
|
|
|
RegCloseKey( KeyHandle );
|
|
free( ReadValue );
|
|
|
|
|
|
//
|
|
// Print the buffer
|
|
//
|
|
|
|
if ( Verbose )
|
|
{
|
|
if ( !WriteFile(GetStdHandle( STD_OUTPUT_HANDLE ),
|
|
GlobalBuf,
|
|
TmpBuf-GlobalBuf,
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: WriteFile to screen failed, returned 0x%lx\n",(PVOID)Status);
|
|
}
|
|
}
|
|
|
|
if ( CommandsFromScript )
|
|
{
|
|
if ( !WriteFile(Scripts[ScriptIndex].LogHandle,
|
|
GlobalBuf,
|
|
TmpBuf-GlobalBuf,
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: WriteFile to logfile failed, returned 0x%lx\n",(PVOID)Status);
|
|
}
|
|
|
|
}
|
|
else if ( CommandLineLogging )
|
|
{
|
|
if ( !WriteFile(CommandLineLogHandle,
|
|
GlobalBuf,
|
|
TmpBuf-GlobalBuf,
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
TpctlErrorLog("\n\tTpctl: WriteFile to logfile failed, returned 0x%lx\n",(PVOID)Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free up resources
|
|
//
|
|
free( ReadValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
TpctlInitCommandBuffer(
|
|
OUT PCMD_ARGS CmdArgs,
|
|
IN DWORD CmdCode
|
|
)
|
|
|
|
// -------------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Initialize the cmd buffer to be passed to the driver with the arguments
|
|
// read from the command line or the script file.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// CmdArgs - The buffer to store the arguments in.
|
|
//
|
|
// CmdCode - The command that is being issued, and therefore the command
|
|
// to write the arguments for into the buffer.
|
|
// Return Value:
|
|
//
|
|
// BOOL - TRUE if the OpenInstance is valid and all the arguments are
|
|
// written to the buffer, FALSE otherwise.
|
|
//
|
|
// ----------------
|
|
|
|
{
|
|
LPBYTE p, q, s, t;
|
|
DWORD i, j;
|
|
DWORD OidIndex;
|
|
|
|
//
|
|
// If the OpenInstance is invalid return immediately.
|
|
//
|
|
switch ( CmdCode )
|
|
{
|
|
case SETENV :
|
|
case GO :
|
|
case PAUSE :
|
|
case OPEN :
|
|
case CLOSE :
|
|
case QUERYINFO :
|
|
case SETPF :
|
|
case SETLA :
|
|
case ADDMA :
|
|
case DELMA :
|
|
case SETFA :
|
|
case SETGA :
|
|
case SETINFO :
|
|
case RESET :
|
|
case STOPSEND :
|
|
case WAITSEND :
|
|
case RECEIVE :
|
|
case STOPREC :
|
|
case GETEVENTS :
|
|
case STRESSSERVER:
|
|
case ENDSTRESS :
|
|
case WAITSTRESS :
|
|
case CHECKSTRESS :
|
|
case SEND :
|
|
case STRESS :
|
|
case PERFSERVER:
|
|
case PERFCLIENT:
|
|
if (( GlobalCmdArgs.OpenInstance < 1 ) ||
|
|
( GlobalCmdArgs.OpenInstance > NUM_OPEN_INSTANCES ))
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: %d not a valid Open Instance Value ",
|
|
(PVOID)GlobalCmdArgs.OpenInstance);
|
|
TpctlErrorLog("(1-%d).\n", (PVOID)NUM_OPEN_INSTANCES);
|
|
return FALSE;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Otherwise let's stuff the arguments into the buffer.
|
|
//
|
|
|
|
CmdArgs->CmdCode = CmdCode;
|
|
CmdArgs->OpenInstance = GlobalCmdArgs.OpenInstance;
|
|
|
|
//
|
|
// Now do the command dependant stuff.
|
|
//
|
|
|
|
switch( CmdCode )
|
|
{
|
|
case SETENV:
|
|
|
|
CmdArgs->ARGS.ENV.WindowSize =
|
|
GlobalCmdArgs.ARGS.ENV.WindowSize;
|
|
|
|
CmdArgs->ARGS.ENV.RandomBufferNumber =
|
|
GlobalCmdArgs.ARGS.ENV.RandomBufferNumber;
|
|
|
|
CmdArgs->ARGS.ENV.StressDelayInterval =
|
|
GlobalCmdArgs.ARGS.ENV.StressDelayInterval;
|
|
|
|
CmdArgs->ARGS.ENV.UpForAirDelay =
|
|
GlobalCmdArgs.ARGS.ENV.UpForAirDelay;
|
|
|
|
CmdArgs->ARGS.ENV.StandardDelay =
|
|
GlobalCmdArgs.ARGS.ENV.StandardDelay;
|
|
|
|
p = CmdArgs->ARGS.ENV.StressAddress;
|
|
q = GlobalCmdArgs.ARGS.ENV.StressAddress;
|
|
|
|
s = CmdArgs->ARGS.ENV.ResendAddress;
|
|
t = GlobalCmdArgs.ARGS.ENV.ResendAddress;
|
|
|
|
for( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
*s++ = *t++;
|
|
}
|
|
break;
|
|
|
|
case BEGINLOGGING:
|
|
strcpy( CmdArgs->ARGS.FILES.LogFile,GlobalCmdArgs.ARGS.FILES.LogFile );
|
|
break;
|
|
|
|
case RECORDINGENABLE:
|
|
strcpy( CmdArgs->ARGS.RECORD.ScriptFile,GlobalCmdArgs.ARGS.RECORD.ScriptFile );
|
|
break;
|
|
|
|
case GO:
|
|
case PAUSE:
|
|
p = CmdArgs->ARGS.PAUSE_GO.RemoteAddress;
|
|
q = GlobalCmdArgs.ARGS.PAUSE_GO.RemoteAddress;
|
|
|
|
for( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
|
|
CmdArgs->ARGS.PAUSE_GO.TestSignature =
|
|
GlobalCmdArgs.ARGS.PAUSE_GO.TestSignature;
|
|
|
|
srand(TpctlSeed);
|
|
CmdArgs->ARGS.PAUSE_GO.UniqueSignature = TpctlSeed = rand();
|
|
break;
|
|
|
|
case OPEN:
|
|
strcpy( CmdArgs->ARGS.OPEN_ADAPTER.AdapterName,
|
|
GlobalCmdArgs.ARGS.OPEN_ADAPTER.AdapterName );
|
|
CmdArgs->ARGS.OPEN_ADAPTER.NoArcNet = 0;
|
|
if (getenv( "NOARCNET" ))
|
|
{
|
|
CmdArgs->ARGS.OPEN_ADAPTER.NoArcNet = 1;
|
|
}
|
|
break;
|
|
|
|
case QUERYINFO:
|
|
OidIndex = TpLookUpOidInfo( GlobalCmdArgs.ARGS.TPQUERY.OID );
|
|
|
|
if (( OidIndex == -1 ) || ( OidArray[OidIndex].QueryInfo != TRUE ))
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: 0x%08lX not a valid NdisRequestQueryInformation OID.\n",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPQUERY.OID);
|
|
return FALSE;
|
|
}
|
|
CmdArgs->ARGS.TPQUERY.OID = GlobalCmdArgs.ARGS.TPQUERY.OID;
|
|
break;
|
|
|
|
case SETPF:
|
|
case SETLA:
|
|
case ADDMA:
|
|
case SETFA:
|
|
case SETGA:
|
|
case SETINFO:
|
|
CmdArgs->ARGS.TPSET.OID = 0x0;
|
|
|
|
//
|
|
// Sanjeevk: Performed a scrub on the multiple if. Bug #5203
|
|
//
|
|
|
|
switch ( CmdCode )
|
|
{
|
|
case SETINFO:
|
|
CmdArgs->ARGS.TPSET.OID = GlobalCmdArgs.ARGS.TPSET.OID;
|
|
break;
|
|
|
|
case SETPF:
|
|
CmdArgs->ARGS.TPSET.OID = OID_GEN_CURRENT_PACKET_FILTER;
|
|
break;
|
|
|
|
case SETLA:
|
|
CmdArgs->ARGS.TPSET.OID = OID_GEN_CURRENT_LOOKAHEAD;
|
|
break;
|
|
case ADDMA:
|
|
if ( Open[CmdArgs->OpenInstance-1].MediumType == NdisMedium802_3 )
|
|
{
|
|
CmdArgs->ARGS.TPSET.OID = OID_802_3_MULTICAST_LIST;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Only FDDI and 802.3 permit multicast addressing. Since the
|
|
// medium is not 802.3, it must be FDDI
|
|
//
|
|
CmdArgs->ARGS.TPSET.OID = OID_FDDI_LONG_MULTICAST_LIST;
|
|
}
|
|
break;
|
|
|
|
case SETFA:
|
|
CmdArgs->ARGS.TPSET.OID = OID_802_5_CURRENT_FUNCTIONAL;
|
|
break;
|
|
|
|
case SETGA:
|
|
CmdArgs->ARGS.TPSET.OID = OID_802_5_CURRENT_GROUP;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch ( CmdArgs->ARGS.TPSET.OID )
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
CmdArgs->ARGS.TPSET.U.PacketFilter =
|
|
GlobalCmdArgs.ARGS.TPSET.U.PacketFilter;
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
CmdArgs->ARGS.TPSET.U.LookaheadSize =
|
|
GlobalCmdArgs.ARGS.TPSET.U.LookaheadSize;
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
case OID_FDDI_LONG_MULTICAST_LIST:
|
|
{
|
|
PMULT_ADDR NextMultAddr;
|
|
DWORD OI = GlobalCmdArgs.OpenInstance - 1;
|
|
|
|
p = CmdArgs->ARGS.TPSET.U.MulticastAddress[0];
|
|
q = GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0];
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
|
|
NextMultAddr = Open[OI].MulticastAddresses;
|
|
|
|
//
|
|
// XXX: Should the stress tests be required to add and
|
|
// delete the stress multicast address to/from this list?
|
|
//
|
|
|
|
j = 1;
|
|
|
|
while ( NextMultAddr != NULL )
|
|
{
|
|
p = CmdArgs->ARGS.TPSET.U.MulticastAddress[j++];
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = NextMultAddr->MulticastAddress[i];
|
|
}
|
|
|
|
NextMultAddr = NextMultAddr->Next;
|
|
}
|
|
CmdArgs->ARGS.TPSET.NumberMultAddrs = Open[OI].NumberMultAddrs + 1;
|
|
break;
|
|
}
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
case OID_802_5_CURRENT_GROUP:
|
|
p = CmdArgs->ARGS.TPSET.U.FunctionalAddress;
|
|
q = GlobalCmdArgs.ARGS.TPSET.U.FunctionalAddress;
|
|
|
|
for ( i=0;i<FUNCTIONAL_ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
TpctlErrorLog("\n\tTpctl: 0x%08lX not a valid NdisRequestSetInformation OID.\n",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.OID);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case DELMA:
|
|
{
|
|
PMULT_ADDR NextMultAddr;
|
|
DWORD OI = CmdArgs->OpenInstance - 1;
|
|
BOOL AddressFound = FALSE;
|
|
|
|
j = 0;
|
|
|
|
//
|
|
// Copy the addresses that do not match the one to be deleted into
|
|
// the multicast list buffer to be reset.
|
|
//
|
|
|
|
//
|
|
// Sanjeevk: Another change point. Bug #5203
|
|
//
|
|
if ( Open[CmdArgs->OpenInstance-1].MediumType == NdisMedium802_3 )
|
|
{
|
|
CmdArgs->ARGS.TPSET.OID = OID_802_3_MULTICAST_LIST;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Only FDDI and 802.3 permit multicast addressing. Since the
|
|
// medium is not 802.3, it must be FDDI
|
|
//
|
|
CmdArgs->ARGS.TPSET.OID = OID_FDDI_LONG_MULTICAST_LIST;
|
|
}
|
|
|
|
CmdArgs->ARGS.TPSET.NumberMultAddrs = 0;
|
|
NextMultAddr = Open[OI].MulticastAddresses;
|
|
|
|
while ( NextMultAddr != NULL )
|
|
{
|
|
if ( memcmp(GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0],
|
|
NextMultAddr->MulticastAddress,
|
|
ADDRESS_LENGTH) != 0 )
|
|
{
|
|
p = CmdArgs->ARGS.TPSET.U.MulticastAddress[j++];
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = NextMultAddr->MulticastAddress[i];
|
|
}
|
|
|
|
CmdArgs->ARGS.TPSET.NumberMultAddrs++;
|
|
|
|
}
|
|
else
|
|
{
|
|
AddressFound = TRUE;
|
|
}
|
|
|
|
NextMultAddr = NextMultAddr->Next;
|
|
}
|
|
|
|
if ( AddressFound == FALSE )
|
|
{
|
|
TpctlErrorLog("\n\tTpctl: The multicast address %02X",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][0]);
|
|
TpctlErrorLog("-%02X",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][1]);
|
|
TpctlErrorLog("-%02X",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][2]);
|
|
TpctlErrorLog("-%02X",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][3]);
|
|
TpctlErrorLog("-%02X",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][4]);
|
|
TpctlErrorLog("-%02X has not been added.\n",
|
|
(PVOID)GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0][5]);
|
|
|
|
//
|
|
// We will let the call go thru since we expect the driver to agree
|
|
// with our findings which is the MA which is being deleted is not present
|
|
//
|
|
//
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SEND:
|
|
p = CmdArgs->ARGS.TPSEND.DestAddress;
|
|
q = GlobalCmdArgs.ARGS.TPSEND.DestAddress;
|
|
s = CmdArgs->ARGS.TPSEND.ResendAddress;
|
|
t = GlobalCmdArgs.ARGS.TPSEND.ResendAddress;
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
*s++ = *t++;
|
|
}
|
|
|
|
CmdArgs->ARGS.TPSEND.PacketSize =
|
|
GlobalCmdArgs.ARGS.TPSEND.PacketSize;
|
|
|
|
CmdArgs->ARGS.TPSEND.NumberOfPackets =
|
|
GlobalCmdArgs.ARGS.TPSEND.NumberOfPackets;
|
|
|
|
break;
|
|
|
|
case STRESS:
|
|
|
|
CmdArgs->ARGS.TPSTRESS.MemberType =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.MemberType;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.PacketType =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.PacketType;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.PacketSize =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.PacketSize;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.PacketMakeUp =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.PacketMakeUp;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.ResponseType =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.ResponseType;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.DelayType =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.DelayType;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.DelayLength =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.DelayLength;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.TotalIterations =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.TotalIterations;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.TotalPackets =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.TotalPackets;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.WindowEnabled =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.WindowEnabled;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.DataChecking =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.DataChecking;
|
|
|
|
CmdArgs->ARGS.TPSTRESS.PacketsFromPool =
|
|
GlobalCmdArgs.ARGS.TPSTRESS.PacketsFromPool;
|
|
|
|
break;
|
|
|
|
|
|
case REGISTRY :
|
|
CmdArgs->ARGS.REGISTRY_ENTRY.OperationType =
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.OperationType ;
|
|
CmdArgs->ARGS.REGISTRY_ENTRY.KeyDatabase =
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.KeyDatabase ;
|
|
CmdArgs->ARGS.REGISTRY_ENTRY.ValueType =
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.ValueType ;
|
|
|
|
strcpy( CmdArgs->ARGS.REGISTRY_ENTRY.SubKey ,
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKey );
|
|
strcpy( CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyClass ,
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyClass );
|
|
|
|
strcpy( CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyValueName,
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyValueName );
|
|
strcpy( CmdArgs->ARGS.REGISTRY_ENTRY.SubKeyValue,
|
|
GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyValue );
|
|
|
|
break;
|
|
|
|
|
|
case PERFCLIENT:
|
|
p = CmdArgs->ARGS.TPPERF.PerfServerAddr;
|
|
q = GlobalCmdArgs.ARGS.TPPERF.PerfServerAddr;
|
|
s = CmdArgs->ARGS.TPPERF.PerfSendAddr;
|
|
t = GlobalCmdArgs.ARGS.TPPERF.PerfSendAddr;
|
|
|
|
for ( i=0;i<ADDRESS_LENGTH;i++ )
|
|
{
|
|
*p++ = *q++;
|
|
*s++ = *t++;
|
|
}
|
|
CmdArgs->ARGS.TPPERF.PerfPacketSize = GlobalCmdArgs.ARGS.TPPERF.PerfPacketSize;
|
|
CmdArgs->ARGS.TPPERF.PerfNumPackets = GlobalCmdArgs.ARGS.TPPERF.PerfNumPackets;
|
|
CmdArgs->ARGS.TPPERF.PerfDelay = GlobalCmdArgs.ARGS.TPPERF.PerfDelay;
|
|
CmdArgs->ARGS.TPPERF.PerfMode = GlobalCmdArgs.ARGS.TPPERF.PerfMode;
|
|
break;
|
|
|
|
case CLOSE:
|
|
case RESET:
|
|
case STOPSEND:
|
|
case WAITSEND:
|
|
case RECEIVE:
|
|
case STOPREC:
|
|
case GETEVENTS:
|
|
case STRESSSERVER:
|
|
case ENDSTRESS:
|
|
case WAITSTRESS:
|
|
case CHECKSTRESS:
|
|
case WAIT:
|
|
case VERBOSE:
|
|
case BREAKPOINT:
|
|
case QUIT:
|
|
case HELP:
|
|
case SHELL:
|
|
case RECORDINGDISABLE:
|
|
case DISABLE:
|
|
case ENABLE:
|
|
case PERFSERVER:
|
|
break;
|
|
|
|
default:
|
|
TpctlErrorLog("TpctlInitCommandBuffer: Invalid Command code.\n",NULL);
|
|
break;
|
|
|
|
} // switch();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
LPSTR
|
|
TpctlGetEventType(
|
|
TP_EVENT_TYPE TpEventType
|
|
)
|
|
{
|
|
static TP_EVENT_TYPE Event[] = {
|
|
CompleteOpen,
|
|
CompleteClose,
|
|
CompleteSend,
|
|
CompleteTransferData,
|
|
CompleteReset,
|
|
CompleteRequest,
|
|
IndicateReceive,
|
|
IndicateReceiveComplete,
|
|
IndicateStatus,
|
|
IndicateStatusComplete,
|
|
Unknown
|
|
};
|
|
|
|
#define EventCount (sizeof(Event)/sizeof(TP_EVENT_TYPE))
|
|
|
|
static LPSTR EventString[] = { // BUGUBUG Add new events open close...
|
|
"NdisCompleteOpen",
|
|
"NdisCompleteClose",
|
|
"NdisCompleteSend",
|
|
"NdisCompleteTransferData",
|
|
"NdisCompleteReset",
|
|
"NdisCompleteRequest",
|
|
"NdisIndicateReceive",
|
|
"NdisIndicateReceiveComplete",
|
|
"NdisIndicateStatus",
|
|
"NdisIndicateStatusComplete",
|
|
"Unknown Function"
|
|
};
|
|
|
|
static BYTE BadEvent[] = "UNDEFINED";
|
|
DWORD i;
|
|
|
|
|
|
for (i=0; i<EventCount; i++)
|
|
{
|
|
if (TpEventType == Event[i])
|
|
{
|
|
return EventString[i];
|
|
}
|
|
}
|
|
|
|
return BadEvent;
|
|
|
|
#undef StatusCount
|
|
}
|
|
|
|
|
|
|
|
LPSTR
|
|
TpctlGetStatus(
|
|
NDIS_STATUS GeneralStatus
|
|
)
|
|
{
|
|
|
|
static NDIS_STATUS Status[] = {
|
|
NDIS_STATUS_SUCCESS,
|
|
NDIS_STATUS_PENDING,
|
|
NDIS_STATUS_NOT_RECOGNIZED,
|
|
NDIS_STATUS_NOT_COPIED,
|
|
NDIS_STATUS_ONLINE,
|
|
NDIS_STATUS_RESET_START,
|
|
NDIS_STATUS_RESET_END,
|
|
NDIS_STATUS_RING_STATUS,
|
|
NDIS_STATUS_CLOSED,
|
|
|
|
NDIS_STATUS_WAN_LINE_UP,
|
|
NDIS_STATUS_WAN_LINE_DOWN,
|
|
NDIS_STATUS_WAN_FRAGMENT,
|
|
|
|
NDIS_STATUS_NOT_RESETTABLE,
|
|
NDIS_STATUS_SOFT_ERRORS,
|
|
NDIS_STATUS_HARD_ERRORS,
|
|
NDIS_STATUS_FAILURE,
|
|
NDIS_STATUS_RESOURCES,
|
|
NDIS_STATUS_CLOSING,
|
|
NDIS_STATUS_BAD_VERSION,
|
|
NDIS_STATUS_BAD_CHARACTERISTICS,
|
|
NDIS_STATUS_ADAPTER_NOT_FOUND,
|
|
NDIS_STATUS_OPEN_FAILED,
|
|
NDIS_STATUS_DEVICE_FAILED,
|
|
NDIS_STATUS_MULTICAST_FULL,
|
|
NDIS_STATUS_MULTICAST_EXISTS,
|
|
NDIS_STATUS_MULTICAST_NOT_FOUND,
|
|
NDIS_STATUS_REQUEST_ABORTED,
|
|
NDIS_STATUS_RESET_IN_PROGRESS,
|
|
NDIS_STATUS_CLOSING_INDICATING,
|
|
NDIS_STATUS_NOT_SUPPORTED,
|
|
NDIS_STATUS_INVALID_PACKET,
|
|
NDIS_STATUS_OPEN_LIST_FULL,
|
|
NDIS_STATUS_ADAPTER_NOT_READY,
|
|
NDIS_STATUS_ADAPTER_NOT_OPEN,
|
|
NDIS_STATUS_NOT_INDICATING,
|
|
NDIS_STATUS_INVALID_LENGTH,
|
|
NDIS_STATUS_INVALID_DATA,
|
|
NDIS_STATUS_BUFFER_TOO_SHORT,
|
|
NDIS_STATUS_INVALID_OID,
|
|
NDIS_STATUS_ADAPTER_REMOVED,
|
|
NDIS_STATUS_UNSUPPORTED_MEDIA,
|
|
NDIS_STATUS_GROUP_ADDRESS_IN_USE,
|
|
NDIS_STATUS_FILE_NOT_FOUND,
|
|
NDIS_STATUS_ERROR_READING_FILE,
|
|
NDIS_STATUS_ALREADY_MAPPED,
|
|
NDIS_STATUS_RESOURCE_CONFLICT,
|
|
NDIS_STATUS_TOKEN_RING_OPEN_ERROR,
|
|
TP_STATUS_NO_SERVERS,
|
|
TP_STATUS_NO_EVENTS
|
|
};
|
|
|
|
#define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS))
|
|
|
|
static PUCHAR String[] = {
|
|
"NDIS_STATUS_SUCCESS",
|
|
"NDIS_STATUS_PENDING",
|
|
"NDIS_STATUS_NOT_RECOGNIZED",
|
|
"NDIS_STATUS_NOT_COPIED",
|
|
"NDIS_STATUS_ONLINE",
|
|
"NDIS_STATUS_RESET_START",
|
|
"NDIS_STATUS_RESET_END",
|
|
"NDIS_STATUS_RING_STATUS",
|
|
"NDIS_STATUS_CLOSED",
|
|
"NDIS_STATUS_WAN_LINE_UP",
|
|
"NDIS_STATUS_WAN_LINE_DOWN",
|
|
"NDIS_STATUS_WAN_FRAGMENT",
|
|
"NDIS_STATUS_NOT_RESETTABLE",
|
|
"NDIS_STATUS_SOFT_ERRORS",
|
|
"NDIS_STATUS_HARD_ERRORS",
|
|
"NDIS_STATUS_FAILURE",
|
|
"NDIS_STATUS_RESOURCES",
|
|
"NDIS_STATUS_CLOSING",
|
|
"NDIS_STATUS_BAD_VERSION",
|
|
"NDIS_STATUS_BAD_CHARACTERISTICS",
|
|
"NDIS_STATUS_ADAPTER_NOT_FOUND",
|
|
"NDIS_STATUS_OPEN_FAILED",
|
|
"NDIS_STATUS_DEVICE_FAILED",
|
|
"NDIS_STATUS_MULTICAST_FULL",
|
|
"NDIS_STATUS_MULTICAST_EXISTS",
|
|
"NDIS_STATUS_MULTICAST_NOT_FOUND",
|
|
"NDIS_STATUS_REQUEST_ABORTED",
|
|
"NDIS_STATUS_RESET_IN_PROGRESS",
|
|
"NDIS_STATUS_CLOSING_INDICATING",
|
|
"NDIS_STATUS_NOT_SUPPORTED",
|
|
"NDIS_STATUS_INVALID_PACKET",
|
|
"NDIS_STATUS_OPEN_LIST_FULL",
|
|
"NDIS_STATUS_ADAPTER_NOT_READY",
|
|
"NDIS_STATUS_ADAPTER_NOT_OPEN",
|
|
"NDIS_STATUS_NOT_INDICATING",
|
|
"NDIS_STATUS_INVALID_LENGTH",
|
|
"NDIS_STATUS_INVALID_DATA",
|
|
"NDIS_STATUS_BUFFER_TOO_SHORT",
|
|
"NDIS_STATUS_INVALID_OID",
|
|
"NDIS_STATUS_ADAPTER_REMOVED",
|
|
"NDIS_STATUS_UNSUPPORTED_MEDIA",
|
|
"NDIS_STATUS_GROUP_ADDRESS_IN_USE",
|
|
"NDIS_STATUS_FILE_NOT_FOUND",
|
|
"NDIS_STATUS_ERROR_READING_FILE",
|
|
"NDIS_STATUS_ALREADY_MAPPED",
|
|
"NDIS_STATUS_RESOURCE_CONFLICT",
|
|
"NDIS_STATUS_TOKEN_RING_OPEN_ERROR",
|
|
"TP_STATUS_NO_SERVERS",
|
|
"TP_STATUS_NO_EVENTS"
|
|
};
|
|
|
|
static BYTE BadStatus[] = "UNDEFINED";
|
|
DWORD i;
|
|
|
|
for (i=0; i<StatusCount; i++)
|
|
{
|
|
if (GeneralStatus == Status[i])
|
|
{
|
|
return String[i];
|
|
}
|
|
}
|
|
return BadStatus;
|
|
|
|
#undef StatusCount
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
TpctlGetCommandCode(
|
|
LPSTR Argument
|
|
)
|
|
|
|
{
|
|
DWORD i;
|
|
|
|
for ( i=1;i<NUM_COMMANDS;i++ )
|
|
{
|
|
if (_stricmp( Argument, CommandCode[i].CmdAbbr ) == 0 )
|
|
{
|
|
return CommandCode[i].CmdCode;
|
|
}
|
|
|
|
if (_stricmp( Argument, CommandCode[i].CmdName ) == 0 )
|
|
{
|
|
return CommandCode[i].CmdCode;
|
|
}
|
|
}
|
|
return CMD_ERR;
|
|
}
|
|
|
|
|
|
|
|
LPSTR
|
|
TpctlGetCommandName(
|
|
LPSTR Command
|
|
)
|
|
|
|
{
|
|
DWORD i;
|
|
|
|
for ( i=1;i<NUM_COMMANDS;i++ )
|
|
{
|
|
if (_stricmp(Command,CommandCode[i].CmdAbbr) == 0 )
|
|
{
|
|
return CommandCode[i].CmdName;
|
|
}
|
|
if (_stricmp(Command,CommandCode[i].CmdName) == 0 )
|
|
{
|
|
return CommandCode[i].CmdName;
|
|
}
|
|
}
|
|
return CommandCode[CMD_ERR].CmdName;
|
|
}
|
|
|
|
|
|
|
|
LPSTR
|
|
TpctlGetCmdCode(
|
|
DWORD CmdCode
|
|
)
|
|
{
|
|
static BYTE BadCmdCode[] = "UNDEFINED";
|
|
|
|
DWORD i;
|
|
|
|
for(i=1; i<NUM_COMMANDS; i++)
|
|
{
|
|
if ( CmdCode == CommandCode[i].CmdCode )
|
|
{
|
|
return(CommandCode[i].CmdName);
|
|
}
|
|
}
|
|
return BadCmdCode;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlCopyAdapterAddress(
|
|
DWORD OpenInstance,
|
|
PREQUEST_RESULTS Results
|
|
)
|
|
{
|
|
DWORD i;
|
|
PUCHAR Source, Destination;
|
|
|
|
//
|
|
// Sanjeevk: Bug# 5203: This routine needed modification to support
|
|
// the additional NDIS_MEDIUM information sent
|
|
// back
|
|
//
|
|
|
|
Source = (PUCHAR)( Results->InformationBuffer + sizeof( NDIS_MEDIUM ) );
|
|
Destination = (PUCHAR)( Open[OpenInstance].AdapterAddress );
|
|
|
|
for (i=0;i<ADDRESS_LENGTH;i++)
|
|
{
|
|
*Destination++ = *Source++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TpctlRecordArguments(
|
|
IN TESTPARAMS Options[],
|
|
IN DWORD OptionTableSize,
|
|
IN DWORD argc,
|
|
IN LPSTR argv[TPCTL_MAX_ARGC]
|
|
)
|
|
|
|
// -----------------
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Create Sanjeevk 7-1-93
|
|
//
|
|
// This function is responsible for creating the command in parts and records
|
|
// it to the file accessed by ScriptRecordHandle
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Options The TestParameter options from which the command is created
|
|
//
|
|
// OptionTableSize The size of the table for the option under consideration
|
|
//
|
|
// argc The number of arguments passed on the TPCTL command line
|
|
// prompt
|
|
//
|
|
// argv The arguments passed on the TPCTL command line prompt
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// -------------------
|
|
|
|
|
|
{
|
|
DWORD i;
|
|
CHAR TmpBuffer[256];
|
|
DWORD BytesWritten,Status ;
|
|
DWORD CmdCode = TpctlGetCommandCode( argv[0] );
|
|
|
|
|
|
//
|
|
// 1. Clear the temporary buffer which will be used to construct an option
|
|
// one at a time
|
|
//
|
|
ZeroMemory ( TmpBuffer, 256 );
|
|
|
|
//
|
|
// 2. Attempt to access the complete name of the command code.
|
|
//
|
|
if ( CmdCode == CMD_ERR )
|
|
{
|
|
sprintf( TmpBuffer, "%s", argv[0] );
|
|
}
|
|
else
|
|
{
|
|
sprintf( TmpBuffer, "%s", TpctlGetCommandName(argv[0]) );
|
|
}
|
|
|
|
//
|
|
// 3. Write the first argument accessed into the script file
|
|
//
|
|
|
|
if ( !WriteFile(ScriptRecordHandle,
|
|
TmpBuffer,
|
|
strlen( TmpBuffer ),
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
printf("\n\tTpctlRecordArguments: write to script record file failed, returned 0x%lx\n",
|
|
Status);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// 4. Set up the buffer for reuse
|
|
//
|
|
ZeroMemory ( TmpBuffer, 256 );
|
|
|
|
//
|
|
// 5. Now for the number of argument passed on the TPCTL command prompt, reconstruct
|
|
// each sub option one at a time
|
|
//
|
|
for( i = 1; i < argc; i++ )
|
|
{
|
|
//
|
|
// 5.a Check if a valid Option Table has been provided and if so get the
|
|
// the lvalue and rvalue and combine them to form an expression
|
|
//
|
|
|
|
if ( Options != NULL )
|
|
{
|
|
sprintf( TmpBuffer, "\t+\n %s=%s", Options[i-1].ArgName, argv[i] );
|
|
}
|
|
else
|
|
{
|
|
if ( CmdCode != CMD_ERR )
|
|
{
|
|
sprintf( TmpBuffer, "\t+\n %s", argv[i] );
|
|
}
|
|
else
|
|
{
|
|
sprintf( TmpBuffer, " %s", argv[i] );
|
|
}
|
|
}
|
|
|
|
//
|
|
// 5.b Write this reconstructed string which now signifies the complete
|
|
// sub-option into the script file
|
|
//
|
|
|
|
if ( !WriteFile(ScriptRecordHandle,
|
|
TmpBuffer,
|
|
strlen( TmpBuffer ),
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
printf("\n\tTpctlRecordArguments: write to script record file failed, returned 0x%lx\n",
|
|
Status);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// 5.c And clear the buffer for reuse(next sub-option)
|
|
//
|
|
ZeroMemory ( TmpBuffer, 256 );
|
|
|
|
}
|
|
|
|
//
|
|
// 6. Since it is possible to specifiy one or more suboptions and the command prompt
|
|
// we must dteremine all of the lvalues and rvalues of the current option
|
|
// Since we can also specify a semicolon to accept default values, we must
|
|
// carefully consider the various types of data associated with the rvalues
|
|
//
|
|
for( i = argc; i <= OptionTableSize; i++ )
|
|
{
|
|
PUCHAR p;
|
|
|
|
switch ( Options[i-1].TestType )
|
|
{
|
|
case Integer :
|
|
sprintf( TmpBuffer, "\t+\n %s=%ld", Options[i-1].ArgName,
|
|
*(PDWORD)Options[i-1].Destination );
|
|
break;
|
|
|
|
case String :
|
|
sprintf(TmpBuffer, "\t+\n %s=%s", Options[i-1].ArgName, Options[i-1].Destination);
|
|
break;
|
|
|
|
case Address4 :
|
|
p = Options[i-1].Destination;
|
|
sprintf( TmpBuffer, "\t+\n %s=%02x-%02x-%02x-%02x", Options[i-1].ArgName,
|
|
*p, *(p+1), *(p+2), *(p+3) );
|
|
break;
|
|
|
|
case Address6 :
|
|
p = Options[i-1].Destination;
|
|
sprintf( TmpBuffer, "\t+\n %s=%02x-%02x-%02x-%02x-%02x-%02x", Options[i-1].ArgName,
|
|
*p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5) );
|
|
break;
|
|
|
|
case ParsedInteger :
|
|
p = Options[i-1].Destination;
|
|
sprintf( TmpBuffer, "\t+\n %s=0x%4.4x", Options[i-1].ArgName, *(LPDWORD)p );
|
|
break;
|
|
}
|
|
|
|
if ( !WriteFile(ScriptRecordHandle,
|
|
TmpBuffer,
|
|
strlen( TmpBuffer ),
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
printf("\n\tTpctlRecordArguments: write to script record file failed, returned 0x%lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
ZeroMemory ( TmpBuffer, 256 );
|
|
|
|
}
|
|
|
|
//
|
|
// 7. Finally add the newline to end the command
|
|
//
|
|
sprintf( TmpBuffer, "\n\n" );
|
|
if ( !WriteFile(ScriptRecordHandle,
|
|
TmpBuffer,
|
|
strlen( TmpBuffer ),
|
|
&BytesWritten,
|
|
NULL ))
|
|
{
|
|
Status = GetLastError();
|
|
printf("\n\tTpctlRecordArguments: write to script record file failed, returned 0x%lx\n",
|
|
Status);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
LPSTR
|
|
TpctlEnumerateRegistryInfo(
|
|
IN PUCHAR TmpBuf,
|
|
IN PUCHAR DbaseName,
|
|
IN PUCHAR SubKeyName,
|
|
IN PUCHAR ValueName,
|
|
IN DWORD ReadValueType,
|
|
IN PUCHAR ReadValue,
|
|
IN DWORD ReadValueSize )
|
|
{
|
|
|
|
INT i;
|
|
|
|
TmpBuf += sprintf( TmpBuf,
|
|
"\tDataBase Name = %s\n\tSub Key Name = %s\n\tValue Name = %s\n",
|
|
DbaseName, SubKeyName, ValueName );
|
|
|
|
TmpBuf += sprintf( TmpBuf, "\tValue Type = %s\n", TpctlGetValueType( ReadValueType ) );
|
|
|
|
switch( ReadValueType )
|
|
{
|
|
case REG_BINARY :
|
|
TmpBuf += sprintf( TmpBuf, "\tValue(IN HEX) = ");
|
|
for( i = 0; i < (INT)ReadValueSize; i++ )
|
|
{
|
|
if ( i%6 || (i == 0) )
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "%2.2x ", ReadValue[i] );
|
|
}
|
|
else
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "\n\t %2.2x ", ReadValue[i] );
|
|
}
|
|
}
|
|
TmpBuf += sprintf( TmpBuf, "\n" );
|
|
break;
|
|
|
|
case REG_DWORD :
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = 0x%lx\n", *(LPDWORD)ReadValue );
|
|
break;
|
|
|
|
//
|
|
// This code section had to be commented out because the idiot who defined
|
|
// the types made LITTLE_ENDIAN = DWORD. If we were to port over to a
|
|
// BIG_ENDIAN system, we would have to comment out the code for BIG_ENDIAN
|
|
//
|
|
// case REG_DWORD_LITTLE_ENDIAN :
|
|
// TmpBuf += sprintf( TmpBuf, "\tValue = LITTLE_ENDIAN 0x" );
|
|
// for( i = 0 ; i < ReadValueSize ; i++ )
|
|
// {
|
|
// TmpBuf += sprintf( TmpBuf, "%2.2x", ReadValue[i] );
|
|
// }
|
|
// TmpBuf += sprintf( TmpBuf, " DWORD VALUE 0x%lx\n", *(LPDWORD)ReadValue );
|
|
// break;
|
|
|
|
case REG_DWORD_BIG_ENDIAN:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = BIG_ENDIAN 0x" );
|
|
for( i = 0 ; i < (INT)ReadValueSize ; i++ )
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "%2.2x", ReadValue[i] );
|
|
}
|
|
TmpBuf += sprintf( TmpBuf, " DWORD VALUE 0x" );
|
|
for( i = 0 ; i < (INT)ReadValueSize ; i++ )
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "%2.2x", ReadValue[i] );
|
|
}
|
|
TmpBuf += sprintf( TmpBuf, "\n" );
|
|
break;
|
|
|
|
case REG_LINK:
|
|
case REG_EXPAND_SZ:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = %s\n", ReadValue );
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue(s)\n" );
|
|
{
|
|
PUCHAR Tmp1 = ReadValue;
|
|
|
|
while ( strlen( Tmp1 ) != 0 )
|
|
{
|
|
TmpBuf += sprintf( TmpBuf, "\t\t%s\n", Tmp1 );
|
|
Tmp1 += (strlen( Tmp1 ) + 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_NONE:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = %s\n", ReadValue );
|
|
break;
|
|
|
|
case REG_RESOURCE_LIST:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = %s\n", ReadValue );
|
|
break;
|
|
|
|
case REG_SZ:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = %s\n", ReadValue );
|
|
break;
|
|
|
|
default:
|
|
TmpBuf += sprintf( TmpBuf, "\tValue = UNKNOWN\n" );
|
|
break;
|
|
|
|
}
|
|
|
|
return TmpBuf;
|
|
|
|
}
|
|
|
|
|
|
LPSTR
|
|
TpctlGetValueType(
|
|
IN DWORD ValueType
|
|
)
|
|
{
|
|
static UCHAR ValueTypeString[20];
|
|
|
|
ZeroMemory( ValueTypeString, 20 );
|
|
|
|
switch ( ValueType )
|
|
{
|
|
case REG_BINARY :
|
|
strcpy( ValueTypeString, "REG_BINARY" );
|
|
break;
|
|
|
|
case REG_DWORD :
|
|
strcpy( ValueTypeString, "REG_DWORD" );
|
|
break;
|
|
//
|
|
// This code section had to be commented out because the idiot who defined
|
|
// the types made LITTLE_ENDIAN = DWORD. If we were to port over to a
|
|
// BIG_ENDIAN system, we would have to comment out the code for BIG_ENDIAN
|
|
//
|
|
// case REG_DWORD_LITTLE_ENDIAN :
|
|
// strcpy( ValueTypeString, "REG_DWORD_LITTLE_ENDIAN" );
|
|
// break;
|
|
//
|
|
|
|
case REG_DWORD_BIG_ENDIAN :
|
|
strcpy( ValueTypeString, "REG_DWORD_BIG_ENDIAN" );
|
|
break;
|
|
|
|
case REG_EXPAND_SZ :
|
|
strcpy( ValueTypeString, "REG_EXPAND_SZ" );
|
|
break;
|
|
|
|
case REG_LINK :
|
|
strcpy( ValueTypeString, "REG_LINK" );
|
|
break;
|
|
|
|
case REG_MULTI_SZ :
|
|
strcpy( ValueTypeString, "REG_MULTI_SZ" );
|
|
break;
|
|
|
|
case REG_NONE :
|
|
strcpy( ValueTypeString, "REG_NONE" );
|
|
break;
|
|
|
|
case REG_RESOURCE_LIST :
|
|
strcpy( ValueTypeString, "REG_RESOURCE_LIST" );
|
|
break;
|
|
|
|
case REG_SZ :
|
|
strcpy( ValueTypeString, "REG_SZ" );
|
|
break;
|
|
|
|
default :
|
|
strcpy( ValueTypeString, "UNDEFINED" );
|
|
break;
|
|
}
|
|
|
|
return ValueTypeString;
|
|
|
|
}
|
|
|
|
|