// -------------------------------------------------------------------- // // 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 #include #include #include #include #include #include #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. (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 .\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= 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 , then the buffer contains a single // 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;iARGS.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;iARGS.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;iARGS.TPSET.U.MulticastAddress[j++]; for ( i=0;iMulticastAddress[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;iOpenInstance - 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;iMulticastAddress[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;iARGS.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;iARGS.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; iInformationBuffer + sizeof( NDIS_MEDIUM ) ); Destination = (PUCHAR)( Open[OpenInstance].AdapterAddress ); for (i=0;i