diff options
Diffstat (limited to '')
51 files changed, 45744 insertions, 0 deletions
diff --git a/private/ntos/ndis/testprot/dirs b/private/ntos/ndis/testprot/dirs new file mode 100644 index 000000000..e348735d6 --- /dev/null +++ b/private/ntos/ndis/testprot/dirs @@ -0,0 +1,28 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Steve Wood (stevewo) 17-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS=tplib \ + tpdrvr \ + tpctl \ + tpdiff.new + +OPTIONAL_DIRS=tpkd diff --git a/private/ntos/ndis/testprot/docs/arcnet.doc b/private/ntos/ndis/testprot/docs/arcnet.doc Binary files differnew file mode 100644 index 000000000..db7a2302e --- /dev/null +++ b/private/ntos/ndis/testprot/docs/arcnet.doc diff --git a/private/ntos/ndis/testprot/docs/rfc1051 b/private/ntos/ndis/testprot/docs/rfc1051 new file mode 100644 index 000000000..7121f0019 --- /dev/null +++ b/private/ntos/ndis/testprot/docs/rfc1051 @@ -0,0 +1,227 @@ + + + + + + +Network Working Group P. Prindeville +Request for Comments: 1051 McGill University + March 1988 + + + A Standard for the Transmission of IP Datagrams + and ARP Packets over ARCNET Networks + + +Status of this Memo + + This RFC specifies a standard protocol for the Internet community. + Distribution of this memo is unlimited. + +Introduction + + This RFC specifies a standard method of encapsulating Internet + Protocol (IP) [1] and Address Resolution Protocol (ARP) [2] datagrams + on an ARCNET [3]. + +Acknowledgements + + The author wishes to express thanks to Robert Craig of the McGill + University Computing Centre and Bruce Hughes of Datapoint Corporation + for their generous support of facilities and information. I also + extend my gratitude to the readers of the PCIP mailing list for their + helpful ideas and comments. + +Frame Format + + IP and ARP datagrams are transmitted in standard ARCNET packets. As + required by Datapoint Corporation, the first octet of the data field + is reserved for the network layer protocol identification (the + "system code" in Datapoint nomenclature), and must contain the value + 240 (F0 hex) for IP or 241 (F1 hex) for ARP. The ARP hardware + address type for ARCNET is 7 [9]. + + ARCNET supports packet formats containing 1-253 octets of data + (normal format) and 257-508 octets of data (extended format), + inclusive of system code. Note that there exists a range of data + lengths (254-256) which are 'forbidden'. IP packets within this + range should be padded (with octets of zero) to meet the minimum + extended packet size of 257 data octets. This padding is not part of + the IP packet and is not included in the total length field of the IP + header. + + + + + + +Prindeville [Page 1] + +RFC 1051 IP and ARP on ARCNET March 1988 + + + On networks where some hosts do not support extended packet format, + the IP Maximum Transmission Unit (MTU) should be set to 253, though + implementors are encouraged to support the extended packet format + mode of operation. + + Because the ARCNET maximum packet length is less than the Internet + default MTU, implementations are strongly encouraged to support IP + level fragmentation and reassembly. Hosts not supporting this should + take steps to discourage others from sending fragmented packets, such + as using the TCP Maximum Segment Size option [4]. + + The frame format is: + + Normal Packet Extended Packet + +----------------+ +----------------+ + | ALERT* | | ALERT* | + +----------------+ +----------------+ + | SOH (1) | | SOH (1) | + +----------------+ +----------------+ + | SID | | SID | + +----------------+ +----------------+ + | | | | + + DID + + DID + + | | | | + +----------------+ +----------------+ + | COUNT | | NUL (0) | + +----------------+ + + + | SYSTEM CODE | | COUNT | + +----------------+ +----------------+ + | | | SYSTEM CODE | + : DATA : +----------------+ + | | | | + +----------------+ : DATA : + | | | | + + CRC + +----------------+ + | | | | + +----------------+ + CRC + + | | + +----------------+ + + ALERT*: Six mark bits signifying the beginning of a frame. + SID: Sender's node ID. + DID: Receipient's node ID (repeated for reliability). + COUNT: Length of data and system code (one's complement). + SYSTEM CODE: 240 for IP, 241 for ARP (decimal). + DATA: Is either an IP or an ARP packet, padded with NULs so + as to not be between 254 and 256 octets long. + CRC: Cyclic redundancy check (CRC-16). + + + +Prindeville [Page 2] + +RFC 1051 IP and ARP on ARCNET March 1988 + + +Address Mappings + + The mappings between 32-bit Internet addresses to 8-bit ARCNET + addresses can be done several ways, recommended are: + + Host Number Extraction + + The easiest thing to do is to use the last eight bits of host + number part of the Internet address as the host's node id. This + has been implemented on Experimental Ethernet [5] and ProNET-10 + [6]. + + Dynamic Discovery + + Mappings between 32-bit Internet addresses and 8-bit ARCNET node + ids could be accomplished through ARP. Internet addresses are + assigned arbitrarily on some Internet networks. All + implementations supporting ARP must have a means of disabling ARP + and using the above Host Number Extraction method of address + mapping so that systems may interoperate. + + The use of ARP is optional. However, ARP is desirable when using + IP implementations that don't support subnetting [7], as in the + Proxy ARP scenario [8]. + +Broadcast Address + + The broadcast Internet address (the address on the network with a + host part of all binary ones) should be mapped to the broadcast node + id 0. + + + + + + + + + + + + + + + + + + + + + +Prindeville [Page 3] + +RFC 1051 IP and ARP on ARCNET March 1988 + + +References + + [1] Postel, J., "Internet Protocol", RFC-791, Network Information + Center, SRI, September 1981. + + [2] Plummer, D., "An Ethernet Address Resolution Protocol", RFC- 826, + Network Information Center, SRI, November 1982. + + [3] "ARCNET Designer's Handbook", Order Number 61610, Datapoint + Corporation, 1983. + + [4] Postel, J., "The TCP Maximum Segment Size Option and Related + Topics", RFC-879, Network Information Center, SRI, November 1983. + + [5] Postel, J., "A Standard for the Transmission of IP Datagrams over + Experimental Ethernet Networks", RFC-895, Network Information + Center, SRI, April 1984. + + [6] "ProNET-10 Model p1300 IBM PC Interface System Installation and + Programming Guide", Version 4.0, Proteon Inc., July 1986. + + [7] Mogul, J. and J. Postel, "Internet Standard Subnetting + Procedure", RFC-950, Network Information Center, SRI, October + 1984. + + [8] Carl-Mitchell, S. and J.S. Quarterman, "Using ARP to Implement + Transparent Subnet Gateways", RFC-1027, Network Information + Center, SRI, October 1987. + + [9] Reynolds, J., and J. Postel, "Assigned Numbers", RFC-1010, + Network Information Center, SRI, May 1987. + + + + + + + + + + + + + + + + + + + + +Prindeville [Page 4] + diff --git a/private/ntos/ndis/testprot/docs/rfc1201 b/private/ntos/ndis/testprot/docs/rfc1201 new file mode 100644 index 000000000..8f7d90890 --- /dev/null +++ b/private/ntos/ndis/testprot/docs/rfc1201 @@ -0,0 +1,388 @@ +Network Working Group D. Provan +Request for Comments: 1201 Novell, Inc. +Obsoletes: RFC 1051 February 1991 + + + Transmitting IP Traffic over ARCNET Networks + +Status of this Memo + + This memo defines a protocol for the transmission of IP and ARP + packets over the ARCnet Local Area Network. This RFC specifies an + IAB standards track protocol for the Internet community, and requests + discussion and suggestions for improvements. Please refer to the + current edition of the "IAB Official Protocol Standards" for the + standardization state and status of this protocol. Distribution of + this memo is unlimited. + +1. Introduction + + This memo specifies a method of encapsulating Internet Protocol (IP) + [1] and Address Resolution Protocol (ARP) [2] datagrams for + transmission across ARCNET [3] using the "ARCNET Packet Header + Definition Standard" [4]. This memo offers a replacement for RFC + 1051. RFC 1051 uses an ARCNET framing protocol which limits + unfragmented IP packets to 508 octets [5]. + +2. ARCNET Packet Format + + In 1989, Apple Computers, Novell, ACTINET Systems, Standard + Microsystems, and Pure Data Research agreed to use the ARCNET + datalink protocol defined in "ARCNET Packet Header Definition + Standard" [4]. We'll begin with a brief description of that + protocol. + +2.1. ARCNET Framing + + ARCNET hardware supports two types of frames: short frames, which are + always 256 octets long, and long frames, which are always 512 octets + long. All frames begin with a hardware header and end with the + client's data preceded by a software header. Software places padding + in the middle of the packet between the hardware header and the + software header to make the frame the appropriate fixed length. + Unbeknown to the software, the hardware removes this padding during + transmission. + + Short frames can hold from 0 to 249 octets of client data. Long + frames can hold from 253 to 504 octets of client data. To handle + frames with 250, 251, or 252 octets of data, the datalink protocol + + + +Provan [Page 1] + +RFC 1201 IP on ARCNET February 1991 + + + introduces a third frame type: the exception frame. + + These three frame formats are shown here. Except as noted, each + block represents one octet. + + + Short Frame Long Frame Exception Frame + + +---------------+ +---------------+ +---------------+ + | source | | source | | source | + +---------------+ +---------------+ +---------------+ + | destination | | destination | | destination | + +---------------+ +---------------+ +---------------+ + | offset | | 0 | | 0 | + +---------------+ +---------------+ +---------------+ + . unused . | offset | | offset | + . (offset - 3 . +---------------+ +---------------+ + . octets) . . unused . . unused . + +---------------+ . (offset - 4 . . (offset - 4 . + | protocol ID | . octets) . . octets) . + +---------------+ +---------------+ +---------------+ + | split flag | | protocol ID | | protocol ID | + +---------------+ +---------------+ +---------------+ + | sequence | | split flag | | flag: FF hex | + + number + +---------------+ +---------------+ + | (2 octets) | | sequence | | padding: 0xFF | + +---------------+ + number + +---------------+ + . . | (2 octets) | | padding: 0xFF | + . client data . +---------------+ +---------------+ + . (256 - offset . . . | (protocol ID) | + . - 4 octets) . . . +---------------+ + . . . . | split flag | + +---------------+ . . +---------------+ + . . | sequence | + . client data . + number + + . (512 - offset . | (2 octets) | + . - 4 octets) . +---------------+ + . . . . + . . . client data . + . . . (512 - offset . + . . . - 8 octets) . + . . . . + +---------------+ +---------------+ + + These packet formats are presented as software would see them + through ARCNET hardware. [3] refers to this as the "buffer + format". The actual format of packets on the wire is a little + different: the destination ID is duplicated, the padding between + + + +Provan [Page 2] + +RFC 1201 IP on ARCNET February 1991 + + + the offset field and the protocol ID field is not transmitted, and + there's some hardware framing information. In addition, the + hardware transmits special packets for buffer allocation and + reception acknowledgement which are not described here [3]. + +2.2. Datalink Layer Fragmentation + + ARCNET hardware limits individual frames to 512 octets, which allows + 504 octets of client data. This ARCNET datalink protocol allows the + datalink layer to break packets into as many as 120 fragments for + transmission. This allows ARCNET clients to transmit up to 60,480 + octets in each packet. + + The "split flag" describes datalink layer packet fragments. There + are three cases: an unfragmented packet, the first fragment of a + fragmented packet, and any other fragment of a fragmented packet. + + Unfragmented packets always have a split flag of zero. + + The first fragment of a fragmented packet has a split flag equal to + ((T-2)*2)+1, where T is the total number of fragments to expect for + the packet. + + Subsequent fragments of a fragmented packet have a split flag equal + to ((N-1)*2), where N is the number of this fragment. For example, + the fourth fragment of a packet will always have the split flag value + of six ( (4-1)*2 ). + + The receiving station can identify the last fragment of a packet + because the value of its 8-bit split flag will be one greater than + the split flag of the first fragment of the packet. + + A previous version of this ARCNET datalink protocol definition + only allowed packets which could be contained in two fragments. + In this older standard, the only legal split flags were 0, 1, and + 2. Compatibility with this older standard can be maintained by + configuring the maximum client data length to 1008 octets. + + No more that 120 fragments are allowed. The highest legal split flag + value is EE hex. (Notice that the split flag value FF hex is used to + flag exception packets in what would otherwise be a long packet's + split flag field.) + + All fragments of a single packet carry the same sequence number. + +2.3. Datalink Layer Reassembly + + The previous section provides enough information to implement + + + +Provan [Page 3] + +RFC 1201 IP on ARCNET February 1991 + + + datalink reassembly. To avoid buffer allocation problems during + reassembly, we recommend allocating enough space for the entire + reassembled packet when the first fragment arrives. + + Since fragments are sent in order, the reassembly procedure can give + up on a packet if it receives a fragment out of order. There is one + exception, however. It is possible for successfully received + fragments to be retransmitted. Reassembly software should ignore + repetitious fragments without giving up on the packet. + + Since fragments will be sent briskly, the reassembly procedure can + give up on a partially reassembled packet if no additional fragments + for it arrive within a few seconds. + +2.4. Datalink Layer Retransmission + + For each unicast ARCNET packet, the hardware indicates to the sender + whether or not the receiver acknowledged the packet. To improve + reliability, datalink implementations are encouraged to retransmit + unacknowledged packets or packet fragments. Several retransmissions + may be necessary. Broadcast packets, however, are never acknowledged + and, therefore, they should never be retransmitted. + + Packets which are successfully received may not be successfully + acknowledged. Consequently, retransmission by the datalink + implementation can cause duplicate packets or duplicate fragments. + Duplicate packets are not a problem for IP or ARP. As mentioned in + the previous section, ARCNET reassembly support should ignore any + redundant fragments. + +3. Transmitting IP and ARP Datagrams + + IP and ARP datagrams are carried in the client data area of ARCNET + packets. Datalink support places each datagram in an appropriate + size ARCNET frame, fragmenting IP datagrams larger than 504 octets + into multiple frames as described in the previous section. + +4. IP Address Mappings + + This section explains how each of the three basic 32-bit internet + address types are mapped to 8-bit ARCNET addresses. + +4.1. Unicast Addresses + + A unicast IP address is mapped to an 8-bit ARCNET address using ARP + as specified in [2]. A later section covers the specific values + which should be used in ARP packets sent on ARCNET networks. + + + + +Provan [Page 4] + +RFC 1201 IP on ARCNET February 1991 + + + It is possible to assign IP addresses such that the last eight + bits are the same as the 8-bit ARCNET address. This would allow + direct mapping of IP address to ARCNET address without using a + discovery protocol. Some implementations might provide this as an + option, but it is not recommended practice. Although such hard- + wired mapping is initially appealing, experience shows that ARP is + a much more flexible and convenient approach which has a very + small cost. + +4.2. Broadcast Addresses + + All IP broadcast addresses must be mapped to the ARCNET broadcast + address of 0. + + Unlike unicast packets, ARCNET does not attempt to insure delivery + of broadcast packets, so they may be lost. This will not have a + major impact on IP since neither IP nor ARP expect all packets to + be delivered. + +4.3. Multicast Addresses + + Since ARCNET provides no support for multicasts, all IP multicast + addresses must be mapped to the ARCNET broadcast address of 0. + +5. ARP + + The hardware address length is 1 octet for ARP packets sent over + ARCNET networks. The ARP hardware type for ARCNET is 7. ARP request + packets are broadcast by directing them to ARCNET broadcast address, + which is 0. + +6. RARP + + Reverse Address Resolution Protocol [6] packets can also be + transmitted over ARCNET. For the purposes of datalink transmission + and reception, RARP is identical to ARP and can be handled the same + way. There are a few differences to notice, however, between RARP + when running over ARCNET, which has a one octet hardware address, and + Ethernet, which has a six octet hardware address. + + First, there are only 255 different hardware addresses for any given + ARCNET while there's an very large number of possible Ethernet + addresses. Second, ARCNET hardware addresses are more likely to be + duplicated on different ARCNET networks; Ethernet hardware addresses + will normally be globally unique. Third, an ARCNET hardware address + is not as constant as an Ethernet address: ARCNET hardware addresses + are set by switches, not fixed in ROM as they are on Ethernet. + + + + +Provan [Page 5] + +RFC 1201 IP on ARCNET February 1991 + + +7. Maximum Transmission Unit + + The maximum IP packet length possible using this encapsulation method + is 60,480 octets. Since this length is impractical, all ARCNET + implementations on a given ARCNET network will need to agree on a + smaller value. Therefore, the maximum packet size MUST be + configurable in implementations of this specification. + + In any case, implementations must be able to send and receive IP + datagrams up to 576 octets in length, and are strongly encouraged to + handle IP datagrams up to 1500 octets in length. + + Implementations may accept arriving IP datagrams which are larger + than their configured maximum transmission unit. They are not + required to discard such datagrams. + + To minimize the amount of ARCNET fragmentation, implementations may + want to aim at an optimum IP packet size of 504 bytes. This avoids + the overhead of datalink fragmentation, but at the expense of + increasing the number of IP packets which must be handled by each + node in the path. In addition to encouraging local applications to + generate smaller packets, an implementation might also use the TCP + maximum segment size option to indicate a desire for 464 octet TCP + segments [7], or it might announce an IP MTU of 504 octets through + an MTU discovery mechanism such as [8]. These would inform non- + ARCNET nodes of the smaller optimum packet size. + +8. Assigned Numbers + + Datapoint Corporation assigns ARCNET protocol IDs to identify + different protocols running on the same ARCNET medium. For + implementations of this specification, Datapoint has assigned 212 + decimal to IP, 213 decimal to ARP, and 214 decimal to RARP. These + are not the numbers assigned to the IP encapsulation defined by RFC + 1051 [5]. Implementations of RFC 1051 can exist on the same ARCNET + as implementations of this specification, although the two would not + be able to communicate with each other. + + The Internet Assigned Numbers Authority (IANA) assigns ARP hardware + type values. It has assigned ARCNET the ARP hardware type of 7 [9]. + +Acknowledgements + + Several people have reviewed this specification and provided useful + input. I'd like to thank Wesley Hardell at Datapoint and Troy Thomas + at Novell's Provo office for helping me figure out ARCNET. In + addition, I particularly appreciate the effort by James VanBokkelen + at FTP Software who picked on me until all the fuzzy edges were + + + +Provan [Page 6] + +RFC 1201 IP on ARCNET February 1991 + + + smoothed out. + + The pioneering work in transmitting IP traffic on ARCNET networks was + done by Philippe Prindeville. + +References + + [1] Postel, J., "Internet Protocol", RFC 791, DARPA, September 1981. + + [2] Plummer, D., "An Ethernet Address Resolution Protocol", RFC 826, + MIT, November 1982. + + [3] Datapoint, Corp., "ARCNET Designer's Handbook", Document Number + 61610, 2nd Edition, Datapoint Corporation, 1988. + + [4] Novell, Inc., "ARCNET Packet Header Definition Standard", Novell, + Inc., November 1989. + + [5] Prindeville, P., "A Standard for the Transmission of IP Datagrams + and ARP Packets over ARCNET Networks", RFC 1051, McGill + University, March 1988. + + [6] Finlayson, R., Mann, T., Mogul, J., and M. Theimer, "A Reverse + Address Resolution Protocol", RFC 903, Stanford, June 1984. + + [7] Postel, J., "Transmission Control Protocol", RFC 793, DARPA, + September 1981. + + [8] Mogul, J., Kent, C., Partridge, C., and K. McCloghrie, "IP MTU + Discovery Options", RFC 1063, DEC, BBN, TWG, July 1988. + + [9] Reynolds, J., and J. Postel, "Assigned Numbers", RFC 1060, + USC/Information Sciences Institute, March 1990. + +Security Considerations + + Security issues are not discussed in this memo. + +Author's Address + + Don Provan + Novell, Inc. + 2180 Fortune Drive + San Jose, California, 95131 + + Phone: (408) 473-8440 + EMail: donp@Novell.Com + + + + +Provan [Page 7] diff --git a/private/ntos/ndis/testprot/inc/common.h b/private/ntos/ndis/testprot/inc/common.h new file mode 100644 index 000000000..eccf084b3 --- /dev/null +++ b/private/ntos/ndis/testprot/inc/common.h @@ -0,0 +1,835 @@ +// ------------------------------------- +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// common.h +// +// Abstract: +// +// Common definitions for Test Protocol driver and its control application. +// +// Author: +// +// Tomad Adams (tomad) 11-Mar-1991 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Sanjeev Katariya (sanjeevk) +// 4-19-1993 Added support for varying address length dependent on the media type +// Effected the structure CMD_ARGS +// +// Tim Wynsma (timothyw) +// 4-27-1994 Added support for performance testing +// 5-18-1994 1st round, global variable access +// 6-08-1994 Client-server model for performance tests +// +// ----------------------------------- + + +#include "defaults.h" + +// +// Define the type of member that the protocol will be running as. +// +// As a CLIENT the protocol is responsible for initiating the test, +// controlling the flow of the test, and keeping results. A SERVER +// merely loops packets back to the CLIENT in the manner specified +// by the test arguments. A protocol may act as BOTH a CLIENT and a +// Server. +// + +typedef enum _MEMBER_TYPE { + TP_CLIENT, + TP_SERVER, + BOTH +} MEMBER_TYPE; + +// +// Define the size of packets to be used in a test. +// +// Fixedsize means the all packets in the test will be of a fixedsize +// X, Randomsize means the all packets in the test will randomly range +// between a minimum packetsize and X, Cyclical means that packets of +// every size will be sent start at a minimum size and walking through +// all sizes until the maximum packetsize for the given media type +// has been reached. +// + +typedef enum _PACKET_TYPE { + FIXEDSIZE, + RANDOMSIZE, + CYCLICAL +} PACKET_TYPE; + + +// +// Define the different sizes of buffers a packet made be constructed with. +// +// Rand means the size of each buffer will be randomly selected from a +// range of zero to a , Small means the size of each buffer will be randomly +// selected from a range of zero to , Zeros and Ones mean that the size +// of each buffer will be selected the same way as Rand, however the will +// be a large number of zero or one byte buffers intersperced in each +// packet. Known means the each buffer in the packet is the same size. +// + +typedef enum _PACKET_MAKEUP { + RAND, + SMALL, + ZEROS, + ONES, + KNOWN +} PACKET_MAKEUP; + +// +// Define the method the Server will use to respond to each packet the +// CLIENT sends. +// +// No Response means the Server will never respond to the packets from the +// CLIENT, Full Response means the server will respond to every packet the +// CLIENT sends with a packet of the same size and data, Ack Every means the +// Server will send an acknowlegement packet after every from the CLIENT, Ack +// Every 10 means the Server will send an acknowlegement packet after every +// 10th packet from the CLIENT, Ack 10 Times means the Server will send 10 +// acknowlegement packets for every packet the CLIENT sends. +// + +typedef enum _RESPONSE_TYPE { + FULL_RESPONSE, + ACK_EVERY, + ACK_10_TIMES, + NO_RESPONSE +} RESPONSE_TYPE; + +// +// Define the delay between two consecutive packet sends to a given Server. +// +// The delay will either be a fixed number of iterations, or a random +// number of iterations. NOTE: That this will be changing to a fixed +// or random length of time in the future. +// + +typedef enum _INTERPACKET_DELAY { + FIXEDDELAY, + RANDOMDELAY +} INTERPACKET_DELAY; + + +// +// Registry typedefs. +// + +// +// Define the operation being asked to execute on the registry +// + +typedef enum _OPERATION { + ADD_KEY, + DELETE_KEY, + QUERY_KEY, + ADD_VALUE, + CHANGE_VALUE, + DELETE_VALUE, + QUERY_VALUE +} OPERATION; + +// +// Define the 4 possible registry DataBases +// + +typedef enum _KEYDBASE { + CLASSES_ROOT, + CURRENT_USER, + LOCAL_MACHINE, + USERS +} KEYDBASE; + +// +// Define the various types a value can be +// + +typedef enum _VALUETYPE { + BINARY, + DWORD_REGULAR, + DWORD_LITTLE_ENDIAN, + DWORD_BIG_ENDIAN, + EXPAND_SZ, + LINK, + MULTI_SZ, + NONE, + RESOURCE_LIST, + SZ +} VALUETYPE; + +// +// Tpctl Command Codes +// + +#define CMD_ERR 0x00000000 // an invalid command was entered. +#define GETSTATS 0x00000001 // get the test statistics. +#define DISPSTATS 0x00000002 // continuously get test statistics. +#define VERBOSE 0x00000003 // toggle verbose mode on and off. +#define SETENV 0x00000004 // set the driver's test environment vars. +#define READSCRIPT 0x00000005 // read a script file. +#define BEGINLOGGING 0x00000006 // begin logging command line cmds. +#define ENDLOGGING 0x00000007 // end logging command line cmds. +#define WAIT 0x00000008 // wait for X msecs. +#define GO 0x00000009 // Tell remote protocol to continue. +#define PAUSE 0x0000000A // Pause the local protocol. +#define LOAD 0x0000000B // call NtLoad to load a driver +#define UNLOAD 0x0000000C // call NtUnload to unload a driver +#define OPEN 0x0000000D // open a MAC adapter. +#define CLOSE 0x0000000E // close a MAC adapter. +#define SETPF 0x0000000F // set the packet filter on the MAC. +#define SETLA 0x00000010 // set the lookahead buffer size. +#define DELMA 0x00000011 // del a multicast address from the MAC. +#define ADDMA 0x00000012 // add a multicast address to the MAC. +#define SETFA 0x00000013 // set a functional address on the MAC. +#define SETGA 0x00000014 // set a group address on the MAC. +#define QUERYINFO 0x00000015 // query MAC information. +#define QUERYSTATS 0x00000016 // query GLOBAL MAC information. +#define SETINFO 0x00000017 // set MAC information. +#define RESET 0x00000018 // reset the MAC adapter. +#define SEND 0x00000019 // send a packet or packets. +#define STOPSEND 0x0000001A // stop sending packets. +#define WAITSEND 0x0000001B // wait for send to end, display results. +#define RECEIVE 0x0000001C // start accepting packets. +#define STOPREC 0x0000001D // stop accepting packets. +#define GETEVENTS 0x0000001E // get events off the EVENT_QUEUE. +#define STRESS 0x0000001F // run a stress test, (CLIENT or BOTH). +#define STRESSSERVER 0x00000020 // act as a SERVER for a stress test. +#define ENDSTRESS 0x00000021 // end a stress test. +#define WAITSTRESS 0x00000022 // wait for stress to end, display results. +#define CHECKSTRESS 0x00000023 // see if stress has ended, if so display +#define BREAKPOINT 0x00000024 // call DbgBreakPoint. +#define QUIT 0x00000025 // quit TPCTL.EXE. +#define HELP 0x00000026 // print the help screen + +// +// New Tpctl Command Codes +// + +#define SHELL 0x00000027 +#define RECORDINGENABLE 0x00000028 +#define RECORDINGDISABLE 0x00000029 +#define DISABLE 0x0000002A +#define ENABLE 0x0000002B +#define REGISTRY 0x0000002C + +// performance testing + +#define PERFSERVER 0x0000002D +#define PERFCLIENT 0x0000002E +#define PERFABORT 0x0000002F // only used in TP_CONTROL_CODE call + +// globalvars + +#define SETGLOBAL 0x00000030 + + +#define CMD_COMPLETED 0xFFFFFFFF // skip the second half of cmd processing. + + + +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code represent the +// method, and specify how the input and output buffers are +// passed to the driver via NtDeviceIoControlFile() +// +// + +#define IOCTL_METHOD 2 + +#define IOCTL_TP_BASE FILE_DEVICE_TRANSPORT + +#define TP_CONTROL_CODE(request,method) \ + ((IOCTL_TP_BASE)<<16 | (request<<2) | method) + + +#define IOCTL_TP_GETSTATS TP_CONTROL_CODE( GETSTATS, IOCTL_METHOD ) +#define IOCTL_TP_DISPSTATS TP_CONTROL_CODE( DISPSTATS, IOCTL_METHOD ) +#define IOCTL_TP_SETENV TP_CONTROL_CODE( SETENV, IOCTL_METHOD ) +#define IOCTL_TP_GO TP_CONTROL_CODE( GO, IOCTL_METHOD ) +#define IOCTL_TP_PAUSE TP_CONTROL_CODE( PAUSE, IOCTL_METHOD ) +#define IOCTL_TP_OPEN TP_CONTROL_CODE( OPEN, IOCTL_METHOD ) +#define IOCTL_TP_CLOSE TP_CONTROL_CODE( CLOSE, IOCTL_METHOD ) +#define IOCTL_TP_SETPF TP_CONTROL_CODE( SETPF, IOCTL_METHOD ) +#define IOCTL_TP_SETLA TP_CONTROL_CODE( SETLA, IOCTL_METHOD ) +#define IOCTL_TP_ADDMA TP_CONTROL_CODE( ADDMA, IOCTL_METHOD ) +#define IOCTL_TP_DELMA TP_CONTROL_CODE( DELMA, IOCTL_METHOD ) +#define IOCTL_TP_SETFA TP_CONTROL_CODE( SETFA, IOCTL_METHOD ) +#define IOCTL_TP_SETGA TP_CONTROL_CODE( SETGA, IOCTL_METHOD ) +#define IOCTL_TP_QUERYINFO TP_CONTROL_CODE( QUERYINFO, IOCTL_METHOD ) +#define IOCTL_TP_QUERYSTATS TP_CONTROL_CODE( QUERYSTATS, IOCTL_METHOD ) +#define IOCTL_TP_SETINFO TP_CONTROL_CODE( SETINFO, IOCTL_METHOD ) +#define IOCTL_TP_RESET TP_CONTROL_CODE( RESET, IOCTL_METHOD ) +#define IOCTL_TP_SEND TP_CONTROL_CODE( SEND, IOCTL_METHOD ) +#define IOCTL_TP_STOPSEND TP_CONTROL_CODE( STOPSEND, IOCTL_METHOD ) +#define IOCTL_TP_RECEIVE TP_CONTROL_CODE( RECEIVE, IOCTL_METHOD ) +#define IOCTL_TP_STOPREC TP_CONTROL_CODE( STOPREC, IOCTL_METHOD ) +#define IOCTL_TP_GETEVENTS TP_CONTROL_CODE( GETEVENTS, IOCTL_METHOD ) +#define IOCTL_TP_STRESS TP_CONTROL_CODE( STRESS, IOCTL_METHOD ) +#define IOCTL_TP_STRESSSERVER TP_CONTROL_CODE( STRESSSERVER, IOCTL_METHOD ) +#define IOCTL_TP_ENDSTRESS TP_CONTROL_CODE( ENDSTRESS, IOCTL_METHOD ) +#define IOCTL_TP_BREAKPOINT TP_CONTROL_CODE( BREAKPOINT, IOCTL_METHOD ) +#define IOCTL_TP_TRANSFERDATA TP_CONTROL_CODE( TRANSFERDATA, IOCTL_METHOD ) +#define IOCTL_TP_QUIT TP_CONTROL_CODE( QUIT, IOCTL_METHOD ) + +// performance testing + +#define IOCTL_TP_PERF_SERVER TP_CONTROL_CODE( PERFSERVER, IOCTL_METHOD) +#define IOCTL_TP_PERF_CLIENT TP_CONTROL_CODE( PERFCLIENT, IOCTL_METHOD) +#define IOCTL_TP_PERF_ABORT TP_CONTROL_CODE( PERFABORT, IOCTL_METHOD) + +// +// The following structure contains the arguments passed +// to the driver for each of the commands. +// +// NOTE: Any additions to arguments in this structure must +// be mapped in the parse options structure TESTPARAMS for +// the given command, and in the TpctlInitCommandBuffer +// routine for the given command. +// +// Current types of addresses in use +// +// 1. STATION ADDRESS 2. STRESS MULTICAST ADDRESS +// 3. PAUSE_GO REMOTE ADDRESS 4 MULTICAST ADDRESS +// 5. GROUP ADDRESS 6. FUNCTIONAL ADDRESS +// 7. DESTINATION ADDRESS 8. RESEND ADDRESS +// +// These can all be classified under two headings +// +// CURRENT ADDRESS LENGTHS(SOURCE, DESTINATION) and +// FUNCTIONAL/GROUP ADDRESS LENGTHS which are dependencies of the first category. +// +// Functional address length will always be (CURRENT_ADDRESS_LEN*10)/15 +// e.g. When the address length is 6, FA's are 4 +// WHen the address length is 2, FA's are 1 +// +#define TPCTL_OPTION_SIZE 14 + +typedef struct _CMD_ARGS { + + ULONG CmdCode; + ULONG OpenInstance; + + + + union _ARGS { + + // + // SETENV command environment variable arguments. + // + + struct _ENV { + + ULONG WindowSize; + ULONG RandomBufferNumber; + UCHAR StressAddress[ADDRESS_LENGTH]; + UCHAR ResendAddress[ADDRESS_LENGTH]; + ULONG StressDelayInterval; + ULONG UpForAirDelay; + ULONG StandardDelay; + + } ENV; + + // + // READSCRIPT script and logging file arguments. + // + + struct _FILES { + + UCHAR ScriptFile[MAX_FILENAME_LENGTH]; + UCHAR LogFile[MAX_FILENAME_LENGTH]; + + } FILES; + + // + // RECORDING script file + // + + struct _RECORD { + + UCHAR ScriptFile[MAX_FILENAME_LENGTH]; + + } RECORD; + + // + // Registry operations + // + + struct _REGISTRY_ENTRY { + + UCHAR SubKey[MAX_KEYNAME_LENGTH] ; + UCHAR SubKeyClass[MAX_CLASS_LENGTH] ; + UCHAR SubKeyValueName[MAX_VALUENAME_LENGTH] ; + UCHAR SubKeyValue[MAX_VALUE_LENGTH] ; + OPERATION OperationType; + KEYDBASE KeyDatabase ; + VALUETYPE ValueType ; + + } REGISTRY_ENTRY; + + // + // PAUSE and GO protocol arguments. + // + + struct _PAUSE_GO { + + UCHAR RemoteAddress[ADDRESS_LENGTH]; + ULONG TestSignature; + ULONG UniqueSignature; + + } PAUSE_GO; + + // + // OPEN command adapter name argument. + // + + struct _OPEN_ADAPTER + { + UCHAR AdapterName[MAX_ADAPTER_NAME_LENGTH]; + BOOLEAN NoArcNet; + } OPEN_ADAPTER; + + UCHAR DriverName[MAX_ADAPTER_NAME_LENGTH]; + + // + // QUERYINFO command information OID. + // + + struct _TPQUERY { + + NDIS_OID OID; + //NDIS_REQUEST_TYPE RequestType; + + } TPQUERY; + + // + // QUERYSTATS command Device name and OID to query. + // + + struct _TPQUERYSTATS { + + UCHAR DeviceName[MAX_ADAPTER_NAME_LENGTH]; + NDIS_OID OID; + + } TPQUERYSTATS; + + // + // SETINFO command information class and info. + // + + struct _TPSET { + + NDIS_OID OID; + + union _U { + + ULONG PacketFilter; + ULONG LookaheadSize; + UCHAR MulticastAddress[MAX_MULTICAST_ADDRESSES][ADDRESS_LENGTH]; + UCHAR FunctionalAddress[FUNCTIONAL_ADDRESS_LENGTH]; + UCHAR GroupAddress[FUNCTIONAL_ADDRESS_LENGTH]; + + } U; + + ULONG NumberMultAddrs; + + } TPSET; + + // + // SEND command packet definitions. + // + + struct _TPSEND { + + UCHAR DestAddress[ADDRESS_LENGTH]; + ULONG PacketSize; + ULONG NumberOfPackets; + UCHAR ResendAddress[ADDRESS_LENGTH]; + + } TPSEND; + + // + // PERFSEND command packet definitions + // + + struct _TPPERF + { + UCHAR PerfServerAddr[ADDRESS_LENGTH]; + UCHAR PerfSendAddr[ADDRESS_LENGTH]; + ULONG PerfPacketSize; + ULONG PerfNumPackets; + ULONG PerfDelay; + ULONG PerfMode; + } TPPERF; + + // + // STRESS command test arguments. + // + + struct _TPSTRESS { + + MEMBER_TYPE MemberType; + PACKET_TYPE PacketType; + ULONG PacketSize; + PACKET_MAKEUP PacketMakeUp; + RESPONSE_TYPE ResponseType; + INTERPACKET_DELAY DelayType; + ULONG DelayLength; + ULONG TotalIterations; + ULONG TotalPackets; + ULONG WindowEnabled; + ULONG DataChecking; + ULONG PacketsFromPool; + UCHAR AdapterName[MAX_ADAPTER_NAME_LENGTH]; + + } TPSTRESS; + + // + // HELP Command to print the help message for. + // + + UCHAR CmdName[MAX_FILENAME_LENGTH]; + + } ARGS; + + + // + // STARTCHANGE + // + UCHAR CurrentAddressLength; + UCHAR CurrentFALength; + + UCHAR TpctlOptions[TPCTL_OPTION_SIZE]; + // + // STOPCHANGE + // + +} CMD_ARGS, *PCMD_ARGS; + +// +// User App command data struct to hold per command info. +// + +typedef struct _CMD_CODE { + ULONG CmdCode; + PSZ CmdName; + PSZ CmdAbbr; +} CMD_CODE, * PCMD_CODE; + +#define NUM_COMMANDS sizeof( CommandCode ) / sizeof( CommandCode[0] ) + +// +// Set Environment Command Variables +// + +typedef struct _ENVIRONMENT_VARIABLES { + ULONG WindowSize; + ULONG RandomBufferNumber; + UCHAR StressAddress[ADDRESS_LENGTH]; + UCHAR ResendAddress[ADDRESS_LENGTH]; + ULONG StressDelayInterval; + ULONG UpForAirDelay; + ULONG StandardDelay; + ULONG MulticastListSize; +} ENVIRONMENT_VARIABLES, * PENVIRONMENT_VARIABLES; + +// +// The pointers to these structures need to be defined as UNALIGNED for MIPS. +// + +// +// Counters used to measure performance and results of a test run. +// + +typedef struct _GLOBAL_COUNTERS { + ULONG Sends; + ULONG SendComps; + ULONG Receives; + ULONG ReceiveComps; + ULONG CorruptRecs; + ULONG InvalidPacketRecs; +} GLOBAL_COUNTERS; +typedef GLOBAL_COUNTERS UNALIGNED *PGLOBAL_COUNTERS; + +// +// Counters for a given Open Instance +// + +typedef struct _INSTANCE_COUNTERS { + ULONG Sends; + ULONG SendPends; + ULONG SendComps; + ULONG SendFails; + + ULONG Receives; + ULONG ReceiveComps; + ULONG CorruptRecs; + ULONG XferData; + + ULONG XferDataPends; + ULONG XferDataComps; + ULONG XferDataFails; +} INSTANCE_COUNTERS; +typedef INSTANCE_COUNTERS UNALIGNED *PINSTANCE_COUNTERS; + +// +// The following data structure are use to pass specific test results +// up to the application from the driver. +// + +typedef struct _SERVER_RESULTS { + ULONG Signature; + UCHAR Address[ADDRESS_LENGTH]; + ULONG OpenInstance; + BOOLEAN StatsRcvd; + INSTANCE_COUNTERS Instance; + INSTANCE_COUNTERS S_Instance; + GLOBAL_COUNTERS S_Global; +} SERVER_RESULTS, *PSERVER_RESULTS; + +#define MAX_SERVERS 10 + +typedef struct _STRESS_RESULTS { + ULONG Signature; + UCHAR Address[ADDRESS_LENGTH]; + ULONG OpenInstance; + ULONG NumServers; + ULONG PacketsPerSecond; + GLOBAL_COUNTERS Global; + SERVER_RESULTS Servers[MAX_SERVERS]; +} STRESS_RESULTS, *PSTRESS_RESULTS; + +typedef struct _SEND_RECEIVE_RESULTS { + ULONG Signature; + BOOLEAN ResultsExist; + INSTANCE_COUNTERS Counters; +} SEND_RECEIVE_RESULTS, *PSEND_RECEIVE_RESULTS; + +typedef struct _PERF_RESULTS +{ + ULONG Signature; + BOOLEAN ResultsExist; + ULONG Mode; + ULONG PacketSize; + ULONG PacketCount; + ULONG Milliseconds; + ULONG Sends; + ULONG SendFails; + ULONG Receives; + ULONG Restarts; + ULONG SelfReceives; + ULONG S_Milliseconds; + ULONG S_Sends; + ULONG S_SendFails; + ULONG S_Receives; + ULONG S_Restarts; + ULONG S_SelfReceives; +} PERF_RESULTS, *PPERF_RESULTS; + + +typedef enum _TP_EVENT_TYPE { + CompleteOpen, + CompleteClose, + CompleteSend, + CompleteTransferData, + CompleteReset, + CompleteRequest, + IndicateReceive, + IndicateReceiveComplete, + IndicateStatus, + IndicateStatusComplete, + Unknown +} TP_EVENT_TYPE; + +typedef struct _EVENT_RESULTS { + ULONG Signature; + TP_EVENT_TYPE TpEventType; + BOOLEAN QueueOverFlowed; + //TP_EVENT_INFO TpEventInfo; +} EVENT_RESULTS, * PEVENT_RESULTS; + +typedef struct _REQUEST_RESULTS { + ULONG Signature; + ULONG IoControlCode; + BOOLEAN RequestPended; + NDIS_STATUS RequestStatus; + NDIS_REQUEST_TYPE NdisRequestType; + NDIS_OID OID; + UINT BytesReadWritten; + UINT BytesNeeded; + NDIS_STATUS OpenRequestStatus; + UINT InformationBufferLength; + UCHAR InformationBuffer[1]; +} REQUEST_RESULTS, *PREQUEST_RESULTS; + +#define IOCTL_BUFFER_SIZE 0x200 + +#define OPEN_RESULTS_SIGNATURE 0x12345678 +#define CLOSE_RESULTS_SIGNATURE 0x23456789 +#define RESET_RESULTS_SIGNATURE 0x34567890 +#define REQUEST_RESULTS_SIGNATURE 0x45678901 + +#define EVENT_RESULTS_SIGNATURE 0x56789012 +#define SENDREC_RESULTS_SIGNATURE 0x67890123 +#define STRESS_RESULTS_SIGNATURE 0x89012345 +#define PERF_RESULTS_SIGNATURE 0x90123456 + +// +// Create two sets of debug macros to allow printing of debug messages, +// and enabling ASSERT that will be checking the values and pointers +// returned by the various ndis indications, and completions. +// + +#if DBG + +#define IF_TPDBG(flags) \ + if ( TpDebug & ( flags )) + +#define TP_ASSERT(equality) { \ + if (!(equality)) { \ + TpPrint0("ASSERT: "); \ + TpPrint0(#equality); \ + TpBreakPoint(); } } +// +// +// if ( TpAssert == TRUE ) { +// ASSERT(equality); +// } +// } + +// +// DEBUGGING SUPPORT. IF_TPDBG is a macro that is turned on at compile +// time to enable debugging code in the system. If this is turned on, then +// you can use the IF_TPDBG(flags) macro in the TP code to selectively +// enable a piece of debugging code in the transport. This macro tests +// TpDebug, a global ULONG defined in TPDRVR.C. +// + +#define TP_DEBUG_NDIS_CALLS 0x00000001 // print Ndis Status returns +#define TP_DEBUG_NDIS_ERROR 0x00000002 // print Ndis Error returns +#define TP_DEBUG_STATISTICS 0x00000004 // print stress statistics +#define TP_DEBUG_DATA 0x00000008 // print Data Corruption msgs + +#define TP_DEBUG_DISPATCH 0x00000010 // TpDispatch routines +#define TP_DEBUG_IOCTL_ARGS 0x00000020 // print args from the ioctl + +#define TP_DEBUG_NT_STATUS 0x00000100 // print !success NT Status returns +#define TP_DEBUG_DPC 0x00000200 // print DPC problem info +#define TP_DEBUG_INITIALIZE 0x00000400 // print init error info +#define TP_DEBUG_RESOURCES 0x00000800 // print resource allocation errors + +#define TP_DEBUG_BREAKPOINT 0x00001000 // enable and disable DbgBreakPoints + +#define TP_DEBUG_INFOLEVEL_1 0x00010000 // print information. Level 1 +#define TP_DEBUG_INFOLEVEL_2 0x00020000 // through 4 represent different +#define TP_DEBUG_INFOLEVEL_3 0x00040000 // types of information where +#define TP_DEBUG_INFOLEVEL_4 0x00080000 // Level 1 is purely informational + // Level 2 is corrective action information + // Level 3 is sequential action information + // Level 4 Reserved. Currently undefined. + +#define TP_DEBUG_ALL 0xFFFFFFFF // turns on all flags + +extern ULONG TpDebug; // in TPDRVR.C. +extern BOOLEAN TpAssert; // in TPDRVR.C. + +#define TpPrint0(fmt) DbgPrint(fmt) +#define TpPrint1(fmt,v1) DbgPrint(fmt,v1) +#define TpPrint2(fmt,v1,v2) DbgPrint(fmt,v1,v2) +#define TpPrint3(fmt,v1,v2,v3) DbgPrint(fmt,v1,v2,v3) +#define TpPrint4(fmt,v1,v2,v3,v4) DbgPrint(fmt,v1,v2,v3,v4) +#define TpPrint5(fmt,v1,v2,v3,v4,v5) DbgPrint(fmt,v1,v2,v3,v4,v5) +#define TpPrint6(fmt,v1,v2,v3,v4,v5,v6) DbgPrint(fmt,v1,v2,v3,v4,v5,v6) + +#define TpBreakPoint() DbgBreakPoint() + +#else // NO DBG + +// +// Disable debugging IFs and printing +// + +#define IF_TPDBG(flags) \ + if (0) + +#define TP_ASSERT(equality) \ + if (0) + +#define TpPrint0(fmt) +#define TpPrint1(fmt,v1) +#define TpPrint2(fmt,v1,v2) +#define TpPrint3(fmt,v1,v2,v3) +#define TpPrint4(fmt,v1,v2,v3,v4) +#define TpPrint5(fmt,v1,v2,v3,v4,v5) +#define TpPrint6(fmt,v1,v2,v3,v4,v5,v6) + +#define TpBreakPoint() + +#endif // DBG + +// +// define null packet type for command line interface +// + +#define NDIS_PACKET_TYPE_NONE 0x00 + + +// +// Test Protocol Status Returns +// + +// +// No stress servers found for a stress test. +// + +#define TP_STATUS_NO_SERVERS ((NDIS_STATUS)0x4001FFFFL) + +// +// No events on the event queue. +// + +#define TP_STATUS_NO_EVENTS ((NDIS_STATUS)0x4001FFFEL) + +// +// Go or Pause Timed out with out receiving correct response. +// + +#define TP_STATUS_TIMEDOUT ((NDIS_STATUS)0x4001FFFDL) + +// +// OID Info structure containing the size of the oid info and what +// the valid uses of the structure are: i.e. querying and setting +// info for that OID. +// + +typedef struct _OID_INFO { + NDIS_OID Oid; + ULONG Length; + BOOLEAN QueryInfo; + BOOLEAN SetInfo; + BOOLEAN QueryStats; +} OID_INFO, * POID_ONFO; + +extern OID_INFO OidArray[]; + +#define NUM_OIDS sizeof( OidArray ) / sizeof( OidArray[0] ) + +ULONG +TpLookUpOidInfo( + IN NDIS_OID RequestOid + ); + + + + diff --git a/private/ntos/ndis/testprot/inc/defaults.h b/private/ntos/ndis/testprot/inc/defaults.h new file mode 100644 index 000000000..19f9d6cd9 --- /dev/null +++ b/private/ntos/ndis/testprot/inc/defaults.h @@ -0,0 +1,193 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + defaults.h + +Abstract: + + Default definitions for Test Protocol driver and its control application. + +Author: + + Tomad Adams (tomad) 7-Nov-1991 + + Sanjeev Katariya (sanjeevk) 4-6-1993 + Added support for native ARCNET + +Environment: + + Kernel mode, FSD + +Revision History: + +--*/ + +// +// The number of Open Instances the Test Protocol will support +// + +#define NUM_OPEN_INSTANCES 8 + +// +// +// + +static UCHAR NULL_ADDRESS[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static UCHAR STRESS_MULTICAST[] = { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }; + +static UCHAR DEFAULT_MULTICAST[] = { 0x07, 0x12, 0x34, 0x56, 0x78, 0x90 }; + +static UCHAR STRESS_FUNCTIONAL[] = { 0xC0, 0x00, 0x00, 0x01, 0x00, 0x00 }; + +static UCHAR DEFAULT_FUNCTIONAL[] = { 0xC0, 0x00, 0x12, 0x23, 0x34, 0x45 }; + +static UCHAR STRESS_ARCNET_BROADCAST[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// + +#define DD_TP_DEVICE_NAME "\\Device\\TestProtocol" + +// +// TPCTL Defaults +// + +// +// The symbolic link for the test protocol device driver +// name for win32 apis +// + +#define DEVICE_NAME "\\\\.\\Tpdrvr" + +#define TPCTL_CMDLINE_SIZE 0x200 + +#define TPCTL_MAX_ARGC 20 + +#define TPCTL_PROMPT "[TPCTL:]" + +#define TPCTL_MAX_PATHNAME_SIZE 256 + +#define ADDRESS_LENGTH 6 + +// +// STARTCHANGE +// +#define ADDRESS_LENGTH_1_OCTET 1 + +#define ADDRESS_LENGTH_2_OCTETS 2 +// +// STOPCHANGE +// + + +#define MAX_MULTICAST_ADDRESSES 64 + +#define FUNCTIONAL_ADDRESS_LENGTH 4 + +#define GROUP_ADDRESS_LENGTH 4 + +#define MAX_FILENAME_LENGTH 256 + +#define MAX_ADAPTER_NAME_LENGTH 32 + +#define MAX_DRIVER_NAME_LENGTH 32 + +#define MAX_KEYNAME_LENGTH 256 + +#define MAX_CLASS_LENGTH 80 + +#define MAX_VALUENAME_LENGTH 256 + +#define MAX_VALUE_LENGTH 1024 + + + +// +// STARTCHANGE +// +#define ARCNET_DEFAULT_PROTOCOLID 0xE7 +// +// STOPCHANGE +// + +// +// Time definitions to be used by the driver in calls to KeSetTimer. +// These times are hard coded in the driver in some cases, or passed +// down to the driver via the SETENV call in others. +// + +#define ONE_HUNDREDTH_SECOND 100000 +#define ONE_TENTH_SECOND ( 10 * ONE_HUNDREDTH_SECOND ) +#define ONE_SECOND ( 100 * ONE_HUNDREDTH_SECOND ) +#define ONE_MINUTE ( 600 * ONE_HUNDREDTH_SECOND ) + + +// +// TPCTL default command argument values +// + +#define OPEN_INSTANCE 1 + +#define TPCTL_SCRIPTFILE "TESTPROT.TPS" + +#define TPCTL_LOGFILE "TESTPROT.LOG" + +#define TPCTL_CMDLINE_LOG "CMDLINE.LOG" + +#define TPCTL_CMDLINE_SCRIPT "CMDLINE.TPS" + +#define RESEND_ADDRESS "ResendAddress" + +#define LOCAL_ADDRESS "LocalAddress" + +#define ADAPTER_NAME "ELNKII" + +#define LOOKAHEADSIZE 0x64 + +#define PACKET_SIZE 0x200 + +#define DELAY_LENGTH 0 + +#define STRESS_ITERATIONS -1 + +#define STRESS_PACKETS -1 + +#define WINDOWING_ENABLED "TRUE" + +#define DATA_CHECKING "TRUE" + +#define PACKETS_FROM_POOL "TRUE" + + +// +// TPCTL default environment variable values +// + +#define WINDOW_SIZE 10 + +#define BUFFER_NUMBER 5 + +#define DELAY_INTERVAL 10 + +#define UP_FOR_AIR_DELAY 100000 + +#define STANDARD_DELAY 10000 + +// +// Window control defines +// + +#define MAX_PACKET_DELAY 100 // XXX: is this the correct size? + +#define MAX_WINDOW_RESETS 3 + diff --git a/private/ntos/ndis/testprot/tpctl/cmd.c b/private/ntos/ndis/testprot/tpctl/cmd.c new file mode 100644 index 000000000..ec5ca1465 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/cmd.c @@ -0,0 +1,4160 @@ +// -------------------------------------------------------------------- +// +// 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; + +} + + diff --git a/private/ntos/ndis/testprot/tpctl/cpuperf.c b/private/ntos/ndis/testprot/tpctl/cpuperf.c new file mode 100644 index 000000000..ebd92cb11 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/cpuperf.c @@ -0,0 +1,307 @@ +// +// Include files +// +// #include <ntos.h> + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntexapi.h> + +#include <windows.h> + +extern VOID printf(UCHAR *,...); +// extern LARGE_INTEGER KeQueryPerformanceCounter(PLARGE_INTEGER); + +#define MAX_CPUS 64 // supports maximum of 64 cpus... + +// #include "tpdefs.h" +// #include "media.h" +// #include "tpprocs.h" +// #include "string.h" + +PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pStartData; +PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pEndData; +ULONG NumCpus; +ULONG ProcessorBufSize; +PULONG pKernelPercent; +DWORD StartTestTime; + +// -------------------------------------------------- +// +// Function: TpPerfInitCpuUsage +// +// Arguments: none +// +// Returns: none +// +// Descript: This function allocates and initializes all the structures +// necessary for finding the %cpu usage during performance tests +// +// -------------------------------------------------- + + +VOID +CpuUsageInit(VOID) +{ + if (!NumCpus) // if NumCpus is zero, need to do first pass initializations + { // (allocate all buffers, set NumCpus) + + SYSTEM_BASIC_INFORMATION BasicInfo; + + // + // First get the number of processors... + // + + NtQuerySystemInformation(SystemBasicInformation, + &BasicInfo, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + + NumCpus = BasicInfo.NumberOfProcessors; + if ( (NumCpus < 1) || (NumCpus > MAX_CPUS) ) + { + printf("CpuUsageInit: Illegal number of cpus\n"); + goto init_abort; + } + + // + // get the memory for the processor instance data + // + + ProcessorBufSize = NumCpus * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + + if ( (pStartData = GlobalAlloc(GMEM_FIXED, ProcessorBufSize)) == NULL) + { + printf("CpuUsageInit: unable to allocate pStartData buffer\n"); + goto init_abort; + } + + if ( (pEndData = GlobalAlloc(GMEM_FIXED, ProcessorBufSize)) == NULL) + { + printf("CpuUsageInit: unable to allocate pEndData buffer\n"); + goto init_abort; + } + + if ( (pKernelPercent = GlobalAlloc(GMEM_FIXED , (NumCpus + 1) * sizeof(ULONG))) == NULL) + { + printf("CpuUsageInit: unable to allocate pKernelPercent buffer\n"); +init_abort: + if (pStartData) + { + GlobalFree(pStartData); +// pStartData = NULL; + } + if (pEndData) + { + GlobalFree(pEndData); +// pEndData = NULL + } + if (pKernelPercent) + { + GlobalFree(pKernelPercent); +// pKernelPercent = NULL; + } + NumCpus = 0; + return; + } + } + + NtQuerySystemInformation(SystemProcessorPerformanceInformation, + pStartData, + ProcessorBufSize, + NULL); + StartTestTime = GetTickCount(); + +} + + +// ------------------------------------------------ +// +// Function: TpPerfGetCpuUsage +// +// Arguments: oldptr -- cpu processor performance data from time 0 +// ProcessorTime -- place to put processor times +// KernelTime -- place to put kernel times +// +// Returns: number of processors--0 if error +// +// Descript: This function reads the performance counters +// at the end of the test, stored them in an appropriate +// location, and then cleans up the structures and exits +// +// ------------------------------------------------- + + +ULONG +CpuUsageGetData(PULONG *ppKernPC, + ULONG TestTime) +{ + SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *pOldProcessorInformation; + SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *pNewProcessorInformation; + ULONG CurProc; + LARGE_INTEGER TotalProcessorTime; + LARGE_INTEGER TotalKernelTime; + LARGE_INTEGER TempUser; + LARGE_INTEGER TempKern; + LARGE_INTEGER TempIdle; + LARGE_INTEGER trash; + LARGE_INTEGER WholeTestTime; + DWORD EndTestTime; + ULONG flag; + + if (!NumCpus) + { + printf("CpuUsageGetData: called before initialization\n"); + return 0; + } + + + NtQuerySystemInformation(SystemProcessorPerformanceInformation, + pEndData, + ProcessorBufSize, + NULL); + // + // find the total time in milliseconds + // + EndTestTime = GetTickCount(); +// if (EndTestTime > StartTestTime) +// { + WholeTestTime.LowPart = EndTestTime - StartTestTime; +// } +// else +// { +// +// } +// WholeTestTime.LowPart = GetTickCount() - StartTestTime; + WholeTestTime.HighPart = 0; +// printf("Kludge factor = %d/%d\n", TestTime, WholeTestTime.LowPart); + + TotalProcessorTime.HighPart = 0; + TotalProcessorTime.LowPart = 0; + TotalKernelTime.HighPart = 0; + TotalKernelTime.LowPart = 0; + + // + // Total time = UserTime + KernelTime + // KernelTime = IdleTime + Priviledged time + // We need total time and priviledged time + // + + pOldProcessorInformation = pStartData; + pNewProcessorInformation = pEndData; + + for ( CurProc = 0; CurProc < NumCpus; CurProc++ ) + { +// DEBUG +// printf("\nCpuUsageGetData: processor %d\n", CurProc); +// printf("Initial Idletime = %08x%08x\n", pOldProcessorInformation->IdleTime.HighPart, +// pOldProcessorInformation->IdleTime.LowPart); +// printf("Initial Usertime = %08x%08x\n", pOldProcessorInformation->UserTime.HighPart, +// pOldProcessorInformation->UserTime.LowPart); +// printf("Initial Kerntime = %08x%08x\n\n", pOldProcessorInformation->KernelTime.HighPart, +// pOldProcessorInformation->KernelTime.LowPart); +// +// printf("Final Idletime = %08x%08x\n", pNewProcessorInformation->IdleTime.HighPart, +// pNewProcessorInformation->IdleTime.LowPart); +// printf("Final Usertime = %08x%08x\n", pNewProcessorInformation->UserTime.HighPart, +// pNewProcessorInformation->UserTime.LowPart); +// printf("Final Kerntime = %08x%08x\n\n", pNewProcessorInformation->KernelTime.HighPart, +// pNewProcessorInformation->KernelTime.LowPart); +// END DEBUG + + // first, find all the deltas... + + TempUser = RtlLargeIntegerSubtract(pNewProcessorInformation->UserTime, + pOldProcessorInformation->UserTime); + TempKern = RtlLargeIntegerSubtract(pNewProcessorInformation->KernelTime, + pOldProcessorInformation->KernelTime); + TempIdle = RtlLargeIntegerSubtract(pNewProcessorInformation->IdleTime, + pOldProcessorInformation->IdleTime); + // check for wrapping +// if (pOldProcessor->UserTime.HighPart > pNewProcessorInformation->UserTime.HighPart) +// { +// +// } + +// printf("Delta IdleTime = %08x%08x\n", TempIdle.HighPart, TempIdle.LowPart); +// printf("Delta UserTime = %08x%08x\n", TempUser.HighPart, TempUser.LowPart); +// printf("Delta KernTime = %08x%08x\n", TempKern.HighPart, TempKern.LowPart); + + // now find the total processor time = UserTime + KernelTime + + TempUser = RtlLargeIntegerAdd(TempUser, TempKern); + +// printf("Total ProcTime = %08x%08x\n", TempUser.HighPart, TempUser.LowPart); + + // adjust by kludge factor -- TestTime/WholeTestTime + + TempUser = RtlExtendedIntegerMultiply(TempUser, TestTime); + TempUser = RtlLargeIntegerDivide(TempUser, WholeTestTime, &trash); + + if ((TempUser.HighPart == 0) && (TempUser.LowPart < 10)) // sanity check + { + flag = 0; + printf("Kludge factor = %d/%d\n", TestTime, WholeTestTime.LowPart); + printf("Adjusted ProcTime = %08x%08x\n", TempUser.HighPart, TempUser.LowPart); + } + else + { + flag = 1; + } + + TotalProcessorTime = RtlLargeIntegerAdd(TotalProcessorTime, TempUser); + + // now find the true kernel time = KernelTime - IdleTime + + TempKern = RtlLargeIntegerSubtract(TempKern, TempIdle); + +// printf("True KernTime = %08x%08x\n", TempKern.HighPart, TempKern.LowPart); + + if (TempKern.HighPart < 0) + { + TempKern.HighPart = 0; + TempKern.LowPart = 0; + } + TotalKernelTime = RtlLargeIntegerAdd(TotalKernelTime, TempKern); + + // + // finally, calc the percent kernel is of total + // + + if (flag) + { + TempKern = RtlExtendedIntegerMultiply(TempKern, 1000); + TempKern = RtlLargeIntegerDivide(TempKern, TempUser, &trash); + } + else + { + TempKern.LowPart = 0; + } + pKernelPercent[CurProc+1] = TempKern.LowPart; + + // move to info for next processor + + pNewProcessorInformation++; + pOldProcessorInformation++; + } + + // + // last of all, calc the percent kernel is of total + // + if ((TotalProcessorTime.HighPart == 0) && (TotalProcessorTime.LowPart < 10)) + { + TempKern.LowPart = 0; + } + else + { + TempKern = RtlExtendedIntegerMultiply(TotalKernelTime, 1000); + TempKern = RtlLargeIntegerDivide(TempKern, TotalProcessorTime, &trash); + } + pKernelPercent[0] = TempKern.LowPart; + + *ppKernPC = pKernelPercent; + + return NumCpus; +} + diff --git a/private/ntos/ndis/testprot/tpctl/globals.c b/private/ntos/ndis/testprot/tpctl/globals.c new file mode 100644 index 000000000..49f9c5d6e --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/globals.c @@ -0,0 +1,390 @@ +// ****************************************************************** +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// globals.c +// +// Abstract: +// +// This module contains the routines for parsing global variables entered from +// the command line or read from script files. +// +// Author: +// +// Tim Wynsma (timothyw) 5-18-94 +// +// Revision History: +// +// ****************************************************************** + + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "tpctl.h" +#include "parse.h" + +typedef struct _GLOBALS +{ + // String variables + + UCHAR TestCard[64]; + UCHAR TrustedCard[64]; + + // Address6 variables + + UCHAR TestCardAddress[6]; + UCHAR TrustedCardAddress[6]; + UCHAR MulticastAddress[6]; + UCHAR MulticastAddress2[6]; + UCHAR BroadcastAddress[6]; + UCHAR RandomAddress[6]; + UCHAR RemoteTestCardAddress[6]; + UCHAR RemoteTrustedCardAddress[6]; + + // Address4 variables + + UCHAR FunctionalAddress[4]; + UCHAR FunctionalAddress2[4]; + + // Integer variables + + ULONG MaxFrameSize; + ULONG MaxLookaheadSize; + +} GLOBALS; + +GLOBALS glob; + +typedef struct _GLOBALVAR +{ + PUCHAR varname; + PARAMTYPES vartype; + PVOID varaddress; +} GLOBALVAR, *PGLOBALVAR; + + +GLOBALVAR globalvars[] = + { { "test_card", String, glob.TestCard }, + { "trusted_card", String, glob.TrustedCard }, + { "test_card_address", Address6, glob.TestCardAddress }, + { "trusted_card_address", Address6, glob.TrustedCardAddress }, + { "multicast_address", Address6, glob.MulticastAddress }, + { "multicast_address2", Address6, glob.MulticastAddress2 }, + { "broadcast_address", Address6, glob.BroadcastAddress }, + { "random_address", Address6, glob.RandomAddress }, + { "rem_test_card_address", Address6, glob.RemoteTestCardAddress }, + { "rem_trusted_card_address", Address6, glob.RemoteTrustedCardAddress }, + { "functional_address", Address4, glob.FunctionalAddress }, + { "functional_address2", Address4, glob.FunctionalAddress2 }, + { "max_frame_size", Integer, &glob.MaxFrameSize }, + { "max_lookahead_size", Integer, &glob.MaxLookaheadSize } + }; + + +DWORD +NumGlobalVars = sizeof(globalvars) / sizeof(globalvars[0]); + + + +DWORD +ParseGlobalArgs(OUT PUCHAR commandline, + OUT LPSTR tokenptr[], + IN DWORD ArgC, + IN LPSTR ArgV[]); + + + +PVOID +TpctlParseGlobalVariable( + IN BYTE Buffer[], + IN PARAMTYPES reqtype + ) + +// ------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------------ + +{ + BYTE TmpBuffer[100]; + LPSTR EndOfVar = Buffer; // Anything that isn't NULL. + ULONG count; + + + // + // make sure that there is actually something passed in.. + // + + if ( Buffer == NULL) + { + return NULL; + } + + // + // copy the variable into a temp buffer. + // + + strcpy( TmpBuffer,&Buffer[1] ); + + // + // Now null out the '$' symbol if it exists to allow the querying + // of the global variable. + // + + EndOfVar = strchr( TmpBuffer,'$' ); + + if ( EndOfVar == NULL ) + { + return NULL; + } + + *EndOfVar = '\0'; + + // + // Search for the named global variable + // + + for (count=0; count < NumGlobalVars; count++) + { + if (!_stricmp(TmpBuffer, globalvars[count].varname)) + { + // + // Make sure the required type matched the type of the global + // + if (globalvars[count].vartype != reqtype) + { + return NULL; + } + return globalvars[count].varaddress; + + } + } + + return NULL; +} + +VOID +TpctlInitGlobalVariables(VOID) +{ + ULONG count; + UCHAR NameBuf[128]; + PUCHAR varptr; + LPBYTE NextToken; + + + // + // first, initialize those globals that will always have a certain value... + // (all others should already be zero) + // + + glob.MulticastAddress[0] = 0x01; + glob.MulticastAddress[1] = 0x02; + glob.MulticastAddress[2] = 0x03; + glob.MulticastAddress[3] = 0x04; + glob.MulticastAddress[4] = 0x05; + glob.MulticastAddress[5] = 0x00; + + glob.MulticastAddress2[0] = 0x01; + glob.MulticastAddress2[1] = 0x02; + glob.MulticastAddress2[2] = 0x03; + glob.MulticastAddress2[3] = 0x04; + glob.MulticastAddress2[4] = 0x05; + glob.MulticastAddress2[5] = 0x01; + + glob.BroadcastAddress[0] = 0xFF; + glob.BroadcastAddress[1] = 0xFF; + glob.BroadcastAddress[2] = 0xFF; + glob.BroadcastAddress[3] = 0xFF; + glob.BroadcastAddress[4] = 0xFF; + glob.BroadcastAddress[5] = 0xFF; + + glob.RandomAddress[0] = 0x00; + glob.RandomAddress[1] = 0x02; + glob.RandomAddress[2] = 0x04; + glob.RandomAddress[3] = 0x06; + glob.RandomAddress[4] = 0x08; + glob.RandomAddress[5] = 0x0A; + + glob.FunctionalAddress[0] = 0xC0; + glob.FunctionalAddress[1] = 0x02; + glob.FunctionalAddress[2] = 0x03; + glob.FunctionalAddress[3] = 0x04; + + glob.FunctionalAddress2[0] = 0x00; + glob.FunctionalAddress2[1] = 0x00; + glob.FunctionalAddress2[2] = 0x00; + glob.FunctionalAddress2[3] = 0x00; + + + // + // now, loop thru all the global vars, checking for an associated environment variable + // If the env variable is found, then set that global variable accordingly. + // + + for (count=0; count < NumGlobalVars; count++) + { + strcpy(NameBuf, "tp_"); + strcat(NameBuf, globalvars[count].varname); + varptr = getenv( _strupr( NameBuf )); + if (varptr != NULL) + { + switch ( globalvars[count].vartype ) + { + case Integer: + *(PDWORD)globalvars[count].varaddress = strtol( varptr,&NextToken,0 ); + break; + + case String: + strcpy( (LPSTR)globalvars[count].varaddress,varptr ); + break; + + case Address4: + TpctlParseAddress( varptr, + (PDWORD)globalvars[count].varaddress, + 0, + FUNCTIONAL_ADDRESS_LENGTH ); + break; + + case Address6: + TpctlParseAddress( varptr, + (PDWORD)globalvars[count].varaddress, + 0, + ADDRESS_LENGTH ) ; + break; + } + } + } +} + + +DWORD +TpctlParseSet( + IN DWORD ArgC, + IN LPSTR ArgV[] + ) + +{ + DWORD count; + UCHAR commandline[120]; + LPSTR tokenptr[20]; + DWORD numstrings; + + printf("\nIn TpctlParseSet\n"); + + if (ArgC < 2) + { + printf("Error in setglobalvar command: no arguments\n"); + return 0; + } + + numstrings = ParseGlobalArgs(commandline,tokenptr,ArgC, ArgV); + + for (count=0; count < numstrings; count++) + { + printf("token %d equals \"%s\".\n",count, tokenptr[count]); + } + printf("\n"); + + // now that they are all parsed into separate strings + return 0; +} + + +DWORD +ParseGlobalArgs(OUT PUCHAR clptr, + OUT LPSTR tokenptr[], + IN DWORD ArgC, + IN LPSTR ArgV[]) + +{ + + DWORD count; + DWORD tokencnt = 0; + LPSTR srcptr; + DWORD state; + DWORD chtype; + UCHAR ch; + + // parse into legal strings. For our purposes, the following are legal strings: + // 1) Global variable. Must start and end with a '$'. Legal characters are 'A-Z', 'a-z', + // '0-9', and '_'. Lowercase are converted to uppercase + // 2) Environment variable. Same as global, except must start and end with a '%' + // 3) Number. Must contain only digits '0' thru '9' + // 4) Address. Must start and end with a '&'. Fields are in hex, separated by '-'. + // For example, &00-03-a3-f1-07-54& + // 5) Comparisons Legal strings are "=", "<", ">", "<>", "<=", ">=" + // 6) Operators. Legal strings are '+', '-', '*', '/' + + + for(count=1; count < ArgC; count++) + { + srcptr = ArgV[count]; + state = 0; + + while ( (ch = *srcptr++) != 0) + { + if ((ch >= '0') && (ch <= '9')) + { + chtype = 1; + } + else if ((ch == '%') || (ch == '$') || ((ch >= 'A') && (ch <= 'Z'))) + { + chtype = 2; + } + else if ((ch >= 'a') && (ch <= 'z')) + { + chtype = 2; + ch = toupper(ch); + } + else if ((ch == '(') || (ch == ')') || (ch == '+') || (ch = '-') || + (ch == '*') || (ch == '/') || (ch == '=')) + { + chtype = 3; + } + else + { + printf("Error in setglobalvar command--illegal char\n"); + return 0; + } + + if (chtype != state) + { + if (state != 0) + { + *clptr++ = 0; + } + tokenptr[tokencnt++] = clptr; + if (chtype == 3) + { + state = 4; + } + else + { + state = chtype; + } + } + *clptr++ = ch; + } + *clptr++ = 0; + } + + return tokencnt; +} + diff --git a/private/ntos/ndis/testprot/tpctl/info.c b/private/ntos/ndis/testprot/tpctl/info.c new file mode 100644 index 000000000..96acecd09 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/info.c @@ -0,0 +1,1497 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + info.c + +Abstract: + + This module handles the printing of the results of the Query and + Set commands. + +Author: + + Tom Adams (tomad) 2-Dec-1991 + +Revision History: + + 2-Apr-1991 tomad + + created + + Sanjeev Katariya (sanjeevk) + 4-12-1993 Added Arcnet support + 4-15-1993 Added additional OIDS + + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> + +//#include <ndis.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "tpctl.h" +#include "parse.h" + + +#define CHAR_SP 0x20 +#define INDENT 12 +#define MAX_STR_LEN 80 + + +/*++ + +VOID +TpctlDumpNewLine( + LPSTR Buffer + ); + +--*/ + + +#define TpctlDumpNewLine( Buffer ) { \ + Buffer += (BYTE)sprintf( Buffer,"\n" ); \ +} + +/*++ + +VOID +TpctlDumpLabel( + LPSTR Buffer, + PBYTE Label + ); + +--*/ + +#define TpctlDumpLabel( Buffer,Label ) { \ + DWORD i; \ + DWORD Length; \ + BYTE _Str[MAX_STR_LEN]; \ + \ + for ( i=0;i<INDENT;i++ ) { \ + _Str[i] = CHAR_SP; \ + } \ + Length = strlen( Label ); \ + strncpy( &_Str[INDENT],#Label,Length+2 ); \ + \ + for ( i=strlen( _Str ) ; i<MAX_STR_LEN ; i++ ) { \ + _Str[i] = CHAR_SP; \ + } \ + _Str[INDENT+Length+2] = '\0'; \ + Buffer += (BYTE)sprintf( Buffer,"%s",_Str ); \ + \ + TpctlDumpNewLine( Buffer ); \ +} + +/*++ + +VOID +TpctlDumpEquality( + LPSTR Buffer, + DWORD Value, + DWORD String + ); + +--*/ + +#define TpctlDumpEquality( Buffer,Value,String ) { \ + \ + if ( Value == String ) { \ + TpctlDumpLabel( Buffer,#String ); \ + return; \ + } \ +} + +/*++ + +VOID +TpctlDumpBitField( + LPSTR Buffer, + DWORD PacketFilter, + DWORD BitField + ); + +--*/ + +#define TpctlDumpBitfield( Buffer,Value,BitField ) { \ + \ + if (( Value ) & BitField ) { \ + TpctlDumpLabel( Buffer,#BitField ); \ + } \ +} + +VOID +TpctlDumpOID( + LPSTR *B, + DWORD OID + ) +{ + // + // General Objects + // + + TpctlDumpEquality( *B,OID,OID_GEN_SUPPORTED_LIST ); + TpctlDumpEquality( *B,OID,OID_GEN_HARDWARE_STATUS ); + TpctlDumpEquality( *B,OID,OID_GEN_MEDIA_SUPPORTED ); + TpctlDumpEquality( *B,OID,OID_GEN_MEDIA_IN_USE ); + TpctlDumpEquality( *B,OID,OID_GEN_MAXIMUM_LOOKAHEAD ); + TpctlDumpEquality( *B,OID,OID_GEN_MAXIMUM_FRAME_SIZE ); + TpctlDumpEquality( *B,OID,OID_GEN_LINK_SPEED ); + TpctlDumpEquality( *B,OID,OID_GEN_TRANSMIT_BUFFER_SPACE ); + TpctlDumpEquality( *B,OID,OID_GEN_RECEIVE_BUFFER_SPACE ); + TpctlDumpEquality( *B,OID,OID_GEN_TRANSMIT_BLOCK_SIZE ); + TpctlDumpEquality( *B,OID,OID_GEN_RECEIVE_BLOCK_SIZE ); + TpctlDumpEquality( *B,OID,OID_GEN_VENDOR_ID ); + TpctlDumpEquality( *B,OID,OID_GEN_VENDOR_DESCRIPTION ); + TpctlDumpEquality( *B,OID,OID_GEN_CURRENT_PACKET_FILTER ); + TpctlDumpEquality( *B,OID,OID_GEN_CURRENT_LOOKAHEAD ); + TpctlDumpEquality( *B,OID,OID_GEN_DRIVER_VERSION ); + TpctlDumpEquality( *B,OID,OID_GEN_MAXIMUM_TOTAL_SIZE ); + TpctlDumpEquality( *B,OID,OID_GEN_PROTOCOL_OPTIONS ); + TpctlDumpEquality( *B,OID,OID_GEN_MAC_OPTIONS ); + + TpctlDumpEquality( *B,OID,OID_GEN_XMIT_OK ); + TpctlDumpEquality( *B,OID,OID_GEN_RCV_OK ); + TpctlDumpEquality( *B,OID,OID_GEN_XMIT_ERROR ); + TpctlDumpEquality( *B,OID,OID_GEN_RCV_ERROR ); + TpctlDumpEquality( *B,OID,OID_GEN_RCV_NO_BUFFER ); + + TpctlDumpEquality( *B,OID,OID_GEN_DIRECTED_BYTES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_DIRECTED_FRAMES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_MULTICAST_BYTES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_MULTICAST_FRAMES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_BROADCAST_BYTES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_BROADCAST_FRAMES_XMIT ); + TpctlDumpEquality( *B,OID,OID_GEN_DIRECTED_BYTES_RCV ); + TpctlDumpEquality( *B,OID,OID_GEN_DIRECTED_FRAMES_RCV ); + TpctlDumpEquality( *B,OID,OID_GEN_MULTICAST_BYTES_RCV ); + TpctlDumpEquality( *B,OID,OID_GEN_MULTICAST_FRAMES_RCV ); + TpctlDumpEquality( *B,OID,OID_GEN_BROADCAST_BYTES_RCV ); + TpctlDumpEquality( *B,OID,OID_GEN_BROADCAST_FRAMES_RCV ); + + TpctlDumpEquality( *B,OID,OID_GEN_RCV_CRC_ERROR ); + TpctlDumpEquality( *B,OID,OID_GEN_TRANSMIT_QUEUE_LENGTH ); + + // + // 802.3 Objects + // + + TpctlDumpEquality( *B,OID,OID_802_3_PERMANENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_802_3_CURRENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_802_3_MULTICAST_LIST ); + TpctlDumpEquality( *B,OID,OID_802_3_MAXIMUM_LIST_SIZE ); + + TpctlDumpEquality( *B,OID,OID_802_3_RCV_ERROR_ALIGNMENT ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_ONE_COLLISION ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_MORE_COLLISIONS ); + + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_DEFERRED); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_MAX_COLLISIONS ); + TpctlDumpEquality( *B,OID,OID_802_3_RCV_OVERRUN ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_UNDERRUN ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_HEARTBEAT_FAILURE ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_TIMES_CRS_LOST ); + TpctlDumpEquality( *B,OID,OID_802_3_XMIT_LATE_COLLISIONS ); + + // + // 802.5 Objects + // + + TpctlDumpEquality( *B,OID,OID_802_5_PERMANENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_802_5_CURRENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_802_5_CURRENT_FUNCTIONAL ); + TpctlDumpEquality( *B,OID,OID_802_5_CURRENT_GROUP ); + TpctlDumpEquality( *B,OID,OID_802_5_LAST_OPEN_STATUS ); + TpctlDumpEquality( *B,OID,OID_802_5_CURRENT_RING_STATUS ); + TpctlDumpEquality( *B,OID,OID_802_5_CURRENT_RING_STATE ); + + TpctlDumpEquality( *B,OID,OID_802_5_LINE_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_LOST_FRAMES ); + + TpctlDumpEquality( *B,OID,OID_802_5_BURST_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_AC_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_ABORT_DELIMETERS ); + TpctlDumpEquality( *B,OID,OID_802_5_FRAME_COPIED_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_FREQUENCY_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_TOKEN_ERRORS ); + TpctlDumpEquality( *B,OID,OID_802_5_INTERNAL_ERRORS ); + + // + // Fddi object + // + + TpctlDumpEquality( *B,OID,OID_FDDI_LONG_PERMANENT_ADDR ); + TpctlDumpEquality( *B,OID,OID_FDDI_LONG_CURRENT_ADDR ); + TpctlDumpEquality( *B,OID,OID_FDDI_LONG_MULTICAST_LIST ); + TpctlDumpEquality( *B,OID,OID_FDDI_LONG_MAX_LIST_SIZE ); + TpctlDumpEquality( *B,OID,OID_FDDI_SHORT_PERMANENT_ADDR ); + TpctlDumpEquality( *B,OID,OID_FDDI_SHORT_CURRENT_ADDR ); + TpctlDumpEquality( *B,OID,OID_FDDI_SHORT_MULTICAST_LIST ); + TpctlDumpEquality( *B,OID,OID_FDDI_SHORT_MAX_LIST_SIZE); + + TpctlDumpEquality( *B,OID,OID_FDDI_ATTACHMENT_TYPE ); + TpctlDumpEquality( *B,OID,OID_FDDI_UPSTREAM_NODE_LONG ); + TpctlDumpEquality( *B,OID,OID_FDDI_DOWNSTREAM_NODE_LONG ); + TpctlDumpEquality( *B,OID,OID_FDDI_FRAME_ERRORS ); + TpctlDumpEquality( *B,OID,OID_FDDI_FRAMES_LOST ); + TpctlDumpEquality( *B,OID,OID_FDDI_RING_MGT_STATE ); + TpctlDumpEquality( *B,OID,OID_FDDI_LCT_FAILURES ); + TpctlDumpEquality( *B,OID,OID_FDDI_LEM_REJECTS ); + TpctlDumpEquality( *B,OID,OID_FDDI_LCONNECTION_STATE ); + + // + // STARTCHANGE + // + TpctlDumpEquality( *B,OID,OID_ARCNET_PERMANENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_ARCNET_CURRENT_ADDRESS ) ; + TpctlDumpEquality( *B,OID,OID_ARCNET_RECONFIGURATIONS ) ; + // + // STOPCHANGE + // + + // + // Async Objects + // + +/* Not currently supported. + + TpctlDumpEquality( *B,OID,OID_ASYNC_PERMANENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_ASYNC_CURRENT_ADDRESS ); + TpctlDumpEquality( *B,OID,OID_ASYNC_QUALITY_OF_SERVICE ); + TpctlDumpEquality( *B,OID,OID_ASYNC_PROTOCOL_TYPE ); +*/ + // + // LocalTalk Objects + // + +/* Not currently supported. + + TpctlDumpEquality( *B,OID,OID_LTALK_CURRENT_NODE_ID ); + + TpctlDumpEquality( *B,OID,OID_LTALK_IN_BROADCASTS ); + TpctlDumpEquality( *B,OID,OID_LTALK_IN_LENGTH_ERRORS ); + + TpctlDumpEquality( *B,OID,OID_LTALK_OUT_NO_HANDLERS ); + TpctlDumpEquality( *B,OID,OID_LTALK_COLLISIONS ); + TpctlDumpEquality( *B,OID,OID_LTALK_DEFERS ); + TpctlDumpEquality( *B,OID,OID_LTALK_NO_DATA_ERRORS ); + TpctlDumpEquality( *B,OID,OID_LTALK_RANDOM_CTS_ERRORS ); + TpctlDumpEquality( *B,OID,OID_LTALK_FCS_ERRORS ); +*/ +} + + +VOID +TpctlDumpHardWareStatus( + LPSTR *B, + DWORD Status + ) +{ + TpctlDumpNewLine( *B ); + TpctlDumpEquality( *B,Status,NdisHardwareStatusClosing ); + TpctlDumpEquality( *B,Status,NdisHardwareStatusInitializing ); + TpctlDumpEquality( *B,Status,NdisHardwareStatusNotReady ); + TpctlDumpEquality( *B,Status,NdisHardwareStatusReady ); + TpctlDumpEquality( *B,Status,NdisHardwareStatusReset ); + TpctlDumpNewLine( *B ); +} + +VOID +TpctlDumpPacketFilter( + LPSTR *B, + DWORD PacketFilter + ) +{ + TpctlDumpNewLine( *B ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_DIRECTED ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_MULTICAST ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_ALL_MULTICAST ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_BROADCAST ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_SOURCE_ROUTING ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_PROMISCUOUS ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_MAC_FRAME ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_GROUP ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_FUNCTIONAL ); + TpctlDumpBitfield( *B,PacketFilter,NDIS_PACKET_TYPE_ALL_FUNCTIONAL ); + TpctlDumpNewLine( *B ); +} + +VOID +TpctlDumpNdisMedium( + LPSTR *B, + DWORD NdisMedium + ) +{ + TpctlDumpEquality( *B,NdisMedium,NdisMedium802_3 ); + TpctlDumpEquality( *B,NdisMedium,NdisMedium802_5 ); + TpctlDumpEquality( *B,NdisMedium,NdisMediumFddi ); + // + // STARTCHANGE ARCNET + // + TpctlDumpEquality( *B,NdisMedium,NdisMediumArcnet878_2 ); + // + // STOPCHANGE ARCNET + // + +} + + +VOID +TpctlPrintQueryInfoResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + DWORD Status; + LPSTR TmpBuf; + LPBYTE Address; + LPDWORD Counters; + DWORD BytesWritten; + DWORD i; + DWORD Number; + LPDWORD Supported; + + + //ASSERT( Results->Signature == REQUEST_RESULTS_SIGNATURE ); + //ASSERT(( Results->NdisRequestType == NdisRequestQueryInformation ) || + // ( Results->NdisRequestType == NdisRequestQueryStatistics )); + //ASSERT( Results->OID == OID ); + + TmpBuf = GlobalBuf; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCmdCode = %s\n\n", + TpctlGetCmdCode( CmdCode )); + + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t OID = 0x%08lX\n",OID); + TpctlDumpOID( &TmpBuf,OID ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tReturn Status = %s\n", + TpctlGetStatus( Results->RequestStatus )); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRequest Pended = %s", + Results->RequestPended ? "TRUE" : "FALSE"); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + if (( Results->RequestStatus != NDIS_STATUS_SUCCESS ) && + ( Results->RequestStatus != NDIS_STATUS_NOT_SUPPORTED )) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesWritten = %d\n", + Results->BytesReadWritten); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesNeeded = %d\n\n", + Results->BytesNeeded); + + } else if ( Results->RequestStatus == NDIS_STATUS_SUCCESS ) { + + switch ( Results->OID ) { + + // + // GENERAL OBJECTS + // + + // + // General Operational Characteristics + // + + case OID_GEN_SUPPORTED_LIST: // 0x00010101 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tSupported OIDs are:\n\n"); + + Number = Results->BytesReadWritten / sizeof( DWORD ); + + Supported = (LPDWORD)Results->InformationBuffer; + + for ( i=0;i<Number;i++ ) { + TpctlDumpOID( &TmpBuf,*Supported++ ); + } + + ADD_DIFF_FLAG( TmpBuf, "\t MAY_DIFFER" ); + + break; + + case OID_GEN_HARDWARE_STATUS: // 0x00010102 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tHardware Status = 0x%lx\n", + *(LPDWORD)Results->InformationBuffer); + + TpctlDumpHardWareStatus( &TmpBuf,*(LPDWORD)Results->InformationBuffer ); + + break; + + case OID_GEN_MEDIA_SUPPORTED: // 0x00010103 + case OID_GEN_MEDIA_IN_USE: // 0x00010104 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMedia Types Supported are:\n\n"); + + Number = Results->BytesReadWritten / sizeof( DWORD ); + Supported = (LPDWORD)Results->InformationBuffer; + + for ( i=0;i<Number;i++ ) { + + TpctlDumpNdisMedium( &TmpBuf,*Supported++ ); + } + + break; + + case OID_GEN_MAXIMUM_LOOKAHEAD: // 0x00010105 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMaximum Lookahead Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: // 0x00010106 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMaximum Frame Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + case OID_GEN_LINK_SPEED: // 0x00010107 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLink Speed (bps) = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_TRANSMIT_BUFFER_SPACE: // 0x00010108 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tTransmit Buffer Space = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RECEIVE_BUFFER_SPACE: // 0x00010109 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tReceive Buffer Space = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_TRANSMIT_BLOCK_SIZE: // 0x0001010A + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tTransmit Block Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RECEIVE_BLOCK_SIZE: // 0x0001010B + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tReceive Block Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_VENDOR_ID: // 0x0001010C + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tVendor ID = %u", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_VENDOR_DESCRIPTION: // 0x0001010D + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tVendor Description = %s", + (PCHAR)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER"); + + break; + + case OID_GEN_DRIVER_VERSION: // 0x00010110 + { + LPBYTE Version = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tDriver Version Number = %d.%d\n", + Version[1],Version[0]); + break; + } + case OID_GEN_CURRENT_PACKET_FILTER: // 0x0001010E + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Packet Filter = 0x%lx\n", + *(LPDWORD)Results->InformationBuffer); + + TpctlDumpPacketFilter( &TmpBuf,*(LPDWORD)Results->InformationBuffer ); + + break; + + case OID_GEN_CURRENT_LOOKAHEAD: // 0x0001010F + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Lookahead Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: // 0x00010111 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMaximum Total Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_PROTOCOL_OPTIONS: // 0x00010112 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tGeneral Protocol Options = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MAC_OPTIONS: // 0x00010113 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tGeneral MAC Options = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // General Statitics - Mandatory + // + + case OID_GEN_XMIT_OK: // 0x00020101 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Transmits - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RCV_OK: // 0x00020102 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Receives - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_XMIT_ERROR: // 0x00020103 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Tranmsits With Error = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RCV_ERROR: // 0x00020104 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Receives With Error = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RCV_NO_BUFFER: // 0x00020105 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Missed, No Buffers = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // General Statitics - Optional + // + + case OID_GEN_DIRECTED_BYTES_XMIT: // 0x00020201 + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tDirected Bytes Transmitted - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_DIRECTED_FRAMES_XMIT: // 0x00020202 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tDirected Frames Transmitted - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MULTICAST_BYTES_XMIT: // 0x00020203 + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMulticast Bytes Transmitted - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MULTICAST_FRAMES_XMIT: // 0x00020204 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMulticast Frames Transmitted - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_BROADCAST_BYTES_XMIT: // 0x00020205 + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tBroadcast Bytes Transmitted - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_BROADCAST_FRAMES_XMIT: // 0x00020206 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tBroadcast Frames Transmitted - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_DIRECTED_BYTES_RCV: // 0x00020207 + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tDirected Bytes Received - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_DIRECTED_FRAMES_RCV: // 0x00020208 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tDirected Frames Received - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MULTICAST_BYTES_RCV: // 0x00020209 + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMulticast Bytes Received - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_MULTICAST_FRAMES_RCV: // 0x0002020A + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMulticast Frames Received - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_BROADCAST_BYTES_RCV: // 0x0002020B + + Counters = (LPDWORD)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tBroadcast Bytes Received - OK = 0x%08lX - 0x%08lX", + Counters[1],Counters[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_BROADCAST_FRAMES_RCV: // 0x0002020C + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tBroadcast Frames Received - OK = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_RCV_CRC_ERROR: // 0x0002020D + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Received With CRC/FCS Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_GEN_TRANSMIT_QUEUE_LENGTH: // 0x0002020E + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLength of Tramsit Queue = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.3 OBJECTS + // + + // + // 802.3 Operation Characteristics + // + + case OID_802_3_PERMANENT_ADDRESS: // 0x01010101 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPermanent Station Address = %02X-%02X-%02X-%02X-%02X-%02X", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_CURRENT_ADDRESS: // 0x01010102 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Station Address = %02X-%02X-%02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + break; + + case OID_802_3_MULTICAST_LIST: // 0x01010103 + + Number = Results->BytesReadWritten / ADDRESS_LENGTH; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMulticast Address List:\n\n"); + + if ( Number == 0 ) { + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\tNone.\n"); + } else { + + Address = (LPBYTE)&Results->InformationBuffer; + + for ( i=0;i<Number;i++ ) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\t%02X-%02X-%02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + Address += (BYTE)ADDRESS_LENGTH; + } + } + + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: // 0x01010104 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tMaximum Multicast List Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.3 Statitics - Mandatory + // + + case OID_802_3_RCV_ERROR_ALIGNMENT: // 0x01020101 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Received With Alignment Error = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_ONE_COLLISION: // 0x01020102 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Transmitted With One Collision = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_MORE_COLLISIONS: // 0x01020103 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Transmitted With Greater Than One Collision = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.3 Statitics - Optional + // + + case OID_802_3_XMIT_DEFERRED: // 0x01020201 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Transmitted After Deferral = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_MAX_COLLISIONS: // 0x01020202 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Not Transmitted Due To Collisions = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_RCV_OVERRUN: // 0x01020203 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Not Received Due To Overrun = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_UNDERRUN: // 0x01020204 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Not Transmitted Due To Underrun = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_HEARTBEAT_FAILURE: // 0x01020205 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Transmitted With Heartbeat Failure = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_TIMES_CRS_LOST: // 0x01020206 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tTimes CRC Lost During Transmit = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_3_XMIT_LATE_COLLISIONS: // 0x01020207 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLate Collisions Detected = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.5 OBJECTS + // + + // + // 802.5 Operation Characteristics + // + + case OID_802_5_PERMANENT_ADDRESS: // 0x02010101 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPermanent Station Address = %02X-%02X-%02X-%02X-%02X-%02X", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_CURRENT_ADDRESS: // 0x02010102 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Station Address = %02X-%02X-%02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + break; + + case OID_802_5_CURRENT_FUNCTIONAL: // 0x02010103 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Functional Address = %02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3]); + + break; + + case OID_802_5_CURRENT_GROUP: // 0x02010104 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Group Address = %02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3]); + + break; + + case OID_802_5_LAST_OPEN_STATUS: // 0x02010105 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLast Open Status = %d", + *(LPWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_CURRENT_RING_STATUS: // 0x02010106 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Ring Status = %d", + *(LPWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_CURRENT_RING_STATE: // 0x02010107 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Ring State = %d", + *(LPWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.5 Statitics - Mandatory + // + + case OID_802_5_LINE_ERRORS: // 0x02020101 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLine Errors Detected= %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_LOST_FRAMES: // 0x02020102 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLost Frames = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // 802.5 Statitics - Optional + // + + case OID_802_5_BURST_ERRORS: // 0x02020201 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tBurst Errors Detected = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_AC_ERRORS: // 0x02020202 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tA/C Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_ABORT_DELIMETERS: // 0x02020203 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tAbort Delimeter Detected = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_FRAME_COPIED_ERRORS: // 0x02020204 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Copied Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_FREQUENCY_ERRORS: // 0x02020205 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrequency Errors Detected = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_TOKEN_ERRORS: // 0x02020206 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tToken Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_802_5_INTERNAL_ERRORS: // 0x02020207 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tInternal Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // FDDI + // + + case OID_FDDI_LONG_PERMANENT_ADDR : // 0x03010101 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Permanent Station Address = %02X-%02X-%02X-%02X-%02X-%02X", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_LONG_CURRENT_ADDR : // 0x03010102 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Current Station Address = %02X-%02X-%02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + break; + + case OID_FDDI_LONG_MULTICAST_LIST : // 0x03010103 + + Number = Results->BytesReadWritten / ADDRESS_LENGTH; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Multicast Address List:\n\n"); + + if ( Number == 0 ) { + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\tNone.\n"); + } else { + + Address = (LPBYTE)&Results->InformationBuffer; + + for ( i=0;i<Number;i++ ) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\t%02X-%02X-%02X-%02X-%02X-%02X\n", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + Address += (BYTE)ADDRESS_LENGTH; + } + } + + break; + + case OID_FDDI_LONG_MAX_LIST_SIZE : // 0x03010104 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Maximum Multicast List Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_SHORT_PERMANENT_ADDR : // 0x03010105 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tShort Permanent Station Address = %02X-%02X", + Address[0],Address[1]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_SHORT_CURRENT_ADDR : // 0x03010106 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tShort Current Station Address = %02X-%02X\n", + Address[0],Address[1]); + + break; + + case OID_FDDI_SHORT_MULTICAST_LIST : // 0x03010107 + + Number = Results->BytesReadWritten / ADDRESS_LENGTH; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tShort Multicast Address List:\n\n"); + + if ( Number == 0 ) { + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\tNone.\n"); + } else { + + Address = (LPBYTE)&Results->InformationBuffer; + + for ( i=0;i<Number;i++ ) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t\t%02X-%02X\n", + Address[0],Address[1]); + + Address += (BYTE)ADDRESS_LENGTH; + } + } + + break; + + case OID_FDDI_SHORT_MAX_LIST_SIZE: // 0x03010108 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tShort Maximum Multicast List Size = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_ATTACHMENT_TYPE: // 0x03020101 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tAttachment Type = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_UPSTREAM_NODE_LONG: // 0x03020102 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Upstream Node Address = %02X-%02X-%02X-%02X-%02X-%02X", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_DOWNSTREAM_NODE_LONG: // 0x03020103 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLong Downstream Node Address = %02X-%02X-%02X-%02X-%02X-%02X", + Address[0],Address[1],Address[2],Address[3],Address[4],Address[5]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_FRAME_ERRORS: // 0x03020104 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrame Errors = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_FRAMES_LOST: // 0x03020105 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tFrames Lost = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_RING_MGT_STATE: // 0x03020106 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tRing Management State = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_LCT_FAILURES: // 0x03020107 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLCT Failures = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_LEM_REJECTS: // 0x03020108 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tLEM Rejects = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_FDDI_LCONNECTION_STATE: // 0x03020109 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tL Connection State = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // STARTCHANGE ARCNET + // + case OID_ARCNET_PERMANENT_ADDRESS: // 0x06010101 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPermanent Station Address = %02X", Address[0]); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + case OID_ARCNET_CURRENT_ADDRESS: // 0x06010102 + + Address = (LPBYTE)&Results->InformationBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCurrent Station Address = %02X\n", Address[0]); + + break; + + case OID_ARCNET_RECONFIGURATIONS: // 0x06010103 + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tReconfigurations = %d", + *(LPDWORD)Results->InformationBuffer); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + break; + + // + // STOPCHANGE ARCNET + // + + default: + + TmpBuf +=(BYTE)sprintf(TmpBuf,"\tInvalid OID or OID not yet supported.\n"); + break; + } + } + + if (( CommandsFromScript ) || ( CommandLineLogging )) { + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\t**********************************"); + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + 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); + } + } +} + + +VOID +TpctlPrintSetInfoResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + BOOL ErrorReturned = FALSE; + + + //ASSERT( Results->Signature == REQUEST_RESULTS_SIGNATURE ); + //ASSERT( Results->NdisRequestType == NdisRequestSetInformation ); + //ASSERT( Results->OID == OID ); + + TmpBuf = GlobalBuf; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCmdCode = %s\n\n", + TpctlGetCmdCode( CmdCode )); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t OID = 0x%08lX\n",OID); + TpctlDumpOID( &TmpBuf,OID ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tReturn Status = %s\n", + TpctlGetStatus( Results->RequestStatus )); + + if ( Results->RequestStatus != STATUS_SUCCESS ) { + ErrorReturned = TRUE; + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRequest Pended = %s", + Results->RequestPended ? "TRUE" : "FALSE"); + + ADD_DIFF_FLAG( TmpBuf, "\tMAY_DIFFER" ); + + if ( Results->RequestStatus != NDIS_STATUS_SUCCESS ) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesRead = %d\n", + Results->BytesReadWritten); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesNeeded = %d\n", + Results->BytesNeeded); + } + + if (( CommandsFromScript ) || ( CommandLineLogging )) { + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\t**********************************"); + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + 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 ) && + ((( !Verbose ) && ( ErrorReturned )) || ( Verbose ))) { + + 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); + } + } +} diff --git a/private/ntos/ndis/testprot/tpctl/init.c b/private/ntos/ndis/testprot/tpctl/init.c new file mode 100644 index 000000000..99a289c1a --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/init.c @@ -0,0 +1,1098 @@ +// ******************************** +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpctl.c +// +// Abstract: +// +// This is the main component of the NDIS 3.0 MAC Tester control program. +// +// Author: +// +// Tom Adams (tomad) 2-Apr-1991 +// +// Revision History: +// +// 2-Apr-1991 tomad +// +// created +// +// 7-1-1993 SanjeevK +// +// Added support for recording of sessions to a script file +// Added support for write through and error handling conditions +// +// 5-18-1994 timothyw +// added hooks for global variable access; cleanup +// 6-08-1994 timothyw +// changed to client/server model for perf tests +// +// ********************************* + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> +//#include <ndis.h> +#include <ntddndis.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "tpctl.h" +#include "parse.h" + +BOOL Verbose = TRUE; + +BOOL CommandsFromScript = FALSE; + +BOOL CommandLineLogging = FALSE; + +BOOL RecordToScript = FALSE; + +HANDLE CommandLineLogHandle; + +HANDLE ScriptRecordHandle; + +BOOL ExitFlag = FALSE; + +SCRIPTCONTROL Scripts[TPCTL_MAX_SCRIPT_LEVELS+1]; + +DWORD ScriptIndex; + +CHAR RecordScriptName[TPCTL_MAX_PATHNAME_SIZE]; + +OPEN_BLOCK Open[NUM_OPEN_INSTANCES]; + +CMD_ARGS GlobalCmdArgs; + +LPSTR GlobalBuf = NULL; + +BOOL ContinueLooping = TRUE; + +BOOL WriteThrough = TRUE; + +BOOL ContinueOnError = FALSE; + +INT TpctlSeed = 0; + +// +// the MAIN routine +// + + +VOID _cdecl +main( + IN WORD argc, + IN LPSTR argv[] + ) + +// --------- +// +// Routine Description: +// +// This routine initializes the TPCTL control structures, opens the +// TPDRVR driver, and send it a wakeup ioctl. Once this has completed +// the user is presented with the test prompt to enter commands, +// or if a script file was entered at the command line, it is opened, +// and the commands are read from the file. +// +// Arguments: +// +// IN WORD argc - Supplies the number of parameters +// IN LPSTR argv[] - Supplies the parameter list. +// +// Return Value: +// +// None. +// +// ---------- + +{ + HANDLE TpdrvrHandle; + DWORD Status; + + + // + // Adding this for version control recognition + // + printf( "\nMAC NDIS 3.0 Tester - Test Control Tool Version 1.5.3\n\n" ); + + + // + // First we will disable Ctrl-C by installing a handler. + // + + if ( !SetConsoleCtrlHandler( TpctlCtrlCHandler,TRUE )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to install Ctrl-C handler, returned 0x%lx.\n", + (PVOID)Status); + ExitProcess(Status); + } + + // + // Initialize the Scripts control structure before we check to + // see if there are any scripts on the command line to be read. + // + + TpctlInitializeScripts(); + + // + // Initialize the script-accessible global variables + // + + TpctlInitGlobalVariables(); + + // + // Check the command line parameters, and if there is a script file + // and log file open each. + // + + Status = TpctlParseCommandLine( argc,argv ); + + if ( Status != NO_ERROR ) + { + ExitProcess((DWORD)Status); + } + + // + // Initialize the Open Block Structure and Environment Variables. + // + + Status = TpctlInitializeOpenArray(); + + if ( Status != NO_ERROR ) + { + TpctlFreeOpenArray(); + TpctlCloseScripts(); + ExitProcess((DWORD)Status); + } + + // + // Open the first instance of the Test Protocol driver. + // + + Status = TpctlOpenTpdrvr( &TpdrvrHandle ); + + if ( Status != NO_ERROR ) + { + TpctlFreeOpenArray(); + TpctlCloseScripts(); + ExitProcess((DWORD)Status); + } + + // + // Start the actual tests, TpctlRunTest prompts for the commands or + // reads the script files and then drives the tests. + // + + Status = TpctlRunTest( TpdrvrHandle ); + + if ( Status != NO_ERROR ) + { + TpctlCloseTpdrvr( TpdrvrHandle ); + TpctlFreeOpenArray(); + TpctlCloseScripts(); + ExitProcess((DWORD)Status); + } + + // + // Close the Test Protocol driver, and free the Open Array data structs. + // + + TpctlCloseTpdrvr( TpdrvrHandle ); + + TpctlFreeOpenArray(); + + TpctlCloseScripts(); + + if ( !SetConsoleCtrlHandler( TpctlCtrlCHandler,FALSE )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to remove Ctrl-C handler, returned 0x%lx.\n", + (PVOID)Status); + ExitProcess(Status); + } + + ExitProcess((DWORD)NO_ERROR); +} + + +DWORD +TpctlInitializeOpenArray( + VOID + ) + +// ---------------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// --------------- + +{ + DWORD Status; + DWORD i; + + ZeroMemory( Open,NUM_OPEN_INSTANCES * sizeof( OPEN_BLOCK )); + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + Open[i].Signature = OPEN_BLOCK_SIGNATURE; + Open[i].OpenInstance = 0xFF; + Open[i].AdapterOpened = FALSE; + + Open[i].MediumType = 0; + Open[i].NdisVersion = 0; + + Open[i].AdapterName = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + MAX_ADAPTER_NAME_LENGTH ); + + if ( Open[i].AdapterName == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Adapter Name, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].AdapterName[0] = '\0'; + Open[i].LookaheadSize = 0; + Open[i].PacketFilter = NDIS_PACKET_TYPE_NONE; + Open[i].MulticastAddresses = NULL; + Open[i].NumberMultAddrs = 0; + + Open[i].EnvVars = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( ENVIRONMENT_VARIABLES ) ); + + if ( Open[i].EnvVars == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc EnvVars structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].EnvVars->WindowSize = WINDOW_SIZE; + Open[i].EnvVars->RandomBufferNumber = BUFFER_NUMBER; + Open[i].EnvVars->StressDelayInterval = DELAY_INTERVAL; + Open[i].EnvVars->UpForAirDelay = UP_FOR_AIR_DELAY; + Open[i].EnvVars->StandardDelay = STANDARD_DELAY; + + strcpy( Open[i].EnvVars->StressAddress,STRESS_MULTICAST ); + strcpy( Open[i].EnvVars->ResendAddress,NULL_ADDRESS ); + + Open[i].EventThreadStarted = FALSE; + Open[i].Events[TPCONTROL] = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].Events[TPSTRESS] = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].Events[TPSEND] = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].Events[TPRECEIVE] = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].Events[TPPERF] = CreateEvent( NULL,FALSE,FALSE,NULL ); + + Open[i].Stressing = FALSE; + Open[i].StressEvent = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].StressResultsCompleted = FALSE; + Open[i].StressClient = FALSE; + + Open[i].StressResults = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, + sizeof( STRESS_RESULTS ) ); + + if ( Open[i].StressResults == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Stress Results structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].StressArgs = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( CMD_ARGS ) ); + + if ( Open[i].StressArgs == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Stress Args structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].Sending = FALSE; + Open[i].SendEvent = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].SendResultsCompleted = FALSE; + + Open[i].SendResults = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( SEND_RECEIVE_RESULTS ) ); + + if ( Open[i].SendResults == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Send Results structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].SendArgs = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( CMD_ARGS ) ); + + if ( Open[i].SendArgs == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Send Args structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].Receiving = FALSE; + Open[i].ReceiveEvent = CreateEvent( NULL,FALSE,FALSE,NULL ); + Open[i].ReceiveResultsCompleted = FALSE; + + Open[i].ReceiveResults = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( SEND_RECEIVE_RESULTS ) ); + + if ( Open[i].ReceiveResults == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Receive Results structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Open[i].PerfEvent = CreateEvent( NULL, FALSE, FALSE, NULL); + Open[i].PerfResultsCompleted = FALSE; + Open[i].PerfResults = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof (PERF_RESULTS) ); + + if ( Open[i].PerfResults == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Perf Results structure, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + Status = TpctlStartEventHandlerThread( &Open[i] ); + + if ( Status != NO_ERROR ) + { + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to start EventHandler thread, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + else + { + Open[i].EventThreadStarted = TRUE; + } + } + + GlobalBuf = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, + 0x1000 + ( MAX_SERVERS * 0x400 ) ); + + if ( GlobalBuf == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctlInitializeOpenArray: failed to alloc Global Statistics buffer, returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + return NO_ERROR; +} + + +DWORD +TpctlResetOpenState( + IN POPEN_BLOCK Open, + IN HANDLE FileHandle + ) + +// ------------- +// +// Routine Description: +// +// This routine reset the state of an open to its initial state. +// +// Arguments: +// +// IN POPEN_BLOCK Open - the open block to reset to it initial state. +// IN HANDLE FileHandle - the handle to the driver to close the open +// iff already opened. +// +// Return Value: +// +// DWORD - NO_ERROR if the adapter was closed successfully or was never +// opened. Otherwise, the result of the close if it fails. +// +// ----------- + +{ + DWORD Status = NO_ERROR; + PMULT_ADDR MultAddr = NULL; + PMULT_ADDR NextMultAddr = NULL; + + // + // If the adapter is closed attempt to close it, and then + // set the opened flag to FALSE. + // + + if ( Open->AdapterOpened == TRUE ) + { + HANDLE Event; + IO_STATUS_BLOCK IoStatusBlock; + PBYTE InputBuffer[0x100]; + DWORD InputBufferSize = 0x100; + PBYTE OutputBuffer[0x100]; + DWORD OutputBufferSize = 0x100; + PCMD_ARGS CmdArgs; + + Event = CreateEvent( NULL,FALSE,FALSE,NULL ); + + if (Event == NULL) + { + Status = GetLastError(); + TpctlErrorLog("\n\tCreateEvent failed: returned 0x%lx.\n",(PVOID)Status); + } + + CmdArgs = (PCMD_ARGS)InputBuffer; + + CmdArgs->CmdCode = CLOSE; + CmdArgs->OpenInstance = Open->OpenInstance + 1; + +// !!NOT WIN32!! + + Status = NtDeviceIoControlFile( FileHandle, + Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + TP_CONTROL_CODE( CLOSE,IOCTL_METHOD ), + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize ); + + if (( Status != STATUS_SUCCESS ) && ( Status != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + + } + else + { + if (( Status == STATUS_PENDING ) && ( Event != NULL )) + { + // + // If the ioctl pended, then wait for it to complete. + // + + Status = WaitForSingleObject( Event,60000 ); // ONE_MINUTE + + if ( Status == WAIT_TIMEOUT ) + { + // + // The wait timed out, this probable means there + // was a failure in the MAC not completing the + // close. + // + + TpctlErrorLog( + "\n\tTpctl: WARNING - WaitForSingleObject unexpectedly timed out.\n",NULL); + TpctlErrorLog( + "\t IRP was never completed in protocol driver.\n",NULL); + } + else if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit + // the test app with the error. + // + + TpctlErrorLog( + "\n\tTpctl: ERROR - WaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + } + else if ( IoStatusBlock.Status != STATUS_SUCCESS ) + { + // + // else if the pending ioctl returned failure again + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile pended.\n",NULL); + TpctlErrorLog("\n\t NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)IoStatusBlock.Status); + ExitFlag = TRUE; + Status = IoStatusBlock.Status; + } + } + } + + Open->AdapterOpened = FALSE; + } + + // + // Then reset the various card and test specific flags to their + // original state. + // + + Open->OpenInstance = 0xFF; + Open->MediumType = 0; + Open->NdisVersion = 0; + + Open->AdapterName = NULL; + Open->LookaheadSize = 0; + Open->PacketFilter = NDIS_PACKET_TYPE_NONE; + Open->MulticastAddresses = NULL; + Open->NumberMultAddrs = 0; + + // Environment variables. + + Open->EnvVars->WindowSize = WINDOW_SIZE; + Open->EnvVars->RandomBufferNumber = BUFFER_NUMBER; + Open->EnvVars->StressDelayInterval = DELAY_INTERVAL; + Open->EnvVars->UpForAirDelay = UP_FOR_AIR_DELAY; + Open->EnvVars->StandardDelay = STANDARD_DELAY; + + strcpy( Open->EnvVars->StressAddress,STRESS_MULTICAST ); + strcpy( Open->EnvVars->ResendAddress,NULL_ADDRESS ); + + // Stress test flags. + + Open->Stressing = FALSE; + Open->StressResultsCompleted = FALSE; + Open->StressClient = FALSE; + + // Send test flags. + + Open->Sending = FALSE; + Open->SendResultsCompleted = FALSE; + + // Receive test flags. + + Open->Receiving = FALSE; + Open->ReceiveResultsCompleted = FALSE; + + // performance test flags + + Open->PerfResultsCompleted = FALSE; + + // Card state variables and structures. + + MultAddr = Open->MulticastAddresses; + + while ( MultAddr != NULL ) + { + NextMultAddr = MultAddr->Next; + GlobalFree( MultAddr ); + MultAddr = NextMultAddr; + } + + Open->MulticastAddresses = NULL; + Open->NumberMultAddrs = 0; + + ZeroMemory(Open->FunctionalAddress, FUNCTIONAL_ADDRESS_LENGTH); + ZeroMemory(Open->GroupAddress, FUNCTIONAL_ADDRESS_LENGTH); + + return Status; +} + + + +VOID +TpctlFreeOpenArray( + VOID + ) + +// ------------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// --------------- + +{ + DWORD i; + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + // + // First free up all of the allocated data structs, + // + + if ( Open[i].AdapterName != NULL ) + { + GlobalFree( Open[i].AdapterName ); + } + + if ( Open[i].EnvVars != NULL ) + { + GlobalFree( Open[i].EnvVars ); + } + + if ( Open[i].StressResults != NULL ) + { + GlobalFree( Open[i].StressResults ); + } + + if ( Open[i].StressArgs != NULL ) + { + GlobalFree( Open[i].StressArgs ); + } + + if ( Open[i].SendResults != NULL ) + { + GlobalFree( Open[i].SendResults ); + } + + if ( Open[i].StressArgs != NULL ) + { + GlobalFree( Open[i].SendArgs ); + } + + if ( Open[i].ReceiveResults != NULL ) + { + GlobalFree( Open[i].ReceiveResults ); + } + + if ( Open[i].PerfResults != NULL ) + { + GlobalFree( Open[i].PerfResults ); + } + + // + // Then stop the EventHandler thread, + // + + TpctlStopEventHandlerThread( &Open[i] ); + + // + // And finally close all of the event handles. + // + + if ( Open[i].Events[TPCONTROL] != NULL ) + { + CloseHandle( Open[i].Events[TPCONTROL] ); + } + + if ( Open[i].Events[TPCONTROL] != NULL ) + { + CloseHandle( Open[i].Events[TPSTRESS] ); + } + + if ( Open[i].Events[TPSEND] != NULL ) + { + CloseHandle( Open[i].Events[TPSEND] ); + } + + if ( Open[i].Events[TPRECEIVE] != NULL ) + { + CloseHandle( Open[i].Events[TPRECEIVE] ); + } + + if ( Open[i].Events[TPPERF] != NULL ) + { + CloseHandle( Open[i].Events[TPPERF] ); + } + + if ( Open[i].StressEvent != NULL ) + { + CloseHandle( Open[i].StressEvent ); + } + + if ( Open[i].SendEvent != NULL ) + { + CloseHandle( Open[i].SendEvent ); + } + + if ( Open[i].ReceiveEvent != NULL ) + { + CloseHandle( Open[i].ReceiveEvent ); + } + + if ( Open[i].PerfEvent != NULL ) + { + CloseHandle( Open[i].PerfEvent ); + } + } + + GlobalFree( GlobalBuf ); +} + + +DWORD +TpctlOpenTpdrvr( + IN OUT PHANDLE lphFileHandle + ) + +// ------------- +// +// Routine Description: +// +// This routine calls CreateFile to open the TPDRVR.SYS device driver. +// +// Arguments: +// +// lphFileHandle - the file handle of the file to be opened. +// +// Return Value: +// +// lphFileHandle contains a positive value if successful, -1 if not. +// +// ------------- + +{ + DWORD Status = NO_ERROR; + + *lphFileHandle = CreateFile(DEVICE_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttirbutes + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); // lpTemplateFile + + if ( *lphFileHandle == (HANDLE)-1 ) + { + Status = GetLastError(); + if ( Status == STATUS_DEVICE_ALREADY_ATTACHED ) + { + TpctlErrorLog("\n\tTpctl: Tpdrvr.sys already opened by another instance of\n",NULL); + TpctlErrorLog("\t the control application. Only one open allowed.\n",NULL); + } + else + { + TpctlErrorLog("\n\tTpctlOpenTpdrvr: CreateFile failed: returned 0x%lx.\n", + (PVOID)Status); + } + } + + return Status; +} + + + +VOID +TpctlCloseTpdrvr( + IN HANDLE hFileHandle + ) + +// ---------------- +// +// Routine Description: +// +// This routine calls CloseHandle to close the first instance of the +// TPDRVR.EXE driver. +// +// Arguments: +// +// hFileHandle - the file handle returned from the call to OpenFile. +// +// Return Value: +// +// STATUS - the status of the CloseHandle call. +// +// ----------------- + +{ + DWORD Status; + + if ( !CloseHandle( hFileHandle )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctlCloseTpdrvr: CloseHandle failed: returned 0x%lx.\n", + (PVOID)Status); + } + + return; +} + + + +DWORD +TpctlStartEventHandlerThread( + POPEN_BLOCK Open + ) + +// ----------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// -------------- + +{ + DWORD Status = NO_ERROR; + DWORD StackSize = 0x1000; + DWORD ThreadId; + HANDLE EventThread; + + + EventThread = CreateThread( NULL, + StackSize, + TpctlEventHandler, + (LPVOID)Open, + 0, + &ThreadId ); + + if ( EventThread == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("TpctlStartEventHandlerThread: CreateThread failed; returned 0x%lx.\n", + (PVOID)Status); + } + else + { + // + // the CreateT succeeded, we don't need the handle so close it. + // + + if ( !CloseHandle( EventThread ) ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctlStartEventHandlerThread: CloseHandle failed; returned 0x%lx\n", + (PVOID)Status); + } + } + + return Status; +} + + + +DWORD +TpctlEventHandler( + LPVOID Open + ) + +// -------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---------- + +{ + BOOL Continue = TRUE; + DWORD EventNumber; + DWORD Status; + + while ( Continue == TRUE ) + { + EventNumber = WaitForMultipleObjects( 5, + (LPHANDLE)((POPEN_BLOCK)Open)->Events, + FALSE, + INFINITE ); + + switch ( EventNumber ) + { + case TPCONTROL: // ResetWaitEvent; + Continue = FALSE; + break; + + case TPSTRESS: // StressEvent + // + // Set the Stressing flag to false to indicate that we have + // finished the STRESS test, and the ResultsCompleted flag to + // true to indicate that the results are ready to be displayed. + // + + ((POPEN_BLOCK)Open)->Stressing = FALSE; + + if (((POPEN_BLOCK)Open)->StressClient == TRUE ) + { + ((POPEN_BLOCK)Open)->StressResultsCompleted = TRUE; + } + + // + // And then signal the app that we have finished. + // + + if (!SetEvent(((POPEN_BLOCK)Open)->StressEvent)) + { + Status = GetLastError(); + OutputDebugString("TpctlEventHandler: failed to signal Stress Event 0x%lx.\n"); + } + break; + + case TPSEND: // SendEvent + // + // Set the Sending flag to false to indicate that we have + // finished the SEND test, and the ResultsCompleted flag to + // true to indicate that the results are ready to be displayed. + // + + ((POPEN_BLOCK)Open)->Sending = FALSE; + ((POPEN_BLOCK)Open)->SendResultsCompleted = TRUE; + + // + // And then signal the app that we have finished. + // + + if (!SetEvent( ((POPEN_BLOCK)Open)->SendEvent )) + { + Status = GetLastError(); + OutputDebugString("TpctlEventHandler: failed to signal Send Event 0x%lx.\n"); + } + break; + + case TPRECEIVE: // ReceiveEvent + // + // Set the Receiving flag to false to indicate that we have + // finished the RECEIVE test, and the ResultsCompleted flag to + // true to indicate that the results are ready to be displayed. + // + + ((POPEN_BLOCK)Open)->Receiving = FALSE; + ((POPEN_BLOCK)Open)->ReceiveResultsCompleted = TRUE; + + // + // And then signal the app that we have finished. + // + + if (!SetEvent( ((POPEN_BLOCK)Open)->ReceiveEvent )) + { + Status = GetLastError(); + OutputDebugString("TpctlEventHandler: failed to signal Receive Event.\n"); + } + break; + + case TPPERF: // PerfEvent + // + // Set the PerfResultsCompleted flag to + // true to indicate that the results are ready to be displayed. + // + + ((POPEN_BLOCK)Open)->PerfResultsCompleted = TRUE; + + // + // And then signal the app that we have finished. + // + + if (!SetEvent( ((POPEN_BLOCK)Open)->PerfEvent )) + { + Status = GetLastError(); + OutputDebugString("TpctlEventHandler: failed to signal Perf Event.\n"); + } + break; + } + } + + return EventNumber; +} + + + +VOID +TpctlStopEventHandlerThread( + POPEN_BLOCK Open + ) + +// ---------------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// ---------------- + +{ + DWORD Status; + + // + // First signal the thread to stop the Wait call. + // + + if ( Open->EventThreadStarted == TRUE ) + { + if ( !SetEvent( Open->Events[TPCONTROL] )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctlStopEventHandlerThread: SetEvent failed; returned 0x%lx.\n", + (PVOID)Status); + } + } +} + + + +BOOL +TpctlCtrlCHandler( + IN DWORD CtrlType + ) + +// -------------- +// +// Routine Description: +// +// This routine catches any instances of Ctrl-C and sets the +// ContinueLooping flag to FALSE. WaitStress, WaitSend, GetEvents, +// Pause and Go, and parsing of script file commands will halt +// when this flag is set to true. +// +// Arguments: +// +// DWORD CtrlType - the event passed in by the system. +// +// Return Value: +// +// BOOL - TRUE if this event should be ignored by the system, FALSE +// otherwise. +// +// -------------- + + +{ + if ( CtrlType == CTRL_BREAK_EVENT ) + { + return FALSE; + } + else if ( CtrlType == CTRL_C_EVENT ) + { + if ( ContinueLooping == TRUE ) + { + ContinueLooping = FALSE; + } + } + return TRUE; +} + + diff --git a/private/ntos/ndis/testprot/tpctl/makefile b/private/ntos/ndis/testprot/tpctl/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/testprot/tpctl/parse.c b/private/ntos/ndis/testprot/tpctl/parse.c new file mode 100644 index 000000000..613e10473 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/parse.c @@ -0,0 +1,2526 @@ +// ****************************************************************** +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// parse.c +// +// Abstract: +// +// This module contains the routines for parsing commands entered from +// the command line or read from script files. +// +// Author: +// +// Tom Adams (tomad) 11-May-1991 +// +// Revision History: +// +// +// Sanjeev Katariya (sanjeevk) +// 4-12-1993 Added ARCNET support +// 4-15-1993 Added additional OIDS +// 7-01-1993 Added suppport for recoring sessions and spawning +// command shells within tpctl +// Tim Wynsma (timothyw) +// 4-27-94 added performance testing +// 5-16-94 added globvars hooks; cleanup +// 6-08-94 chgd to client/server model for perf test +// +// ****************************************************************** + + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "tpctl.h" +#include "parse.h" + + +VOID +TpctlFixBuffer( + IN BYTE Buffer[] + ); + + +DWORD +TpctlParseInteger( + IN BYTE Buffer[], + IN PARSETABLE ParseTable[], + IN DWORD ParseTableSize, + OUT PDWORD Ret + ); + + +BOOL +TpctlParseArgumentPairs( + IN LPSTR Argument, + OUT LPSTR *ArgName, + OUT LPSTR *ArgValue + ); + + +BOOL +TpctlParseSetInfoArguments( + IN OUT DWORD *ArgC, + IN OUT LPSTR ArgV[], + IN OUT DWORD *tmpArgC, + IN OUT LPSTR tmpArgV[] + ); + + +BOOL +TpctlParseEnvironmentVariable( + IN BYTE Buffer[] + ); + + +BOOL +TpctlFirstChar( + IN BYTE Buffer[], + IN BYTE Char + ); + + +DWORD +TpctlGetOptionNumber( + IN PTESTPARAMS Options, + IN DWORD TestSize, + IN LPSTR ArgName + ); + + +DWORD +TpctlGetOpenInstance( + IN DWORD ArgC, + IN LPSTR ArgV[] + ); + + + +PARSETABLE +BooleanTable[] = { + NamedField( TRUE ), + NamedField( FALSE ), + { "T", TRUE }, + { "F", FALSE } +}; + + + +PARSETABLE +PacketFilterTable [] = { + NamedField( NDIS_PACKET_TYPE_DIRECTED ), + NamedField( NDIS_PACKET_TYPE_MULTICAST ), + NamedField( NDIS_PACKET_TYPE_ALL_MULTICAST ), + NamedField( NDIS_PACKET_TYPE_BROADCAST ), + NamedField( NDIS_PACKET_TYPE_SOURCE_ROUTING ), + NamedField( NDIS_PACKET_TYPE_PROMISCUOUS ), + NamedField( NDIS_PACKET_TYPE_MAC_FRAME ), + NamedField( NDIS_PACKET_TYPE_GROUP ), + NamedField( NDIS_PACKET_TYPE_FUNCTIONAL ), + NamedField( NDIS_PACKET_TYPE_ALL_FUNCTIONAL ), + NamedField( NDIS_PACKET_TYPE_NONE ), + + { "Directed", NDIS_PACKET_TYPE_DIRECTED }, + { "Multicast", NDIS_PACKET_TYPE_MULTICAST }, + { "AllMulticast", NDIS_PACKET_TYPE_ALL_MULTICAST }, + { "Broadcast", NDIS_PACKET_TYPE_BROADCAST }, + { "SourceRouting", NDIS_PACKET_TYPE_SOURCE_ROUTING }, + { "Promiscuous", NDIS_PACKET_TYPE_PROMISCUOUS }, + { "MacFrame", NDIS_PACKET_TYPE_MAC_FRAME }, + { "Group", NDIS_PACKET_TYPE_GROUP }, + { "Functional", NDIS_PACKET_TYPE_FUNCTIONAL }, + { "AllFunctional", NDIS_PACKET_TYPE_ALL_FUNCTIONAL }, + { "None", NDIS_PACKET_TYPE_NONE } +}; + + +PARSETABLE +QueryInfoOidTable [] = { + + // + // General Objects + // + + NamedField( OID_GEN_SUPPORTED_LIST ), + NamedField( OID_GEN_HARDWARE_STATUS ), + NamedField( OID_GEN_MEDIA_SUPPORTED ), + NamedField( OID_GEN_MEDIA_IN_USE ), + NamedField( OID_GEN_MAXIMUM_LOOKAHEAD ), + NamedField( OID_GEN_MAXIMUM_FRAME_SIZE ), + NamedField( OID_GEN_LINK_SPEED ), + NamedField( OID_GEN_TRANSMIT_BUFFER_SPACE ), + NamedField( OID_GEN_RECEIVE_BUFFER_SPACE ), + NamedField( OID_GEN_TRANSMIT_BLOCK_SIZE ), + NamedField( OID_GEN_RECEIVE_BLOCK_SIZE ), + NamedField( OID_GEN_VENDOR_ID ), + NamedField( OID_GEN_VENDOR_DESCRIPTION ), + NamedField( OID_GEN_CURRENT_PACKET_FILTER ), + NamedField( OID_GEN_CURRENT_LOOKAHEAD ), + NamedField( OID_GEN_DRIVER_VERSION ), + NamedField( OID_GEN_MAXIMUM_TOTAL_SIZE ), + NamedField( OID_GEN_PROTOCOL_OPTIONS ), + NamedField( OID_GEN_MAC_OPTIONS ), + + NamedField( OID_GEN_XMIT_OK ), + NamedField( OID_GEN_RCV_OK ), + NamedField( OID_GEN_XMIT_ERROR ), + NamedField( OID_GEN_RCV_ERROR ), + NamedField( OID_GEN_RCV_NO_BUFFER ), + + NamedField( OID_GEN_DIRECTED_BYTES_XMIT ), + NamedField( OID_GEN_DIRECTED_FRAMES_XMIT ), + NamedField( OID_GEN_MULTICAST_BYTES_XMIT ), + NamedField( OID_GEN_MULTICAST_FRAMES_XMIT ), + NamedField( OID_GEN_BROADCAST_BYTES_XMIT ), + NamedField( OID_GEN_BROADCAST_FRAMES_XMIT ), + NamedField( OID_GEN_DIRECTED_BYTES_RCV ), + NamedField( OID_GEN_DIRECTED_FRAMES_RCV ), + NamedField( OID_GEN_MULTICAST_BYTES_RCV ), + NamedField( OID_GEN_MULTICAST_FRAMES_RCV ), + NamedField( OID_GEN_BROADCAST_BYTES_RCV ), + NamedField( OID_GEN_BROADCAST_FRAMES_RCV ), + + NamedField( OID_GEN_RCV_CRC_ERROR ), + NamedField( OID_GEN_TRANSMIT_QUEUE_LENGTH ), + + // + // 802.3 Objects + // + + NamedField( OID_802_3_PERMANENT_ADDRESS ), + NamedField( OID_802_3_CURRENT_ADDRESS ), + NamedField( OID_802_3_MULTICAST_LIST ), + NamedField( OID_802_3_MAXIMUM_LIST_SIZE ), + + NamedField( OID_802_3_RCV_ERROR_ALIGNMENT ), + NamedField( OID_802_3_XMIT_ONE_COLLISION ), + NamedField( OID_802_3_XMIT_MORE_COLLISIONS ), + + NamedField( OID_802_3_XMIT_DEFERRED ), + NamedField( OID_802_3_XMIT_MAX_COLLISIONS ), + NamedField( OID_802_3_RCV_OVERRUN ), + NamedField( OID_802_3_XMIT_UNDERRUN ), + NamedField( OID_802_3_XMIT_HEARTBEAT_FAILURE ), + NamedField( OID_802_3_XMIT_TIMES_CRS_LOST ), + NamedField( OID_802_3_XMIT_LATE_COLLISIONS ), + + // + // 802.5 Objects + // + + NamedField( OID_802_5_PERMANENT_ADDRESS ), + NamedField( OID_802_5_CURRENT_ADDRESS ), + NamedField( OID_802_5_CURRENT_FUNCTIONAL ), + NamedField( OID_802_5_CURRENT_GROUP ), + NamedField( OID_802_5_LAST_OPEN_STATUS ), + NamedField( OID_802_5_CURRENT_RING_STATUS ), + NamedField( OID_802_5_CURRENT_RING_STATE ), + + NamedField( OID_802_5_LINE_ERRORS ), + NamedField( OID_802_5_LOST_FRAMES ), + + NamedField( OID_802_5_BURST_ERRORS ), + NamedField( OID_802_5_AC_ERRORS ), + NamedField( OID_802_5_ABORT_DELIMETERS ), + NamedField( OID_802_5_FRAME_COPIED_ERRORS ), + NamedField( OID_802_5_FREQUENCY_ERRORS ), + NamedField( OID_802_5_TOKEN_ERRORS ), + NamedField( OID_802_5_INTERNAL_ERRORS ), + + // + // Fddi objects + // + + NamedField( OID_FDDI_LONG_PERMANENT_ADDR ), + NamedField( OID_FDDI_LONG_CURRENT_ADDR ), + NamedField( OID_FDDI_LONG_MULTICAST_LIST ), + NamedField( OID_FDDI_LONG_MAX_LIST_SIZE ), + NamedField( OID_FDDI_SHORT_PERMANENT_ADDR ), + NamedField( OID_FDDI_SHORT_CURRENT_ADDR ), + NamedField( OID_FDDI_SHORT_MULTICAST_LIST ), + NamedField( OID_FDDI_SHORT_MAX_LIST_SIZE ), + + NamedField( OID_FDDI_ATTACHMENT_TYPE ), + NamedField( OID_FDDI_UPSTREAM_NODE_LONG ), + NamedField( OID_FDDI_DOWNSTREAM_NODE_LONG ), + NamedField( OID_FDDI_FRAME_ERRORS ), + NamedField( OID_FDDI_FRAMES_LOST ), + NamedField( OID_FDDI_RING_MGT_STATE ), + NamedField( OID_FDDI_LCT_FAILURES ), + NamedField( OID_FDDI_LEM_REJECTS ), + NamedField( OID_FDDI_LCONNECTION_STATE ), + + // + // STARTCHANGE + // + // ARCNET objects + // + NamedField( OID_ARCNET_PERMANENT_ADDRESS ), + NamedField( OID_ARCNET_CURRENT_ADDRESS ), + NamedField( OID_ARCNET_RECONFIGURATIONS ), + // + // STOPCHANGE + // + + // + // Async Objects + // + +#if 0 + +// Not currently supported. + + NamedField( OID_ASYNC_PERMANENT_ADDRESS ), + NamedField( OID_ASYNC_CURRENT_ADDRESS ), + NamedField( OID_ASYNC_QUALITY_OF_SERVICE ), + NamedField( OID_ASYNC_PROTOCOL_TYPE ), + +#endif + + // + // LocalTalk Objects + // + +#if 0 + +// Not currently supported. + + NamedField( OID_LTALK_CURRENT_NODE_ID ), + + NamedField( OID_LTALK_IN_BROADCASTS ), + NamedField( OID_LTALK_IN_LENGTH_ERRORS ), + + NamedField( OID_LTALK_OUT_NO_HANDLERS ), + NamedField( OID_LTALK_COLLISIONS ), + NamedField( OID_LTALK_DEFERS ), + NamedField( OID_LTALK_NO_DATA_ERRORS ), + NamedField( OID_LTALK_RANDOM_CTS_ERRORS ), + NamedField( OID_LTALK_FCS_ERRORS ), + +#endif + + // + // General Objects + // + + { "SupportedOIDList", OID_GEN_SUPPORTED_LIST }, + { "HardwareStatus", OID_GEN_HARDWARE_STATUS }, + { "MediaTypeSupported", OID_GEN_MEDIA_SUPPORTED }, + { "MediaTypeInUse", OID_GEN_MEDIA_IN_USE }, + { "MaximumLookahead", OID_GEN_MAXIMUM_LOOKAHEAD }, + { "MaximumFrameSize", OID_GEN_MAXIMUM_FRAME_SIZE }, + { "LinkSpeed", OID_GEN_LINK_SPEED }, + { "TransmitBufferSpace", OID_GEN_TRANSMIT_BUFFER_SPACE }, + { "ReceiveBufferSpace", OID_GEN_RECEIVE_BUFFER_SPACE }, + { "TransmitBlockSize", OID_GEN_TRANSMIT_BLOCK_SIZE }, + { "ReceiveBlockSize", OID_GEN_RECEIVE_BLOCK_SIZE }, + { "VendorID", OID_GEN_VENDOR_ID }, + { "VendorDescription", OID_GEN_VENDOR_DESCRIPTION }, + { "CurrentPacketFilter", OID_GEN_CURRENT_PACKET_FILTER }, + { "CurrentLookahead", OID_GEN_CURRENT_LOOKAHEAD }, + { "DriverVersion", OID_GEN_DRIVER_VERSION }, + { "MaximumTotalSize", OID_GEN_MAXIMUM_TOTAL_SIZE }, + + { "TransmitGood", OID_GEN_XMIT_OK }, + { "ReceiveGood", OID_GEN_RCV_OK }, + { "TransmitBad", OID_GEN_XMIT_ERROR }, + { "ReceiveBad", OID_GEN_RCV_ERROR }, + { "ReciveNoBuffer", OID_GEN_RCV_NO_BUFFER }, + + { "DirectedBytesTransmits", OID_GEN_DIRECTED_BYTES_XMIT }, + { "DirectedFramesTransmits", OID_GEN_DIRECTED_FRAMES_XMIT }, + { "MulticastBytesTransmits", OID_GEN_MULTICAST_BYTES_XMIT }, + { "MulticastFramesTransmits", OID_GEN_MULTICAST_FRAMES_XMIT }, + { "BroadcastBytesTransmits", OID_GEN_BROADCAST_BYTES_XMIT }, + { "BroadcastFramesTransmits", OID_GEN_BROADCAST_FRAMES_XMIT }, + { "DirectedBytesReceives", OID_GEN_DIRECTED_BYTES_RCV }, + { "DirectedFramesReceives", OID_GEN_DIRECTED_FRAMES_RCV }, + { "MulticastBytesReceives", OID_GEN_MULTICAST_BYTES_RCV }, + { "MulticastFramesReceives", OID_GEN_MULTICAST_FRAMES_RCV }, + { "BroadcastBytesReceives", OID_GEN_BROADCAST_BYTES_RCV }, + { "BroadcastFramesReceives", OID_GEN_BROADCAST_FRAMES_RCV }, + + { "ReceiveCRC", OID_GEN_RCV_CRC_ERROR }, + { "TransmitQueueLength", OID_GEN_TRANSMIT_QUEUE_LENGTH }, + + // + // 802.3 Objects + // + + { "EthPermanentAddress", OID_802_3_PERMANENT_ADDRESS }, + { "EthCurrentAddress", OID_802_3_CURRENT_ADDRESS }, + { "CurrentMulticastList", OID_802_3_MULTICAST_LIST }, + { "MaxMulticastListSize", OID_802_3_MAXIMUM_LIST_SIZE }, + + { "ReceiveErrorAlignment", OID_802_3_RCV_ERROR_ALIGNMENT }, + { "TransmitOneCollsion", OID_802_3_XMIT_ONE_COLLISION }, + { "TransmitMoreCollostions", OID_802_3_XMIT_MORE_COLLISIONS }, + + { "TransmitDeferred", OID_802_3_XMIT_DEFERRED }, + { "TransmitMaxCollisions", OID_802_3_XMIT_MAX_COLLISIONS }, + { "ReceiveOverrun", OID_802_3_RCV_OVERRUN }, + { "TransmitUnderrun", OID_802_3_XMIT_UNDERRUN }, + { "TransmitHeartbeatFailure", OID_802_3_XMIT_HEARTBEAT_FAILURE }, + { "TransmitTimesCRSLost", OID_802_3_XMIT_TIMES_CRS_LOST }, + { "TransmitLateCollisions", OID_802_3_XMIT_LATE_COLLISIONS }, + + // + // 802.5 Objects + // + + { "TRPermanentAddress", OID_802_5_PERMANENT_ADDRESS }, + { "TRCurrentAddress", OID_802_5_CURRENT_ADDRESS }, + { "CurrentFunctionalAddress", OID_802_5_CURRENT_FUNCTIONAL }, + { "CurrentGroupAddress", OID_802_5_CURRENT_GROUP }, + { "LastOpenStatus", OID_802_5_LAST_OPEN_STATUS }, + { "CurrentRingStatus", OID_802_5_CURRENT_RING_STATUS }, + { "CurrentRingState", OID_802_5_CURRENT_RING_STATE }, + + { "LineErrors", OID_802_5_LINE_ERRORS }, + { "LostFrames", OID_802_5_LOST_FRAMES }, + + { "BurstErrors", OID_802_5_BURST_ERRORS }, + { "ACErrors", OID_802_5_AC_ERRORS }, + { "AbortDelimeters", OID_802_5_ABORT_DELIMETERS }, + { "FrameCopiedErrors", OID_802_5_FRAME_COPIED_ERRORS }, + { "FrequencyErrors", OID_802_5_FREQUENCY_ERRORS }, + { "TokenErrors", OID_802_5_TOKEN_ERRORS }, + { "InternalErrors", OID_802_5_INTERNAL_ERRORS }, + + // + // Fddi objects + // + + { "FddiLongPermanentAddress", OID_FDDI_LONG_PERMANENT_ADDR }, + { "FddiLongCurrentAddress", OID_FDDI_LONG_CURRENT_ADDR }, + { "FddiLongMulticastList", OID_FDDI_LONG_MULTICAST_LIST }, + { "FddiLongMaxListSize", OID_FDDI_LONG_MAX_LIST_SIZE }, + { "FddiShortPermanentAddress", OID_FDDI_SHORT_PERMANENT_ADDR }, + { "FddiShortCurrentAddress", OID_FDDI_SHORT_CURRENT_ADDR }, + { "FddiShortMulticastList", OID_FDDI_SHORT_MULTICAST_LIST }, + { "FddiShortMaxListSize", OID_FDDI_SHORT_MAX_LIST_SIZE }, + + // + // STARTCHANGE + // + // ARCNET objects + // + { "ArcPermanentAddress", OID_ARCNET_PERMANENT_ADDRESS }, + { "ArcCurrentAddress", OID_ARCNET_CURRENT_ADDRESS }, + { "ArcReconfigurations", OID_ARCNET_RECONFIGURATIONS }, + // + // STOPCHANGE + // + + // + // Async Objects + // + +#if 0 + +// Not currently supported. + + { "AsyncPermanentAddress", OID_ASYNC_PERMANENT_ADDRESS }, + { "AsyncCurrentAddress", OID_ASYNC_CURRENT_ADDRESS }, + { "AsyncQualityOfService", OID_ASYNC_QUALITY_OF_SERVICE }, + { "AsyncProtocolType", OID_ASYNC_PROTOCOL_TYPE }, + +#endif + + // + // LocalTalk Objects + // + +#if 0 + +// Not currently supported. + + { "LTalkCurrentNodeId", OID_LTALK_CURRENT_NODE_ID }, + + { "LTalkInBroadcasts", OID_LTALK_IN_BROADCASTS }, + { "LTalkInLengthErrors", OID_LTALK_IN_LENGTH_ERRORS }, + + { "LTalkOutNoHandlers", OID_LTALK_OUT_NO_HANDLERS }, + { "LTalkCollisions", OID_LTALK_COLLISIONS }, + { "LTalkDefers", OID_LTALK_DEFERS }, + { "LTalkNoDataErrors", OID_LTALK_NO_DATA_ERRORS }, + { "LTalkRandomCTSErrors", OID_LTALK_RANDOM_CTS_ERRORS }, + { "LTalkFCSErrors", OID_LTALK_FCS_ERRORS } + +#endif + +}; + + +PARSETABLE +SetInfoOidTable [] = { + NamedField( OID_GEN_CURRENT_PACKET_FILTER ), + NamedField( OID_GEN_CURRENT_LOOKAHEAD ), + NamedField( OID_802_3_MULTICAST_LIST ), + NamedField( OID_802_5_CURRENT_FUNCTIONAL ), + NamedField( OID_802_5_CURRENT_GROUP ), + NamedField( OID_FDDI_LONG_CURRENT_ADDR ), + NamedField( OID_FDDI_LONG_MULTICAST_LIST ), + NamedField( OID_FDDI_SHORT_CURRENT_ADDR ), + NamedField( OID_FDDI_SHORT_MULTICAST_LIST ), + + // + // STARTCHANGE + // + NamedField( OID_ARCNET_CURRENT_ADDRESS ), + // + // STOPCHANGE + // + + { "CurrentPacketFilter", OID_GEN_CURRENT_PACKET_FILTER }, + { "CurrentLookAhead", OID_GEN_CURRENT_LOOKAHEAD }, + { "CurrentMulticastList", OID_802_3_MULTICAST_LIST }, + { "CurrentFunctionalAddress", OID_802_5_CURRENT_FUNCTIONAL }, + { "CurrentGroupAddress", OID_802_5_CURRENT_GROUP }, + { "FddiLongCurrentAddress", OID_FDDI_LONG_CURRENT_ADDR }, + { "FddiLongMulticastList", OID_FDDI_LONG_MULTICAST_LIST }, + { "FddiShortCurrentAddress", OID_FDDI_SHORT_CURRENT_ADDR }, + { "FddiShortMulticastList", OID_FDDI_SHORT_MULTICAST_LIST }, + + // + // STARTCHANGE + // + { "ArcCurrentAddress", OID_ARCNET_CURRENT_ADDRESS } + // + // STOPCHANGE + // + + +}; + + +PARSETABLE +MemberTypeTable [] = { + NamedField( TP_CLIENT ), + NamedField( TP_SERVER ), + NamedField( BOTH ), + + { "Client", TP_CLIENT }, + { "Server", TP_SERVER }, + { "Both", BOTH } +}; + + +PARSETABLE +PacketTypeTable [] = { + NamedField( FIXEDSIZE ), + NamedField( RANDOMSIZE ), + NamedField( CYCLICAL ), + + { "Fixed", FIXEDSIZE }, + { "Random", RANDOMSIZE }, + { "Cyclic", CYCLICAL } +}; + + +PARSETABLE +PacketMakeUpTable [] = { + NamedField( RAND ), + NamedField( SMALL ), + NamedField( ZEROS ), + NamedField( ONES ), + NamedField( KNOWN ), + + { "Random_MakeUp", RAND }, + { "Small_MakeUp", SMALL }, + { "Zeros_MakeUp", ZEROS }, + { "Ones_MakeUp", ONES }, + { "Known_MakeUp", KNOWN } +}; + + +PARSETABLE +ResponseTypeTable [] = { + NamedField( NO_RESPONSE ), + NamedField( FULL_RESPONSE ), + NamedField( ACK_EVERY ), + NamedField( ACK_10_TIMES ), + + { "No Response", NO_RESPONSE }, + { "Response", FULL_RESPONSE }, + { "ACK", ACK_EVERY }, + { "ACK10", ACK_10_TIMES } +}; + + +PARSETABLE +DelayTable [] = { + NamedField( FIXEDDELAY ), + NamedField( RANDOMDELAY ), + + { "Fixed", FIXEDDELAY }, + { "Random", RANDOMDELAY } +}; + + +PARSETABLE +OperationTypeTable[] = { + NamedField( ADD_KEY ), + NamedField( DELETE_KEY ), + NamedField( QUERY_KEY ), + NamedField( ADD_VALUE ), + NamedField( CHANGE_VALUE ), + NamedField( DELETE_VALUE ), + NamedField( QUERY_VALUE ), + + { "Add Key" , ADD_KEY }, + { "Delete Key" , DELETE_KEY }, + { "Query Key" , QUERY_KEY }, + { "Add Value" , ADD_VALUE }, + { "Change Value" , CHANGE_VALUE }, + { "Delete Value" , DELETE_VALUE }, + { "Query Value" , QUERY_VALUE } +}; + + +PARSETABLE +KeyDbaseTable [] = { + NamedField( CLASSES_ROOT ), + NamedField( CURRENT_USER ), + NamedField( LOCAL_MACHINE ), + NamedField( USERS ), + + { "HKEY_CLASSES_ROOT" , CLASSES_ROOT }, + { "HKEY_CURRENT_USER" , CURRENT_USER }, + { "HKEY_LOCAL_MACHINE", LOCAL_MACHINE }, + { "HKEY_USERS" , USERS } +}; + + +PARSETABLE +ValueTypeTable[] = { + NamedField( BINARY ), + NamedField( DWORD_REGULAR ), + NamedField( DWORD_LITTLE_ENDIAN ), + NamedField( DWORD_BIG_ENDIAN ), + NamedField( EXPAND_SZ ), + NamedField( LINK ), + NamedField( MULTI_SZ ), + NamedField( NONE ), + NamedField( RESOURCE_LIST ), + NamedField( SZ ), + + { "Binary", BINARY }, + { "Double Word", DWORD_REGULAR }, + { "Double Word Litlle Endian", DWORD_LITTLE_ENDIAN }, + { "Double Word Big Endian", DWORD_BIG_ENDIAN }, + { "String with unexpanded environment references", EXPAND_SZ }, + { "Symbolic Link", LINK }, + { "Array of strings", MULTI_SZ }, + { "None", NONE }, + { "Resource List", RESOURCE_LIST }, + { "String", SZ } + +}; + +// +// The Test Parameters Structure and command parameter definitions. +// +// typedef struct _TestOptions { +// DWORD OptionNumber; +// LPSTR TestPrompt; +// LPSTR ArgName; +// LPSTR ArgNameAbbr; +// +// BOOL ArgValueSet; +// PARAMTYPES TestType; +// DWORD IntegerDefault; +// LPSTR StringDefault; +// +// PPARSETABLE ParsedIntTable; +// DWORD ParsedIntTableSize; +// PVOID Destination; +// } TESTPARAMS, *PTESTPARAMS; +// +// + +TESTPARAMS +CommandLineOptions[] = { + + + { 1, "Options", "Options", "OP", FALSE, String, + 0, NULL, NULL, 0, GlobalCmdArgs.TpctlOptions }, + + { 2, "ScriptFile Name", "ScriptFile", "SF", FALSE, String, + 0, NULL, NULL, 0, GlobalCmdArgs.ARGS.FILES.ScriptFile }, + + { 3, "LogFile Name", "LogFile", "LF", FALSE, String, 0, + NULL, NULL, 0, GlobalCmdArgs.ARGS.FILES.LogFile } +}; + + +DWORD +Num_CommandLine_Params = sizeoftable( CommandLineOptions ); + + +TESTPARAMS +SetEnvOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Window Size", "WindowSize", "WS", FALSE, Integer, WINDOW_SIZE, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.ENV.WindowSize }, + + { 3, "Random Buffer", "RandomBuffer", "RB", FALSE, Integer, BUFFER_NUMBER, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.ENV.RandomBufferNumber }, + + { 4, "Stress Address", "StressAddress" , "SA", FALSE, Address6, 0, + STRESS_MULTICAST, NULL, 0, GlobalCmdArgs.ARGS.ENV.StressAddress }, + + { 5, "Resend Address", "ResendAddress" , "RA", FALSE, Address6, 0, + NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.ENV.ResendAddress }, + + { 6, "Stress Delay", "StressDelay", "SD", FALSE, Integer, + STANDARD_DELAY, NULL, NULL, 0, &GlobalCmdArgs.ARGS.ENV.StandardDelay }, + + { 7, "Up-For-Air Delay", "UpForAirDelay", "UD", FALSE, Integer, + UP_FOR_AIR_DELAY, NULL, NULL, 0, &GlobalCmdArgs.ARGS.ENV.UpForAirDelay }, + + { 8, "Delay Interval", "DelayInterval", "I", FALSE, Integer, DELAY_INTERVAL, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.ENV.StressDelayInterval } +}; + + +DWORD +Num_SetEnv_Params = sizeoftable( SetEnvOptions ); + + +TESTPARAMS ReadScriptOptions[] = { + + { 1, "ScriptFile Name", "ScriptFile", "SF", FALSE, String, 0, + NULL, NULL, 0, GlobalCmdArgs.ARGS.FILES.ScriptFile }, + + { 2, "LogFile Name", "LogFile", "LF", FALSE, String, 0, NULL, + NULL, 0, GlobalCmdArgs.ARGS.FILES.LogFile } +}; + + +DWORD +Num_ReadScript_Params = sizeoftable( ReadScriptOptions ); + + +TESTPARAMS +LoggingOptions[] = { + + { 1, "LogFile Name", "LogFile", "LF", FALSE, String, 0, + TPCTL_CMDLINE_LOG, NULL, 0, GlobalCmdArgs.ARGS.FILES.LogFile } +}; + + +DWORD +Num_Logging_Params = sizeoftable( LoggingOptions ); + + +TESTPARAMS +RecordingOptions[] = { + + { 1, "ScriptFile Name", "ScriptFile", "SF", FALSE, String, 0, + TPCTL_CMDLINE_SCRIPT, NULL, 0, GlobalCmdArgs.ARGS.RECORD.ScriptFile } +}; + + +DWORD +Num_Recording_Params = sizeoftable( RecordingOptions ); + + +TESTPARAMS +PauseGoOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Remote Address", "RemoteAddress" , "RA", FALSE, Address6, 0, + NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.PAUSE_GO.RemoteAddress }, + + { 3, "Test Signature", "TestSignature", "TS", FALSE, Integer, + 0, NULL, NULL, 0, &GlobalCmdArgs.ARGS.PAUSE_GO.TestSignature }, + + { 4, "Unique Signature", "UniqueSig", "UI", FALSE, Integer, 0, NULL, + NULL, 0, &GlobalCmdArgs.ARGS.PAUSE_GO.UniqueSignature }, +}; + + +DWORD +Num_PauseGo_Params = sizeoftable( PauseGoOptions ); + + +TESTPARAMS +LoadUnloadOptions[] = { + + { 1, "Driver Name", "DriverName", "DN", FALSE, String, 0, + NULL, NULL, 0, GlobalCmdArgs.ARGS.DriverName } +}; + + +DWORD +Num_LoadUnload_Params = sizeoftable( LoadUnloadOptions ); + + +TESTPARAMS +OpenOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Adapter Name", "AdapterName", "AN", FALSE, String, 0, + NULL, NULL, 0, GlobalCmdArgs.ARGS.OPEN_ADAPTER.AdapterName } +}; + + +DWORD +Num_Open_Params = sizeoftable( OpenOptions ); + + +TESTPARAMS +SetPacketFilterOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Packet Filter", "PacketFilter", "PF", FALSE, ParsedInteger, + 0, "DIRECTED", PacketFilterTable, sizeoftable( PacketFilterTable ), + &GlobalCmdArgs.ARGS.TPSET.U.PacketFilter } +}; + + +DWORD +Num_SetPacketFilter_Params = sizeoftable( SetPacketFilterOptions ); + + +TESTPARAMS +SetLookaheadOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Lookahead Buffer Size", "Lookahead", "LA", FALSE, + Integer, LOOKAHEADSIZE, NULL, NULL, 0, + &GlobalCmdArgs.ARGS.TPSET.U.LookaheadSize } +}; + + +DWORD +Num_SetLookahead_Params = sizeoftable( SetLookaheadOptions ); + + +TESTPARAMS +MulticastAddrOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Multicast Address", "MulticastAddress", "MA", + FALSE, Address6, 0, DEFAULT_MULTICAST, NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0] } +}; + + +DWORD +Num_MulticastAddr_Params = sizeoftable( MulticastAddrOptions ); + + +TESTPARAMS +FunctionalAddrOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Functional Address", "FunctionalAddress", "FA", + FALSE, Address4, 0, &DEFAULT_FUNCTIONAL[2], NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.FunctionalAddress } +}; + + +DWORD +Num_FunctionalAddr_Params = sizeoftable( FunctionalAddrOptions ); + + +TESTPARAMS +GroupAddrOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Group Address", "GroupAddress", "GA", + FALSE, Address4, 0, &DEFAULT_FUNCTIONAL[2], NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.FunctionalAddress } +}; + + +DWORD +Num_GroupAddr_Params = sizeoftable( GroupAddrOptions ); + + +TESTPARAMS +QueryInfoOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "OID Request", "ObjectIdentifier", "OID", FALSE, ParsedInteger, + 0x00010101, "SupportedOidList", QueryInfoOidTable, + sizeoftable( QueryInfoOidTable ), &GlobalCmdArgs.ARGS.TPQUERY.OID }, +}; + + +DWORD +Num_QueryInfo_Params = sizeoftable( QueryInfoOptions ); + + +TESTPARAMS +QueryStatsOptions[] = { + + + { 1, "Device Name", "DeviceName", "DN", FALSE, String, 0, NULL, + NULL, 0, GlobalCmdArgs.ARGS.TPQUERYSTATS.DeviceName }, + + { 2, "OID Request", "ObjectIdentifier", "OID", FALSE, ParsedInteger, + 0x00010101, "SupportedOidList", QueryInfoOidTable, + sizeoftable( QueryInfoOidTable ), &GlobalCmdArgs.ARGS.TPQUERYSTATS.OID }, +}; + + +DWORD +Num_QueryStats_Params = sizeoftable( QueryStatsOptions ); + + +TESTPARAMS +SetInfoOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "OID Request", "ObjectIdentifier", "OID", FALSE, ParsedInteger, + 0x0001010e, "CurrentPacketFilter", SetInfoOidTable, + sizeoftable( SetInfoOidTable ), &GlobalCmdArgs.ARGS.TPSET.OID } +}; + + +DWORD +Num_SetInfo_Params = sizeoftable( SetInfoOptions ); + + +TESTPARAMS +SetInfoPFOptions[] = { + + { 1, "Packet Filter", "PacketFilter", "PF", FALSE, ParsedInteger, + 0, "DIRECTED", PacketFilterTable, sizeoftable( PacketFilterTable ), + &GlobalCmdArgs.ARGS.TPSET.U.PacketFilter } +}; + + +DWORD +Num_SetInfoPF_Params = sizeoftable( SetInfoPFOptions ); + + +TESTPARAMS +SetInfoLAOptions[] = { + + { 1, "Lookahead Buffer Size", "Lookahead", "LA", + FALSE, Integer, LOOKAHEADSIZE, NULL, NULL, 0, + &GlobalCmdArgs.ARGS.TPSET.U.LookaheadSize } +}; + + +DWORD +Num_SetInfoLA_Params = sizeoftable( SetInfoLAOptions ); + + +TESTPARAMS +SetInfoMAOptions[] = { + + { 1, "Multicast Address", "MulticastAddress", "MA", + FALSE, Address6, 0, DEFAULT_MULTICAST, NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0] } +}; + + +DWORD +Num_SetInfoMA_Params = sizeoftable( SetInfoMAOptions ); + +TESTPARAMS +SetInfoFAOptions[] = { + + { 1, "Functional Address", "FunctionalAddress", "FA", + FALSE, Address4, 0, &DEFAULT_FUNCTIONAL[2], NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.FunctionalAddress } +}; + + +DWORD +Num_SetInfoFA_Params = sizeoftable( SetInfoFAOptions ); + + +TESTPARAMS +SetInfoGAOptions[] = { + + { 1, "Group Address", "GroupAddress", "GA", FALSE, + Address4, 0, &DEFAULT_FUNCTIONAL[2], NULL, 0, + GlobalCmdArgs.ARGS.TPSET.U.FunctionalAddress } +}; + + +DWORD +Num_SetInfoGA_Params = sizeoftable( SetInfoGAOptions ); + + +TESTPARAMS +SendOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Destination Address", "DestinationAddress", "DA", FALSE, Address6, + 0, NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.TPSEND.DestAddress }, + + { 3, "Packet Size", "PacketSize", "PS", FALSE, Integer, PACKET_SIZE, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.TPSEND.PacketSize }, + + { 4, "Number to Send", "Number", "N", FALSE, Integer, 1, NULL, NULL, + 0, &GlobalCmdArgs.ARGS.TPSEND.NumberOfPackets }, + + { 5, "Resend Address", "ResendAddress", "RA", FALSE, Address6, 0, + NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.TPSEND.ResendAddress } + + // + // Both Resend and Dest address will default to the local address + // which must be queried and then stored in the application somewhere? + // +}; + + +DWORD +Num_Send_Params = sizeoftable( SendOptions ); + + +TESTPARAMS +PerfClntOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Server Address", "ServerAddress", "SVA", FALSE, Address6, + 0, NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.TPPERF.PerfServerAddr }, + + { 3, "Send Address", "SendAddress", "SA", FALSE, Address6, + 0, NULL_ADDRESS, NULL, 0, GlobalCmdArgs.ARGS.TPPERF.PerfSendAddr }, + + { 4, "Packet Size", "PacketSize", "PS", FALSE, Integer, PACKET_SIZE, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.TPPERF.PerfPacketSize }, + + { 5, "Number to Send", "Number", "N", FALSE, Integer, 100000, NULL, NULL, + 0, &GlobalCmdArgs.ARGS.TPPERF.PerfNumPackets }, + + { 6, "Delay", "Delay", "D", FALSE, Integer, 0, NULL, NULL, + 0, &GlobalCmdArgs.ARGS.TPPERF.PerfDelay }, + + { 7, "Mode", "Mode", "M", FALSE, Integer, 0, NULL, NULL, + 0, &GlobalCmdArgs.ARGS.TPPERF.PerfMode } +}; + + +DWORD +Num_PerfClnt_Params = sizeoftable( PerfClntOptions ); + + +TESTPARAMS +StressOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance }, + + { 2, "Stress Member Type", "MemberType", "MT", FALSE, ParsedInteger, + 0, "TP_CLIENT", MemberTypeTable, sizeoftable( MemberTypeTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.MemberType }, + + { 3, "Total Number of Packets", "Packets", "P", FALSE, Integer, + (DWORD)STRESS_PACKETS, NULL, NULL, 0, &GlobalCmdArgs.ARGS.TPSTRESS.TotalPackets }, + + { 4, "Total Number of Iterations", "Iterations", "I", FALSE, Integer, + (DWORD)STRESS_ITERATIONS, NULL, NULL, 0, &GlobalCmdArgs.ARGS.TPSTRESS.TotalIterations }, + + { 5, "Packet Type", "PacketType", "PT", FALSE, ParsedInteger, 0, + "FIXEDSIZE", PacketTypeTable, sizeoftable( PacketTypeTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.PacketType }, + + { 6, "Packet Size", "PacketSize", "PS", FALSE, Integer, PACKET_SIZE, + NULL, NULL, 0, &GlobalCmdArgs.ARGS.TPSTRESS.PacketSize }, + + { 7, "Packet MakeUp", "PacketMakeUp", "PM", FALSE, ParsedInteger, + 0, "RAND", PacketMakeUpTable, sizeoftable( PacketMakeUpTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.PacketMakeUp }, + + { 8, "Response Type", "ResponseType", "RT", FALSE, ParsedInteger, 0, + "FULL_RESPONSE", ResponseTypeTable, sizeoftable( ResponseTypeTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.ResponseType }, + + { 9, "Interpacket Delay Type", "DelayType", "DT", FALSE, + ParsedInteger, 0, "FIXEDDELAY", DelayTable, sizeoftable( DelayTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.DelayType }, + + { 10, "Interpacket Delay Length", "DelayLength", "DL", FALSE, Integer, + 0, NULL, NULL, DELAY_LENGTH, &GlobalCmdArgs.ARGS.TPSTRESS.DelayLength }, + + { 11, "Windowing Enabled","WindowEnabled","WE", FALSE, ParsedInteger, 0, + WINDOWING_ENABLED, BooleanTable, sizeoftable( BooleanTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.WindowEnabled }, + + { 12, "Data Checking Enabled", "DataChecking", "DC", FALSE, ParsedInteger, + 0, DATA_CHECKING, BooleanTable, sizeoftable( BooleanTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.DataChecking }, + + { 13, "Packets from Pool", "PacketPool", "PP", FALSE, ParsedInteger, + 0, PACKETS_FROM_POOL, BooleanTable, sizeoftable( BooleanTable ), + &GlobalCmdArgs.ARGS.TPSTRESS.PacketsFromPool } +}; + + +DWORD +Num_Stress_Params = sizeoftable( StressOptions ); + + +TESTPARAMS +OpenInstanceOptions[] = { + + { 1, "Open Instance", "OpenInstance", "OI", FALSE, Integer, + OPEN_INSTANCE, NULL, NULL, 0, &GlobalCmdArgs.OpenInstance } +}; + + +DWORD +Num_OpenInstance_Params = sizeoftable( OpenInstanceOptions ); + + +TESTPARAMS +HelpOptions[] = { + + { 1, "Command Name", "CommandName", "CN", FALSE, String, 0, + NULL, NULL, 0, GlobalCmdArgs.ARGS.CmdName } +}; + + +DWORD +Num_Help_Params = sizeoftable( HelpOptions ); + + +TESTPARAMS +RegistryOptions[] = { + + { 1, "Operation Type", "Operation", "OP", FALSE, ParsedInteger, 0, + "QUERY_KEY", OperationTypeTable, sizeoftable( OperationTypeTable ), + &GlobalCmdArgs.ARGS.REGISTRY_ENTRY.OperationType }, + + { 2, "Key Database", "KeyDatabase", "KD", FALSE, ParsedInteger, 0, + "LOCAL_MACHINE", KeyDbaseTable, sizeoftable( KeyDbaseTable ), + &GlobalCmdArgs.ARGS.REGISTRY_ENTRY.KeyDatabase }, + + { 3, "Sub Key Name", "SubKey", "SK", FALSE, String, 0, + "\"System\\CurrentControlSet\\Services\\Sonic01\\Parameters\"", NULL, 0, + GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKey }, + + {4, "Sub Key Class", "SubKeyClass", "SC", FALSE, String, 0, + "\"Network Drivers\"", NULL, 0, + GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyClass }, + + {5, "Sub Key Value Name", "SubKeyValueName", "SN", FALSE, String, 0, + "\"NetworkAddress\"", NULL, 0, + GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyValueName }, + + {6, "Sub Key Value Type", "SubKeyValueType", "ST", FALSE, ParsedInteger, 0, + "DWORD_REGULAR", ValueTypeTable, sizeoftable( ValueTypeTable ), + &GlobalCmdArgs.ARGS.REGISTRY_ENTRY.ValueType }, + + {7, "Sub Key Value", "SubKeyValue", "SV", FALSE, String, 0, + "\0", NULL, 0, + GlobalCmdArgs.ARGS.REGISTRY_ENTRY.SubKeyValue } + +}; + + +DWORD +Num_Registry_Params = sizeoftable( RegistryOptions ); + + + + + +DWORD +TpctlParseArguments ( + IN TESTPARAMS Options[], + IN DWORD TestSize, + IN DWORD ArgC, + IN LPSTR ArgV[] + ) + +// --------------------- +// +// Routine Description: +// +// This routine parses a table +// +// Arguments: +// +// IN PARSE_PARAMS Option, - [Supplies | Returns] description-of-argument +// IN DWORD ArgC, - [Supplies | Returns] description-of-argument +// IN LPSTR ArgV[] - [Supplies | Returns] description-of-argument +// +// Return Value: +// +// DWORD = -1 if there was a parse error. +// = The number of parameters "eaten" otherwise. +// +// -------------------- + +{ + DWORD i, j; + BYTE Buffer[TPCTL_CMDLINE_SIZE]; + LPSTR ArgName, ArgValue; + BYTE ArgPrompt[TPCTL_CMDLINE_SIZE]; + LPBYTE NextToken; + DWORD RetVal; + BOOL Reparse; + BOOL Error; + BOOL ParsedArgumentsYet; + BOOL ArgNameValuePair; + DWORD OptionNumber; + DWORD OpenInstance; + LPBYTE p, q; + + // + // First determine the Open Instance, we may need it later. + // + + OpenInstance = TpctlGetOpenInstance( ArgC,ArgV ); + + // + // Lower the argument count thus ignoring the command itself, + // we don't care about that here. + // + + if ( ArgC ) + { + ArgC -= 1; // Don't count command in args. + } + + RetVal = min( ArgC, TestSize ); + + if ( ArgC > TestSize ) + { + ArgC = TestSize; + } + + // + // Load the defaults for each of the arguments into the Destination + // field. + // + + for ( i=0;i<TestSize;i++ ) + { + Options[i].ArgValueSet = FALSE; + + switch ( Options[i].TestType ) + { + case Integer: + *(PDWORD)Options[i].Destination = Options[i].IntegerDefault; + break; + + case String: + if ( Options[i].StringDefault != NULL ) + { + strcpy( (LPSTR)Options[i].Destination, Options[i].StringDefault ); + } + else + { + ((LPSTR)Options[i].Destination)[0] = '\0'; + } + break; + + case Address4: + p = Options[i].Destination; + q = Options[i].StringDefault; + + for ( j=0;j<FUNCTIONAL_ADDRESS_LENGTH;j++ ) + { + *p++ = *q++; + } + break; + + case Address6: + p = Options[i].Destination; + q = Options[i].StringDefault; + + for ( j=0;j<ADDRESS_LENGTH;j++ ) + { + *p++ = *q++; + } + break; + + + case ParsedInteger: + TpctlParseInteger( Options[i].StringDefault, + Options[i].ParsedIntTable, + Options[i].ParsedIntTableSize, + Options[i].Destination); + + break; + + default: + TpctlErrorLog("\nTpctl: ParseArguments: Invalid TestType\n",NULL); + return (DWORD)-1; + } + } + + // + // Now parse the input command line, and determine if any arguments + // exist on the command line. The command line may be made up in one + // of the following ways: + // + // 1) nothing, prompt the user for all of the arguments to the given + // command. + // + // 2) argument name=value pairs, parse each pair and set up the options + // structure. if the line ends with a semicolon ';' then return the + // options structure to the caller, otherwise prompt the user for the + // remainder of the commands for the given command then return. + // + // 3) arguments values only, parse each value and place in the options + // structure. if the line ends with a semicolon ';' then return the + // options structure to the caller, otherwise prompt the user for the + // remainder of the commands for the given command then return. + // + // NOTE: a command line may not contain name=value pairs, and values, it + // may only contain one type or the other. + // + + ArgNameValuePair = FALSE; + ParsedArgumentsYet = FALSE; + + for( i=1;i<=ArgC;i++ ) + { + if ( ArgV[i][0] == ';' ) + { + return RetVal; + } + + if ( TpctlParseArgumentPairs( ArgV[i],&ArgName,&ArgValue )) + { + if ( ParsedArgumentsYet == FALSE ) + { + // + // We have an argument name/value pair, and this is the + // first argument in the command line, all the rest of the + // arguments MUST have an arguments name-value pairing, set + // the flags appropriately, and continue. + // + + ArgNameValuePair = TRUE; + ParsedArgumentsYet = TRUE; + + } + else if ( ArgNameValuePair == FALSE ) + { + + // + // The first argument was an argument value only, and now + // we have an argument name=value pair. This is an illegal + // entry on the command line, report the error, and return. + // if we are running a script file end it now reporting an + // error. + // + + TpctlErrorLog("\n\tTpctl: ERROR - \"%s",ArgName); + TpctlErrorLog("=%s\"\n",ArgValue); + TpctlErrorLog("\n\tArgument values and argument name-value pairs\n",NULL); + TpctlErrorLog("\tmay not be combined in the same command.\n",NULL); + return (DWORD)-1;; + } + + } + else // We have only a Argument Value. + { + if ( ParsedArgumentsYet == FALSE ) + { + + // + // This is the first arugment, set the flags appropriately, + // and continue. + // + + ParsedArgumentsYet = TRUE; + + } + else if ( ArgNameValuePair == TRUE ) + { + + // + // The first argument was an argument name=value pair, and + // now we have an argument value only. This is an illegal + // entry on the command line, report the error, and return. + // if we are running a script file end it now reporting an + // error. + // + + TpctlErrorLog("\n\tTpctl: ERROR - \"%s\"\n",ArgValue); + TpctlErrorLog("\n\tArgument name-value pairs and argument values\n",NULL); + TpctlErrorLog("\tmay not be combined in the same command.\n",NULL); + return (DWORD)-1;; + } + } + + if ( ArgNameValuePair == TRUE ) + { + + OptionNumber = TpctlGetOptionNumber( Options,TestSize,ArgName ); + + if ( OptionNumber == -1 ) + { + + // + // This is an invalid option number report the error, and return. + // if we are running a script file end it now reporting an error. + // + + TpctlErrorLog("\n\tTpctl: Invalid Argument Name: \"%s\"",ArgName); + TpctlErrorLog("\n\tThis argument does not exist for this command\n",NULL); + return (DWORD)-1;; + } + } + else + { + OptionNumber = i; + } + + { // ParsePtr scope. + + PTESTPARAMS ParsePtr = &Options[OptionNumber-1]; + + Error = FALSE; + + // + // If the argument passed in from the command line is the + // '*' symbol, the user wants to use the default argument for + // this variable, set the argument value and set flag to TRUE + // indicating that we do not need to prompt for it further, and + // continue with the next argument. + // + + if ( ArgValue[0] == '*' ) + { + ParsePtr->ArgValueSet = TRUE; + continue; + } + +// globvars access + + if ( ArgValue[0] == '$') + { + PVOID valptr = TpctlParseGlobalVariable(ArgValue, ParsePtr->TestType); + LPBYTE s,d; + ULONG i; + + if (valptr != NULL) + { + switch ( ParsePtr->TestType) + { + case Integer: + *(PDWORD)ParsePtr->Destination = *(PDWORD)valptr; + break; + + case String: + strcpy( (LPSTR)ParsePtr->Destination, (LPSTR)valptr); + break; + + case Address4: + s = (LPBYTE)valptr; + d = (LPBYTE)ParsePtr->Destination; + for (i=0; i < FUNCTIONAL_ADDRESS_LENGTH; i++) + { + *d++ = *s++; + } + break; + + case Address6: + s = (LPBYTE)valptr; + d = (LPBYTE)ParsePtr->Destination; + for (i=0; i < ADDRESS_LENGTH; i++) + { + *d++ = *s++; + } + break; + } + } + continue; + } + +// end of globvars access + + switch( ParsePtr->TestType ) + { + + case Integer: + *(PDWORD)ParsePtr->Destination = strtoul( ArgValue,&NextToken,0 ); + break; + + case String: + strcpy( (LPSTR)ParsePtr->Destination,ArgValue ); + break; + + case Address4: + if ( TpctlParseAddress( ArgValue, + ParsePtr->Destination, + OpenInstance - 1, + FUNCTIONAL_ADDRESS_LENGTH ) != 0 ) + { + Error = TRUE; + } + + break; + + case Address6: + if ( TpctlParseAddress( ArgValue, + ParsePtr->Destination, + OpenInstance - 1, + ADDRESS_LENGTH ) != 0 ) + { + Error = TRUE; + } + break; + + case ParsedInteger: + if ( TpctlParseInteger( ArgValue, + ParsePtr->ParsedIntTable, + ParsePtr->ParsedIntTableSize, + ParsePtr->Destination ) != 0 ) + { + Error = TRUE; + } + + break; + + default: + TpctlErrorLog("ParseArguments: Invalid TestType\n",NULL); + Error = TRUE; + } + + if ( Error == TRUE ) + { + TpctlErrorLog("\n\tTpctl: Invalid Argument Value\n",NULL); + return (DWORD)-1;; + } + + // + // We have set this options new value from the command line, so + // set the flag stating not to prompt the user again if necessary. + // + + ParsePtr->ArgValueSet = TRUE; + + } // end of ParsePtr for now. + } + + // + // Set Up the "ArgPrompt" to request the new value for the argument. + // + + for ( i=1;i<=TestSize;i++ ) + { + + PTESTPARAMS ParsePtr = &Options[i-1]; + PTESTPARAMS OIParsePtr = &Options[0]; + + if (ScriptIndex != -1) + { + + // + // We are reading from a script file, so there is no prompting + // required. + + break; + } + + if ( ParsePtr->ArgValueSet != TRUE ) + { + + // + // If there was a command line argument, use it for the + // argument, otherwise prompt for the argument. + // + + Reparse = TRUE; + + strcpy( ArgPrompt, "\t" ); + strcat( ArgPrompt, ParsePtr->TestPrompt ); + strcat( ArgPrompt, " [" ); + + switch ( ParsePtr->TestType ) + { + case Integer: + { + BYTE Int[20]; + _ltoa( ParsePtr->IntegerDefault, Int , 10 ); + strcat( ArgPrompt, Int ); + } + break; + + case ParsedInteger: + case String: + if ( ParsePtr->StringDefault!=NULL ) + { + strcat( ArgPrompt,ParsePtr->StringDefault ); + } + break; + + case Address4: + if ( ParsePtr->StringDefault != NULL ) + { + p = ArgPrompt + strlen( ArgPrompt ); + q = ParsePtr->StringDefault; + + for( j=0;j<FUNCTIONAL_ADDRESS_LENGTH;j++ ) + { + p += (BYTE)sprintf(p,"%02X",*q++); + + if ( j < ( FUNCTIONAL_ADDRESS_LENGTH - 1 )) + { + *p++ = '-'; + } + } + *p = '\0'; + } + break; + + case Address6: + if ( ParsePtr->StringDefault!=NULL ) + { + p = ArgPrompt + strlen( ArgPrompt ); + q = ParsePtr->StringDefault; + + for( j=0;j<ADDRESS_LENGTH;j++ ) + { + p += (BYTE)sprintf(p,"%02X",*q++); + + if ( j < ( ADDRESS_LENGTH - 1 )) + { + *p++ = '-'; + } + } + *p = '\0'; + } + break; + + } // switch + + // + // Now prompt the user for the new value. + // + + strcat( ArgPrompt,"] >" ); + + TpctlPrompt( ArgPrompt,Buffer,TPCTL_CMDLINE_SIZE ); + + // + // and print the response to the log file if requested. + // + + TpctlCmdLneLog( Buffer, NULL ); + TpctlCmdLneLog( "\n", NULL ); + + + while ( Reparse ) + { + + // + // Clean up the buffer, removing any unnecessary spaces. + // + + TpctlFixBuffer( Buffer ); + + // + // If the user entered a ';' meaning all desired values + // have been entered, use the defaults for the rest. + // + + if ( TpctlFirstChar( Buffer,';' )) + { + i = TestSize; + break; + } + + // + // If the user simply hit enter meaning that we should + // use the default value for this argument, then do so. + // + + if ( TpctlFirstChar( Buffer,'\0' )) + { + break; + } + + // + // If the argument starts with '%' then it is an Environment + // variable, and we need to find out its actual value and + // replace it. + // + + if ( Buffer[0] == '%' ) + { + if ( !TpctlParseEnvironmentVariable( Buffer )) + { + return (DWORD)-1;; + } + } + + // + // Now put the newly entered value in its destination. + // + + + Error = FALSE; + + switch ( ParsePtr->TestType ) + { + case Integer: + *(PDWORD)ParsePtr->Destination = + strtol( Buffer,&NextToken,0 ); + Reparse = FALSE; + break; + + case String: + strcpy( (LPSTR)ParsePtr->Destination,Buffer ); + Reparse = FALSE; + break; + + case Address4: + if ( OpenInstance == -1 ) + { + OpenInstance = *(PDWORD)OIParsePtr->Destination; + } + + if ( TpctlParseAddress( Buffer, + ParsePtr->Destination, + OpenInstance - 1, + FUNCTIONAL_ADDRESS_LENGTH) != 0) + { + Error = TRUE; + } + Reparse = FALSE; + break; + + case Address6: + if ( OpenInstance == -1 ) + { + OpenInstance = *(PDWORD)OIParsePtr->Destination; + } + + if ( TpctlParseAddress( Buffer, + ParsePtr->Destination, + OpenInstance - 1, + ADDRESS_LENGTH ) != 0 ) + { + Error = TRUE; + } + Reparse = FALSE; + break; + + case ParsedInteger: + if ( TpctlParseInteger( Buffer, + ParsePtr->ParsedIntTable, + ParsePtr->ParsedIntTableSize, + ParsePtr->Destination ) != 0 ) + { + Error = TRUE; + } + Reparse = FALSE; + break; + } + + if ( Error ) + { + + // + // A bad value was entered for the last variable, see if + // the user would like to enter a new value. + // + + TpctlPrompt("\tTpctl: Argument Error, Re-enter? [Y]", + Buffer, TPCTL_CMDLINE_SIZE); + + // + // and print the response to the log file if requested. + // + + TpctlCmdLneLog( Buffer, NULL); + TpctlCmdLneLog( "\n", NULL); + + if ((( Buffer[0] == '\0' ) || + ( Buffer[0] == 'Y' )) || + ( Buffer[0] == 'y' )) + { + + // + // if so, reprompt the user for a new value. + // + + TpctlPrompt( ArgPrompt,Buffer,TPCTL_CMDLINE_SIZE ); + + // + // and print the response to the log file if requested. + // + + TpctlCmdLneLog( Buffer, NULL); + TpctlCmdLneLog( "\n", NULL); + Reparse = TRUE; + + } + else + { + + // + // Otherwise return an error. + // + + return (DWORD)-1;; + } + } + } + } + } + + return RetVal; +} + + +VOID +TpctlFixBuffer( + IN BYTE Buffer[] + ) + +// --------------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------------------- + +{ + LPSTR Token = Buffer; + LPSTR NextToken = Buffer; // Anything that isn't NULL. + + if ( Buffer == NULL ) + { + return; + } + + while (( *Token != '\0' ) && ( *Token <= ' ' )) + { + Token++; // ignore leading blanks + } + + NextToken = strchr( Token,' ' ); // now see if there are any spaces. + + if ( NextToken != NULL ) // and if so, null them out. + { + *NextToken++ = '\0'; + } +} + + +DWORD +TpctlParseInteger ( + IN BYTE Buffer[], + IN PPARSETABLE ParseTable, + IN DWORD ParseTableSize, + OUT PDWORD Ret + ) + +// --------------------- +// +// Routine Description: +// +// This routine parses a "parsed integer" and returns it to the caller. +// +// Arguments: +// +// IN BYTE Buffer[], - [Supplies | Returns] description-of-argument +// IN PPARSETABLE ParseTable, - [Supplies | Returns] description-of-argument +// IN DWORD ParseTableSize - [Supplies | Returns] description-of-argument +// OUT PDWORD Ret +// +// Return Value: +// +// DWORD +// +// -------------------- + +{ + LPSTR Token = Buffer; + LPSTR NextToken = Buffer; // Anything that isn't NULL. + LPBYTE savePointer = NULL; + BYTE saveToken; + DWORD i; + + if ( Buffer == NULL ) + { + *Ret = 0; + return 0; + } + + // + // If the user specified an absolute number, return that. + // + + if ( isdigit( *Token )) + { + *Ret = strtoul( Token,&NextToken,0 ); + return 0; + } + + // + // Nope, the user passed in a string, parse that. + // + + // + // Initialize the initial value of the returned value to NULL. + // + + *Ret = 0; + + while ( NextToken != NULL ) + { + NextToken = strchr( Token,'|' ); + + if ( NextToken != NULL ) + { + saveToken = *NextToken; + savePointer = NextToken; + *NextToken++ = '\0'; + } + + for ( i=0;i<ParseTableSize;i++ ) + { + if ( _stricmp( Token,ParseTable[i].FieldName ) == 0 ) + { + *Ret |= ParseTable[i].FieldValue; + break; + } + } + + if ( i == ParseTableSize ) + { + TpctlErrorLog("\n\tTpctl: Unknown option \"%s\" entered.\n", + (PVOID)Token); + TpctlErrorLog("\n\t\tValid options are:\n\n",NULL); + + for ( i=0;i<ParseTableSize;i++ ) + { + TpctlErrorLog("\t\t\t%s\n", (PVOID)ParseTable[i].FieldName); + } + + TpctlErrorLog("\n",NULL); + return (DWORD)-1;; + } + + if ( savePointer != NULL ) + { + *savePointer = saveToken; // Restore byte trompled on. + } + + Token = NextToken; + } + + return 0; +} + + + +DWORD +TpctlParseAddress( + IN BYTE Buffer[], + OUT PDWORD RetAddr, + IN DWORD OpenInstance, + IN DWORD AddressLength + ) + +// ----------------- +// +// Routine Description: +// +// This routine parses a network address and returns it to the caller. +// +// Arguments: +// +// IN BYTE Buffer[], - [Supplies | Returns] description-of-argument +// OUT PDWORD RetAddr +// +// Return Value: +// +// DWORD +// +// ---------------- + +{ + BYTE TmpBuf[100]; + PBYTE TmpAddr; + BYTE digit; + DWORD i, j; + BYTE n[2]; + LPBYTE p; + + + if ( Buffer == NULL ) + { + *RetAddr = 0; + return 0; + } + + TmpAddr = (PBYTE)RetAddr; + + // + // See if the user entered one of the text string addresses at the + // command line. + // + + if ( _stricmp( Buffer,RESEND_ADDRESS ) == 0 ) + { + + // + // If the user has entered "resendaddress" at the command line, + // then we will use the resend address stored in the ResendAddress + // environment variable. + // + + p = (LPBYTE)Open[OpenInstance].EnvVars->ResendAddress; + + for ( i=0 ; i < AddressLength ; i++ ) + { + *TmpAddr++ = *p++; + } + return 0; + + } + else if ( _stricmp( Buffer,LOCAL_ADDRESS ) == 0 ) + { + + // + // If the user has entered "localaddress" at the command line + // then we will use the local address stored in the Open Block. + // + + p = (LPBYTE)Open[OpenInstance].AdapterAddress; + + for ( i=0 ; i < AddressLength ; i++ ) + { + *TmpAddr++ = *p++; + } + return 0; + } + + i = j = 0; + + // + // Remove any spaces or hyphens from the address. + // + + while ( i < ( AddressLength * 2 )) + { + if (( Buffer[j] != ' ' ) && ( Buffer[j] != '-' )) + { + TmpBuf[i++] = Buffer[j]; + } + + // + // If we run of the end of the buffer return with an error. + // + + if ( ++j==100 ) + { + return (DWORD)-1;; + } + } + + // + // Now parse the "packed" address and turn the characters into numbers. + // + + for( i=0 ; i < AddressLength ; i++ ) + { + digit = '\0'; + + for( j=0;j<2;j++ ) + { + if (( TmpBuf[i*2+j] >= '0' ) && ( TmpBuf[i*2+j] <= '9' )) + { + n[0] = TmpBuf[i*2+j]; + n[1] = '\0'; + digit += (BYTE)(atoi( n )); + + } + else if (( TmpBuf[i*2+j] >= 'a' ) && ( TmpBuf[i*2+j] <= 'f' )) + { + digit += (BYTE)(( TmpBuf[i*2+j] - 'a' ) + 10 ); + } + else if (( TmpBuf[i*2+j] >= 'A' ) && ( TmpBuf[i*2+j] <= 'F' )) + { + digit += (BYTE)(( TmpBuf[i*2+j] - 'A' ) + 10 ); + } + else + { + + // + // We have an invalid Address; return error. + // + + return (DWORD)-1;; + } + + // + // Raise the high half by 0xf. + // + + if ( j==0 ) + { + digit *= 16; + } + } + + *TmpAddr++ = (BYTE)digit; + } + + return 0; +} + + + +BOOL +TpctlParseArgumentPairs( + IN LPSTR Argument, + OUT LPSTR *ArgName, + OUT LPSTR *ArgValue + ) + +// --------------------- +// +// Routine Description: +// +// This routine parses an argument string to determine if it contains +// an argument name/value pair, or just an argument value. +// +// Arguments: +// +// Argument - The argument string. +// +// ArgName - The name of the argument if there is one. +// +// ArgValue - The argument value. +// +// Return Value: +// +// BOOL - TRUE if there is a name/value pair, FALSE otherwise. +// +// ------------------- + +{ + LPSTR temp; + BOOL EqualsSign; + + temp = Argument; + EqualsSign = FALSE; + + if ( strchr(Argument,'=') != NULL ) + { + EqualsSign = TRUE ; + } + + // + // If there is an equals sign, then we have an argument name/value + // pair. Get each, and put them in their respective return strings. + // + + if (EqualsSign) + { + *ArgName = Argument; + temp = Argument; + + // + // Search for the end of the argument name, and null terminate it. + // + + while ((*temp != '=') && (*temp != ' ')) + { + temp++; + } + + *temp++ = '\0'; + + // + // Then search for the beginning of the argument value, and return + // it in ArgValue. + // + + while ((*temp == '=') || (*temp == ' ')) + { + temp++; + } + + *ArgValue = temp; + + } + else + { + + // + // There is only an argument value so null out the ArgName, and + // return the value in ArgValue. + // + + ArgName = '\0'; + *ArgValue = Argument; + } + + return EqualsSign; +} + + + +BOOL +TpctlParseSetInfoArguments( + IN OUT DWORD *ArgC, + IN OUT LPSTR ArgV[], + IN OUT DWORD *tmpArgC, + IN OUT LPSTR tmpArgV[] + ) + +// -------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// BOOL - +// +// ------------- + +{ + DWORD i; + + *tmpArgC = 1; + tmpArgV[0] = '\0'; + + // + // See if the arguments are name-value pairs, or just the + // argument values, if there is an equal sign in the first + // argument then they are name-value paired arguments. + // + + if ( strchr(ArgV[1],'=') != NULL ) + { + // + // We have name value pairs + // + + for (i=1;i<*ArgC;i++) + { + + // + // So search the ArgV for the correct argument name, and + // if it is found have tmpArgV refernce it. + // + + if (( _strnicmp(ArgV[i],"PacketFilter",12) == 0 ) || + ( _strnicmp(ArgV[i],"StationAddress",14) == 0 ) || + ( _strnicmp(ArgV[i],"FunctionalAddress",17) == 0 ) || + ( _strnicmp(ArgV[i],"GroupAddress",17) == 0 ) || + ( _strnicmp(ArgV[i],"Lookahead",9) == 0 ) || + ( _strnicmp(ArgV[i],"PF",2) == 0 ) || + ( _strnicmp(ArgV[i],"SA",2) == 0 ) || + ( _strnicmp(ArgV[i],"FA",2) == 0 ) || + ( _strnicmp(ArgV[i],"GA",2) == 0 ) || + ( _strnicmp(ArgV[i],"LA",2) == 0 )) + { + + // + // We have found what we are looking for. Set the tmpArgC, + // and set tmpArgV[i] to point to it. + // + + ++*tmpArgC; + tmpArgV[1] = ArgV[i]; + + // + // then make sure that it is at the end of the ArgV. + // This is required by ParseArguments to successfully + // handle parsing the OpenInstance and InfoClass + // arguments first. + // + + if ( i != *ArgC - 1 ) + { + ArgV[i] = ArgV[*ArgC-1]; + //ArgV[*ArgC-1] = //tmpArgV[1]; + } + + ArgV[*ArgC-1] = NULL; + --*ArgC; + + return TRUE; + } + } + + } + else + { + + // + // If there are no name-value pairings for the arguments, then + // we know the commands must be in the correct order, and the + // Class Specific Info argument MUST be last or 4th in ArgV. + // + + if ( *ArgC >= 4 ) + { + + // + // We have found the argument, have tmpArgV reference it and + // return. + // + + *tmpArgC = 2; + tmpArgV[1] = ArgV[3]; + + --*ArgC; + ArgV[3] = NULL; + + return TRUE; + + } + } + + // + // Otherwise there are not enough arguments on the command + // line to include the Class Specific Info, or it simply does + // not exist on the command line, if it is needed, ti will + // have to be prompted for later. + // + + return FALSE; +} + + +BOOL +TpctlParseEnvironmentVariable( + IN BYTE Buffer[] + ) + +// ------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------------ + +{ + BYTE TmpBuffer[100]; + LPSTR EndOfVar = Buffer; // Anything that isn't NULL. + LPSTR Variable; + + // + // If the environment variable passed in is null, return false now. + // + + if ( Buffer == NULL ) + { + TpctlErrorLog("\n\tTpctl: Invalid Environment Variable Format \"%%\".\n",NULL); + return FALSE; + } + + // + // Otherwise copy the variable into a temp buffer. + // + + strcpy( TmpBuffer,&Buffer[1] ); + + // + // Now null out the '%' symbol if it exists to allow the querying + // of the environment variable. + // + + EndOfVar = strchr( TmpBuffer,'%' ); + + if ( EndOfVar == NULL ) + { + TpctlErrorLog("\n\tTpctl: Invalid Environment Variable Format \"%%%s\".\n",TmpBuffer); + return FALSE; + } + else + { + *EndOfVar = '\0'; + } + + // + // and then query the environment variable. + // + + Variable = getenv( _strupr( TmpBuffer )); + + if ( Variable == NULL ) + { + TpctlErrorLog("\n\tTpctl: Undefined Environment Variable \"%%%s%%\".\n",TmpBuffer); + return FALSE; + } + + strcpy( Buffer,Variable); + + return TRUE; +} + + + +BOOL +TpctlFirstChar( + IN BYTE Buffer[], + IN BYTE Char + ) +{ + LPSTR Token = Buffer; + + if ( Buffer == NULL ) + { + return FALSE; + } + + while (( *Token != '\0' ) && ( *Token == ' ' )) + { + Token++; // ignore leading blanks + } + + if ( *Token == (CHAR)Char ) + { + return TRUE; + } + + return FALSE; +} + + +DWORD +TpctlGetOptionNumber( + IN PTESTPARAMS Options, + IN DWORD TestSize, + IN LPSTR ArgName + ) + +// ------------ +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----------- + +{ + DWORD i; + + for(i=0; i<TestSize; i++) + { + if (_stricmp(ArgName,Options[i].ArgName) == 0 ) + { + return Options[i].OptionNumber; + } + if (_stricmp(ArgName,Options[i].ArgNameAbbr) == 0 ) + { + return Options[i].OptionNumber; + } + } + return (DWORD)-1;; +} + + +DWORD +TpctlGetOpenInstance( + IN DWORD ArgC, + IN LPSTR ArgV[] + ) + +{ + DWORD i; + LPSTR EqualSign; + LPBYTE NextToken; + + // + // If we have no arguments, only the command, then return an error. + // + + if ( ArgC <= 0 ) + { + return (DWORD)-1; + } + + // + // Otherwise walk the argument vector looking for an instance of either + // an OpenInstance = Value or simply return the first argument. + // + + for (i=1; i<ArgC; i++) + { + if (( EqualSign = strchr(ArgV[i],'=')) == NULL ) // no = sign. + { + // + // Since there is no equal sign we know that the Open Instance + // must be the first argument, so simply return it. + // + + return (strtoul(ArgV[i], &NextToken, 0)); + + } + else + { + + // + // we have an argument value pair, check if its the + // Open Instance. + // + + if ((_strnicmp(ArgV[i],"OI",2) == 0 ) || + (_strnicmp(ArgV[i],"OpenInstance",12))) + { + + // + // It is the open instance so return the value. + // + + ++(EqualSign); + return ( strtoul( EqualSign,&NextToken,0 )); + } + } + } + + return (DWORD)-1;; +} diff --git a/private/ntos/ndis/testprot/tpctl/parse.h b/private/ntos/ndis/testprot/tpctl/parse.h new file mode 100644 index 000000000..c3206263a --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/parse.h @@ -0,0 +1,312 @@ +// --------------------------------------------------- +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// parse.h +// +// Abstract: +// +// +// Author: +// +// Tom Adams (tomad) 11-May-1991 +// +// Revision History: +// +// 11-May-1991 tomad +// Created +// +// 4-27-94 timothyw +// added externs for performance test +// 6-8-94 timothyw +// changes for client/server model, perf tests +// +// ------------------------------------------------- + +#define sizeoftable(TableName) (sizeof(TableName) / sizeof(TableName[0])) + +#define NamedField(Flag) {#Flag, Flag} + + +// +// external declarations of the Command Option Argument Parse +// Tables and their sizes. +// + + +extern +PARSETABLE +BooleanTable[]; + +extern +PARSETABLE +PacketFilterTable []; + +extern +PARSETABLE +QueryInfoOidTable []; + +extern +PARSETABLE +SetInfoOidTable []; + +extern +PARSETABLE +MemberTypeTable []; + +extern +PARSETABLE +PacketTypeTable []; + +extern +PARSETABLE +PacketMakeUpTable []; + +extern +PARSETABLE +ResponseTypeTable []; + +extern +PARSETABLE +DelayTable []; + +extern +PARSETABLE +TestDurationTable []; + +extern +PARSETABLE +OperationTypeTable[]; + +extern +PARSETABLE +KeyDbaseTable []; + +extern +PARSETABLE +ValueTypeTable[]; + + +// +// external declarations of the Test Parameter Arrays and their sizes. +// + +extern +TESTPARAMS +CommandLineOptions[]; + +extern +DWORD +Num_CommandLine_Params; + +extern +TESTPARAMS +SetEnvOptions[]; + +extern +DWORD +Num_SetEnv_Params; + +extern +TESTPARAMS +ReadScriptOptions[]; + +extern +DWORD +Num_ReadScript_Params; + +extern +TESTPARAMS +LoggingOptions[]; + +extern +DWORD +Num_Logging_Params; + +extern +TESTPARAMS +RecordingOptions[]; + +extern +DWORD +Num_Recording_Params; + +extern +TESTPARAMS +PauseGoOptions[]; + +extern +DWORD +Num_PauseGo_Params; + +extern +TESTPARAMS +LoadUnloadOptions[]; + +extern +DWORD +Num_LoadUnload_Params; + +extern +TESTPARAMS +OpenOptions[]; + +extern +DWORD +Num_Open_Params; + +extern +TESTPARAMS +SetPacketFilterOptions[]; + +extern +DWORD +Num_SetPacketFilter_Params; + +extern +TESTPARAMS +SetLookaheadOptions[]; + +extern +DWORD +Num_SetLookahead_Params; + +extern +TESTPARAMS +MulticastAddrOptions[]; + +extern +DWORD +Num_MulticastAddr_Params; + +extern +TESTPARAMS +FunctionalAddrOptions[]; + +extern +DWORD +Num_FunctionalAddr_Params; + +extern +TESTPARAMS +GroupAddrOptions[]; + +extern +DWORD +Num_GroupAddr_Params; + +extern +TESTPARAMS +QueryInfoOptions[]; + +extern +DWORD +Num_QueryInfo_Params; + +extern +TESTPARAMS +QueryStatsOptions[]; + +extern +DWORD +Num_QueryStats_Params; + +extern +TESTPARAMS +SetInfoOptions[]; + +extern +DWORD +Num_SetInfo_Params; + +extern +TESTPARAMS +SetInfoPFOptions[]; + +extern +DWORD +Num_SetInfoPF_Params; + +extern +TESTPARAMS +SetInfoLAOptions[]; + +extern +DWORD +Num_SetInfoLA_Params; + +extern +TESTPARAMS +SetInfoMAOptions[]; + +extern +DWORD +Num_SetInfoMA_Params; + +extern +TESTPARAMS +SetInfoFAOptions[]; + +extern +DWORD +Num_SetInfoFA_Params; + +extern +TESTPARAMS +SetInfoGAOptions[]; + +extern +DWORD +Num_SetInfoGA_Params; + +extern +TESTPARAMS +SendOptions[]; + +extern +DWORD +Num_Send_Params; + +extern +TESTPARAMS +PerfClntOptions[]; + +extern +DWORD +Num_PerfClnt_Params; + +extern +TESTPARAMS +StressOptions[]; + +extern +DWORD +Num_Stress_Params; + +extern +TESTPARAMS +OpenInstanceOptions[]; + +extern +DWORD +Num_OpenInstance_Params; + +extern +TESTPARAMS +HelpOptions[]; + +extern +DWORD +Num_Help_Params; + +extern +TESTPARAMS +RegistryOptions[]; + +extern +DWORD +Num_Registry_Params; + + diff --git a/private/ntos/ndis/testprot/tpctl/results.c b/private/ntos/ndis/testprot/tpctl/results.c new file mode 100644 index 000000000..02665bf03 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/results.c @@ -0,0 +1,1312 @@ +// -------------------------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// results.c +// +// Abstract: +// +// This module handles the printing of the results of a given command. +// +// Author: +// +// Tom Adams (tomad) 2-Apr-1991 +// +// Revision History: +// +// 2-Apr-1991 tomad +// +// created +// +// Sanjeev Katariya (sanjeevk) +// 4-12-1993 #5963 Events printed out are not being used/tested for one to one +// correspondence The IndicationStatus. Thereby I am adding a +// MAY_DIFFER flag to the event +// +// Tim Wynsma (timothyw) 4-27-94 +// Added performance testing +// 5-18-94 +// Revised output format for performance tests; cleanup +// 6-08-94 +// Chgd perf output format for client/server model +// +// -------------------------------------------- + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "tpctl.h" +#include "parse.h" + + + +VOID +TpctlPrintResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ) + +// ---------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// --------- + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + BOOL ErrorReturned = FALSE; + + TmpBuf = GlobalBuf; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tCmdCode = %s\n", + TpctlGetCmdCode( CmdCode )); + + if ( CmdCode == SETINFO ) + { + //ASSERT( Results->OID == OID ); + //ASSERT( Results->NdisRequestType == NdisRequestSetInformation ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tOID = %d\n",OID); + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tReturn Status = %s\n", + TpctlGetStatus( Results->RequestStatus )); + + if ( Results->RequestStatus != STATUS_SUCCESS ) + { + ErrorReturned = TRUE; + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRequest Pended = %s", + Results->RequestPended ? "TRUE" : "FALSE"); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + if ( CmdCode == OPEN ) + { + if ( Results->OpenRequestStatus != NDIS_STATUS_SUCCESS ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tWARNING: Secondary Open Request failed.\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRequest OID = 0x%08lX\n",Results->OID); + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRequest Returned Status = %s\n", + TpctlGetStatus( Results->OpenRequestStatus )); + + if ( Results->OpenRequestStatus != STATUS_SUCCESS ) + { + ErrorReturned = TRUE; + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesWritten = %d\n", + Results->BytesReadWritten); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tBytesNeeded = %d\n\n", + Results->BytesNeeded); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tThe open instance exists but some tests may not\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"\twork properly due to this failure.\n"); + } + } + + 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); + } + } +} + + + +VOID +TpctlPrintStressResults( + IN PSTRESS_RESULTS Results, + IN BOOL Ack10 + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// -------- + +{ + PGLOBAL_COUNTERS gc; + PINSTANCE_COUNTERS ic; + DWORD i; + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + + + //ASSERT( Results->Signature == STRESS_RESULTS_SIGNATURE ); + + TmpBuf = GlobalBuf; + TmpBuf += (BYTE)sprintf(TmpBuf,"\nCLIENT STRESS STATISTICS:\n\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"Client Address %02X-%02X-%02X-%02X-%02X-%02X - ", + Results->Address[0],Results->Address[1],Results->Address[2], + Results->Address[3],Results->Address[4],Results->Address[5]); + TmpBuf += (BYTE)sprintf(TmpBuf,"OpenInstance %d",Results->OpenInstance); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER\n" ); + gc = &Results->Global; + + for ( i=0;i<Results->NumServers;i++ ) + { + ic = &Results->Servers[i].Instance; + gc->Sends += ic->Sends; + gc->Receives += ic->Receives; + gc->CorruptRecs = ic->CorruptRecs; + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"Total Packets Sent:\t\t%10lu\n", + gc->Sends); + TmpBuf += (BYTE)sprintf(TmpBuf,"Total Packets Received:\t\t%10lu\n", + gc->Receives); + + if ( Ack10 == TRUE ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"Total Packets Lost:\t\t%10lu\n\n", + (( 10 * gc->Sends ) - gc->Receives )); + } + else + { + TmpBuf += (BYTE)sprintf(TmpBuf,"Total Packets Lost:\t\t%10lu\n\n", + ( gc->Sends - gc->Receives )); + } + + if ( gc->CorruptRecs > 0 ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"Corrupted Packet Receives:\t%10lu\n\n", + gc->CorruptRecs); + } + + if ( gc->InvalidPacketRecs > 0 ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"Invalid Packet Receives:\t%10lu\n\n", + gc->InvalidPacketRecs); + } + + // + // Display the number of packets sent/received per second. + // + + TmpBuf += (BYTE)sprintf(TmpBuf,"Packets Per Second:\t\t%10lu", + Results->PacketsPerSecond ); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER\n" ); + + // + // And then print out the information about each of the Servers + // involved in the test. + // + + TmpBuf += (BYTE)sprintf(TmpBuf,"The Client had %d Server(s) for this test as follows:", + Results->NumServers); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER\n" ); + + for ( i=0;i<Results->NumServers;i++ ) + { + //ASSERT( Results->Servers[i].Signature == STRESS_RESULTS_SIGNATURE ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"Server # %d - ",i+1); + TmpBuf += (BYTE)sprintf(TmpBuf,"Address %02X-%02X-%02X-%02X-%02X-%02X - ", + Results->Servers[i].Address[0],Results->Servers[i].Address[1], + Results->Servers[i].Address[2],Results->Servers[i].Address[3], + Results->Servers[i].Address[4],Results->Servers[i].Address[5]); + + TmpBuf += (BYTE)sprintf(TmpBuf,"OpenInstance %d", + Results->Servers[i].OpenInstance); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + } + + TmpBuf += (BYTE)sprintf(TmpBuf,"\nSERVER STRESS STATISTICS:\n\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"Server Instance Counters collected on the Client:\n\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"Server #"); + + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu",i+1); + } + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER\n" ); + + // Number of packets sent to the server. + + TmpBuf += (BYTE)sprintf(TmpBuf,"S:\t"); + + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.Sends); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets received from the server. + + TmpBuf += (BYTE)sprintf(TmpBuf,"R:\t"); + + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.Receives); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets lost in transit to the server and back. + + TmpBuf += (BYTE)sprintf(TmpBuf,"L:\t"); + + for ( i=0;i<Results->NumServers;i++ ) + { + if ( Ack10 == TRUE ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + (( 10 * Results->Servers[i].Instance.Sends ) - + Results->Servers[i].Instance.Receives )); + } + else + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + ( Results->Servers[i].Instance.Sends - + Results->Servers[i].Instance.Receives )); + } + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packet sends that pended. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SP:\t"); + + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.SendPends); + } + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + // Number of packet sends pending that completed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SC:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.SendComps); + } + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + // Number of packet sends that failed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SF:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.SendFails); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of corrupted packets received. + + TmpBuf += (BYTE)sprintf(TmpBuf,"CR:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].Instance.CorruptRecs); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\nServer Instance Counters collected on the Server:\n\n"); + + // Number of packets received from the server. + + TmpBuf += (BYTE)sprintf(TmpBuf,"R:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.Receives); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets sent to the server. + + TmpBuf += (BYTE)sprintf(TmpBuf,"S:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.Sends); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets lost in transit to the server and back. + + TmpBuf += (BYTE)sprintf(TmpBuf,"L:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + if ( Ack10 == TRUE ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + (( 10 * Results->Servers[i].S_Instance.Receives ) - + Results->Servers[i].S_Instance.Sends )); + } + else + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + ( Results->Servers[i].S_Instance.Receives - + Results->Servers[i].S_Instance.Sends )); + } + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets sends that failed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SF:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.SendFails); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + // Number of packets sends that pended. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SP:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.SendPends); + } + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + // Number of packets sends pending that completed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"SC:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.SendComps); + } + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + // Number of transfer datas on packets. + + TmpBuf += (BYTE)sprintf(TmpBuf,"TD:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.XferData); + } + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + // Number of transfer datas on packets that pended. + + TmpBuf += (BYTE)sprintf(TmpBuf,"TDP:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.XferDataPends); + } + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + // Number of transfer datas on packets that completed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"TDC:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.XferDataComps); + } + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + // Number of transfer datas on packets that failed. + + TmpBuf += (BYTE)sprintf(TmpBuf,"TDF:\t"); + for ( i=0;i<Results->NumServers;i++ ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"%10lu", + Results->Servers[i].S_Instance.XferDataFails); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); + + 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); + } + } + + TpctlZeroStressStatistics( Results ); +} + + + +VOID +TpctlPrintSendResults( + PSEND_RECEIVE_RESULTS Results + ) + +// ---- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----- + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + + + //ASSERT( Results->Signature == SENDREC_RESULTS_SIGNATURE ); + + TmpBuf = GlobalBuf; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPacket Sends = %10lu\n", + Results->Counters.Sends); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Pends = %10lu", + Results->Counters.SendPends); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Send Completes = %10lu", + Results->Counters.SendComps); + + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Send Fails = %10lu\n", + Results->Counters.SendFails); + + 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); + } + } +} + + + +VOID +TpctlPrintReceiveResults( + PSEND_RECEIVE_RESULTS Results + ) + +// ------ +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---- + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + + //ASSERT( Results->Signature == SENDREC_RESULTS_SIGNATURE ); + + TmpBuf = GlobalBuf; + + // Receive statistics + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPacket Receives = %10lu\n", + Results->Counters.Receives); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Receive Completes = %10lu", + Results->Counters.ReceiveComps); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tCorrupt Receives = %10lu\n", + Results->Counters.CorruptRecs); + + + // RESEND initiated statistics + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tRESEND initiated Packet Sends = %10lu\n", + Results->Counters.Sends); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRESEND initiated Packet Send Pends = %10lu", + Results->Counters.SendPends); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRESEND initiated Packet Send Completes = %10lu", + Results->Counters.SendComps); + + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRESEND initiated Packet Send Fails = %10lu\n", + Results->Counters.SendFails); + + // Transfer Data statistics + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPacket Transfer Data = %10lu\n", + Results->Counters.XferData); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Transfer Data Pends = %10lu", + Results->Counters.XferDataPends); + + ADD_DIFF_FLAG( TmpBuf, "MAY_DIFFER" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Transfer Data Completes = %10lu", + Results->Counters.XferDataComps); + + ADD_DIFF_FLAG( TmpBuf, "EQUAL_LAST" ); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Transfer Data Fails = %10lu\n", + Results->Counters.XferDataFails); + + 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); + } + } +} + + +VOID +TpctlPrintPerformResults( + PPERF_RESULTS Results + ) + +// ---- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----- + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + ULONG speed; + double d_speed; + PULONG KernelPercent; + ULONG NumCpus; + + ASSERT( Results->Signature == PERF_RESULTS_SIGNATURE ); + if (!Results->ResultsExist) + { + return; + } + + if (Results->Mode < 4) + { + NumCpus = CpuUsageGetData(&KernelPercent, Results->Milliseconds); + } + else if (Results->Mode < 6) + { + NumCpus = CpuUsageGetData(&KernelPercent, Results->S_Milliseconds); + } + TmpBuf = GlobalBuf; + + switch(Results->Mode) + { + case 0: // client -> address + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 0: Client -> Address\n\n"); + break; + + case 1: // client -> server + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 1: Client -> Server\n\n"); + break; + + case 2: // client -> server, server ACKS + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 2: Client -> Server with ACKS\n\n"); + break; + + case 3: // client -> server, server -> client + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 3: Client <-> Server\n\n"); + break; + + case 4: // server -> client + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 4: Server -> Client\n\n"); + break; + + case 5: // client REQS, server -> client + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\nPerformance Test 5: Server -> Client with REQS\n\n"); + break; + + default: + printf("\n\nUnknown performance Test: %d\n\n", Results->Mode); + return; + + } + if (!NumCpus) + { + TmpBuf += (BYTE)sprintf(TmpBuf, "Cpu usage information not available\n\n"); + } + else if (NumCpus == 1) + { + if (KernelPercent[0] > 1000) + { + KernelPercent[0] = 1000; + } + TmpBuf += (BYTE)sprintf(TmpBuf, "Cpu usage = %d.%d%%\n\n",KernelPercent[0]/10, KernelPercent[0]%10); + } + else + { + ULONG cpucnt; + ULONG *procPercent; + + procPercent = &KernelPercent[1]; + TmpBuf += (BYTE)sprintf(TmpBuf, "Cpu usage per processor: "); + + for(cpucnt=0; cpucnt < NumCpus; cpucnt++) + { + if ( (cpucnt != 0) && ((cpucnt % 4) == 0) ) + { + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + TmpBuf += (BYTE)sprintf(TmpBuf, " "); + } + if (*procPercent > 1000) + { + *procPercent = 1000; + } + TmpBuf += (BYTE)sprintf(TmpBuf, "#%d - %d.%d%% ", + cpucnt, *procPercent/10, *procPercent%10); + } + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + TmpBuf += (BYTE)sprintf(TmpBuf, "Average cpu usage = %d.%d%%\n\n", + KernelPercent[0]/10, KernelPercent[0]%10); + } + + + TmpBuf += (BYTE)sprintf(TmpBuf, "Sending %d packets of %d bytes each\n\n", + Results->PacketCount, Results->PacketSize); + + if (Results->Mode < 4) + { + TmpBuf += (BYTE)sprintf(TmpBuf, "Client transmission statistics\n\n"); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPackets Sent = %10lu\n", Results->Sends); + if (Results->SendFails) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Send Failures = %10lu\n", + Results->SendFails); + } + if (Results -> Restarts) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRestarts Required = %10lu\n", + Results->Restarts); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\tElapsed time = %10lu milliseconds\n", + Results->Milliseconds); + + d_speed = (1.0 * Results->Sends) / Results->Milliseconds; + speed = (ULONG)((1000.0 * d_speed) + 0.5); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tTransmit Rate = %10lu packets per second\n", + speed); + + d_speed *= Results->PacketSize; + speed = (ULONG)(d_speed + 0.5); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t = %10lu Kbytes per second\n\n", + speed); + + if (NumCpus && (Results->Mode < 2)) + { + d_speed *= 100.0; + d_speed /= KernelPercent[0]; + speed = (ULONG)(d_speed + 0.5); + TmpBuf += (BYTE)sprintf(TmpBuf, "\tSend KB/sec/cpu = %8lu.%u\n\n", speed/10, speed%10); + } + + if (Results->Mode > 0) + { + TmpBuf += (BYTE)sprintf(TmpBuf, "Server reception statistics\n\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPackets Received = %10lu\n", + Results->S_Receives); + if (Results->S_Receives != Results->PacketCount) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPackets Lost = %10lu\n", + Results->PacketCount - Results->S_Receives); + } + if (Results->S_SelfReceives) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tOwn Packets Received = %10lu\n", + Results->S_SelfReceives); + } + } + } + + if (Results->Mode > 2) + { + TmpBuf += (BYTE)sprintf(TmpBuf, "\nServer transmission statistics\n\n"); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPackets Sent = %10lu\n", Results->S_Sends); + if (Results->S_SendFails) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPacket Send Failures = %10lu\n", + Results->S_SendFails); + } + if (Results -> S_Restarts) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tRestarts Required = %10lu\n", + Results->S_Restarts); + } + TmpBuf += (BYTE)sprintf(TmpBuf,"\tElapsed time = %10lu milliseconds\n", + Results->S_Milliseconds); + + d_speed = (1.0 * Results->S_Sends) / Results->S_Milliseconds; + speed = (ULONG)((1000.0 * d_speed) + 0.5); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tTransmit Rate = %10lu packets per second\n", + speed); + + d_speed *= Results->PacketSize; + speed = (ULONG)(d_speed + 0.5); + + TmpBuf += (BYTE)sprintf(TmpBuf,"\t = %10lu Kbytes per second\n\n", + speed); + + + TmpBuf += (BYTE)sprintf(TmpBuf, "Client reception statistics\n\n"); + TmpBuf += (BYTE)sprintf(TmpBuf,"\n\tPackets Received = %10lu\n", + Results->Receives); + + if (NumCpus && (Results->Mode == 4)) + { + d_speed *= 100.0; + d_speed /= KernelPercent[0]; + speed = (ULONG)(d_speed + 0.5); + TmpBuf += (BYTE)sprintf(TmpBuf, "\tReceive KB/sec/cpu = %8lu.%u\n\n", speed/10, speed%10); + } + + if (Results->Receives != Results->PacketCount) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tPackets Lost = %10lu", + Results->PacketCount - Results->Receives); + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + } + if (Results->SelfReceives) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tOwn Packets Received = %10lu", + Results->SelfReceives); + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + } + + } + + TmpBuf += (BYTE)sprintf(TmpBuf, "\n\n\n"); + + + 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); + } + + } +} + + + +VOID +TpctlPrintEventResults( + PEVENT_RESULTS Event + ) + +// ---- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// --- + +{ + DWORD Status; + LPSTR TmpBuf; + DWORD BytesWritten; + + + //ASSERT( Event->Signature == EVENT_RESULTS_SIGNATURE ); + + TmpBuf = GlobalBuf; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\tEvent Type = %s", + TpctlGetEventType( Event->TpEventType )); + + // + // SanjeevK : #5963 + // #11324 Enhancement + // + + if ( ( Event->TpEventType == IndicateStatusComplete ) || + ( Event->TpEventType == IndicateStatus ) ) + { + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + } + else + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\n" ); + } + + if ( Event->QueueOverFlowed == TRUE ) + { + TmpBuf += (BYTE)sprintf(TmpBuf,"\tEvent Queue Overflowed."); + // + // SanjeevK : #5963 + // + // Note: This flag was added since all this does is cause an + // this line to be ignored. The event however gets + // reported which is the primary aim of this statement. + // + ADD_SKIP_FLAG( TmpBuf, "SKIP_LINE" ); + } + + 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); + } + } +} + + + +VOID +TpctlZeroStressStatistics( + PSTRESS_RESULTS Results + ) + +// ---- +// +// Routine Description: +// +// This routine zeros out the stress results buffer. +// +// Arguments: +// +// Results - the buffer to zero out the contents of. +// +// Return Value: +// +// None. +// +// ---- + +{ + DWORD i; + + ZeroMemory (Results->Address, ADDRESS_LENGTH); + + Results->OpenInstance = 0xFFFFFFFF; + Results->NumServers = 0; + + Results->Global.Sends = 0; + Results->Global.Receives = 0; + Results->Global.CorruptRecs = 0; + Results->Global.InvalidPacketRecs = 0; + + for ( i=0;i<MAX_SERVERS;i++ ) + { + ZeroMemory (Results->Servers[i].Address, ADDRESS_LENGTH); + + Results->Servers[i].OpenInstance = 0xFFFFFFFF; + Results->Servers[i].StatsRcvd = FALSE; + + Results->Servers[i].Instance.Sends = 0; + Results->Servers[i].Instance.SendPends = 0; + Results->Servers[i].Instance.SendComps = 0; + Results->Servers[i].Instance.SendFails = 0; + Results->Servers[i].Instance.Receives = 0; + Results->Servers[i].Instance.CorruptRecs = 0; + + Results->Servers[i].S_Instance.Sends = 0; + Results->Servers[i].S_Instance.SendPends = 0; + Results->Servers[i].S_Instance.SendComps = 0; + Results->Servers[i].S_Instance.SendFails = 0; + Results->Servers[i].S_Instance.Receives = 0; + Results->Servers[i].S_Instance.CorruptRecs = 0; + + Results->Servers[i].S_Global.Sends = 0; + Results->Servers[i].S_Global.Receives = 0; + Results->Servers[i].S_Global.CorruptRecs = 0; + Results->Servers[i].S_Global.InvalidPacketRecs = 0; + } +} + + + +DWORD +TpctlLog( + LPSTR String, + PVOID Input + ) +{ + DWORD Status; + + // + // If we are in verbose mode, then print the string to the screen. + // + + if ( Verbose ) + { + printf( String,Input ); + + // + // If we are reading commands from a script write the string to + // the script log file. + // + + if ( CommandsFromScript ) + { + Status = TpctlScriptLog( String, Input ); + } + + // + // Otherwise if we are logging commands entered by hand write + // the string to the commandline log file. + // + + else if ( CommandLineLogging ) + { + Status = TpctlCmdLneLog( String,Input ); + } + } + + return NO_ERROR; +} + + + +DWORD +TpctlErrorLog( + LPSTR String, + PVOID Input + ) +{ + DWORD Status; + + // + // First print the error message to the screen. + // + + printf( String,Input ); + + // + // If we are reading commands from a script write the string to + // the script log file. + // + + if ( CommandsFromScript ) + { + Status = TpctlScriptLog( String, Input ); + } + + // + // Otherwise we are logging commands entered by hand write the + // string to the commandline log file. + // + + else if ( CommandLineLogging ) + { + Status = TpctlCmdLneLog( String,Input ); + } + + return NO_ERROR; +} + + + +DWORD +TpctlScriptLog( + LPSTR String, + PVOID Input + ) +{ + DWORD Status; + BYTE Buffer[0x100]; + DWORD BytesWritten; + + // + // If we are reading commands from a script write the string to + // the script's log file. + // + + if ( CommandsFromScript ) + { + // + // set up the buffer that will print it to the logfile, and write + // it out. + // + + sprintf( Buffer,String,Input ); + + if ( !WriteFile(Scripts[ScriptIndex].LogHandle, + Buffer, + strlen( Buffer ), + &BytesWritten, + NULL )) + { + Status = GetLastError(); + printf("\n\tTpctlScriptLog: write to logfile failed, returned 0x%lx\n",Status); + return Status; + } + } + + return NO_ERROR; +} + + + +DWORD +TpctlCmdLneLog( + LPSTR String, + PVOID Input + ) +{ + DWORD Status; + BYTE Buffer[0x100]; + DWORD BytesWritten; + + // + // If we are logging commands entered by hand write the + // string to that log file. We will not do this if we are + // already logging commands to a scriptfile log file.. + // + + if (( CommandLineLogging ) && ( !CommandsFromScript )) + { + // + // Then set up the buffer that will print it to the logfile + // + + sprintf( Buffer,String,Input ); + + // + // and print it. + // + + if ( !WriteFile(CommandLineLogHandle, + Buffer, + strlen( Buffer ), + &BytesWritten, + NULL )) + { + Status = GetLastError(); + printf("\n\tTpctlCmdLneLog: write to command logging file failed, returned 0x%lx\n", + Status); + return Status; + } + } + + return NO_ERROR; +} + + diff --git a/private/ntos/ndis/testprot/tpctl/sources b/private/ntos/ndis/testprot/tpctl/sources new file mode 100644 index 000000000..a1cbfb202 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/sources @@ -0,0 +1,49 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +UMLIBS=obj\*\tpctl.lib ..\tplib\obj\*\tplib.lib \nt\public\sdk\lib\*\setargv.obj +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=testprot +MINORCOMP=tpctl + +TARGETNAME=tpctl +TARGETPATH=obj +TARGETTYPE=PROGRAM + +INCLUDES=..\inc;..\..\..\inc + +SOURCES=init.c \ + cmd.c \ + parse.c \ + results.c \ + globals.c \ + info.c \ + cpuperf.c \ + tpctl.c + +RELATIVE_DEPTH=..\..\.. + +UMTYPE=console +UMLIBS=..\tplib\obj\*\tplib.lib \ + $(BASEDIR)\public\sdk\lib\*\setargv.obj \ + $(BASEDIR)\public\sdk\lib\*\ntdll.lib diff --git a/private/ntos/ndis/testprot/tpctl/tp_ndis.h b/private/ntos/ndis/testprot/tpctl/tp_ndis.h new file mode 100644 index 000000000..ac633213a --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/tp_ndis.h @@ -0,0 +1,180 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tpc_ndis.h + +Abstract: + + This module defines NDIS 3.0 specific DEFINE for the TPCTL app. + +Author: + + Tom Adams (tomad) 20-Nov-1992 + +Revision History: + + 20-Nov-1992 tomad + + Created + +--*/ + +#include <ntddndis.h> + +typedef int NDIS_STATUS, *PNDIS_STATUS; // note default size + +// +// Request types used by NdisRequest; constants are added for +// all entry points in the MAC, for those that want to create +// their own internal requests. +// + +typedef enum _NDIS_REQUEST_TYPE { + NdisRequestQueryInformation, + NdisRequestSetInformation, + NdisRequestQueryStatistics, + NdisRequestOpen, + NdisRequestClose, + NdisRequestSend, + NdisRequestTransferData, + NdisRequestReset, + NdisRequestGeneric1, + NdisRequestGeneric2, + NdisRequestGeneric3, + NdisRequestGeneric4 +} NDIS_REQUEST_TYPE, *PNDIS_REQUEST_TYPE; + + +/* + * Medium Ndis Driver is running on + * + * + * typedef enum _NDIS_MEDIUM { + * NdisMedium802_3, + * NdisMedium802_5, + * NdisMediumFddi, + * NdisMediumAsync, + * NdisMediumLocalTalk, + * NdisMediumDix + * } NDIS_MEDIUM, *PNDIS_MEDIUM + * + * SanjeevK: Took out this definition since this structure is now defined in + * NTDDNDIS.H + * + */ + +// +// NDIS_STATUS values +// + +#define NDIS_STATUS_SUCCESS ((NDIS_STATUS) STATUS_SUCCESS) +#define NDIS_STATUS_PENDING ((NDIS_STATUS) STATUS_PENDING) +#define NDIS_STATUS_NOT_RECOGNIZED ((NDIS_STATUS)0x00010001L) +#define NDIS_STATUS_NOT_COPIED ((NDIS_STATUS)0x00010002L) + +#define NDIS_STATUS_ONLINE ((NDIS_STATUS)0x40010003L) +#define NDIS_STATUS_RESET_START ((NDIS_STATUS)0x40010004L) +#define NDIS_STATUS_RESET_END ((NDIS_STATUS)0x40010005L) +#define NDIS_STATUS_RING_STATUS ((NDIS_STATUS)0x40010006L) +#define NDIS_STATUS_CLOSED ((NDIS_STATUS)0x40010007L) +#define NDIS_STATUS_WAN_LINE_UP ((NDIS_STATUS)0x40010008L) +#define NDIS_STATUS_WAN_LINE_DOWN ((NDIS_STATUS)0x40010009L) +#define NDIS_STATUS_WAN_FRAGMENT ((NDIS_STATUS)0x4001000AL) + +#define NDIS_STATUS_NOT_RESETTABLE ((NDIS_STATUS)0x80010001L) +#define NDIS_STATUS_SOFT_ERRORS ((NDIS_STATUS)0x80010003L) +#define NDIS_STATUS_HARD_ERRORS ((NDIS_STATUS)0x80010004L) + +#define NDIS_STATUS_FAILURE ((NDIS_STATUS) STATUS_UNSUCCESSFUL) +#define NDIS_STATUS_RESOURCES ((NDIS_STATUS) \ + STATUS_INSUFFICIENT_RESOURCES) +#define NDIS_STATUS_CLOSING ((NDIS_STATUS)0xC0010002L) +#define NDIS_STATUS_BAD_VERSION ((NDIS_STATUS)0xC0010004L) +#define NDIS_STATUS_BAD_CHARACTERISTICS ((NDIS_STATUS)0xC0010005L) +#define NDIS_STATUS_ADAPTER_NOT_FOUND ((NDIS_STATUS)0xC0010006L) +#define NDIS_STATUS_OPEN_FAILED ((NDIS_STATUS)0xC0010007L) +#define NDIS_STATUS_DEVICE_FAILED ((NDIS_STATUS)0xC0010008L) +#define NDIS_STATUS_MULTICAST_FULL ((NDIS_STATUS)0xC0010009L) +#define NDIS_STATUS_MULTICAST_EXISTS ((NDIS_STATUS)0xC001000AL) +#define NDIS_STATUS_MULTICAST_NOT_FOUND ((NDIS_STATUS)0xC001000BL) +#define NDIS_STATUS_REQUEST_ABORTED ((NDIS_STATUS)0xC001000CL) +#define NDIS_STATUS_RESET_IN_PROGRESS ((NDIS_STATUS)0xC001000DL) +#define NDIS_STATUS_CLOSING_INDICATING ((NDIS_STATUS)0xC001000EL) +#define NDIS_STATUS_NOT_SUPPORTED ((NDIS_STATUS)STATUS_NOT_SUPPORTED) +#define NDIS_STATUS_INVALID_PACKET ((NDIS_STATUS)0xC001000FL) +#define NDIS_STATUS_OPEN_LIST_FULL ((NDIS_STATUS)0xC0010010L) +#define NDIS_STATUS_ADAPTER_NOT_READY ((NDIS_STATUS)0xC0010011L) +#define NDIS_STATUS_ADAPTER_NOT_OPEN ((NDIS_STATUS)0xC0010012L) +#define NDIS_STATUS_NOT_INDICATING ((NDIS_STATUS)0xC0010013L) +#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) +#define NDIS_STATUS_INVALID_DATA ((NDIS_STATUS)0xC0010015L) +#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) +#define NDIS_STATUS_INVALID_OID ((NDIS_STATUS)0xC0010017L) +#define NDIS_STATUS_ADAPTER_REMOVED ((NDIS_STATUS)0xC0010018L) +#define NDIS_STATUS_UNSUPPORTED_MEDIA ((NDIS_STATUS)0xC0010019L) +#define NDIS_STATUS_GROUP_ADDRESS_IN_USE ((NDIS_STATUS)0xC001001AL) +#define NDIS_STATUS_FILE_NOT_FOUND ((NDIS_STATUS)0xC001001BL) +#define NDIS_STATUS_ERROR_READING_FILE ((NDIS_STATUS)0xC001001CL) +#define NDIS_STATUS_ALREADY_MAPPED ((NDIS_STATUS)0xC001001DL) +#define NDIS_STATUS_RESOURCE_CONFLICT ((NDIS_STATUS)0xC001001EL) + +#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR ((NDIS_STATUS)0xC0011000L) + + +// +// used in error logging +// + +#define NDIS_ERROR_CODE ULONG + +#define NDIS_ERROR_CODE_RESOURCE_CONFLICT EVENT_NDIS_RESOURCE_CONFLICT +#define NDIS_ERROR_CODE_OUT_OF_RESOURCES EVENT_NDIS_OUT_OF_RESOURCE +#define NDIS_ERROR_CODE_HARDWARE_FAILURE EVENT_NDIS_HARDWARE_FAILURE +#define NDIS_ERROR_CODE_ADAPTER_NOT_FOUND EVENT_NDIS_ADAPTER_NOT_FOUND +#define NDIS_ERROR_CODE_INTERRUPT_CONNECT EVENT_NDIS_INTERRUPT_CONNECT +#define NDIS_ERROR_CODE_DRIVER_FAILURE EVENT_NDIS_DRIVER_FAILURE +#define NDIS_ERROR_CODE_BAD_VERSION EVENT_NDIS_BAD_VERSION +#define NDIS_ERROR_CODE_TIMEOUT EVENT_NDIS_TIMEOUT +#define NDIS_ERROR_CODE_NETWORK_ADDRESS EVENT_NDIS_NETWORK_ADDRESS +#define NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION EVENT_NDIS_UNSUPPORTED_CONFIGURATION +#define NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER +#define NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER +#define NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS EVENT_NDIS_BAD_IO_BASE_ADDRESS +#define NDIS_ERROR_CODE_RECEIVE_SPACE_SMALL EVENT_NDIS_RECEIVE_SPACE_SMALL +#define NDIS_ERROR_CODE_ADAPTER_DISABLED EVENT_NDIS_ADAPTER_DISABLED + + + +// +// Ndis Packet Filter Bits +// + +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 + +// +// Ndis Token-Ring Ring Status Codes +// + +#define NDIS_RING_SIGNAL_LOSS 0x00008000 +#define NDIS_RING_HARD_ERROR 0x00004000 +#define NDIS_RING_SOFT_ERROR 0x00002000 +#define NDIS_RING_TRANSMIT_BEACON 0x00001000 +#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800 +#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400 +#define NDIS_RING_REMOVE_RECEIVED 0x00000200 +#define NDIS_RING_COUNTER_OVERFLOW 0x00000100 +#define NDIS_RING_SINGLE_STATION 0x00000080 +#define NDIS_RING_RING_RECOVERY 0x00000040 + diff --git a/private/ntos/ndis/testprot/tpctl/tpctl.c b/private/ntos/ndis/testprot/tpctl/tpctl.c new file mode 100644 index 000000000..83b75b1a5 --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/tpctl.c @@ -0,0 +1,3852 @@ +// -------------------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpctl.c +// +// Abstract: +// +// This is the main component of the NDIS 3.0 MAC Tester control program. +// +// Author: +// +// Tom Adams (tomad) 2-Apr-1991 +// +// Revision History: +// +// 2-Apr-1991 tomad +// +// created +// +// Sanjeev Katariya (sanjeevk) 4-6-1993 +// +// Bug #5203: Changed the routine TpRunTest() at the point where the OPEN returns +// and the InformationBuffer contains information about the address and +// the Medium Type. This was made in order to satisfy the correct setting +// of the OID on multicast addresses(FDDI, 802.3). +// 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 hooks for globvars; 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 <stdlib.h> +#include <string.h> + +#include "tpctl.h" +#include "parse.h" + +BOOL ToolActive = TRUE; + +extern BOOL WriteThrough ; +extern BOOL ContinueOnError; + + + +DWORD +TpctlRunTest( + IN HANDLE hFileHandle + ) + +// ----- +// +// Routine Description: +// +// This routine is the main funciton of the TPCTL program. It +// prompts the user for commands, or reads them from the script +// file, and then issues the call to NtDeviceIoControlFile. +// +// Arguments: +// +// IN HANDLE hFileHandle - Supplies the handle to the Test Protocol +// driver where the IOCTLs will be directed. +// +// Return Value: +// +// DWORD - the status of the last call to take place. +// +// ----- + +{ + BYTE Buffer[TPCTL_CMDLINE_SIZE]; + LPSTR localArgv[TPCTL_MAX_ARGC]; + DWORD localArgc; + DWORD CmdCode; + DWORD Status = NO_ERROR; + NTSTATUS NtStatus; + HANDLE Event; + HANDLE Event1; + IO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK IoStatusBlock2; + HANDLE InputBuffer; + DWORD InputBufferSize = 8*IOCTL_BUFFER_SIZE; + HANDLE OutputBuffer; + HANDLE OutputBuffer2; + DWORD OutputBufferSize = 8*IOCTL_BUFFER_SIZE; + DWORD OutputBufferSize2; + DWORD WaitTime; + BOOL IoctlCommand = FALSE; + PCMD_ARGS CmdArgs; + DWORD OpenInstance; + + + InputBuffer = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,InputBufferSize ); + + if ( InputBuffer == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tGlobalAlloc failed to alloc InputBuffer: returned 0x%lx.\n", + (PVOID)Status); + return Status; + } + + CmdArgs = (PCMD_ARGS)InputBuffer; + + OutputBuffer = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,OutputBufferSize ); + + if ( OutputBuffer == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tGlobalAlloc failed to alloc OutputBuffer: returned 0x%lx.\n", + (PVOID)Status); + GlobalFree( InputBuffer ); + return Status; + } + + Event = CreateEvent( NULL,FALSE,FALSE,NULL ); + + if (Event == NULL) + { + Status = GetLastError(); + TpctlErrorLog("\n\tCreateEvent failed: returned 0x%lx.\n",(PVOID)Status); + GlobalFree( InputBuffer ); + GlobalFree( OutputBuffer ); + return Status; + } + + while ( ExitFlag == FALSE ) + { + if ( ContinueLooping == FALSE ) + { + // + // A Ctrl-c has been entered, If we are reading commands + // from a script file then reset all the open blocks, and + // close the script files. + // + + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + + ContinueLooping = TRUE; + } + + Status = TpctlReadCommand( TPCTL_PROMPT,Buffer,TPCTL_CMDLINE_SIZE ); + + if ( Status != NO_ERROR ) + { + printf("STATUS == Some error\n"); + + // + // there was an error in the last command entered. If we + // are reading commands from a script file then reset all + // the open blocks, and close the script files. + // + if ( !ContinueOnError ) + { + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + } + continue; + } + else if (( !TpctlParseCommand( Buffer, + localArgv, + &localArgc, + TPCTL_MAX_ARGC )) && + ( CommandsFromScript == TRUE )) + { + printf("which means parse command failed.\n"); + + if ( !ContinueOnError ) + { + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + } + continue; + } + + if (( localArgc <= 0 ) || ( localArgv[0][0] == ';' )) + { + continue; + } + + CmdCode = TpctlGetCommandCode( localArgv[0] ); + + switch( CmdCode ) + { + case VERBOSE: + if ( ToolActive ) + { + Verbose = ( Verbose ) ? FALSE : TRUE; + TpctlLog("\n\tTpctl: Verbose Mode enabled.\n",NULL); + + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + + } + + } + CmdCode = CMD_COMPLETED; + break; + + case SETENV: + if ( ToolActive ) + { + if ( TpctlParseArguments( SetEnvOptions, + Num_SetEnv_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( SetEnvOptions, + Num_SetEnv_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + TpctlSaveNewEnvironmentVariables( CmdArgs->OpenInstance - 1 ); + + } + CmdCode = CMD_COMPLETED; + break; + + case READSCRIPT: + if ( ToolActive ) + { + if ( TpctlParseArguments( ReadScriptOptions, + Num_ReadScript_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( ReadScriptOptions, + Num_ReadScript_Params, + localArgc, + localArgv ); + } + + Status = TpctlLoadFiles(GlobalCmdArgs.ARGS.FILES.ScriptFile, + GlobalCmdArgs.ARGS.FILES.LogFile ); + + if ( Status != NO_ERROR ) + { + if ( !ContinueOnError ) + { + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + } + } + } + CmdCode = CMD_COMPLETED; + break; + + case BEGINLOGGING: + if( ToolActive ) + { + if ( CommandsFromScript == TRUE ) + { + TpctlErrorLog("\n\tTpctl: Already logging results to \"%s\".\n", + (PVOID)Scripts[ScriptIndex].LogFile); + } + else if ( CommandLineLogging == TRUE ) + { + TpctlErrorLog("\n\tTpctl: Command Line Logging is already enabled.\n",NULL); + } + else + { + if ( TpctlParseArguments( LoggingOptions, + Num_Logging_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( LoggingOptions, + Num_Logging_Params, + localArgc, + localArgv ); + } + + CommandLineLogHandle = TpctlOpenLogFile(); + + if ( CommandLineLogHandle == (HANDLE)-1 ) + { + TpctlErrorLog("\n\tTpctl: failed to open Log File.\n",NULL); + } + else + { + CommandLineLogging = TRUE; + } + } + } + CmdCode = CMD_COMPLETED; + break; + + case ENDLOGGING: + if ( ToolActive ) + { + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + } + + if ( CommandLineLogging == TRUE ) + { + TpctlCloseLogFile(); + CommandLineLogging = FALSE; + } + else + { + TpctlErrorLog("\n\tTpctl: Logging is not enabled.\n\n",NULL); + } + } + CmdCode = CMD_COMPLETED; + break; + + case RECORDINGENABLE: + if( ToolActive ) + { + if ( RecordToScript == TRUE ) + { + TpctlErrorLog("\n\tTpctl: Already recording commands to \"%s\".\n", + (PVOID)RecordScriptName ); + } + else + { + if ( TpctlParseArguments( RecordingOptions, + Num_Recording_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + ScriptRecordHandle = TpctlOpenScriptFile(); + + if ( ScriptRecordHandle == (HANDLE)-1 ) + { + TpctlErrorLog("\n\tTpctl: failed to open script record File.\n",NULL); + } + else + { + RecordToScript = TRUE; + } + } + } + CmdCode = CMD_COMPLETED; + break; + + case RECORDINGDISABLE: + if ( ToolActive ) + { + if ( RecordToScript == TRUE ) + { + TpctlCloseScriptFile(); + RecordToScript = FALSE; + } + else + { + TpctlErrorLog("\n\tTpctl: Script Recording is not enabled.\n\n",NULL); + } + } + CmdCode = CMD_COMPLETED; + break; + + + case WAIT: + if ( ToolActive ) + { + if ( localArgv[1] != NULL ) + { + WaitTime = atol( localArgv[1] ); + } + else + { + WaitTime = 0; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + min(2,localArgc), + localArgv ); + } + + TpctlLog("\n\tTpctl: Waiting for %d seconds.\n",(PVOID)WaitTime); + + // + // Multiply by 1000 to convert seconds to msecs for us by + // Sleep(). + // + + Sleep( WaitTime * 1000 ); + } + CmdCode = CMD_COMPLETED; + break; + + case GO: + case PAUSE: + if ( ToolActive ) + { + if ( TpctlParseArguments( PauseGoOptions, + Num_PauseGo_Params - 1, // Ignore Unique Signature + // while parsing arguments. + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( PauseGoOptions, + Num_PauseGo_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + TpctlPauseGo( hFileHandle,CmdArgs,InputBufferSize,CmdCode ); + } + CmdCode = CMD_COMPLETED; + break; + + case LOAD: + case UNLOAD: + if ( ToolActive ) + { + if ( TpctlParseArguments( LoadUnloadOptions, + Num_LoadUnload_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( LoadUnloadOptions, + Num_LoadUnload_Params, + localArgc, + localArgv ); + } + TpctlLoadUnload( CmdCode ); + } + CmdCode = CMD_COMPLETED; + break; + + case OPEN: // NdisOpenAdapter + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenOptions, + Num_Open_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenOptions, + Num_Open_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == TRUE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter is already opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case CLOSE: // NdisCloseAdapter + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_COMPLETED; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SETPF: + if ( ToolActive ) + { + if ( TpctlParseArguments( SetPacketFilterOptions, + Num_SetPacketFilter_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( SetPacketFilterOptions, + Num_SetPacketFilter_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SETLA: + if ( ToolActive ) + { + if ( TpctlParseArguments( SetLookaheadOptions, + Num_SetLookahead_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( SetLookaheadOptions, + Num_SetLookahead_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case ADDMA: + case DELMA: + if ( ToolActive ) + { + if ( TpctlParseArguments( MulticastAddrOptions, + Num_MulticastAddr_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( MulticastAddrOptions, + Num_MulticastAddr_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SETFA: + if ( ToolActive ) + { + if ( TpctlParseArguments( FunctionalAddrOptions, + Num_FunctionalAddr_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( FunctionalAddrOptions, + Num_FunctionalAddr_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SETGA: + if ( ToolActive ) + { + if ( TpctlParseArguments( GroupAddrOptions, + Num_GroupAddr_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( GroupAddrOptions, + Num_GroupAddr_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SETINFO: // NdisSetInformation + if ( ToolActive ) + { + DWORD tmpArgc = 1; + LPSTR tmpArgv[2]; + + if ( localArgc > 1 ) + { + TpctlParseSetInfoArguments( &localArgc, + localArgv, + &tmpArgc, + tmpArgv ); + } + + if ( TpctlParseArguments( SetInfoOptions, + Num_SetInfo_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoOptions, + Num_SetInfo_Params, + localArgc, + localArgv ); + } + + // + // If the information class argument is one of Station Address, + // Functional Address, or Lookahead Size, then we need to + // continue parsing the arguments because we have not found + // the class specific argument needed in these three cases. + // + + switch ( GlobalCmdArgs.ARGS.TPSET.OID ) + { + case OID_GEN_CURRENT_PACKET_FILTER: + if ( TpctlParseArguments( SetInfoPFOptions, + Num_SetInfoPF_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoPFOptions, + Num_SetInfoPF_Params, + tmpArgc, + tmpArgv ); + } + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + if ( TpctlParseArguments( SetInfoLAOptions, + Num_SetInfoLA_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoLAOptions, + Num_SetInfoLA_Params, + tmpArgc, + tmpArgv ); + } + break; + + case OID_802_3_MULTICAST_LIST: + if ( TpctlParseArguments( SetInfoMAOptions, + Num_SetInfoMA_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoMAOptions, + Num_SetInfoMA_Params, + tmpArgc, + tmpArgv ); + } + break; + + case OID_FDDI_LONG_MULTICAST_LIST : + if ( TpctlParseArguments( SetInfoMAOptions, + Num_SetInfoMA_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoMAOptions, + Num_SetInfoMA_Params, + tmpArgc, + tmpArgv ); + } + break; + + case OID_FDDI_SHORT_CURRENT_ADDR : + + // + // Not implemented yet + // + + break; + + case OID_FDDI_LONG_CURRENT_ADDR : + + // + // Not implemented yet + // + + break; + + case OID_FDDI_SHORT_MULTICAST_LIST : + + // + // Not implemented yet + // + + break; + + case OID_802_5_CURRENT_FUNCTIONAL: + if ( TpctlParseArguments( SetInfoFAOptions, + Num_SetInfoFA_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoFAOptions, + Num_SetInfoFA_Params, + tmpArgc, + tmpArgv ); + } + break; + + case OID_802_5_CURRENT_GROUP: + if ( TpctlParseArguments( SetInfoGAOptions, + Num_SetInfoGA_Params, + tmpArgc, + tmpArgv ) == -1 ) + { + CmdCode = CMD_ERR; + } + if ( RecordToScript ) + { + TpctlRecordArguments( SetInfoGAOptions, + Num_SetInfoGA_Params, + tmpArgc, + tmpArgv ); + } + break; + + } // end switch + + if ( CmdCode == CMD_ERR ) + { + break; + } + + if ( !TpctlInitCommandBuffer(CmdArgs,SETINFO)) + { + CmdCode = CMD_COMPLETED; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + break; + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case QUERYINFO: + if ( ToolActive ) + { + if ( TpctlParseArguments( QueryInfoOptions, + Num_QueryInfo_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( QueryInfoOptions, + Num_QueryInfo_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_COMPLETED; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case QUERYSTATS: + if ( ToolActive ) + { + if ( TpctlParseArguments( QueryStatsOptions, + Num_QueryStats_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( QueryStatsOptions, + Num_QueryStats_Params, + localArgc, + localArgv ); + } + + TpctlQueryStatistics( GlobalCmdArgs.ARGS.TPQUERYSTATS.DeviceName, + GlobalCmdArgs.ARGS.TPQUERYSTATS.OID, + NULL, //StatsBuffer, + 0); //BufLen + + } + CmdCode = CMD_COMPLETED; + break; + + case RESET: // NdisReset + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case SEND: // NdisSend + if ( ToolActive ) + { + if ( TpctlParseArguments( SendOptions, + Num_Send_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( SendOptions, + Num_Send_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Is this Open Instance already sending packets? + // + + if ( Open[OpenInstance].Sending == TRUE ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: Packets are currently being sent on Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + else if ( Open[OpenInstance].SendResultsCompleted == TRUE ) + { + // + // A previous SEND test has left some results in the SEND + // RESULTS buffer, and they have not been printed. + // + + TpctlLog("\n\tTpctl: Results exist for a prior SEND test.\n",NULL); + + TpctlPrintSendResults( Open[OpenInstance].SendResults ); + Open[OpenInstance].SendResultsCompleted = FALSE; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // Send IoStatusBlock, and the OutputBuffer to point to its + // SendResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].SendStatusBlock; + OutputBuffer2 = Open[OpenInstance].SendResults; + OutputBufferSize2 = sizeof( SEND_RECEIVE_RESULTS ); + + // + // Set up the Send Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPSEND]; + + if ( !ResetEvent( Open[OpenInstance].SendEvent )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to reset Send Event 0x%lx.\n", + (PVOID)Status); + CmdCode = CMD_ERR; + break; + } + + // + // Finally set the Sending flag for this Open Instance, + // + + Open[OpenInstance].Sending = TRUE; + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case STOPSEND: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + // + // Is this Open Instance currently sending packets? + // + + if ( Open[OpenInstance].Sending == FALSE ) + { + // + // If not are the any results to report? + // + + if ( Open[OpenInstance].SendResultsCompleted == FALSE ) + { + // + // If not, print an error message and prompt for next + // command. + // + + TpctlErrorLog( + "\n\tTpctl: A SEND test is not currently running for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_COMPLETED; + break; + } + else // SendResultsCompleted == TRUE + { + // + // If there are results from a previous send, then print + // them, reset the flags, and prompt for the command. + // + + TpctlPrintSendResults(Open[OpenInstance].SendResults); + + Open[OpenInstance].SendResultsCompleted = FALSE; + Open[OpenInstance].Sending = FALSE; + + CmdCode = CMD_COMPLETED; + break; + } + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case WAITSEND: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + if ( Open[OpenInstance].SendResultsCompleted == TRUE ) + { + TpctlPrintSendResults( Open[OpenInstance].SendResults ); + + Open[OpenInstance].SendResultsCompleted = FALSE; + Open[OpenInstance].Sending = FALSE; + } + else if ( Open[OpenInstance].Sending == TRUE ) + { + ContinueLooping = TRUE; + do + { + Status = WaitForSingleObject( Open[OpenInstance].SendEvent, + 1000); // One_Second + if (( Status != NO_ERROR ) && + ( Status != WAIT_TIMEOUT )) + { + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + } + } while (( Status != NO_ERROR ) && ( ContinueLooping == TRUE )); + + if ( ContinueLooping == FALSE ) + { + TpctlLog("\n\tTpctl: Cancelling WaitSend command.\n",NULL); + } + else + { + TpctlPrintSendResults( Open[OpenInstance].SendResults ); + + Open[OpenInstance].SendResultsCompleted = FALSE; + Open[OpenInstance].Sending = FALSE; + } + } + else + { + TpctlErrorLog("\n\tTpctl: No Send results exist, and no Send test is\n", + NULL); + TpctlErrorLog("\t currently running for Open Instance %lu.\n", + (PVOID)CmdArgs->OpenInstance); + } + } + CmdCode = CMD_COMPLETED; + break; + + case RECEIVE: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Is this Open Instance already receiveing packets? + // + + if ( Open[OpenInstance].Receiving == TRUE ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: Packets are currently being received on Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + + } + else if ( Open[OpenInstance].ReceiveResultsCompleted == TRUE ) + { + // + // A previous RECEIVE test has left some results in the RECEIVE + // RESULTS buffer, and they have not been printed. + // + + TpctlLog("\n\tTpctl: Results exist for a prior RECEIVE test.\n",NULL); + TpctlPrintReceiveResults(Open[OpenInstance].ReceiveResults); + Open[OpenInstance].ReceiveResultsCompleted = FALSE; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // Send IoStatusBlock, and the OutputBuffer to point to its + // ReceiveResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].ReceiveStatusBlock; + OutputBuffer2 = Open[OpenInstance].ReceiveResults; + OutputBufferSize2 = sizeof( SEND_RECEIVE_RESULTS ); + + // + // Set up the Receive Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPRECEIVE]; + + if (!ResetEvent(Open[OpenInstance].ReceiveEvent)) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to reset Receive Event 0x%lx.\n", + (PVOID)Status); + CmdCode = CMD_ERR; + break; + } + + // + // Finally set the Receiving flag for this Open Instance, + // + + Open[OpenInstance].Receiving = TRUE; + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case STOPREC: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + // + // Is this Open Instance receiving packets? + // + + if ( Open[OpenInstance].Receiving == FALSE ) + { + // + // If not are the any results to report? + // + + if ( Open[OpenInstance].ReceiveResultsCompleted == FALSE ) + { + // + // If not, print an error message and prompt for next + // command. + // + + TpctlErrorLog( + "\n\tTpctl: A RECEIVE test is not currently running for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + + } + else // ReceiveResultsCompleted == TRUE + { + TpctlPrintReceiveResults( Open[OpenInstance].ReceiveResults ); + + Open[OpenInstance].ReceiveResultsCompleted = FALSE; + Open[OpenInstance].Receiving = FALSE; + + CmdCode = CMD_COMPLETED; + break; + } + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case GETEVENTS: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + TpctlGetEvents( hFileHandle,CmdArgs,InputBufferSize ); + } + CmdCode = CMD_COMPLETED; + break; + + case STRESS: + if ( ToolActive ) + { + if ( TpctlParseArguments( StressOptions, + Num_Stress_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( StressOptions, + Num_Stress_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Is this Open Instance already running a stress test? + // + + if ( Open[OpenInstance].Stressing == TRUE ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: A Stress test is currently running for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + else if ( Open[OpenInstance].StressResultsCompleted == TRUE ) + { + // + // A previous STRESS test has left some results in the STRESS + // RESULTS buffer, and they have not been printed. + // + + TpctlLog("\n\tTpctl: Results exist for a prior STRESS test.\n",NULL); + + TpctlPrintStressResults(Open[OpenInstance].StressResults, + Open[OpenInstance].Ack10 ); + + Open[OpenInstance].StressResultsCompleted = FALSE; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // Stress IoStatusBlock, and the OutputBuffer to point to its + // StressResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].StressStatusBlock; + OutputBuffer2 = Open[OpenInstance].StressResults; + OutputBufferSize2 = sizeof( STRESS_RESULTS ); + + // + // Set up the Stress Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPSTRESS]; + + if (!ResetEvent(Open[OpenInstance].StressEvent)) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to reset Stress Event 0x%lx.\n", + (PVOID)Status); + CmdCode = CMD_ERR; + break; + } + + // + // if we are running a stress test with a response type of + // ack 10 times for every packet, set the flag for displaying. + // + + if ( CmdArgs->ARGS.TPSTRESS.ResponseType == ACK_10_TIMES ) + { + Open[OpenInstance].Ack10 = TRUE; + } + else + { + Open[OpenInstance].Ack10 = FALSE; + } + + // + // Finally set the Stressing flag for this Open Instance, + // + + Open[OpenInstance].Stressing = TRUE; + + // + // the flag indicating that a Client is running on this Open + // Instance, + // + + Open[OpenInstance].StressClient = TRUE; + + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case STRESSSERVER: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Is this Open Instance already running a stress test? + // + + if ( Open[OpenInstance].Stressing == TRUE ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: A Stress test is currently running for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // IoStatusBlock, and the OutputBuffer to point to its + // StressResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].StressStatusBlock; + OutputBuffer2 = Open[OpenInstance].StressResults; + OutputBufferSize2 = sizeof( STRESS_RESULTS ); + + // + // Set up the Stress Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPSTRESS]; + + if (!ResetEvent(Open[OpenInstance].StressEvent)) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tTpctl: failed to reset Stress Event 0x%lx.\n",(PVOID)Status); + CmdCode = CMD_ERR; + break; + } + + // + // Finally set the Stressing flag for this Open Instance, + // + + Open[OpenInstance].Stressing = TRUE; + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case ENDSTRESS: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + // + // Is this Open Instance running a stress test? + // + + if ( Open[OpenInstance].Stressing == FALSE ) + { + // + // If not, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: A Stress test is not currently running for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_COMPLETED; + } + + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case WAITSTRESS: + case CHECKSTRESS: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + if ( Open[OpenInstance].StressResultsCompleted == TRUE ) + { + TpctlPrintStressResults(Open[OpenInstance].StressResults, + Open[OpenInstance].Ack10 ); + + Open[OpenInstance].StressResultsCompleted = FALSE; + Open[OpenInstance].Stressing = FALSE; + + } + else if ( Open[OpenInstance].Stressing == TRUE ) + { + if ( Open[OpenInstance].StressClient != TRUE ) + { + TpctlErrorLog("\n\tTpctl: %s command valid only for Stress Clients.\n", + TpctlGetCommandName( localArgv[0] )); + CmdCode = CMD_ERR; + break; + } + + if ( CmdCode == WAITSTRESS ) + { + ContinueLooping = TRUE; + + do + { + Status = WaitForSingleObject( Open[OpenInstance].StressEvent, + 1000); // One_Second + if (( Status != NO_ERROR ) && + ( Status != WAIT_TIMEOUT )) + { + TpctlErrorLog( + "\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + } + + } while (( Status != NO_ERROR ) && + ( ContinueLooping == TRUE )); + + if ( ContinueLooping == FALSE ) + { + TpctlLog("\n\tTpctl: Cancelling WaitStress command.\n",NULL); + } + else + { + TpctlPrintStressResults(Open[OpenInstance].StressResults, + Open[OpenInstance].Ack10 ); + + Open[OpenInstance].StressResultsCompleted = FALSE; + Open[OpenInstance].Stressing = FALSE; + } + } + else + { + TpctlLog("\n\tTpctl: The Stress test is still running.\n",NULL); + } + } + else + { + TpctlErrorLog("\n\tTpctl: No Stress results exist, and no Stress test is\n", + NULL); + TpctlErrorLog("\t currently running for Open Instance %lu.\n", + (PVOID)CmdArgs->OpenInstance); + } + } + CmdCode = CMD_COMPLETED; + break; + + case BREAKPOINT: + if ( !ToolActive ) + { + CmdCode = CMD_COMPLETED; + } + else + { + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + } + } + break; + + case QUIT: + if ( ToolActive ) + { + DWORD i; + + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + } + + // + // If there are any outstanding ASYNC IRPs print a message + // to the user to wait patiently. + // + + for (i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + if ((( Open[i].Stressing == TRUE ) || + ( Open[i].Sending == TRUE )) || + ( Open[i].Receiving == TRUE )) + { + TpctlErrorLog( + "\n\tTpctl: Cancelling outstanding IRPs, please wait...\n",NULL); + break; + } + } + ExitFlag = TRUE; + Status = NO_ERROR; + } + CmdCode = CMD_COMPLETED; + break; + + case HELP: + if ( ToolActive ) + { + DWORD TmpScriptIndex = ScriptIndex; + + // + // We are going to temporarily override the script index + // to fool the TpctlParseArguments routine into not prompting + // for an argument if none is give with the help command. + // + + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + } + + ScriptIndex = (DWORD)1; + + if ( TpctlParseArguments( HelpOptions, + Num_Help_Params, + localArgc, + localArgv ) == -1 ) + { + break; + } + TpctlHelp( GlobalCmdArgs.ARGS.CmdName ); + ScriptIndex = TmpScriptIndex; + } + CmdCode = CMD_COMPLETED; + break; + + case SHELL: + if ( ToolActive ) + { + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + 1, + localArgv ); + } + + { + CONSOLE_SCREEN_BUFFER_INFO ScreenBuffer; + HANDLE OutputHandle; + COORD Start; + BOOL NoErrorsAccessingConsole = FALSE; + DWORD CharactersWritten; + + ZeroMemory( (PVOID)&ScreenBuffer, sizeof(CONSOLE_SCREEN_BUFFER_INFO)); + Start.X = 0; + Start.Y = 0; + + OutputHandle = GetStdHandle( STD_OUTPUT_HANDLE ); + // + // Record the old console settings + // + if ( GetConsoleScreenBufferInfo( OutputHandle, &ScreenBuffer ) ) + { + NoErrorsAccessingConsole = TRUE; + } + + // + // Set the console foregrounds and background colors to the new settings + // + if( NoErrorsAccessingConsole ) + { + WORD Colors; + + if ( ScreenBuffer.wAttributes & BACKGROUND_BLUE ) + { + Colors = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE| + FOREGROUND_INTENSITY|BACKGROUND_RED; + } + else + { + Colors = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE| + FOREGROUND_INTENSITY|BACKGROUND_BLUE; + } + + SetConsoleTextAttribute( OutputHandle, Colors ); + FillConsoleOutputAttribute( OutputHandle, Colors, + 0xFFFFFFFF, Start, + &CharactersWritten ); + } + + // + // And spawn the command shell + // + { + CHAR ShellCommand[256]; + INT TmpCount; + + ZeroMemory( ShellCommand, sizeof( ShellCommand )); + strcpy( ShellCommand, "CMD" ); + + if ( localArgc > 1 ) + { + strcat( ShellCommand, " /C " ); + for( TmpCount = 1; TmpCount < (INT)localArgc; TmpCount++ ) + { + strcat( ShellCommand, localArgv[TmpCount] ); + strcat( ShellCommand, " " ); + } + } + system( ShellCommand ); + } + + // + // Reset the console foregrounds and background colors to the old settings + // + if( NoErrorsAccessingConsole ) + { + SetConsoleTextAttribute( OutputHandle, ScreenBuffer.wAttributes ); + FillConsoleOutputAttribute( OutputHandle, ScreenBuffer.wAttributes, + 0xFFFFFFFF, Start, + &CharactersWritten ); + } + } + printf("\n"); + } + CmdCode = CMD_COMPLETED; + break; + + case DISABLE: + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + localArgc, + localArgv ); + } + + if ( Disable( localArgc, localArgv ) ) + { + printf( "\n\tDisabling TPCTL...\n\n" ); + } + CmdCode = CMD_COMPLETED; + break; + + case ENABLE: + ToolActive = TRUE; + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + localArgc, + localArgv ); + } + printf( "\n\tEnabling TPCTL...\n\n" ); + CmdCode = CMD_COMPLETED; + break; + + case REGISTRY: + if ( ToolActive ) + { + if ( TpctlParseArguments( RegistryOptions, + Num_Registry_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( RegistryOptions, + Num_Registry_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + TpctlPerformRegistryOperation( CmdArgs ); + } + CmdCode = CMD_COMPLETED; + break; + + + case PERFSERVER: + if ( ToolActive ) + { + if ( TpctlParseArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( OpenInstanceOptions, + Num_OpenInstance_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Is this Open Instance already sending or receiving packets? + // + + if ( (Open[OpenInstance].Sending == TRUE ) || + (Open[OpenInstance].Receiving == TRUE ) || + (Open[OpenInstance].ReceiveResultsCompleted == TRUE ) || + (Open[OpenInstance].SendResultsCompleted == TRUE ) ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: Packets are currently being sent or received on Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // Send IoStatusBlock, and the OutputBuffer to point to its + // SendResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].PerfStatusBlock; + OutputBuffer2 = Open[OpenInstance].PerfResults; + OutputBufferSize2 = sizeof( PERF_RESULTS ); + + // + // Set up the Send Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPPERF]; + + if ( !ResetEvent( Open[OpenInstance].PerfEvent )) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to reset Perf Event 0x%lx.\n", + (PVOID)Status); + CmdCode = CMD_ERR; + break; + } + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + case PERFCLIENT: + if ( ToolActive ) + { + if ( TpctlParseArguments( PerfClntOptions, + Num_PerfClnt_Params, + localArgc, + localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( PerfClntOptions, + Num_PerfClnt_Params, + localArgc, + localArgv ); + } + + if ( !TpctlInitCommandBuffer( CmdArgs,CmdCode )) + { + CmdCode = CMD_ERR; + break; + } + + OpenInstance = CmdArgs->OpenInstance - 1; + + if ( Open[OpenInstance].AdapterOpened == FALSE ) + { + TpctlErrorLog( + "\n\tTpctl: The adapter has not been opened for Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // + // Is this Open Instance already sending or receiving packets? + // + + if ( (Open[OpenInstance].Sending == TRUE ) || + (Open[OpenInstance].Receiving == TRUE ) || + (Open[OpenInstance].ReceiveResultsCompleted == TRUE ) || + (Open[OpenInstance].SendResultsCompleted == TRUE ) ) + { + // + // If so, print an error message and prompt for next command. + // + + TpctlErrorLog( + "\n\tTpctl: Packets are currently being sent or received on Open Instance %lu.\n", + (PVOID)(CmdArgs->OpenInstance)); + CmdCode = CMD_ERR; + break; + } + + // + // Set up the IoStatusBlock to point to this Open Instance's + // Send IoStatusBlock, and the OutputBuffer to point to its + // ReceiveResults structure. + // + + IoStatusBlock2 = Open[OpenInstance].PerfStatusBlock; + OutputBuffer2 = Open[OpenInstance].PerfResults; + OutputBufferSize2 = sizeof( PERF_RESULTS ); + + // + // Set up the Receive Event to wait on. + // + + Event1 = Open[OpenInstance].Events[TPPERF]; + + if (!ResetEvent(Open[OpenInstance].PerfEvent)) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: failed to reset Perf Event 0x%lx.\n", + (PVOID)Status); + CmdCode = CMD_ERR; + break; + } + CpuUsageInit(); + } + else + { + CmdCode = CMD_COMPLETED; + } + break; + + + case SETGLOBAL: + if (ToolActive) + { + if ( TpctlParseSet( localArgc, localArgv ) == -1 ) + { + CmdCode = CMD_ERR; + break; + } + + if ( RecordToScript ) + { + TpctlRecordArguments( NULL, + 0, + min(2,localArgc), + localArgv ); + } + + } + CmdCode = CMD_COMPLETED; + break; + + default: + CmdCode = CMD_COMPLETED; + if( ToolActive ) + { + TpctlErrorLog("\n\tTpctl: Invalid Command Entered.\n",NULL); + CmdCode = CMD_ERR; + } + break; + + } // switch(); + + // + // If we have a command to issue to the driver and the tool + // is active, do it now. + // + + if ( ( CmdCode == STRESS ) || ( CmdCode == STRESSSERVER ) || + ( CmdCode == SEND ) || ( CmdCode == RECEIVE ) || + ( CmdCode == PERFSERVER ) || ( CmdCode == PERFCLIENT ) ) + { + +//!!NOT WIN32!! + + NtStatus = NtDeviceIoControlFile( hFileHandle, + Event1, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock2, + TP_CONTROL_CODE( CmdCode,IOCTL_METHOD ), + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer2, + OutputBufferSize2 ); + + if (( NtStatus == STATUS_SUCCESS ) || + ( NtStatus == STATUS_PENDING )) + { + TpctlLog("\n\tTpctl: The %s command has been issued.\n", + TpctlGetCommandName( localArgv[0] )); + } + + } + else if (( CmdCode != CMD_ERR ) && ( CmdCode != CMD_COMPLETED )) + { +// !!NOT WIN32!! + + NtStatus = NtDeviceIoControlFile( hFileHandle, + Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + TP_CONTROL_CODE( CmdCode,IOCTL_METHOD ), + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer, + OutputBufferSize ); + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + // + // If the IOCTL call failed then close any script files + // and break out of while loop by setting the ExitFlag + // to true. + // + + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + break; + } + else + { + TpctlLog("\n\tTpctl: The %s command has been issued.\n", + TpctlGetCommandName( localArgv[0] )); + + if ( NtStatus == STATUS_PENDING ) + { + // + // If the ioctl pended, then wait for it to complete. + // + + Status = WaitForSingleObject( Event,60000 ); // ONE_MINUTE + + if ( Status == WAIT_TIMEOUT ) + { + // + // The wait timed out, this probable means there + // was a failure in the MAC not completing a + // request, because the IRP was never completed + // by the test protocol driver. + // + + TpctlErrorLog( + "\n\tTpctl: WARNING - WaitForSingleObject unexpectedly timed out.\n", + NULL); + TpctlErrorLog( + "\t IRP was never completed in protocol driver.\n", + NULL); + CmdCode = CMD_ERR; + } + else if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit + // the test app with the error. + // + + TpctlErrorLog( + "\n\tTpctl: ERROR - WaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + CmdCode = CMD_ERR; + } + else if ( IoStatusBlock.Status != STATUS_SUCCESS ) + { + // + // else if the pending ioctl returned failure again + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile pended.\n",NULL); + TpctlErrorLog("\n\t NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)IoStatusBlock.Status); + ExitFlag = TRUE; + Status = IoStatusBlock.Status; + } + } + } + } + + switch ( CmdCode ) + { + case CMD_ERR: + // + // NOTE: if commands are being read from a script file setting + // the CmdCode to CMD_ERR causes this routine to unload ALL + // script files, and wait at the prompt for the next command + // to process, use CMD_ERR wisely. + // + + if( !ContinueOnError ) + { + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + } + break; + + case SETENV: + break; + + case OPEN: + if (((PREQUEST_RESULTS)OutputBuffer)->RequestStatus == NDIS_STATUS_SUCCESS ) + { + // + // The open request succeeded so mark this open instance + // as opened. + // + + Open[OpenInstance].AdapterOpened = TRUE; + + // + // if the open "initialization" requests all succeeded + // copy the adapter address into the open, and set the + // open instance. + // + + if (((PREQUEST_RESULTS)OutputBuffer)->OpenRequestStatus == + NDIS_STATUS_SUCCESS ) + { + // + // STARTCHANGE + // + // Sanjeevk: Bug #5203 + // + PNDIS_MEDIUM MediumType = + (PNDIS_MEDIUM)((PREQUEST_RESULTS)OutputBuffer)->InformationBuffer; + + // + // Copy the Media Type + // + Open[OpenInstance].MediumType = *MediumType; + + // + // STOPCHANGE + // + + // + // Copy the address of the adapter + // + TpctlCopyAdapterAddress(OpenInstance, + (PREQUEST_RESULTS)OutputBuffer ); + + Open[OpenInstance].OpenInstance = (UCHAR)OpenInstance; + } + } + + // + // Now print the Open request results regardless of success or + // failure. + // + + TpctlPrintResults( (PREQUEST_RESULTS)OutputBuffer,CmdCode,0 ); + break; + + case CLOSE: + if (((PREQUEST_RESULTS)OutputBuffer)->RequestStatus == + NDIS_STATUS_SUCCESS ) + { + // + // The close request succeeded, set the flag stating so, + // and reset the open structure to its initial state. + // + + Open[OpenInstance].AdapterOpened = FALSE; + Open[OpenInstance].OpenInstance = (UCHAR)-1; + + TpctlResetOpenState( &Open[OpenInstance],hFileHandle ); + } + + // + // Now print the results regardless of success or failure. + // + + TpctlPrintResults( (PREQUEST_RESULTS)OutputBuffer,CmdCode,0 ); + break; + + case SETPF: + case SETLA: + case ADDMA: + case SETFA: + case SETGA: + case SETINFO: + { + PMULT_ADDR MultAddr = NULL; + BOOL AddressFound = FALSE; + DWORD i; + + if (((PREQUEST_RESULTS)OutputBuffer)->RequestStatus == + NDIS_STATUS_SUCCESS ) + { + // + // If the command succeeded, then update the local + // state to reflect the changed info. + // + + switch ( CmdArgs->ARGS.TPSET.OID ) + { + case OID_GEN_CURRENT_PACKET_FILTER: + Open[OpenInstance].PacketFilter = + CmdArgs->ARGS.TPSET.U.PacketFilter; + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + Open[OpenInstance].LookaheadSize = + CmdArgs->ARGS.TPSET.U.LookaheadSize; + break; + + case OID_FDDI_LONG_MULTICAST_LIST : + case OID_802_3_MULTICAST_LIST : + // + // We successfully added the multicast address to the + // card, if it is not in our local list already, then + // put it on the local multicast address list + // for accounting purposes. + // + // XXX: The stress tests be required to add and delete + // the stress multicast address to/from this list? + // + + MultAddr = Open[OpenInstance].MulticastAddresses; + + if ( MultAddr != NULL ) + { + // + // if the list is not empty see if this addr is + // in it yet. + // + + while ( MultAddr != NULL ) + { + if ( memcmp(CmdArgs->ARGS.TPSET.U.MulticastAddress[0], + MultAddr->MulticastAddress, + ADDRESS_LENGTH ) == 0 ) + { + // + // We found the address in the list already, + // so skip adding it in again. + // + + AddressFound = TRUE; + break; + } + + // + // Otherwise, get the next list entry. + // + + MultAddr = MultAddr->Next; + } + } + + if ( AddressFound == FALSE ) + { + MultAddr = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, + sizeof( MULT_ADDR ) ); + + if ( MultAddr == NULL ) + { + Status = GetLastError(); + TpctlErrorLog( + "\n\tGlobalAlloc failed to alloc a MultAddr stuct: returned 0x%lx.\n", + (PVOID)Status); + break; + } + + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + MultAddr->MulticastAddress[i] = + CmdArgs->ARGS.TPSET.U.MulticastAddress[0][i]; + } + + MultAddr->Next = Open[OpenInstance].MulticastAddresses; + Open[OpenInstance].MulticastAddresses = MultAddr; + + Open[OpenInstance].NumberMultAddrs++; + } + break; + + case OID_802_5_CURRENT_FUNCTIONAL: + for (i=0;i<FUNCTIONAL_ADDRESS_LENGTH;i++) + { + Open[OpenInstance].FunctionalAddress[i] = + CmdArgs->ARGS.TPSET.U.FunctionalAddress[i]; + } + break; + + case OID_802_5_CURRENT_GROUP: + for (i=0;i<FUNCTIONAL_ADDRESS_LENGTH;i++) + { + Open[OpenInstance].GroupAddress[i] = + CmdArgs->ARGS.TPSET.U.GroupAddress[i]; + } + break; + } + } + + TpctlPrintSetInfoResults( (PREQUEST_RESULTS)OutputBuffer, + CmdCode, + CmdArgs->ARGS.TPSET.OID ); + break; + } + + case DELMA: + { + PMULT_ADDR MultAddr = NULL; + PMULT_ADDR BaseMultAddr = NULL; + // + // We successfully deleted the multicast address from the + // card, if it is in our local list already, then remove + // it from the local multicast address list for accounting + // purposes. + // + // The stress tests be required to add and delete the stress + // multicast address to/from this list? + // + + MultAddr = Open[OpenInstance].MulticastAddresses; + + if ( MultAddr != NULL ) + { + // + // if the list is not empty see if this addr is + // in it, first check the initial entry. + // + + if ( memcmp(GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0], + MultAddr->MulticastAddress, + ADDRESS_LENGTH ) == 0 ) + { + // + // and if found remove from list and free + // + Open[OpenInstance].MulticastAddresses = MultAddr->Next; + GlobalFree( MultAddr ); + Open[OpenInstance].NumberMultAddrs--; + } + else + { + // + // Otherwise check the rest of the list. + // + + while ( MultAddr->Next != NULL ) + { + if (memcmp( GlobalCmdArgs.ARGS.TPSET.U.MulticastAddress[0], + MultAddr->Next->MulticastAddress, + ADDRESS_LENGTH ) == 0 ) + { + // + // We found the address in the list, so remove + // it and deallocate the memory + // + MultAddr->Next = MultAddr->Next->Next; + GlobalFree( MultAddr->Next ); + Open[OpenInstance].NumberMultAddrs--; + break; + } + // + // Otherwise, get the next list entry. + // + + MultAddr = MultAddr->Next; + } + } + } + + TpctlPrintSetInfoResults( (PREQUEST_RESULTS)OutputBuffer, + CmdCode, + CmdArgs->ARGS.TPSET.OID ); + + break; + } + + case QUERYINFO: + TpctlPrintQueryInfoResults( (PREQUEST_RESULTS)OutputBuffer, + CmdCode, + CmdArgs->ARGS.TPQUERY.OID ); + break; + + case RESET: + TpctlPrintResults( (PREQUEST_RESULTS)OutputBuffer,CmdCode,0 ); + break; + + case SEND: + // + // If the IOCTL call failed then break out of while loop + // by setting the ExitFlag to true. + // + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + break; + } + // + // If we have only attempted to SEND one packet, then we will + // print the results here and now. + // + + else if ( CmdArgs->ARGS.TPSEND.NumberOfPackets == 1 ) + { + // + // Wait for the SEND event to be signaled telling us that + // the results are complete. + // + + Status = WaitForSingleObject( Open[OpenInstance].SendEvent, + 0xFFFFFFFF ); + + if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the send did not completed successfully then + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: The SEND command failed, returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + else + { + // + // Otherwise print the send test results. + // + + TpctlPrintSendResults( Open[OpenInstance].SendResults ); + } + + // + // then reset the SEND control flags to the initial state + // and return. + // + + Open[OpenInstance].SendResultsCompleted = FALSE; + Open[OpenInstance].Sending = FALSE; + } + break; + + case STOPSEND: + // + // Wait for the SEND event to be signaled telling us that + // the results are complete. + // + + Status = WaitForSingleObject( Open[OpenInstance].SendEvent, + 0xFFFFFFFF ); + + if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the send did not completed successfully then + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: The STOPSEND command failed, returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + else + { + // + // Otherwise print the send test results. + // + + TpctlPrintSendResults( Open[OpenInstance].SendResults ); + } + + // + // then reset the SEND control flags to the initial state + // and return. + // + Open[OpenInstance].SendResultsCompleted = FALSE; + Open[OpenInstance].Sending = FALSE; + break; + + case RECEIVE: + // + // If the IOCTL call failed then break out of while loop + // by setting the ExitFlag to true. + // + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + } + + // + // otherwise the RECEIVE test has been started successfully, and + // there is nothing more to do. + // + break; + + case STOPREC: + // + // Wait for the RECEIVE event to be signaled telling us that + // the results are complete. + // + + Status = WaitForSingleObject( Open[OpenInstance].ReceiveEvent, + 0xFFFFFFFF ); + + if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the receive did not completed successfully then + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: The STOPRECEIVE command failed, returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + else + { + // + // Otherwise print the receive test results. + // + TpctlPrintReceiveResults( Open[OpenInstance].ReceiveResults ); + } + + // + // then reset the RECEIVE control flags to the initial state + // and return. + // + + Open[OpenInstance].ReceiveResultsCompleted = FALSE; + Open[OpenInstance].Receiving = FALSE; + break; + + case STRESS: + // + // If the Ioctl call failed then the attempt to start the + // stress test has failed, then break out of while loop by + // setting the ExitFlag to true. + // + + if ((( NtStatus != TP_STATUS_NO_SERVERS ) && + ( NtStatus != STATUS_SUCCESS )) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + } + else if ( NtStatus == TP_STATUS_NO_SERVERS ) + { + // + // No Stress Servers where found to participate in the + // test, reset the Stress Test control flags to show that + // the test did not start properly. + // + + Open[OpenInstance].Stressing = FALSE; + Open[OpenInstance].StressResultsCompleted = FALSE; + Open[OpenInstance].StressClient = FALSE; + + // + // Then Display the error to the user. + // + + TpctlErrorLog("\n\tTpctl: failed to start STRESS test, returned %s.\n", + (PVOID)TpctlGetStatus( NtStatus )); + + // + // And, if we are reading commands from a script, assume + // that the failure should force the test to stop, therefore + // unload the script files. + // + + if ( !ContinueOnError ) + { + TpctlResetAllOpenStates( hFileHandle ); + TpctlCloseScripts(); + } + + } + break; + + case STRESSSERVER: + // + // If the IOCTL call failed then break out of while loop + // by setting the ExitFlag to true. + // + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + } + + // + // otherwise the STRESS SERVER has been started successfully, and + // there is nothing more to do here. + // + break; + + case ENDSTRESS: + // + // Wait for the STRESS event to be signaled telling us that + // the results are complete. + // + + Status = WaitForSingleObject( Open[OpenInstance].StressEvent, + 0xFFFFFFFF ); + + if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the receive did not completed successfully then + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: The ENDSTRESS command failed, returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + else if ( Open[OpenInstance].StressClient == TRUE ) + { + TpctlPrintStressResults(Open[OpenInstance].StressResults, + Open[OpenInstance].Ack10 ); + + Open[OpenInstance].StressResultsCompleted = FALSE; + Open[OpenInstance].StressClient = FALSE; + Open[OpenInstance].Stressing = FALSE; + } + break; + + case BREAKPOINT: + break; + + case CMD_COMPLETED: + break; + + + case PERFSERVER: + // + // If the IOCTL call failed then break out of while loop + // by setting the ExitFlag to true. + // + Status = NtStatus; + + if (( Status != STATUS_SUCCESS ) && ( Status != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + break; + } + // + // Wait for the PERFSEND event to be signaled telling us that + // the results are complete. + // + + if (Status == STATUS_PENDING) + { + for(;;) + { + Status = WaitForSingleObject( Open[OpenInstance].PerfEvent, + 2000 ); + if (Status == WAIT_TIMEOUT) + { + if (!ContinueLooping) // ctl-C was pressed + { + ContinueLooping = TRUE; // just quit this command + + NtStatus = + NtDeviceIoControlFile( hFileHandle, + Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + IOCTL_TP_PERF_ABORT, + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer, + OutputBufferSize ); + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog( + "\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + Status = NtStatus; + } + ExitFlag = TRUE; + break; + } + } + else if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the command did not complete successfully then + // exit the test app with the error. + // + + TpctlErrorLog( + "\n\tTpctl: The PERFSERVER command failed,returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + else + { + break; + } + } + } + // + // then reset the SEND control flags to the initial state + // and return. + // + Open[OpenInstance].PerfResultsCompleted = FALSE; + break; + + + case PERFCLIENT: + // + // If the IOCTL call failed then break out of while loop + // by setting the ExitFlag to true. + // + + if (( NtStatus != STATUS_SUCCESS ) && ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + ExitFlag = TRUE; + Status = NtStatus; + break; + } + // + // Wait for the RECEIVE event to be signaled telling us that + // the results are complete. + // + + for(;;) + { + Status = WaitForSingleObject( Open[OpenInstance].PerfEvent, + 2000 ); + if (Status == WAIT_TIMEOUT) + { + if (!ContinueLooping) // ctl-C was pressed + { + ContinueLooping = TRUE; // just quit this command + + NtStatus = NtDeviceIoControlFile( hFileHandle, + Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + IOCTL_TP_PERF_ABORT, + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer, + OutputBufferSize ); + + if (( NtStatus != STATUS_SUCCESS ) && + ( NtStatus != STATUS_PENDING )) + { + TpctlErrorLog( + "\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)NtStatus); + Status = NtStatus; + } + ExitFlag = TRUE; + break; + } + } + + else if ( Status != NO_ERROR ) + { + // + // If the wait for single object failed, then exit the + // test app with the error. + // + + TpctlErrorLog("\n\tWaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + ExitFlag = TRUE; + break; + } + else if ( IoStatusBlock2.Status != STATUS_SUCCESS ) + { + // + // If the receive did not completed successfully then + // exit the test app with the error. + // + + TpctlErrorLog("\n\tTpctl: The PERFCLIENT command failed, returned 0x%lx.\n", + (PVOID)IoStatusBlock2.Status); + ExitFlag = TRUE; + Status = IoStatusBlock2.Status; + break; + } + + // + // If here, status was succes. Print the send test results. + // + + else + { + TpctlPrintPerformResults( Open[OpenInstance].PerfResults); + + // + // then reset the RECEIVE control flags to the initial state + // and return. + // + + Open[OpenInstance].PerfResultsCompleted = FALSE; + break; + } + } + break; + + default: + TpctlErrorLog("\n\tTpctl: Invalid Command Entered.\n",NULL); + break; + + } // switch(); + + // + // Now zero out the input and output buffers to guarantee no + // random garbage on the next call. + // + + ZeroMemory( InputBuffer,InputBufferSize ); + + if (((( CmdCode == STRESS ) || ( CmdCode == STRESSSERVER )) || + ( CmdCode == SEND )) || ( CmdCode == RECEIVE )) + { + ZeroMemory( OutputBuffer2,OutputBufferSize2 ); + } + else if (( CmdCode != CMD_ERR ) && ( CmdCode != CMD_COMPLETED )) + { + ZeroMemory( OutputBuffer,OutputBufferSize ); + } + } + + // + // The test has ended either successfully or not, close any opened + // script files, deallocate the memory buffers, and return status. + // + + TpctlCloseScripts(); + + // Reset State + + GlobalFree( InputBuffer ); + GlobalFree( OutputBuffer ); + CloseHandle( Event ); + + return Status; +} + + + +VOID +TpctlGetEvents( + IN HANDLE FileHandle, + IN HANDLE InputBuffer, + IN DWORD InputBufferSize + ) +{ + DWORD Status; + HANDLE OutputBuffer; + DWORD OutputBufferSize = IOCTL_BUFFER_SIZE; + HANDLE Event; + IO_STATUS_BLOCK IoStatusBlock; + BOOL ReadFromEventQueue = FALSE; + + ContinueLooping = TRUE; + + OutputBuffer = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,OutputBufferSize ); + + if ( OutputBuffer == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: GlobalAlloc failed to alloc OutputBuffer: returned 0x%lx.\n", + (PVOID)Status); + return; + } + + Event = CreateEvent( NULL,FALSE,FALSE,NULL ); + + if ( Event == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: CreateEvent failed: returned 0x%lx.\n",(PVOID)Status); + GlobalFree( OutputBuffer ); + return; + } + + TpctlLog("\n",NULL); + + do + { + // + // We want to continuously call the driver for the + // event information, until the event queue is empty. + // this is represented by the IoStatusBlock.Status + // being STATUS_FAILURE. + // + +// !!NOT WIN32!! + + Status = NtDeviceIoControlFile( FileHandle, + Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + TP_CONTROL_CODE( GETEVENTS,IOCTL_METHOD ), + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer, + OutputBufferSize ); + + if ((( Status != TP_STATUS_NO_EVENTS ) && + ( Status != STATUS_SUCCESS )) && + ( Status != STATUS_PENDING )) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)Status); + } + else if ( Status == TP_STATUS_NO_EVENTS ) + { + TpctlLog("\tTpctl: Event Queue is empty.\tMAY_DIFFER\n",NULL); + } + else + { + Status = WaitForSingleObject( Event,0xFFFFFFFF ); + + if ( Status != STATUS_SUCCESS ) + { + TpctlErrorLog("\n\tTpctl: WaitForSingleObject failed: returned 0x%lx.\n", + (PVOID)Status); + } + else if ( IoStatusBlock.Status == TP_STATUS_NO_EVENTS ) + { + TpctlLog("\tTpctl: Event Queue is empty.\tMAY_DIFFER\n",NULL); + } + else if ( IoStatusBlock.Status == STATUS_SUCCESS ) + { + TpctlPrintEventResults( (PEVENT_RESULTS)OutputBuffer ); + } + else + { + TpctlErrorLog("\tTpctl: Error getting events from driver.\n",NULL); + } + } + } while ((( IoStatusBlock.Status == STATUS_SUCCESS ) && + ( ContinueLooping == TRUE )) && + ( Status == STATUS_SUCCESS )); + + GlobalFree( OutputBuffer ); + CloseHandle( Event ); + + return; +} + + + +VOID +TpctlPauseGo( + IN HANDLE FileHandle, + IN HANDLE InputBuffer, + IN DWORD InputBufferSize, + IN DWORD CmdCode + ) +{ + DWORD Status; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE OutputBuffer; + DWORD OutputBufferSize = IOCTL_BUFFER_SIZE; + ULONG TimedOut = 0; + + OutputBuffer = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,OutputBufferSize ); + + if ( OutputBuffer == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: GlobalAlloc failed to alloc OutputBuffer: returned 0x%lx.\n", + (PVOID)Status); + return; + } + + ContinueLooping = TRUE; + + do + { + // + // We want to continuously call the driver for PAUSE or GO + // until a Go is received or the Pause is acknowledged. + // + +// !!NOT WIN32!! + + Status = NtDeviceIoControlFile( FileHandle, + NULL, // Event, + NULL, // ApcRoutine + NULL, // ApcContext + &IoStatusBlock, + TP_CONTROL_CODE( CmdCode,IOCTL_METHOD ), + (PVOID)InputBuffer, + InputBufferSize, + (PVOID)OutputBuffer, + OutputBufferSize ); + + if ( Status != STATUS_SUCCESS ) + { + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile failed: returned 0x%lx.\n", + (PVOID)Status); + } + else if (((PREQUEST_RESULTS)OutputBuffer)->RequestStatus == TP_STATUS_TIMEDOUT ) + { + // + // The GO or PAUSE timed out, if we have looped ten times + // display the error to the user. + // + + if (( ++TimedOut % 12 ) == 0 ) // Two Minutes + { + if ( CmdCode == GO ) + { + printf("\n\tTpctl: GO timed out prior to receiving acknowledgment packet.\n", + NULL); + printf("\t Re-Sending...\n",NULL); + } + else + { + printf("\n\tTpctl: PAUSE timed out prior to receiving GO packet.\n",NULL); + printf("\t Re-Waiting...\n",NULL); + } + } + } + else if (((PREQUEST_RESULTS)OutputBuffer)->RequestStatus != NDIS_STATUS_SUCCESS ) + { + // + // The call to send a GO or GO_ACK packet failed, display the + // error to the user. + // + + if ( CmdCode == GO ) + { + TpctlErrorLog("\n\tTpctl: Failed to send the GO packet: returned %s.\n", + (PVOID)TpctlGetStatus(((PREQUEST_RESULTS)OutputBuffer)->RequestStatus)); + } + else + { + TpctlErrorLog("\n\tTpctl: Failed to send the acknowledgment packet: returned %s.\n", + (PVOID)TpctlGetStatus(((PREQUEST_RESULTS)OutputBuffer)->RequestStatus)); + } + + Status = ((PREQUEST_RESULTS)OutputBuffer)->RequestStatus; + } + else + { + // + // The GO or PAUSE has completed successfully, break + // out of the loop. + // + break; + } + } while (( ContinueLooping == TRUE ) && ( Status == NO_ERROR )); + + if (( Status != NO_ERROR ) || ( ContinueLooping == FALSE )) + { + // + // If we are reading commands from a script, assume + // that the failure should force the test to stop, + // therefore unload the script files, and reset the + // state all opens back to the initial state. + // + + if ( !ContinueOnError ) + { + TpctlResetAllOpenStates( FileHandle ); + TpctlCloseScripts(); + } + } + + GlobalFree( OutputBuffer ); + + return; +} + + + +VOID +TpctlLoadUnload( + IN DWORD CmdCode + ) +{ + SERVICE_STATUS ServiceStatus ; + SC_HANDLE ServiceControlMgrHandle ; + SC_HANDLE ServiceHandle ; + NTSTATUS Status ; + + // + // Open the service control manager + // + ServiceControlMgrHandle = OpenSCManager( NULL, NULL, GENERIC_EXECUTE ); + ServiceHandle = OpenService(ServiceControlMgrHandle, + GlobalCmdArgs.ARGS.DriverName, + SERVICE_START|SERVICE_STOP ); + + if ( CmdCode == LOAD ) + { + if ( !StartService( ServiceHandle, 0, NULL ) ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: Failed to load MAC driver : %s\n", + (PVOID)GlobalCmdArgs.ARGS.DriverName); + TpctlErrorLog("\tError Code Status = %ldL.\n",(PVOID)Status); + } + else + { + TpctlLog( "\n\tLoaded driver %s successfully\tMAY_DIFFER\n", + GlobalCmdArgs.ARGS.DriverName ); + } + } + else + { + if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus ) ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tTpctl: Failed to unload MAC driver : %s\n", + (PVOID)GlobalCmdArgs.ARGS.DriverName); + TpctlErrorLog("\tError Code Status = %ldL with a Service State of ",(PVOID)Status); + TpctlErrorLog("%ld\n",(PVOID)ServiceStatus.dwCurrentState); + } + else + { + TpctlLog( "\n\tUnloaded driver %s successfully.\tMAY_DIFFER\n", + GlobalCmdArgs.ARGS.DriverName ); + } + } + +} + + + +VOID +TpctlQueryStatistics( + IN PUCHAR DriverName, + IN NDIS_OID OID, + IN PUCHAR StatsBuffer, + IN DWORD BufLen + ) +{ + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + ANSI_STRING DrvrNameString; + UNICODE_STRING UnicodeDrvrName; + DWORD NameLength; + LPSTR NameBuffer; + NTSTATUS Status; + PUCHAR TmpBuf[265]; + + NameLength = strlen( DriverName ) + 1 + 8; + + NameBuffer = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, + NameLength ); + + if ( NameBuffer == NULL ) + { + Status = GetLastError(); + TpctlErrorLog("\n\tGlobalAlloc failed to alloc NameBuffer: returned 0x%lx.\n", + (PVOID)Status); + return; + } + + ZeroMemory( NameBuffer, NameLength ); + + memcpy( NameBuffer,"\\Device\\",8 ); + memcpy( NameBuffer + 8, DriverName, NameLength - 8 ); + +// !!NOT WIN32!! + + RtlInitString( &DrvrNameString, NameBuffer ); + +// !!NOT WIN32!! + + RtlAnsiStringToUnicodeString( &UnicodeDrvrName, &DrvrNameString, TRUE ); + +// !!NOT WIN32!! + + InitializeObjectAttributes( &ObjectAttributes, + &UnicodeDrvrName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + +// !!NOT WIN32!! + + Status = NtOpenFile(&FileHandle, + SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_ALERT ); + + if (Status != STATUS_SUCCESS ) + { + TpctlErrorLog("\n\tTpctl: NtOpenFile returned %lx\n\n", (PVOID)Status); + return; + } + +// !!NOT WIN32!! + + Status = NtDeviceIoControlFile( FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_NDIS_QUERY_GLOBAL_STATS, + (PVOID)&OID, + sizeof( NDIS_OID ), + (PVOID)TmpBuf, //StatsBuffer, + 256); //Buflen + + if (( Status != STATUS_SUCCESS ) && + ( IoStatusBlock.Status != STATUS_SUCCESS )) + { + + TpctlErrorLog("\n\tTpctl: NtDeviceIoControlFile returned %lx\n\n", + (PVOID)IoStatusBlock.Status); + return; + } + + TpctlLog("\n\tOID 0x%8.8lx ", (PVOID)OID); + TpctlLog("len %d ", (PVOID)IoStatusBlock.Information ); + TpctlLog("value %u\tMAY_DIFFER\n\n", (PVOID)TmpBuf[0]); + +// !!NOT WIN32!! + + RtlFreeUnicodeString( &UnicodeDrvrName ); + +// !!NOT WIN32!! + + Status = NtClose( FileHandle ); +} + + +BOOL +Disable( + IN DWORD argc, + IN LPSTR argv[] + ) +{ + UINT EnvCounter1 = 0 , EnvCounter2 = 0 ; + DWORD i; + CHAR TmpBuffer[256]; + + ZeroMemory( TmpBuffer, 256 ); + + // + // Detected command Disable + // + for( i = 1; i < argc; i++ ) + { + EnvCounter1++; + + ZeroMemory ( TmpBuffer, sizeof( TmpBuffer ) ); + strncpy( TmpBuffer, argv[i], strlen( argv[i] ) ); + + if ( getenv( TmpBuffer ) != NULL ) + { + EnvCounter2++; + } + } + + // + // If all the environment variables have been enabled + // we must re-enable the tool. Setting of all the + // enviornment variables indicates that all those + // modes are supported and there is no need to disable + // the tool. If has been disabled by a previous disable + // it would require an enable to activate the tool + // + if ( (EnvCounter1 == EnvCounter2) && (EnvCounter1 != 0) ) + { + printf("\n\tSupport for "); + for( i = 1; i < argc; i++ ) + { + if ( i == (argc-1) ) + { + printf("%s ", argv[i] ); + } + else + { + if ( (i%2) == 0 ) + { + printf("\n\t"); + } + printf("%s, ", argv[i] ); + } + } + printf("modes has been detected.\n\tTPCTL has not been disabled.\n\n"); + return FALSE; + } + + // + // Disable TPCTL + // + ToolActive = FALSE; + return TRUE; +} + + diff --git a/private/ntos/ndis/testprot/tpctl/tpctl.h b/private/ntos/ndis/testprot/tpctl/tpctl.h new file mode 100644 index 000000000..129562c1f --- /dev/null +++ b/private/ntos/ndis/testprot/tpctl/tpctl.h @@ -0,0 +1,751 @@ +// ----------------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpctl.h +// +// Abstract: +// +// This module defines the external definitions used for the MAC Tester +// +// Author: +// +// Tom Adams (tomad) 11-May-1991 +// +// Revision History: +// +// 11-May-1991 tomad +// Created +// +// 4-27-94 timothyw +// Added performance test; CPP style comments +// 5-18-94 +// Added globvars; fixed warnings +// 6-08-94 +// chgs for client/server model, perf tests +// +// ----------------------------------- + +#include "tp_ndis.h" +#include "common.h" + +// +// +// + +extern CMD_ARGS GlobalCmdArgs; + +extern LPSTR GlobalBuf; + +extern BOOL Verbose; + +extern BOOL CommandsFromScript; + +extern BOOL CommandLineLogging; + +extern BOOL RecordToScript; + +extern HANDLE CommandLineLogHandle; + +extern HANDLE ScriptRecordHandle; + +extern CHAR RecordScriptName[TPCTL_MAX_PATHNAME_SIZE]; + +extern BOOL ExitFlag; + +extern BOOL ContinueLooping; + +extern INT TpctlSeed; + +// +// Script Control is used to keep track of where in a script file the +// application is, and where to log the next set of results in the +// respective log file. +// + +typedef struct _SCRIPTCONTROL { + LPSTR ScriptFile; + BOOL IsLowestLevel; + LPBYTE Buffer; + DWORD Length; + + DWORD BufIndex; + HANDLE LogHandle; + LPSTR LogFile; +} SCRIPTCONTROL, * PSCRIPTCONTROL; + +// +// Scripts is an array of 10 script control structures allowing recursion +// of upto ten script files at any one time. Any more then 10 and an error +// occurs resulting in the closing of all upper recursive levels of script +// files. +// + +#define TPCTL_MAX_SCRIPT_LEVELS 10 + +extern SCRIPTCONTROL Scripts[TPCTL_MAX_SCRIPT_LEVELS+1]; + +extern DWORD ScriptIndex; + +// +// Initialize the script array. +// + +// ------ +// +// VOID +// TpctlInitializeScripts( +// VOID +// ); +// +// ----- + +#define TpctlInitializeScripts() { \ + DWORD i; \ + ScriptIndex = 0xFFFFFFFF; \ + for (i=0;i<TPCTL_MAX_SCRIPT_LEVELS+1;i++) { \ + Scripts[i].ScriptFile = NULL; \ + Scripts[i].IsLowestLevel = FALSE; \ + Scripts[i].Buffer = NULL; \ + Scripts[i].Length = 0; \ + Scripts[i].BufIndex = 0; \ + Scripts[i].LogHandle = (HANDLE)-1; \ + Scripts[i].LogFile = NULL; \ + } \ +} + +// +// TPCTLCLOSESCRIPTS close any and all script files that +// are currently opened. +// + +// ----- +// +// VOID +// TpctlCloseScripts( +// VOID +// ); +// +// ----- + +#define TpctlCloseScripts() { \ + if ( CommandsFromScript == TRUE ) { \ + while ( ScriptIndex != (ULONG)-1 ) { \ + TpctlUnLoadFiles(); \ + } \ + } \ +} + +// +// PRINT_DIFF_FLAG will print the diff flag string S into the buffer B +// if we are printing the results to a logfile. +// + +// ----- +// +// VOID +// ADD_DIFF_FLAG( +// LPSTR B +// LPSTR S +// ); +// +// ----- + +#define ADD_DIFF_FLAG( B,S ) { \ + if (( CommandsFromScript ) || ( CommandLineLogging )) { \ + B += (BYTE)sprintf(B,"\t%s",S); \ + } \ + TmpBuf += (BYTE)sprintf(TmpBuf,"\n"); \ +} + +#define ADD_SKIP_FLAG( B,S ) ADD_DIFF_FLAG( B,S ) + +// +// Reset all opens to their initial state. +// + +// ----- +// +// VOID +// TpctlResetAllOpenStates( +// HANDLE fh +// ); +// +// ----- + +#define TpctlResetAllOpenStates( fh ) { \ + DWORD i; \ + if ( CommandsFromScript ) { \ + TpctlErrorLog("\n\tTpctl: Resetting the state of all Open Instances.\n",NULL); \ + for ( i = 0 ; i < NUM_OPEN_INSTANCES ; i++ ) { \ + TpctlResetOpenState( &Open[i],fh ); \ + } \ + } \ +} + +// +// Parse Tables are the structures used to contain each of the possible +// argument names for a given command, and their value. +// + +typedef struct _ParsedIntTable { + LPSTR FieldName; + DWORD FieldValue; +} PARSETABLE, *PPARSETABLE; + +// +// Paramtypes are the different types of parameters that may be parsed +// by the ParseOptions routine for each command. +// + +// +// STARTCHANGE +// +typedef enum { + Integer, + String, + ParsedInteger, +// Address2, // Accomodate 802.3, 802.4, 802.5, FDDI addresses + Address4, // Accomodate 802.4, 802.5 addresses + Address6, // Accomodate 802.3, 802.4, 802.5, FDDI addresses +// Address2or6 // Conjugate type in which addresses can be 2 or 6 octets +} PARAMTYPES; +// +// STOPCHANGE +// + + +// +// The Test Options structures is used by the ParseOptions routine to +// load the default value for a given argument, set up the prompt for +// the argument and prompt the user for the argument. If the command is +// entered from a script file the Test Options structures is used to +// determine the Argument names or abbreviations and then stores the +// values in their proper destinations. +// + +typedef struct _TestOptions { + DWORD OptionNumber; + LPSTR TestPrompt; + LPSTR ArgName; + LPSTR ArgNameAbbr; + BOOL ArgValueSet; + PARAMTYPES TestType; + DWORD IntegerDefault; + LPSTR StringDefault; + PPARSETABLE ParsedIntTable; + DWORD ParsedIntTableSize; + PVOID Destination; +} TESTPARAMS, *PTESTPARAMS; + +// +// Array entries for the Events in the Open Block +// + +typedef enum { + TPCONTROL, + TPSTRESS, + TPSEND, + TPRECEIVE, + TPPERF +} TPEVENT_TYPE; + +// +// Multicast Address struct used to create a list of all the +// address set on a given open. +// + +typedef struct _MULT_ADDR { + struct _MULT_ADDR *Next; + BYTE MulticastAddress[ADDRESS_LENGTH]; +} MULT_ADDR, *PMULT_ADDR; + +// +// the Open Block holding the info about the state of the open, +// particulars about the card opened, and the control structs for +// each of the given test types. +// + +typedef struct _OPEN_BLOCK { + DWORD Signature; + UCHAR OpenInstance; + BOOL AdapterOpened; + NDIS_MEDIUM MediumType; + DWORD NdisVersion; + + LPBYTE AdapterName; + BYTE AdapterAddress[ADDRESS_LENGTH]; + PENVIRONMENT_VARIABLES EnvVars; + + BOOL EventThreadStarted; + HANDLE Events[5]; + + BOOL Stressing; + PCMD_ARGS StressArgs; + IO_STATUS_BLOCK StressStatusBlock; + HANDLE StressEvent; + PSTRESS_RESULTS StressResults; + BOOL StressResultsCompleted; + BOOL StressClient; + BOOL Ack10; + + BOOL Sending; + PCMD_ARGS SendArgs; + IO_STATUS_BLOCK SendStatusBlock; + HANDLE SendEvent; + PSEND_RECEIVE_RESULTS SendResults; + BOOL SendResultsCompleted; + + BOOL Receiving; + IO_STATUS_BLOCK ReceiveStatusBlock; + HANDLE ReceiveEvent; + PSEND_RECEIVE_RESULTS ReceiveResults; + BOOL ReceiveResultsCompleted; + + IO_STATUS_BLOCK PerfStatusBlock; + HANDLE PerfEvent; + PPERF_RESULTS PerfResults; + BOOL PerfResultsCompleted; + + DWORD PacketFilter; + + DWORD LookaheadSize; + PMULT_ADDR MulticastAddresses; + ULONG NumberMultAddrs; + BYTE FunctionalAddress[FUNCTIONAL_ADDRESS_LENGTH]; + + BYTE GroupAddress[FUNCTIONAL_ADDRESS_LENGTH]; +} OPEN_BLOCK, *POPEN_BLOCK; + +extern OPEN_BLOCK Open[NUM_OPEN_INSTANCES]; + +#define OPEN_BLOCK_SIGNATURE 0x12121212 + +// +// TPCTL.C function prototypes +// + +DWORD +TpctlInitializeOpenArray( + VOID + ); + +VOID +TpctlFreeOpenArray( + VOID + ); + +DWORD +TpctlOpenTpdrvr( + IN OUT PHANDLE lphFileHandle + ); + +VOID +TpctlCloseTpdrvr( + IN HANDLE hFileHandle + ); + +DWORD +TpctlStartEventHandlerThread( + IN POPEN_BLOCK Open + ); + +VOID +TpctlStopEventHandlerThread( + IN POPEN_BLOCK Open + ); + +DWORD +TpctlEventHandler( + IN LPVOID Open + ); + +BOOL +TpctlCtrlCHandler( + IN DWORD CtrlType + ); + +// +// +// + +DWORD +TpctlRunTest( + IN HANDLE hFileHandle + ); + +VOID +TpctlGetEvents( + IN HANDLE FileHandle, + IN HANDLE InputBuffer, + IN DWORD InputBufferSize + ); + +VOID +TpctlPauseGo( + IN HANDLE FileHandle, + IN HANDLE InputBuffer, + IN DWORD InputBufferSize, + IN DWORD CmdCode + ); + +DWORD +TpctlResetOpenState( + IN POPEN_BLOCK Open, + IN HANDLE FileHandle + ); + +VOID +TpctlLoadUnload( + IN DWORD CmdCode + ); + +VOID +TpctlQueryStatistics( + IN PUCHAR DriverName, + IN NDIS_OID OID, + IN PUCHAR StatsBuffer, + IN DWORD BufLen + ); + +BOOL +Disable( + IN DWORD argc, + IN LPSTR argv[] + ); + +// +// +// + + +VOID +TpctlPrintResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ); + +VOID +TpctlPrintQueryInfoResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ); + +VOID +TpctlPrintSetInfoResults( + PREQUEST_RESULTS Results, + DWORD CmdCode, + NDIS_OID OID + ); + +VOID +TpctlPrintSendResults( + PSEND_RECEIVE_RESULTS Results + ); + +VOID +TpctlPrintReceiveResults( + PSEND_RECEIVE_RESULTS Results + ); + +VOID +TpctlPrintPerformResults( + PPERF_RESULTS Results + ); + +VOID +TpctlPrintStressResults1( + IN PSTRESS_RESULTS Results, + IN BOOL Ack10 + ); + +VOID +TpctlPrintStressResults( + PSTRESS_RESULTS Results, + IN BOOL Ack10 + ); + +VOID +TpctlPrintEventResults( + PEVENT_RESULTS Event + ); + +VOID +TpctlZeroStressStatistics( + PSTRESS_RESULTS Results + ); + +DWORD +TpctlLog( + LPSTR String, + PVOID Input + ); + +DWORD +TpctlErrorLog( + LPSTR String, + PVOID Input + ); + +DWORD +TpctlScriptLog( + LPSTR String, + PVOID Input + ); + +DWORD +TpctlCmdLneLog( + LPSTR String, + PVOID Input + ); + +// +// CMD.C function prototypes +// + +DWORD +TpctlParseCommandLine( + IN WORD argc, + IN LPSTR argv[] + ); + +VOID +TpctlUsage( + VOID + ); + +VOID +TpctlHelp( + LPSTR Command + ); + +DWORD +TpctlLoadFiles( + IN LPSTR ScriptFile, + IN LPSTR LogFile + ); + + +VOID +TpctlUnLoadFiles( + VOID + ); + + +HANDLE +TpctlOpenLogFile( + VOID + ); + + +VOID +TpctlCloseLogFile( + VOID + ); + + +HANDLE +TpctlOpenScriptFile( + VOID + ); + + +VOID +TpctlCloseScriptFile( + VOID + ); + +DWORD +TpctlReadCommand( + IN LPSTR Prompt, + OUT LPSTR Response, + IN DWORD MaximumResponse + ); + + +BOOL +TpctlParseCommand( + IN LPSTR CommandLine, + OUT LPSTR Argv[], + OUT PDWORD Argc, + IN DWORD MaxArgc + ); + + +VOID +TpctlPrompt( + LPSTR Prompt, + LPSTR Buffer, + DWORD BufferSize + ); + + +VOID +TpctlLoadLastEnvironmentVariables( + DWORD OpenInstance + ); + + +VOID +TpctlSaveNewEnvironmentVariables( + DWORD OpenInstance + ); + +VOID +TpctlPerformRegistryOperation( + IN PCMD_ARGS CmdArgs + ); +BOOL +TpctlInitCommandBuffer( + IN OUT PCMD_ARGS CmdArgs, + IN DWORD CmdType + ); + + +LPSTR +TpctlGetEventType( + TP_EVENT_TYPE TpEventType + ); + + +LPSTR +TpctlGetStatus( + NDIS_STATUS GeneralStatus + ); + + +DWORD +TpctlGetCommandCode( + LPSTR Argument + ); + + +LPSTR +TpctlGetCommandName( + LPSTR Command + ); + +LPSTR +TpctlGetCmdCode( + DWORD CmdCode + ); + + +VOID +TpctlCopyAdapterAddress( + DWORD OpenInstance, + PREQUEST_RESULTS Results + ); + +VOID +TpctlRecordArguments( + IN TESTPARAMS Options[], + IN DWORD OptionTableSize, + IN DWORD argc, + IN LPSTR argv[TPCTL_MAX_ARGC] + ); + +LPSTR +TpctlEnumerateRegistryInfo( + IN PUCHAR TmpBuf, + IN PUCHAR DbaseName, + IN PUCHAR SubKeyName, + IN PUCHAR ValueName, + IN DWORD ReadValueType, + IN PUCHAR ReadValue, + IN DWORD ReadValueSize + ); + +LPSTR +TpctlGetValueType( + IN DWORD ValueType + ); + + +// +// PARSE.C Function Prototypes +// + +DWORD +TpctlParseArguments( + IN TESTPARAMS Options[], + IN DWORD TestSize, + IN DWORD ArgC, + IN LPSTR ArgV[] + ); + + +BOOL +TpctlParseSetInfoArguments( + IN OUT DWORD *ArgC, + IN OUT LPSTR ArgV[], + IN OUT DWORD *tmpArgC, + IN OUT LPSTR tmpArgV[] + ); + + +DWORD +TpctlParseAddress( + IN BYTE Buffer[], + OUT PDWORD Ret, + IN DWORD OpenInstance, + IN DWORD AddressLength + ); + + +VOID +Dump_Desired_PacketFilter( + LPSTR Buffer, + DWORD PacketFilter + ); + + +VOID +Dump_Information_Class( + LPSTR Buffer, + DWORD InfoClass + ); + + +VOID +Dump_Ndis_Medium( + LPSTR Buffer, + DWORD Medium + ); + +// +// GLOBALS.C Function Prototypes +// + + +PVOID +TpctlParseGlobalVariable( + IN BYTE Buffer[], + IN PARAMTYPES reqtype + ); + +VOID +TpctlInitGlobalVariables( + VOID + ); + + +DWORD +TpctlParseSet( + IN DWORD ArgC, + IN LPSTR ArgV[] + ); + + +// functions from cpuperf.c + + +VOID CpuUsageInit(VOID); + + +ULONG CpuUsageGetData(PULONG *KernPercent, + ULONG NumCpus); diff --git a/private/ntos/ndis/testprot/tpdiff.new/makefile b/private/ntos/ndis/testprot/tpdiff.new/makefile new file mode 100644 index 000000000..99bdba8ee --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff.new/makefile @@ -0,0 +1,11 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def + + +cleanup: + if exist *.bak del *.bak + if exist build.* del build.* diff --git a/private/ntos/ndis/testprot/tpdiff.new/sources b/private/ntos/ndis/testprot/tpdiff.new/sources new file mode 100644 index 000000000..7667196a8 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff.new/sources @@ -0,0 +1,63 @@ +!IF 0 + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + +!ENDIF + + +# COMMENT: The build "SOURCE" file follows the same syntax as a regular +# makefile. BUILD includes the SOURCES file into the makefile.def +# which is to be found in $(BASEDIR)\public\oak\bin. After that +# has been completed, it passes it on to nmake + + +MAJORCOMP=TESTPROT +MINORCOMP=TPDIFF + +TARGETNAME=tpdiff +TARGETPATH=obj +TARGETTYPE=PROGRAM + +C_DEFINES=-DWIN32 + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\libc.lib \ + $(BASEDIR)\public\sdk\lib\*\ntdll.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + + +SOURCES=tpdiff.c + + +# +# 386 +# +386_WARNING_LEVEL=-W3 +386_STDCALL=1 +386_OPTIMIZATION=/Fc +MAX_ID_LENGTH=/H128 + +# +# MIPS +# +MIPS_FLAGS=-D_stdcall= + +# +# ALPHA +# +ALPHA_FLAGS=-D_stdcall= + + +UMTYPE=console +NTDEBUG=ntsd diff --git a/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c new file mode 100644 index 000000000..3141ef7c5 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.c @@ -0,0 +1,2527 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tpdiff.c + +Abstract: + + This is the main component of the NDIS 3.0 MAC Tester log file program. + +Author: + + Sanjeev Katariya (sanjeevk) 3-May-1993 + +Revision History: + + created + +--*/ + + +// +// Includes +// +#include <windows.h> +#include <stdio.h> +#include <string.h> +#include <process.h> +#include <ctype.h> +#include <stdlib.h> +#include <malloc.h> +#include <math.h> +#include "tpdiff.h" + + +// +// Global Variables +// +CHAR *Keywords[] = { + "-SECTION_START-", + "-SECTION_END-" , + "-OPTIONALS-" , + "-TOKEN_MATCH-" , + "-SECTION_DESC-" +}; + +PCHAR SummaryBuffer; + + +/* + ******************************************************************************** + * * + * General Program Considerations: * + * * + * This program has been designed for generic section matching. However, since * + * the second file for its current use is marked GOLDEN, certain changes have * + * been introduced in line comparison and result printing to account for * + * special type of file. * + * * + * * + ******************************************************************************** +*/ + + +/********************************** main():start ***********************************************/ + + +VOID _cdecl +main( + INT argc, + CHAR *argv[] + ) +{ + + FILE *IoFile; + FILE *DiffTxtFile; + PCHAR *FileList = &argv[1]; + PCHAR Difference_FileName = ( argc == 4 ) ? argv[3] : "DIFF.TXT" ; + PCHAR TmpSummaryBuffer; + MFILE FirstFile, SecondFile; + UINT NumberOfComparisons = 0 ; + UINT NumberOfFilesCompared = 0; + UINT i,j; + ULONG TotalDifferenceCount = 0; + BOOL InputFromFile = FALSE; + ULONG FileOpenErrors = 0; + + + // + // 1. CHECK INCOMING ARGUMENT SYNTAX + // + + if ( ( argc < 3 ) || ( argc > 4 ) ) { + + Usage(); + exit( -1 ); + + } else { + + printf( "\nMAC NDIS 3.0 Tester - Comparator Tool Version 1.0.2\n\n" ); + + } + + + // + // 2. CHECK IF THE FILE LIST TO BE GENERATED IS TO BE EXTRACTED FROM THE COMMAND + // LINE OR FROM A FILE + // + + if ( !strncmp( argv[1], "-f", 2 ) || + !strncmp( argv[1], "-F", 2 ) ) { + + CHAR Buffer[2*MAX_LINE_SIZE]; + + // + // 2.A INDICATE THE LIST IS TO BE GENERATED FROM A FILE + // + InputFromFile = TRUE; + + + // + // 2.B OPEN THE FILE + // + + if ( (IoFile = fopen( argv[2], "r" )) == NULL ) { + + printf( "Could not open the primary log list file: %s\n", argv[2] ); + Usage(); + exit( -1 ); + + } + + + // + // 2.C GENERATE THE FILE PAIRS TO BE ANALYZED + // + + // + // 2.C.1 DETERMINE THE NUMBER OF VALID FILE PAIRS + // + + while( !feof( IoFile ) ) { + + memset( Buffer, 0, sizeof(Buffer) ); + if ( ( fgets( Buffer, sizeof( Buffer ), IoFile ) != NULL ) && + ( strlen( Buffer ) > 2 ) ) { + NumberOfComparisons++; + } + + } + + + // + // 2.C.2 ALLOCATE THE APPROPRIATE SIZED BLOCK + // + + FileList = (PCHAR *)malloc( (NumberOfComparisons*2)*sizeof( PCHAR ) ); + if ( FileList == (PCHAR *)NULL ) { + printf("The system has run out of memory resources. Unable to run this program.\n"); + exit( -1 ); + } else { + memset( FileList, 0, (NumberOfComparisons*2)*sizeof( PCHAR ) ); + } + + + // + // 2.C.2 AND BUILD THE FILE ARRAY LIST + // + + i = j = 0; + fseek( IoFile, 0, SEEK_SET ); + while ( !feof( IoFile ) ) { + + // + // Get the next line out of the file list file + // + memset( Buffer, 0, sizeof(Buffer) ); + if ( ( fgets( Buffer, sizeof( Buffer ), IoFile ) != NULL ) && + ( strlen( Buffer ) > 2 ) ) { + + // + // Replace the newline Character with a NULL Character + // + *(strchr( Buffer, '\n')) = '\0'; + + // + // Extract the log file name pairs + // + if ( !GetFilePair( &FileList[j*2], &FileList[(j*2)+1], Buffer ) ) { + + printf("An error occurred determining the file pair at line %d in the file list: %s\n", + (i+1), argv[2] ); + exit( -1 ); + + } else { + + // + // Increment the file list array counter + // + j++; + + } + + } + + // + // Increment the file line counter + // + i++; + + } + + + // + // 2.C.3 CLOSE THE FILE + // + fclose( IoFile ); + + + } else { + + NumberOfComparisons = 1; + + // + // The FileList is pre-initialized to the command line arguments and thus we + // simply need to set the file pair comparison count + // + + } + + + // + // 3. INITIALIZE THE SUMMARY BUFFER + // + SummaryBuffer = calloc( NumberOfComparisons, MAX_LINE_SIZE ); + if ( SummaryBuffer == (PCHAR)NULL ) { + + printf("The system has run out of memory resources for this program\n"); + exit( -1 ); + + } else { + + TmpSummaryBuffer = SummaryBuffer ; + + } + + // + // 4. OBTAIN THE DIFFERENCE FILE NAME INTO WHICH THE RESULTS WILL BE LOGGED + // OR USE THE DEFAULT DIFF.TXT. + // + + DiffTxtFile = fopen( Difference_FileName, "w+" ); + + if ( DiffTxtFile == (FILE *)NULL ) { + + printf( "Unable to open the difference text file %s for logging the results.\n", Difference_FileName ); + exit( -1 ); + + } else { + + fprintf( DiffTxtFile, "\n\n" ); + + } + + + // + // 5. COMPARE THE FILE PAIRS + // + + fprintf( DiffTxtFile, "__________DETAILS_LOG__________\n\n" ); + fprintf( stdout, "__________DETAILS_LOG__________\n\n" ); + for( i = 0; i < NumberOfComparisons; i++ ) { + + memset( &FirstFile , 0, sizeof( MFILE ) ); + memset( &SecondFile, 0, sizeof( MFILE ) ); + + FirstFile.FileName = FileList[2*i]; + SecondFile.FileName = FileList[(2*i)+1]; + + fprintf( stdout, "Comparing files %s and %s\n", FirstFile.FileName, SecondFile.FileName ); + + // + // 5.A OPEN THE FILE PAIR + // + if ( OpenFiles( &FirstFile, FileList[2*i], &SecondFile, FileList[(2*i)+1] ) ) { + + ULONG OldDifferenceCount = TotalDifferenceCount; + + fprintf( DiffTxtFile, "\n\n**Comparing %s and %s\n\n", FirstFile.FileName, SecondFile.FileName ); + + NumberOfFilesCompared++; + + + // + // 5.B COMPARE THEM + // + CompareFiles( &FirstFile, &SecondFile, DiffTxtFile, &TotalDifferenceCount ); + + + // + // 5.C LOG THE RESULTS OF THE COMPARISON INTO THE DIFFERENCE FILE + // + fprintf( DiffTxtFile, "\n\n--TPDIFF %s, %s ERROR(S): %u\n", + FirstFile.FileName, SecondFile.FileName, (TotalDifferenceCount-OldDifferenceCount) ); + + sprintf( TmpSummaryBuffer, "TPDIFF %s, %s ERROR(S): %u\n", + FirstFile.FileName, SecondFile.FileName, (TotalDifferenceCount-OldDifferenceCount) ); + TmpSummaryBuffer += strlen( TmpSummaryBuffer ); + + + } else { + + + fprintf( DiffTxtFile, "\n\n--TPDIFF %s, %s", FirstFile.FileName, SecondFile.FileName ); + + if ( FirstFile.FileP == (FILE *)NULL ) { + + fprintf( DiffTxtFile, "\tUnable to open file %s\n", FirstFile.FileName ); + + } + + if ( SecondFile.FileP == (FILE *)NULL ) { + + fprintf( DiffTxtFile, "\tUnable to open file %s\n", SecondFile.FileName ); + + } + + + sprintf( TmpSummaryBuffer, "TPDIFF %s, %s resulted in a file open error\n", + FirstFile.FileName, SecondFile.FileName ); + + FileOpenErrors++; + + TmpSummaryBuffer += strlen( TmpSummaryBuffer ); + + } + + // + // 5.D CLOSE THE FILE PAIR + // + CloseFiles( FirstFile, SecondFile ); + FirstFile.FileName = (PCHAR)NULL; + SecondFile.FileName = (PCHAR)NULL; + FirstFile.FileP = (FILE *)NULL; + SecondFile.FileP = (FILE *)NULL; + + // + // 5.E FREE THE FILE PAIR FROM THE LIST + // + free( FileList[2*i] ); + free( FileList[(2*i)+1] ); + + + } + fprintf( DiffTxtFile, "\n__________END_DETAILS_LOG__________\n\n" ); + fprintf( stdout, "\n__________END_DETAILS_LOG__________\n\n" ); + + // + // 6. LOG THE CUMMULATIVE RESULTS AND SUMMARY INTO THE DIFFERENCE FILE AND STDOUT + // + + fprintf( DiffTxtFile, "\n\n__________SUMMARY_LOG__________\n\n" ); + fprintf( DiffTxtFile, SummaryBuffer ); + fprintf( DiffTxtFile, "\n__________END_SUMMARY_LOG__________\n\n" ); + fprintf( DiffTxtFile, "\n\n__________CUMMALATIVE_RESULTS_LOG__________\n\n" ); + fprintf( DiffTxtFile, "COMPARED %d FILE PAIR(S)\n" , NumberOfFilesCompared ); + fprintf( DiffTxtFile, "TOTAL NUMBER OF DIFFERENCES ENCOUNTERED: %u\n", TotalDifferenceCount ); + fprintf( DiffTxtFile, "TOTAL NUMBER OF FILE OPEN ERRORS : %u\n", FileOpenErrors ); + fprintf( DiffTxtFile, "\n__________END_CUMMALATIVE_RESULTS_LOG__________\n\n" ); + + fprintf( stdout, "\n\n__________SUMMARY_LOG__________\n\n" ); + fprintf( stdout, SummaryBuffer ); + fprintf( stdout, "\n__________END_SUMMARY_LOG__________\n\n" ); + fprintf( stdout, "\n\n__________CUMMALATIVE_RESULTS_LOG__________\n\n" ); + fprintf( stdout, "COMPARED %d FILE PAIR(S)\n" , NumberOfFilesCompared ); + fprintf( stdout, "TOTAL NUMBER OF DIFFERENCES ENCOUNTERED: %u\n", TotalDifferenceCount ); + fprintf( stdout, "TOTAL NUMBER OF FILE OPEN ERRORS : %u\n", FileOpenErrors ); + fprintf( stdout, "\n__________END_CUMMALATIVE_RESULTS_LOG__________\n\n" ); + + + // + // 7. CLOSE THE DIFFERENCE FILE AND PERFORM ANY REMAINING CLEANUP + // + + fclose( DiffTxtFile ); + free( SummaryBuffer ); + if ( InputFromFile ) { + + free( FileList ); + + } + +} + +/********************************** main():end *************************************************/ + + + + + +VOID +Usage() +{ + + printf( "\n\tUsage: TPDIFF LOG_FILE GOLDEN_LOG_FILE [DIFFS_FILE]\n\n" ); + + + printf( "\tWhere:\n\n"); + + + printf( "\tLOG_FILE - is the log file that is to be verified\n" ); + printf( "\t for correctness.\n" ); + printf( "\tKNOWN_LOG_FILE - is the known good log file that will be\n" ); + printf( "\t used to verify the log file.\n" ); + printf( "\tDIFFS_FILE - is the file the differences, if any exist,\n" ); + printf( "\t between the log files and the known good log\n" ); + printf( "\t files will be written to. If no file name is\n" ); + printf( "\t given the differences will be printed to the\n" ); + printf( "\t default file DIFF.TXT and the console.\n" ); + printf( "\t\t- OR -\n\n" ); + + + printf( "\tTPDIFF -F LOG_FILE_LIST [DIFFS_FILE]\n\n" ); + + + printf( "\tWhere:\n\n" ); + + + printf( "\tLOG_FILE_LIST - is a file containing pairs of log file\n" ); + printf( "\t names and known good log file names. The\n" ); + printf( "\t pairs of file names must be on the same line\n" ); + printf( "\t in the file\n" ); + printf( "\tDIFFS_FILE - is the file the differences, if any exist,\n" ); + printf( "\t between the log files and the known good log\n" ); + printf( "\t files will be written to. If no file name is\n" ); + printf( "\t given the differences will be printed to the\n" ); + printf( "\t default file DIFF.TXT and the console.\n" ); + +} + + +BOOLEAN +GetFilePair( + PCHAR *FirstFile, + PCHAR *SecondFile, + PCHAR Buffer + ) +{ + + PCHAR Token[2] ; + PCHAR Seperators = " ,\t" ; + UINT TokenLength[2] ; + + + // + // Extract the log file names from the string buffer + // + Token[0] = strtok( Buffer, Seperators ); + + if ( Token[0] != (PCHAR)NULL ) { + + Token[1] = strtok( NULL, Seperators ); + + if ( Token[1] == (PCHAR)NULL ) { + + printf("The first log file name is:\t%s\nHowever the program was unable to determine the second log file name.\n", + Token[0]); + return FALSE; + + } else { + + TokenLength[0] = strlen( Token[0] ); + TokenLength[1] = strlen( Token[1] ); + + } + + } else { + + printf("Unable to determine the first log file name.\n"); + return FALSE; + + } + + + // + // Create storage on the file list for the file names + // + *FirstFile = malloc( (TokenLength[0]+1)*sizeof(CHAR) ); + *SecondFile = malloc( (TokenLength[1]+1)*sizeof(CHAR) ); + + if ( *FirstFile == (PCHAR)NULL || *SecondFile == (PCHAR)NULL ) { + + printf("The system has run out of memory resources for this program\n"); + free( *FirstFile ); + free( *SecondFile ); + exit( -1 ); + + } + + // + // Copy the file names into the allocated storage + // + memset( *FirstFile, 0, TokenLength[0]+1 ); + memset( *SecondFile, 0, TokenLength[1]+1 ); + strncpy( *FirstFile, Token[0], TokenLength[0] ); + strncpy( *SecondFile, Token[1], TokenLength[1] ); + + // + // And return success + // + return TRUE; + +} + + + +BOOLEAN +OpenFiles( + PMFILE FirstFile, + PCHAR FirstFileName, + PMFILE SecondFile, + PCHAR SecondFileName + ) +{ + // + // Open the two files + // + FirstFile->FileP = fopen( FirstFileName, "r" ); + SecondFile->FileP = fopen( SecondFileName, "r" ); + + // + // If there was an error while opening functionally report it + // + if ( ( FirstFile->FileP == (FILE *)NULL ) || + ( SecondFile->FileP == (FILE *)NULL ) ) { + + return FALSE; + + } + + return TRUE; + +} + + + +BOOLEAN +CompareFiles( + PMFILE FirstFile, + PMFILE SecondFile, + FILE *DifferenceFile, + PULONG TotalDifferenceCounter + ) +{ + + PSECTION SectionZero_FirstFile; + PSECTION SectionZero_SecondFile; + ULONG FileComparisonDifferences = 0 ; + + + // + // Create the two special sections. + // These sections indicate the beggining of the two files being compared + // + SectionZero_FirstFile = CreateSection(); + SectionZero_SecondFile = CreateSection(); + + if ( SectionZero_FirstFile == (PSECTION)NULL) { + printf("The system has run out of memory resources for this program\n"); + if ( SectionZero_SecondFile != (PSECTION)NULL) { + DestroySection( SectionZero_SecondFile ); + } + exit( -1 ); + } else if ( SectionZero_SecondFile == (PSECTION)NULL) { + printf("The system has run out of memory resources for this program\n"); + DestroySection( SectionZero_FirstFile ); + exit( -1 ); + } + + + + // + // Initialize the two sections + // + SectionZero_FirstFile->File = FirstFile ; + SectionZero_SecondFile->File = SecondFile; + strcpy( SectionZero_FirstFile->SectionDescription, FirstFile->FileName ); + strcpy( SectionZero_SecondFile->SectionDescription, SecondFile->FileName ); + + + // + // Now since the second file is also the GOLDEN file, set that as the + // base control section. Lines, sections will be compared AGAINST this control + // section. In the generic case however, this would not be true since either + // one can be marked as the base section. That requires this line to be remarked + // and changes made to the -TOKEN_MATCH-() keyword syntax to accept the variable + // BASE. + // + SectionZero_SecondFile->Control.BaseControlSection = TRUE; + + + // + // Proceed with the comparisons + // + CompareSections( SectionZero_FirstFile, SectionZero_SecondFile, + DifferenceFile, &FileComparisonDifferences ); + + + // + // And indicate the completion of a successful comparison + // + *TotalDifferenceCounter += FileComparisonDifferences; + return TRUE; + +} + + +BOOLEAN +CompareSections( + PSECTION FirstSection, + PSECTION SecondSection, + FILE *DifferenceFile, + PULONG FileDifferenceCounter + ) +{ + + PFUNCTION_ELEMENTS FunctionElements; + + // + // Initialize the lines used to store information extracted from the files + // + FunctionElements = CreateFunctionElements(); + if ( FunctionElements == (PFUNCTION_ELEMENTS)NULL ) { + printf("The system has run out of memory resources for this program\n"); + exit( -1 ); + } else { + FunctionElements->SectionEndsNotSynchronized = TRUE; + } + + + // + // Indicate a sectional compare IF the section is not the base section 0.0 + // + // fprintf( DifferenceFile, "\n\n__PERFORMING SECTIONAL ANALYSIS ON SECTION ID: %f__\n", + // SecondSection->Control.SectionIdentifier ); + + // + // Repeat until the section ends from the two files match + // and the section comparison completes + // + while ( FunctionElements->SectionEndsNotSynchronized ) { + + // + // Get the next line from first section IFF sectional synchronization is not + // required + // + if ( FunctionElements->FirstSectionSynchronize == FALSE ) { + + // + // Keep attempting to access the next line till we do not have to skip lines + // + FunctionElements->SkipLine = TRUE; + while ( FunctionElements->SkipLine ) { + + ClearAndSetLine( FirstSection , &FunctionElements->FirstSectionCurrentLine ); + if ( GetNextLine( FirstSection ) ) { + + if ( DoNotSkipThisLine( FirstSection ) ) { + + ExtractResults( FirstSection ); + FunctionElements->SkipLine = FALSE; + + } + FirstSection->Control.SectionLineCount++; + FirstSection->File->CurrentFileLine++; + + } else { + + // + // Mark this line as type SECTION_END. This is actually the EOF which + // is also the end of section 0.0(the file) + // + FirstSection->CurrentLine->LineType = LINE_TYPE_SECTION_END; + FunctionElements->SkipLine = FALSE ; + + } + + } + + + } + + // + // Get the next line from second section IFF sectional synchronization is not + // required + // + if ( FunctionElements->SecondSectionSynchronize == FALSE ) { + + // + // Keep attempting to access the next line till we do not have to skip lines + // + FunctionElements->SkipLine = TRUE; + while ( FunctionElements->SkipLine ) { + + ClearAndSetLine( SecondSection, &FunctionElements->SecondSectionCurrentLine ); + if ( GetNextLine( SecondSection ) ) { + + if ( DoNotSkipThisLine( SecondSection ) ) { + + // + // Since the second file section is the golden section + // we do not need to extract results from the line. + // However, if the program is changed for generic control + // the line should be included + // + // ExtractResults( FirstSection ); + // + ExtractBetweenValues( SecondSection ); + FunctionElements->SkipLine = FALSE; + + } + SecondSection->Control.SectionLineCount++; + SecondSection->File->CurrentFileLine++; + + } else { + + // + // Mark this line as type SECTION_END. This is actually the EOF which + // is also the end of section 0.0(the file) + // + SecondSection->CurrentLine->LineType = LINE_TYPE_SECTION_END; + FunctionElements->SkipLine = FALSE ; + + } + + } + + } + + + // + // Determine the line types of both sections. + // The line type indicate the beggining of a section, ending of a section, + // or a regular line + // + LineType( FirstSection ); + LineType( SecondSection ); + + + // + // Determine the variation to be examined. The variation is simply a combination + // of the two line types to indicate common behavior. e.g. if the first line was + // a section ending and the second line was a regular line, the behaviour of + // the program would be the same if the line types were reversed + // + CombinedVariation( FirstSection, SecondSection, &FunctionElements->CombinedLineVariation ); + + // + // And now operate on the deduced variation + // + switch( FunctionElements->CombinedLineVariation ) { + + // + // If both lines are the beginning of new sections + // + case SECTIONHDR_SECTIONHDR: + + // + // Examine both section ID's specified in the current lines match the + // following conditions + // 1. The two ID's are the same + // 2. The two ID do NOT match the current section ID's + // + if ( CheckSectionIDFromCurrentLines( FirstSection, SecondSection ) ) { + + + // + // Sections have been synchronized + // + FunctionElements->FirstSectionSynchronize = FALSE; + FunctionElements->SecondSectionSynchronize = FALSE; + + + // + // Create two new sections + // + FunctionElements->NewFirstSection = CreateSection(); + FunctionElements->NewSecondSection = CreateSection(); + if ( FunctionElements->NewFirstSection == (PSECTION)NULL ) { + printf("The system has run out of memory resources for this program\n"); + if ( FunctionElements->NewSecondSection != (PSECTION)NULL ) { + DestroySection( FunctionElements->NewSecondSection ); + } + exit( -1 ); + } else if ( FunctionElements->NewSecondSection == (PSECTION)NULL ) { + printf("The system has run out of memory resources for this program\n"); + DestroySection( FunctionElements->NewFirstSection ); + exit( -1 ); + } + + // + // Initialize section control + // + if ( !InitializeSectionControl( FunctionElements->NewFirstSection, FirstSection ) || + !InitializeSectionControl( FunctionElements->NewSecondSection, SecondSection ) ) { + + // + // Once again this should not occur + // + fprintf( DifferenceFile, "\nA BAD SECTIONAL CONTROL SEGMENT HAS BEEN DETECTED\n"); + fprintf( DifferenceFile, "\nCHECK FOR A SYNTAX ERROR\n" ); + PrintSectionInformation( FirstSection, DifferenceFile ); + PrintSectionInformation( SecondSection, DifferenceFile ); + // + // Free up the resources allocates + // + DestroySection( FunctionElements->NewFirstSection ); + DestroySection( FunctionElements->NewSecondSection ); + + // + // Reset and compare as regular lines + // + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + } else { + + + // + // Compare the two new sections + // + CompareSections( FunctionElements->NewFirstSection, + FunctionElements->NewSecondSection, + DifferenceFile, + FileDifferenceCounter ); + + // + // Readjust the current line counters for the First and Second + // Sections + // + FirstSection->Control.SectionLineCount += + FunctionElements->NewFirstSection->Control.SectionLineCount; + + SecondSection->Control.SectionLineCount += + FunctionElements->NewSecondSection->Control.SectionLineCount; + + // + // Free up the resources allocates + // + DestroySection( FunctionElements->NewFirstSection ); + DestroySection( FunctionElements->NewSecondSection ); + + } + + } else { + + // + // Force synchronize the sections + // + FunctionElements->FirstSectionSynchronize = FALSE; + FunctionElements->SecondSectionSynchronize = FALSE; + + // + // switch them to regular lines. + // This condition should never be reached and if so treat these + // lines as regular lines + // + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + } + break; + + + // + // If both lines are ends of sections + // + case SECTIONEND_SECTIONEND: + + FunctionElements->FirstSectionID = ExtractSectionIDFromLine( FirstSection ); + FunctionElements->SecondSectionID = ExtractSectionIDFromLine( SecondSection ); + + // + // Global section control. Ends section comparisons. + // + if ( FunctionElements->FirstSectionID > FunctionElements->SecondSectionID ) { + + FunctionElements->FirstSectionSynchronize = FALSE; + FunctionElements->SecondSectionSynchronize = TRUE; + + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + + } else if ( FunctionElements->FirstSectionID < FunctionElements->SecondSectionID ) { + + FunctionElements->FirstSectionSynchronize = TRUE; + FunctionElements->SecondSectionSynchronize = FALSE; + + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + } else { + + // + // Sections are synchronized + // + FunctionElements->FirstSectionSynchronize = FALSE; + FunctionElements->SecondSectionSynchronize = FALSE; + + + // + // Now make sure that the extracted section IDs match the + // current section ID + // + if ( FunctionElements->FirstSectionID == FirstSection->Control.SectionIdentifier ) { + + // + // ALL TOKEN MATCHING IS DONE AT THE ENDS OF SECTIONS + // + if ( SecondSection->Control.TokenMatching == TRUE ) { + + CompareTokensAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + } + + FunctionElements->SectionEndsNotSynchronized = FALSE; + + } else { + + // + // Switch them to regular lines + // + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + + } + + } + + break; + + + // + // If one line is the beggining of a section + // and the other is the end of a section + // + case SECTIONHDR_SECTIONEND: + + // + // We have come across the case where another section has been detected + // while another was ending. + // + if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) { + + FunctionElements->FirstSectionSynchronize = TRUE; + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + } else { + + FunctionElements->SecondSectionSynchronize = TRUE; + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + } + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + break; + + + // + // If one line is the beggining of a section and the other + // is a regular line + // + case SECTIONHDR_REGLINE : + + // + // We have come to a point where a section header has been detected + // in one section and a regular line in another + // This forces us to now attempt to re-synchronize the sections + // + if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) { + + if ( ExtractSectionIDFromLine( FirstSection ) != (DOUBLE)0 ) { + + FunctionElements->FirstSectionSynchronize = TRUE; + + } else { + + // + // Simply RESET this line as a regular line and compare + // + FirstSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + } + + } else { + + if ( ExtractSectionIDFromLine( SecondSection ) != (DOUBLE)0 ) { + + FunctionElements->SecondSectionSynchronize = TRUE; + + } else { + + // + // Simply RESET this line as a regular line and compare + // + SecondSection->CurrentLine->LineType = LINE_TYPE_REGULAR; + + } + + + } + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + break; + + + // + // If one line is the end of a section and + // the other is a regular line + // + case SECTIONEND_REGLINE : + + // + // We have come to a point where a section end has been detected + // in one section and a regular line in another + // This forces us to now attempt to re-synchronize the sections + // + if ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) { + + FunctionElements->FirstSectionSynchronize = TRUE; + + } else { + + FunctionElements->SecondSectionSynchronize = TRUE; + + } + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + break; + + // + // If both lines are regular lines + // + case REGLINE_REGLINE : + + CompareLinesAndPrintResults( FirstSection, + SecondSection, + &FunctionElements->ErrorCount, + DifferenceFile ); + + break; + + + } // !switch{} + + + } // !while( FunctionElements->SectionEndsNotSynchronized ) + + + // + // Print out the section comparison results + // + if ( FunctionElements->ErrorCount ) { + + fprintf( DifferenceFile, "\n\n__SECTIONAL RESULTS FOR SECTION ID : %f ERROR(S): %u\n", + SecondSection->Control.SectionIdentifier, + FunctionElements->ErrorCount ); + + } + + // + // Cleanup + // + *FileDifferenceCounter += FunctionElements->ErrorCount; + DestroyFunctionElements( FunctionElements ); + return TRUE; + + +} + + +BOOLEAN +GetNextLine( + PSECTION Section + ) +{ + UINT i,j; + PCHAR Tmp; + + // + // Get the normal line. Read in until MAX_LINE_SIZE-1. This is done to ensure that + // should the line be longer, only the first MAX_LINE_SIZE-1 bytes are read in and + // the last byte is 0. + // + if ( fgets( Section->CurrentLine->NormalLine, + (sizeof( Section->CurrentLine->NormalLine )-1), + Section->File->FileP + ) != NULL ) { + + // + // Replace the first occurence of a new line with a null + // + Tmp = strchr( Section->CurrentLine->NormalLine, '\n'); + if ( Tmp != (PCHAR)NULL ) { + + *Tmp = '\0'; + + } + + Section->CurrentLine->NormalLineSize = strlen( Section->CurrentLine->NormalLine ); + + + // + // Obtain a compressed uppercase version of the line + // + for( i = 0, j = 0 ; i < strlen( Section->CurrentLine->NormalLine ); i++ ) { + + if ( isspace( Section->CurrentLine->NormalLine[i] ) == 0 ) { + + Section->CurrentLine->CompressedLine[j] = toupper( Section->CurrentLine->NormalLine[i] ); + + Section->CurrentLine->CompressedLineSize++; + j++; + + } + + } + + // + // And return + // + return TRUE; + + } + + // + // This indicates an EOF has been reached + // + return FALSE; + +} + + +VOID +LineType( + PSECTION Section + ) +{ + // + // If while entering the line type was marked as SECTION_END + // it indicates the EOF has been encountered. Since EOF is also + // the end of section ID 0.0, the line is premarked + // is read. This is the only special type which is premarked + // + if ( Section->CurrentLine->LineType == LINE_TYPE_SECTION_END ) { + + return; + + } + + // + // If the line contains a MAY_DIFFER, irrespective of what the control + // is it is turned into a regular line + // + if ( strstr( Section->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) { + + Section->CurrentLine->LineType = LINE_TYPE_REGULAR; + return; + } + + // + // Search for the special keyword -SECTION_START- + // + if ( strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_START] ) != NULL ) { + + Section->CurrentLine->LineType = LINE_TYPE_SECTION_START; + return; + } + + // + // Search for the special keyword -SECTION_END- + // + if ( strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_END] ) != NULL ) { + + Section->CurrentLine->LineType = LINE_TYPE_SECTION_END; + return; + } + + Section->CurrentLine->LineType = LINE_TYPE_REGULAR; + return; + +} + + +BOOLEAN +ExtractResults( + PSECTION Section + ) +{ + PCHAR TmpBuf; + PCHAR Token ; + BOOLEAN ExtractMoreResults = TRUE; + CHAR Seperators[] = " ,\t"; + ULONG i; + CHAR TmpLine[MAX_LINE_SIZE]; + + // + // First move the Current results into the Last results and clear the current results + // one at a time + // + for( i = 0; i < Section->NumberOfCurrentResults;i++ ) { + + Section->LastResults[i] = Section->CurrentResults[i]; + Section->CurrentResults[i] = 0 ; + + } + Section->NumberOfLastResults = Section->NumberOfCurrentResults; + Section->NumberOfCurrentResults = 0; + + // + // Clear the tmp variable and copy the Normal Line contents into it + // This is done to preserve the contents of the normal line since strtok + // changes the contents. + // + memset( TmpLine, 0, MAX_LINE_SIZE ); + strcpy( TmpLine, Section->CurrentLine->NormalLine ); + + + // + // Search for the right hand value of the expression. This is extracted + // by searching for the = or the : operator. + // + // NOTE + // + // We use strrchr to get to the last occurence of = or : + // + + // + // Locate the = operator + // + TmpBuf = strrchr( TmpLine, '=' ); + + if ( TmpBuf == NULL ) { + + // + // Locate the : operator + // + TmpBuf = strrchr( TmpLine, ':' ); + + if ( TmpBuf == NULL ) { + + return FALSE; + + } + + } + + // + // The fact that we are here indicates that one of the operator + // types was located + // + TmpBuf++; + + Token = strtok( TmpBuf, Seperators ); + + while ( ( Section->NumberOfCurrentResults < MAX_RESULTS_COUNT ) && + ( Token != NULL ) && + ( ExtractMoreResults ) ) { + + if ( (*Token >= '0') && (*Token <= '9') ) { + + Section->CurrentResults[Section->NumberOfCurrentResults] = atol( Token ); + Section->NumberOfCurrentResults++; + Token = strtok( NULL, Seperators ); + + } else { + + ExtractMoreResults = FALSE; + + } + + } + + if ( Section->NumberOfCurrentResults ) { + + return TRUE; + + } + + return FALSE; + +} + +BOOLEAN +ExtractBetweenValues( + PSECTION Section + ) +{ + PCHAR Tmp, Tmp1; + ULONG SwapValue; + + // + // Search for the AT_LEAST Keyword + // + Tmp = strstr( Section->CurrentLine->CompressedLine, "BETWEEN_VALUES" ); + + if ( Tmp != NULL ) { + + Tmp += strlen( "BETWEEN_VALUES" ); + + // + // Extract the minimum-first value + // + Section->MinimumValue = atol( Tmp ); + + // + // Proceed to look for the maximum-second value + // + Tmp1 = strstr( Tmp, "," ); + + if ( Tmp1 != NULL ) { + + Tmp1 += strlen( "," ); + + // + // Extract the minimum-first value + // + Section->MaximumValue = atol( Tmp1 ); + + + } else { + + Section->MaximumValue = 0xffffffff; + + } + + if ( Section->MinimumValue > Section->MaximumValue ) { + + SwapValue = Section->MinimumValue; + Section->MinimumValue = Section->MaximumValue; + Section->MaximumValue = SwapValue ; + + + } + + return TRUE; + + } + + // + // Could not locate AT_LEAST or no associated value was recovered + // + Section->MinimumValue = 0; + Section->MaximumValue = 0xffffffff; + + return FALSE; + +} + +BOOLEAN +CombinedVariation( + PSECTION FirstSection, + PSECTION SecondSection, + PUCHAR CombinedLineVariation + ) +{ + + // + // THERE ARE THE FOLLOWING POSSIBLE 6 COMBINATIONS + // + // START-START, START-REGLINE, START-END + // END-REGLINE, END-END + // REGLINE-REGLINE + // + if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) { + *CombinedLineVariation = SECTIONHDR_SECTIONHDR; + return TRUE; + } + + if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) { + *CombinedLineVariation = SECTIONEND_SECTIONEND; + return TRUE; + } + + + if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) ) { + *CombinedLineVariation = REGLINE_REGLINE; + return TRUE; + } + + if ( ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) + ) || + ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) + ) ) { + *CombinedLineVariation = SECTIONHDR_SECTIONEND; + return TRUE; + } + + if ( ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) + ) || + ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) + ) ) { + *CombinedLineVariation = SECTIONHDR_REGLINE; + return TRUE; + } + + if ( ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) + ) || + ( + ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) + ) ) { + *CombinedLineVariation = SECTIONEND_REGLINE; + return TRUE; + } + + return FALSE; +} + +RESULT +CompareLines( + PSECTION FirstSection, + PSECTION SecondSection + ) +{ + + BOOLEAN ResultErrorsDiscovered = FALSE; + ULONG i; + + // + // THIS IS ANOTHER VERY CRITICAL PIECE OF THE CODE SINCE BASED ON THE LINE TYPES + // COMPARISONS ARE MADE + // + // ON ENTERING THIS FUNCTION THERE ARE ONLY THREE COMBINATIONS A LINE COULD + // BE IN THE FOLLOWING STATES + // + // REGLINE-REGLINE + // REGLINE-SECTIONHDR + // REGLINE-SECTIONEND + // + // FURTHER SINCE THE SECTIONS ARE SYNCHRONIZED WE CAN USE THE CONTROL SETTINGS + // OF EITHER ONE + // + + + // + // COMMON COMPARISONS BETWEEN ALL LINE TYPES + // + + // + // Possible MAY_DIFFER. + // + if ( MayDifferExistsInOneOrMoreLines( FirstSection, SecondSection ) ) { + + return COMPARE_SUCCESS; + + } + + // + // Possible EQUAL_LAST + // + if ( strstr( FirstSection->CurrentLine->CompressedLine, "EQUAL_LAST" ) != NULL ) { + + if ( SecondSection->Control.OptionalMatching == FALSE ) { + + + for( i = 1; i <= FirstSection->NumberOfCurrentResults; i++ ) { + + if ( i > FirstSection->NumberOfLastResults ) { + + FirstSection->ResultsError[i-1] = RESULTS_NOT_PRESENT; + ResultErrorsDiscovered = TRUE; + + } else { + + if ( FirstSection->CurrentResults[i-1] != FirstSection->LastResults[i-1] ) { + + FirstSection->ResultsError[i-1] = RESULTS_UNEQUAL; + ResultErrorsDiscovered = TRUE; + + } else { + + FirstSection->ResultsError[i-1] = RESULTS_EQUAL; + + } + } + } + + if ( ResultErrorsDiscovered ) { + + return COMPARE_EQUAL_LAST; + + } + + } + + return COMPARE_SUCCESS; + + } + + // + // Possible BETWEEN_VALUES from the Golden log file + // + if ( strstr( SecondSection->CurrentLine->CompressedLine, "BETWEEN_VALUES" ) != NULL ) { + + if ( SecondSection->Control.OptionalMatching == FALSE ) { + + for( i = 1; i <= FirstSection->NumberOfCurrentResults; i++ ) { + + if ( ( FirstSection->CurrentResults[i-1] < SecondSection->MinimumValue ) || + ( FirstSection->CurrentResults[i-1] > SecondSection->MaximumValue ) ) { + + FirstSection->ResultsError[i-1] = RESULTS_MINMAX; + ResultErrorsDiscovered = TRUE; + + } else { + + FirstSection->ResultsError[i-1] = RESULTS_EQUAL; + + } + + + } + + if ( ResultErrorsDiscovered ) { + + return COMPARE_BETWEEN_VALUES; + + } + + } + + return COMPARE_SUCCESS; + + } + + + // + // REGLINE-SECTIONHDR + // + if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) { + + if ( SecondSection->Control.OptionalMatching == TRUE ) { + + return COMPARE_SUCCESS; + + } + + if ( SecondSection->Control.TokenMatching == TRUE ) { + + TokenInsertInSection( FirstSection ); + return COMPARE_SUCCESS; + + } + + return COMPARE_START; + + } + if( ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_START ) ) { + + if ( SecondSection->Control.OptionalMatching == TRUE ) { + + return COMPARE_SUCCESS; + + } + + if ( SecondSection->Control.TokenMatching == TRUE ) { + + TokenInsertInSection( SecondSection ); + return COMPARE_SUCCESS; + + } + + return COMPARE_START; + + } + + + + // + // REGLINE-SECTIONEND + // + if ( ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( SecondSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) { + + if ( SecondSection->Control.OptionalMatching == TRUE ) { + + return COMPARE_SUCCESS; + + } + + if ( SecondSection->Control.TokenMatching == TRUE ) { + + TokenInsertInSection( FirstSection ); + return COMPARE_SUCCESS; + + } + + return COMPARE_END; + + } + if ( ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) && + ( FirstSection->CurrentLine->LineType == LINE_TYPE_SECTION_END ) ) { + + if ( SecondSection->Control.OptionalMatching == TRUE ) { + + return COMPARE_SUCCESS; + + } + + if ( SecondSection->Control.TokenMatching == TRUE ) { + + TokenInsertInSection( SecondSection ); + return COMPARE_SUCCESS; + + } + + return COMPARE_END; + + } + + + + + // + // REGLINE-REGLINE + // + if ( memcmp( FirstSection->CurrentLine->CompressedLine, + SecondSection->CurrentLine->CompressedLine, + max( FirstSection->CurrentLine->CompressedLineSize, SecondSection->CurrentLine->CompressedLineSize ) + ) + != 0 ) { + + // + // Since we can only be at this point if the two section headers match, + // either control sections can be used + // + if ( SecondSection->Control.OptionalMatching == TRUE ) { + + return COMPARE_SUCCESS; + + } + + if ( SecondSection->Control.TokenMatching == TRUE ) { + + TokenInsertInSection( FirstSection ); + TokenInsertInSection( SecondSection ); + return COMPARE_SUCCESS; + + } + + return COMPARE_LINE; + + } + + return COMPARE_SUCCESS; + + +} + + +BOOLEAN +InitializeSectionControl( + PSECTION NewSection, + PSECTION OldSection + ) +{ + + PCHAR TmpBuffer; + INT Length ; + CHAR EnvironmentVar[MAX_LINE_SIZE]; + CHAR TmpLine[MAX_LINE_SIZE] ; + + // + // Initialize the file pointers + // + // NOTE + // + // If you do not specify any control for the section and the section is nested + // it will inherit the options of the parent node + // + NewSection->File = OldSection->File; + NewSection->CurrentLine = (PLINE)NULL; + + NewSection->Control.BaseControlSection = OldSection->Control.BaseControlSection; + NewSection->Control.OptionalMatching = OldSection->Control.OptionalMatching ; + NewSection->Control.TokenMatching = OldSection->Control.TokenMatching ; + + NewSection->Control.TokenMatchStartLine = OldSection->Control.TokenMatchStartLine; + NewSection->Control.TokenMatchStopLine = OldSection->Control.TokenMatchStopLine ; + + // + // Since we are going to use strtok to preserve the Normal and Compressed Lines + // we copy them into two local variables when required + // + memset( TmpLine, 0, MAX_LINE_SIZE ); + + // + // Initialize the section ID + // + // KEYWORD : -SECTION_START- + // USAGE : -SECTION_START-( SectionId ) + // + // + NewSection->Control.SectionIdentifier = ExtractSectionIDFromLine( OldSection ); + if ( NewSection->Control.SectionIdentifier == (DOUBLE)0 ) { + + // + // A section without a section ID has ben defined. This is not acceptable + // + return FALSE; + + } + + + // + // Initialize the section description + // + // KEYWORD : -SECTION_DESC- + // USAGE : -SECTION_DESC-( "Section for MACFRAME testing only" ) + // + // + TmpBuffer = strstr( OldSection->CurrentLine->NormalLine, Keywords[SECTION_DESC] ); + if ( TmpBuffer != NULL ) { + + TmpBuffer = strchr( TmpBuffer, '"' )+1; + Length = strrchr( TmpBuffer, '"' ) - TmpBuffer; + + if ( Length < 0 ) { + Length = 0; + } + strncpy( NewSection->SectionDescription, TmpBuffer, Length ); + } + + // + // Initialize any Optional control sectioning. This if detected without any + // parameters suggests that the section is under optional comparison. Else + // certain environment variables are checked and is found enabled, this + // section is matched + // + // KEYWORD : -OPTIONALS- + // USAGE : -OPTIONALS-( EnvironmentVar1, EnvironmentVar2...EnvironmentVarN ) + // + // + + strcpy( TmpLine, OldSection->CurrentLine->CompressedLine ); + + TmpBuffer = strstr( TmpLine, Keywords[OPTIONALS] ); + + if ( TmpBuffer != NULL ) { + + UINT EnvCounter1 = 0 , EnvCounter2 = 0 ; + PCHAR Token ; + PCHAR Seperators = ",)" ; + + // + // Weve detected an optional section + // + NewSection->Control.OptionalMatching = TRUE; + + TmpBuffer += (strlen( Keywords[OPTIONALS] )+1); + + // + // Now detect which Environment variables are enabled. + // If ALL are not enabled, the section remains an + // optional section + // + Token = strtok( TmpBuffer, Seperators ); + + while ( Token != NULL ) { + + EnvCounter1++; + + memset( EnvironmentVar, 0, sizeof( EnvironmentVar ) ); + strncpy( EnvironmentVar, Token, strlen( Token ) ); + + if ( getenv( EnvironmentVar ) != NULL ) { + + EnvCounter2++; + + } + + Token = strtok( NULL, Seperators ); + + } + + // + // If all the environment variables have been enabled, this is + // no longer an optional section + // + if ( (EnvCounter1 == EnvCounter2) && (EnvCounter1 != 0) ) { + + NewSection->Control.OptionalMatching = FALSE; + + } + + } + + // + // Initialize any Token matching control within the sections. + // + // KEYWORD : -TOKEN_MATCH- + // USAGE : -TOKEN_MATCH-( StartLine, StopLine ) + // + // NOTE: The StopLine is expressed as a relative offset from the start line + // + NewSection->Control.HeadUnmatchedTokens = NULL; + TmpBuffer = strstr( OldSection->CurrentLine->CompressedLine, Keywords[TOKEN_MATCH] ); + if ( TmpBuffer != NULL ) { + + // + // Weve detected an Token matching section + // + NewSection->Control.TokenMatching = TRUE; + + TmpBuffer += (strlen( Keywords[TOKEN_MATCH] )+1); + + NewSection->Control.TokenMatchStartLine = atol( TmpBuffer ); + NewSection->Control.TokenMatchStopLine = atol( (strchr(TmpBuffer, ',')+1) ); + + if ( NewSection->Control.TokenMatchStopLine == 0 ) { + + NewSection->Control.TokenMatchStopLine = TOKEN_MATCHING_ALL; + + } + + } + + return TRUE; + +} + + +VOID +PrintComparisonResults( + PSECTION FirstSection, + PSECTION SecondSection, + RESULT ReturnResult, + ULONG ErrorCount, + FILE *DifferenceFile + ) +{ + + ULONG i; + + switch ( ReturnResult ) { + + case COMPARE_LINE : + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + fprintf( DifferenceFile, "\nFOUND (COMP.FILE LINE CONTENTS) : %s\n", + FirstSection->CurrentLine->NormalLine ); + fprintf( DifferenceFile, "EXPECTED (GOLDEN FILE LINE CONTENTS) : %s\n", + SecondSection->CurrentLine->NormalLine ); + + // + // Since this program is for the second file being the GOLDEN file + // It prints out information with reference to the GOLDEN file + // + + fprintf( DifferenceFile, "\n\tERROR TYPE : LINE COMPARISON FAILURE\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + SecondSection->Control.SectionIdentifier ); + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", + FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n", + FirstSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n", + FirstSection->File->CurrentFileLine ); + fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n", + SecondSection->File->FileName ); + fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n", + SecondSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n", + SecondSection->File->CurrentFileLine ); + + break; + + case COMPARE_EQUAL_LAST: + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + fprintf( DifferenceFile, "\nINDEX FOUND(CURRENT EXTRACTED RESULTS) EXPECTED(LAST EXTRACTED RESULTS)\n" ); + for( i = 0; i < FirstSection->NumberOfCurrentResults; i++ ) { + + if ( FirstSection->ResultsError[i] != RESULTS_EQUAL ) { + + fprintf( DifferenceFile, "%5u %32u %32u\n", + (i+1), + FirstSection->CurrentResults[i], + FirstSection->LastResults[i] + + ); + + } + + } + + fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT VALUE(S) FAILED TO EQUAL LAST\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + FirstSection->Control.SectionIdentifier ); + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n", + FirstSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n", + FirstSection->File->CurrentFileLine ); + + + break; + + case COMPARE_BETWEEN_VALUES: + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + fprintf( DifferenceFile, "\nEXPECTED VALUES BETWEEN (EXTRACTED FROM GOLDEN) : %u, %u\n", + SecondSection->MinimumValue, SecondSection->MaximumValue ); + fprintf( DifferenceFile, "\nFOUND RESULTS IN ERROR(EXTRACTED RESULTS)\n" ); + fprintf( DifferenceFile, "INDEX RESULT\n" ); + + for( i = 0; i < FirstSection->NumberOfCurrentResults; i++ ) { + + if ( FirstSection->ResultsError[i] != RESULTS_EQUAL ) { + + fprintf( DifferenceFile, "%5u %23u\n", + (i+1), + FirstSection->CurrentResults[i] + ); + + } + + } + + fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT VALUE(S) IS(ARE) NOT BETWEEN THE EXPECTED VALUES\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + FirstSection->Control.SectionIdentifier ); + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n", + FirstSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n", + FirstSection->File->CurrentFileLine ); + + break; + + case COMPARE_TOKEN : + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + fprintf( DifferenceFile, "\nUNABLE TO LOCATE LINE IN THE COMP. FILE : %s\n", + SecondSection->Control.HeadUnmatchedTokens->NormalToken ); + + fprintf( DifferenceFile, "\n\tERROR TYPE : UNABLE TO LOCATE TOKEN\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + SecondSection->Control.SectionIdentifier ); + + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", + FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n", + SecondSection->File->FileName ); + fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n", + SecondSection->Control.HeadUnmatchedTokens->LinePosition ); + fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n", + SecondSection->Control.HeadUnmatchedTokens->FileLinePosition ); + + break; + + case COMPARE_START : + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + if ( FirstSection->CurrentLine->LineType != LINE_TYPE_SECTION_START ) { + + fprintf( DifferenceFile, "\nEXTRA LINE DETECTED (COMP. FILE LINE CONTENTS) : %s\n", + FirstSection->CurrentLine->NormalLine ); + fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): %s\n", + SecondSection->CurrentLine->NormalLine ); + + } else { + + fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : %s\n", + FirstSection->CurrentLine->NormalLine ); + fprintf( DifferenceFile, "LINE ABSENT IN COMP. FILE (GOLDEN FILE LINE CONTENTS) : %s\n", + SecondSection->CurrentLine->NormalLine ); + + } + + fprintf( DifferenceFile, "\n\tERROR TYPE : NEW SECTION START SYNCHRONIZATION FAILURE\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + SecondSection->Control.SectionIdentifier ); + + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", + FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n", + FirstSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n", + FirstSection->File->CurrentFileLine ); + + fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n", + SecondSection->File->FileName ); + fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n", + SecondSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n", + SecondSection->File->CurrentFileLine ); + + break; + + + case COMPARE_END : + + // + // Report the difference in the difference file + // + fprintf( DifferenceFile, "\n\n__ERROR__ : %u\n", ErrorCount ); + + if ( FirstSection->CurrentLine->LineType != LINE_TYPE_SECTION_END ) { + + fprintf( DifferenceFile, "\nEXTRA LINE DETECTED (COMP. FILE LINE CONTENTS) : %s\n", + FirstSection->CurrentLine->NormalLine ); + + if ( ( SecondSection->Control.SectionIdentifier == (DOUBLE)0 ) && + ( strlen( SecondSection->CurrentLine->CompressedLine ) == 0 ) ) { + + fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): END_OF_FILE\n" ); + + } else { + + fprintf( DifferenceFile, "GOLDEN FILE LINE CONTENTS (Expected to synchronize on): %s\n", + SecondSection->CurrentLine->NormalLine ); + } + + } else { + + if ( ( FirstSection->Control.SectionIdentifier == (DOUBLE)0 ) && + ( strlen( FirstSection->CurrentLine->CompressedLine ) == 0 ) ) { + + fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : END_OF_FILE\n" ); + + } else { + + fprintf( DifferenceFile, "\nCOMP. FILE LINE CONTENTS (Expected to synchronize on) : %s\n", + FirstSection->CurrentLine->NormalLine ); + + } + + fprintf( DifferenceFile, "LINE ABSENT IN COMP. FILE (GOLDEN FILE LINE CONTENTS) : %s\n", + SecondSection->CurrentLine->NormalLine ); + + } + + fprintf( DifferenceFile, "\n\tERROR TYPE : CURRENT SECTION END SYNCH. FAILURE\n" ); + fprintf( DifferenceFile, "\tCURRENT SECTION ID : %f\n", + SecondSection->Control.SectionIdentifier ); + + fprintf( DifferenceFile, "\tCOMP. FILE : %s\n", + FirstSection->File->FileName ); + fprintf( DifferenceFile, "\tCOMP. FILE SECTION LINE OFFSET : %u\n", + FirstSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tCOMP. FILE LINE OFFSET : %u\n", + FirstSection->File->CurrentFileLine ); + + fprintf( DifferenceFile, "\tGOLDEN FILE : %s\n", + SecondSection->File->FileName ); + fprintf( DifferenceFile, "\tGOLDEN FILE SECTION LINE OFFSET: %u\n", + SecondSection->Control.SectionLineCount ); + fprintf( DifferenceFile, "\tGOLDEN FILE LINE OFFSET : %u\n", + SecondSection->File->CurrentFileLine ); + + break; + + + default : + + fprintf( DifferenceFile, "\n\nUNKNOWN COMPARISON RESULT: %u\n", ReturnResult ); + break; + + } + +} + + +VOID +PrintSectionInformation( + PSECTION Section, + FILE *DifferenceFile + ) +{ + + fprintf( DifferenceFile, "FILE NAME : %s\n" , Section->File->FileName ); + fprintf( DifferenceFile, "SECTION ID : %f\n" , Section->Control.SectionIdentifier ); + fprintf( DifferenceFile, "SECTION OFFSET LINE# : %u\n", Section->Control.SectionLineCount ); + fprintf( DifferenceFile, "SECTION LINE CONTENTS: %s\n" , Section->CurrentLine->NormalLine ); + +} + + + +DOUBLE +ExtractSectionIDFromLine( + PSECTION Section + ) +{ + PCHAR TmpBuffer; + + // + // Examine for -SECTION_START- + // + TmpBuffer = strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_START] ); + + if ( TmpBuffer != (PCHAR)NULL ) { + + TmpBuffer += (strlen( Keywords[SECTION_START] )+1); + return (DOUBLE)(atof( TmpBuffer )); + + } + + // + // Examine for -SECTION_END- + // + TmpBuffer = strstr( Section->CurrentLine->CompressedLine, Keywords[SECTION_END] ); + + if ( TmpBuffer != (PCHAR)NULL ) { + + TmpBuffer += (strlen( Keywords[SECTION_END] )+1); + return (DOUBLE)(atof( TmpBuffer )); + + } + + return (DOUBLE)0; + +} + + + +BOOLEAN +CheckSectionIDFromCurrentLines( + PSECTION FirstSection, + PSECTION SecondSection ) +{ + + DOUBLE SectionID_1, SectionID_2; + + SectionID_1 = ExtractSectionIDFromLine( FirstSection ); + SectionID_2 = ExtractSectionIDFromLine( SecondSection ); + + if ( ( SectionID_1 != SectionID_2 ) || + ( SectionID_1 == (DOUBLE)0 ) || + ( SectionID_2 == (DOUBLE)0 ) ) { + + return FALSE; + + } + + return TRUE; + +} + + +BOOLEAN +CompareLinesAndPrintResults( + PSECTION FirstSection, + PSECTION SecondSection, + PULONG ErrorCount, + FILE *DifferenceFile + ) +{ + + RESULT ComparisonResult; + + ComparisonResult = CompareLines( FirstSection, SecondSection ); + + if ( ComparisonResult != COMPARE_SUCCESS ) { + // + // Increment the section error count + // + (*ErrorCount)++ ; + + PrintComparisonResults( FirstSection, + SecondSection, + ComparisonResult, + *ErrorCount, + DifferenceFile ); + + } + + return TRUE; + +} + + + +VOID +TokenInsertInSection( + PSECTION Section + ) +{ + PTOKEN_LIST Token; + ULONG MaxLineCount; + ULONG MinLineCount; + + // + // A safe way of determining if the maximum line which will generate a valid token + // is <= 0xfffffff + // + if( Section->Control.TokenMatchStartLine > (TOKEN_MATCHING_ALL - Section->Control.TokenMatchStopLine ) ) { + + MaxLineCount = TOKEN_MATCHING_ALL; + + } else { + + MaxLineCount = Section->Control.TokenMatchStartLine + + Section->Control.TokenMatchStopLine ; + + } + MinLineCount = Section->Control.TokenMatchStartLine; + + + // + // First examine if the current line has not exceeded the Maximum StopLine AND is also greater + // than the minimum line count. Because of this condition, it becomes a valid token + // + if( ( Section->Control.SectionLineCount <= MaxLineCount ) && + ( Section->Control.SectionLineCount >= MinLineCount ) ) { + + // + // Create a TOKEN and link it into the section control + // + Token = (PTOKEN_LIST)calloc( 1, sizeof( TOKEN_LIST ) ); + + if ( Token == (PTOKEN_LIST)NULL ) { + + printf( "The system has run out of memory resources\n" ); + exit( -1 ); + + } + + // + // Initialize this token and insert it into the unmatched list + // + strncpy( Token->NormalToken, + Section->CurrentLine->NormalLine, + Section->CurrentLine->NormalLineSize ); + strncpy( Token->CompressedToken, + Section->CurrentLine->CompressedLine, + Section->CurrentLine->CompressedLineSize ); + + Token->LinePosition = Section->Control.SectionLineCount; + Token->FileLinePosition = Section->File->CurrentFileLine ; + Token->TokenState = TOKEN_UNMATCHED; + Token->NextToken = NULL; + + InsertToken( Token, Section->Control.HeadUnmatchedTokens ); + + } + +} + + +RESULT +MatchTopToken( + PTOKEN_LIST BaseList, + PTOKEN_LIST ComparisonList + ) +{ + PTOKEN_LIST CurrentToken ; + INT Length ; + + CurrentToken = ComparisonList; + + // + // Check if the Base Token under comparison is a possible MAY_DIFFER + // + if ( strstr( BaseList->CompressedToken, "MAY_DIFFER" ) != NULL ) { + + return COMPARE_SUCCESS; + + } + + // + // Walk down the token chain list looking for a match. Note if the token has been + // matched before, it is marked so and hence cannot be reused + // + Length = strlen( BaseList->CompressedToken ); + + while ( CurrentToken != (PTOKEN_LIST )NULL ) { + + if ( ( CurrentToken->TokenState == TOKEN_UNMATCHED ) && + ( strncmp( BaseList->CompressedToken, CurrentToken->CompressedToken, Length ) == 0 ) + ) { + + // + // Found a match + // + + CurrentToken->TokenState = TOKEN_MATCHED; + return COMPARE_SUCCESS; + + } + + CurrentToken = CurrentToken->NextToken; + + } + + return COMPARE_TOKEN; + +} + + +VOID +CompareTokensAndPrintResults( + PSECTION FirstSection, + PSECTION SecondSection, + PULONG ErrorCount, + FILE *DifferenceFile + ) +{ + RESULT ComparisonResult; + PTOKEN_LIST Tmp; + + // + // The base set for comparison will always come from the second file(golden file) + // + + // + // And now search for matches for the individual tokens from the base set + // + while ( SecondSection->Control.HeadUnmatchedTokens != (PTOKEN_LIST)NULL ) { + + ComparisonResult = MatchTopToken( SecondSection->Control.HeadUnmatchedTokens, + FirstSection->Control.HeadUnmatchedTokens ); + + + if ( ComparisonResult != COMPARE_SUCCESS ) { + + (*ErrorCount)++ ; + + PrintComparisonResults( FirstSection, + SecondSection, + ComparisonResult, + *ErrorCount, + DifferenceFile ); + } + + // + // And now destroy this token from the base list + // + Tmp = + SecondSection->Control.HeadUnmatchedTokens; + + SecondSection->Control.HeadUnmatchedTokens = + SecondSection->Control.HeadUnmatchedTokens->NextToken; + + DestroyToken( Tmp ); + + } + + // + // Finally cleanup the tokens on the compared section + // + while ( FirstSection->Control.HeadUnmatchedTokens != (PTOKEN_LIST)NULL ) { + + Tmp = + FirstSection->Control.HeadUnmatchedTokens; + + FirstSection->Control.HeadUnmatchedTokens = + FirstSection->Control.HeadUnmatchedTokens->NextToken; + + DestroyToken( Tmp ); + + } + +} + + +BOOLEAN +MayDifferExistsInOneOrMoreLines( + PSECTION FirstSection, + PSECTION SecondSection + ) +{ + + if ( ( strstr( FirstSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) || + ( strstr( SecondSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) != NULL ) ) { + + // + // Token matching is a special case. Since we care only about the second + // section since that is the golden section, we make another exception + // and not check for the first section + // + if ( SecondSection->Control.TokenMatching == TRUE ) { + + if ( strstr( SecondSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) == NULL ) { + // + // This implies that the firstsection line had a MAY_DIFFER in it and the second + // section did not + // + // Now check the line type + // + TokenInsertInSection( FirstSection ); + + if ( SecondSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) { + + TokenInsertInSection( SecondSection ); + + } + + } else { + + // + // The secondsection had a MAY_DIFFER in it + // + TokenInsertInSection( SecondSection ); + + if ( strstr( FirstSection->CurrentLine->CompressedLine, "MAY_DIFFER" ) == NULL ) { + // + // The FirstSection did not have a MAY_DIFFER in it + // + if ( FirstSection->CurrentLine->LineType == LINE_TYPE_REGULAR ) { + + TokenInsertInSection( FirstSection ); + + } + + } else { + // + // At this point we have determined that both lines contained MAY_DIFFER + // in them + // + TokenInsertInSection( FirstSection ); + } + } + } + + return TRUE; + + } + + return FALSE; + +} + + +BOOLEAN +DoNotSkipThisLine( + PSECTION Section + ) +{ + CHAR *SpecialLine = "[TPCTL:]"; + + // + // This function is responsible for informing the calling function to skip lines + // should it detect the presence of the keyword SKIP_LINE or match the compressed + // line with the special line. This can be later extented to cover special lines + // + if ( ( strstr( Section->CurrentLine->CompressedLine, "SKIP_LINE" ) == NULL ) && + ( strcmp( Section->CurrentLine->CompressedLine, SpecialLine ) != 0 ) && + ( strlen( Section->CurrentLine->CompressedLine ) != 0 ) ) { + + return TRUE; + + } + + return FALSE; + +} diff --git a/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h new file mode 100644 index 000000000..a811a8a97 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff.new/tpdiff.h @@ -0,0 +1,213 @@ +#define MULTIPLIER sizeof(ULONG) +#define MAX_LINE_SIZE 64*MULTIPLIER +#define MAX_SECTION_DESC_SIZE 64*MULTIPLIER +#define MAX_RESULTS_COUNT 32 +#define UCHAR_REMAINDER (MULTIPLIER-sizeof(UCHAR)) + + +#define SECTION_START 0 +#define SECTION_END 1 +#define OPTIONALS 2 +#define TOKEN_MATCH 3 +#define SECTION_DESC 4 + +#define LINE_TYPE_SECTION_START ((UCHAR)1) +#define LINE_TYPE_SECTION_END ((UCHAR)2) +#define LINE_TYPE_REGULAR ((UCHAR)3) + + +#define SECTIONHDR_SECTIONHDR ((UCHAR)1) +#define SECTIONHDR_SECTIONEND ((UCHAR)2) +#define SECTIONHDR_REGLINE ((UCHAR)3) +#define SECTIONEND_SECTIONEND ((UCHAR)4) +#define SECTIONEND_REGLINE ((UCHAR)5) +#define REGLINE_REGLINE ((UCHAR)6) + + +#define COMPARE_SUCCESS 0x0UL +#define COMPARE_EQUAL_LAST 0x1UL +#define COMPARE_LINE 0x2UL +#define COMPARE_START 0x3UL +#define COMPARE_END 0x4UL +#define COMPARE_TOKEN 0x5UL +#define COMPARE_BETWEEN_VALUES 0x6UL + +#define RESULTS_EQUAL ((UCHAR)0) +#define RESULTS_UNEQUAL ((UCHAR)1) +#define RESULTS_NOT_PRESENT ((UCHAR)2) +#define RESULTS_MINMAX ((UCHAR)3) + + +#define TOKEN_MATCHING_ALL 0xFFFFFFFF +#define TOKEN_UNMATCHED 0x0UL +#define TOKEN_MATCHED 0x1UL + + +#if !( defined(lint) || defined(_lint) ) +#if i386 +#pragma warning(disable:4103) +#endif +#pragma pack(1) +#endif + + +typedef ULONG RESULT; +typedef double DOUBLE; + +typedef struct _MFILE { + + ULONG CurrentFileLine; + PCHAR FileName; + FILE *FileP ; + +} MFILE, *PMFILE; + + +typedef struct _LINE { + + UINT NormalLineSize ; + UINT CompressedLineSize ; + + CHAR NormalLine[MAX_LINE_SIZE] ; + CHAR CompressedLine[MAX_LINE_SIZE]; + + UCHAR LineType ; + UCHAR Padding[UCHAR_REMAINDER] ; + +} LINE, *PLINE; + + +typedef struct _TOKEN_LIST { + + ULONG LinePosition ; + ULONG FileLinePosition ; + ULONG TokenState ; + + struct _TOKEN_LIST *NextToken ; + + CHAR NormalToken[MAX_LINE_SIZE] ; + CHAR CompressedToken[MAX_LINE_SIZE]; + +} TOKEN_LIST, *PTOKEN_LIST; + +typedef struct _SECTION_CONTROL { + + ULONG SectionLineCount ; + ULONG TokenMatchStartLine; + ULONG TokenMatchStopLine ; + + PTOKEN_LIST HeadUnmatchedTokens; + + DOUBLE SectionIdentifier ; + + BOOLEAN OptionalMatching ; + BOOLEAN TokenMatching ; + BOOLEAN BaseControlSection ; + BOOLEAN Padding ; + +} SECTION_CONTROL, *PSECTION_CONTROL; + +typedef struct _SECTION { + + RESULT LastResults[MAX_RESULTS_COUNT] ; + RESULT CurrentResults[MAX_RESULTS_COUNT] ; + ULONG NumberOfLastResults ; + ULONG NumberOfCurrentResults ; + UCHAR ResultsError[MAX_RESULTS_COUNT] ; + + RESULT MinimumValue ; + RESULT MaximumValue ; + + PMFILE File; + PLINE CurrentLine; + + SECTION_CONTROL Control; + + CHAR SectionDescription[MAX_SECTION_DESC_SIZE]; + + +} SECTION, *PSECTION; + + +typedef struct _FUNCTION_ELEMENTS { + + ULONG ErrorCount ; + + PSECTION NewFirstSection ; + PSECTION NewSecondSection ; + + DOUBLE FirstSectionID ; + DOUBLE SecondSectionID ; + + BOOLEAN FirstSectionSynchronize ; + BOOLEAN SecondSectionSynchronize ; + BOOLEAN SectionEndsNotSynchronized; + BOOLEAN SkipLine ; + + LINE FirstSectionCurrentLine ; + LINE SecondSectionCurrentLine ; + + UCHAR CombinedLineVariation ; + UCHAR Padding[UCHAR_REMAINDER] ; + +} FUNCTION_ELEMENTS, *PFUNCTION_ELEMENTS; + +#if !( defined(lint) || defined(_lint) ) +#if i386 +#pragma warning(disable:4103) +#endif +#pragma pack() +#endif + + + + +// +// MACROS +// +#define CloseFiles( a, b ) { \ + if ( a.FileP != (FILE *)NULL ) fclose( a.FileP ); \ + if ( b.FileP != (FILE *)NULL ) fclose( b.FileP ); \ + } + +#define CreateSection() calloc( 1, sizeof( SECTION ) ) +#define DestroySection( a ) free( a ) +#define ClearAndSetLine( a, b ) { memset( (b), 0, sizeof( LINE ) ); (a)->CurrentLine = (b); } +#define CreateFunctionElements() calloc( 1, sizeof( FUNCTION_ELEMENTS ) ) +#define DestroyFunctionElements( a ) free( a ) + +#define InsertToken( a, b ) { \ + a->NextToken = b; \ + b = a; \ + } +#define DestroyToken( a ) free( a ) + + + +// +// Function definitions +// +VOID _cdecl main ( INT , CHAR ** ); +VOID Usage ( VOID ); +BOOLEAN GetFilePair ( PCHAR * , PCHAR * , PCHAR ); +BOOLEAN CompareFiles ( PMFILE , PMFILE , FILE * , ULONG * ); +BOOLEAN OpenFiles ( PMFILE , PCHAR , PMFILE , PCHAR ); +BOOLEAN CompareFiles ( PMFILE , PMFILE , FILE * , PULONG ); +BOOLEAN CompareSections ( PSECTION, PSECTION, FILE * , PULONG ); +BOOLEAN GetNextLine ( PSECTION ); +BOOLEAN DoNotSkipThisLine ( PSECTION ); +VOID LineType ( PSECTION ); +BOOLEAN ExtractResults ( PSECTION ); +BOOLEAN ExtractBetweenValues ( PSECTION ); +BOOLEAN CombinedVariation ( PSECTION, PSECTION, PUCHAR ); +RESULT CompareLines ( PSECTION, PSECTION ); +BOOLEAN InitializeSectionControl ( PSECTION, PSECTION ); +VOID PrintComparisonResults ( PSECTION, PSECTION, RESULT , ULONG , FILE * ); +VOID PrintSectionInformation ( PSECTION, FILE * ); +DOUBLE ExtractSectionIDFromLine ( PSECTION ); +BOOLEAN CheckSectionIDFromCurrentLines ( PSECTION, PSECTION ); +BOOLEAN CompareLinesAndPrintResults ( PSECTION, PSECTION, PULONG , FILE * ); +VOID TokenInsertInSection ( PSECTION ); +RESULT MatchTopToken ( PTOKEN_LIST, PTOKEN_LIST ); +VOID CompareTokensAndPrintResults ( PSECTION, PSECTION, PULONG , FILE * ); +BOOLEAN MayDifferExistsInOneOrMoreLines( PSECTION, PSECTION ); diff --git a/private/ntos/ndis/testprot/tpdiff/makefile b/private/ntos/ndis/testprot/tpdiff/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/testprot/tpdiff/sources b/private/ntos/ndis/testprot/tpdiff/sources new file mode 100644 index 000000000..ca52757fa --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff/sources @@ -0,0 +1,48 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=testprot +MINORCOMP=tpdiff + +TARGETNAME=tpdiff +TARGETPATH=obj +TARGETTYPE=LIBRARY + +INCLUDES=..\..\wrapper;..\inc;..\..\..\inc + +SOURCES=tpdiff.c + +i860_SOURCES= + +i386_SOURCES= + +MIPS_SOURCES= + +RELATIVE_DEPTH=..\..\.. +NTTEST= +OPTIONAL_NTTEST= + +UMTYPE=console +UMAPPL=tpdiff +UMLIBS=$(BASEDIR)\public\sdk\lib\*\setargv.obj diff --git a/private/ntos/ndis/testprot/tpdiff/tpdiff.c b/private/ntos/ndis/testprot/tpdiff/tpdiff.c new file mode 100644 index 000000000..739227889 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdiff/tpdiff.c @@ -0,0 +1,1749 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tpdiff.c + +Abstract: + + This is the main component of the NDIS 3.0 MAC Tester log file program. + +Author: + + Tom Adams (tomad) 2-Apr-1992 + +Revision History: + + 2-Apr-1992 tomad + + created + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> + +#include <windows.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + + +// +// TpDiff function prototypes +// + +DWORD +TpDiffInitializeFiles( + IN WORD argc, + IN LPSTR argv[] + ); + +VOID +TpDiffFreeFiles( + VOID + ); + + +DWORD +TpDiffInitLogFileList( + IN LPSTR LogFileList + ); + +VOID +TpDiffFreeLogFileList( + VOID + ); + +DWORD +TpDiffLoadNextLogFilePair( + VOID + ); + +DWORD +TpDiffOpenLogFiles( + VOID + ); + +VOID +TpDiffFreeLogFiles( + VOID + ); + +DWORD +TpDiffInitDiffFile( + IN LPSTR DiffFile + ); + +DWORD +TpDiffWriteToDiffFile( + IN LPSTR Buffer + ); + +DWORD +TpDiffWriteErrorToDiffFile( + IN LPSTR Buffer + ); + + +VOID +TpDiffFreeDiffFile( + VOID + ); + +DWORD +TpDiffCompareLogFiles( + VOID + ); + +DWORD +TpDiffGetNextLine( + IN PBYTE Buffer, + IN PDWORD BufOffSet, + IN DWORD BufSize, + IN PDWORD LineNumber, + OUT PBYTE Line + ); + +DWORD +TpDiffGetResults( + IN PBYTE Buffer + ); + +BOOL +TpDiffMayValuesDiffer( + IN PBYTE Buffer + ); + +BOOL +TpDiffMustLastTwoValuesEqual( + IN PBYTE Buffer + ); + +VOID +TpDiffUsage ( + VOID + ); + +// +// TpDiff Global variables +// + +BYTE LogFileListName[256]; +BYTE LogFileName[256]; +BYTE KnownLogFileName[256]; +BYTE DiffFileName[256]; + +HANDLE DiffFileHandle = NULL; + +PBYTE LogFileListBuffer = NULL; +DWORD LogFileListSize = 0; +DWORD LogFileListOffset = 0; + +PBYTE LogFileBuffer = NULL; +DWORD LogFileSize = 0; +DWORD LogFileOffset; +DWORD LogFileLineNumber; + +PBYTE KnownLogFileBuffer = NULL; +DWORD KnownLogFileSize = 0; +DWORD KnownLogFileOffset; +DWORD KnownLogFileLineNumber; + +PBYTE DiffBuffer = NULL; +BOOL LoggingToScreen = FALSE; + +BOOL MoreFilesToDiff = FALSE; + +BYTE LogFileLine[256]; +BYTE KnownLogFileLine[265]; + +DWORD ResultsValue = 0; +DWORD LastResultsValue = 0; + +DWORD LogFileDifferences = 0; +DWORD TotalDifferences = 0; + +// +// the main routine for TpDiff. +// + + +VOID _cdecl +main( + IN WORD argc, + IN LPSTR argv[] + ) + +/*++ + +Routine Description: + + +Arguments: + + IN WORD argc - Supplies the number of parameters + IN LPSTR argv[] - Supplies the parameter list. + +Return Value: + + None. + +--*/ + +{ + DWORD Status; + + // + // Read the command line, and open the requested files and set + // them up to be processed. + // + + Status = TpDiffInitializeFiles( argc,argv ); + + if ( Status != NO_ERROR ) { + ExitProcess( Status ); + } + + // + // We have at least two files to compare so ... + // + + do { + + // + // Compare the LOG_FILE and KNOWN_LOG_FILE. + // + + Status = TpDiffCompareLogFiles(); + + if ( Status != NO_ERROR ) { + break; + } + + // + // Then see if there are any more files to compare. + // + + Status = TpDiffLoadNextLogFilePair(); + + if ( Status != NO_ERROR ) { + break; + } + + // + // and if so open them, and set up their respective buffers + // to be compared. + // + + Status = TpDiffOpenLogFiles(); + + if (( Status == ERROR_FILE_NOT_FOUND ) && + ( MoreFilesToDiff == TRUE )) { + + // + // We failed to open one of the logs files due to the fact + // that it did not exist, AND we are reading from a list of + // log/known log file pairs. We should get the next pair + // and try to open them. + // + + do { + + Status = TpDiffLoadNextLogFilePair(); + + if ( Status != NO_ERROR ) { + break; + } + + Status = TpDiffOpenLogFiles(); + + if (( Status != NO_ERROR ) && + ( Status != ERROR_FILE_NOT_FOUND )) { + break; + } + + } while (( MoreFilesToDiff == TRUE ) && + ( Status == ERROR_FILE_NOT_FOUND )); + + if ( Status != NO_ERROR ) { + break; + } + } else if ( Status != NO_ERROR ) { + break; + } + + } while ( MoreFilesToDiff == TRUE ); + + printf("\n\tTpDiff Pass Contained %d Total Differences.\n",TotalDifferences); + + if ( LoggingToScreen == FALSE ) { + + LPSTR TmpBuf = DiffBuffer; + + TmpBuf += (BYTE)sprintf(TmpBuf,"\nTpDiff: Contained %d Total Differences.\n", + TotalDifferences); + + Status = TpDiffWriteToDiffFile( TmpBuf ); + + if ( Status != NO_ERROR ) { + printf("\n\tTpDiff: failed to write statistics to logfile, return %d\n", + Status); + } + } + + // + // Free all the files handles, and buffers previously allocated. + // + + TpDiffFreeFiles(); + + ExitProcess( (DWORD)NO_ERROR ); +} + + +DWORD +TpDiffInitializeFiles( + IN WORD argc, + IN LPSTR argv[] + ) + +/*++ + +Routine Description: + + This routine parses the command line arguments, and opens the files + that are passed in on the command line. + +Arguments: + + IN WORD argc - Supplies the number of arguments passed in at startup. + + IN LPTSTR argv[] - Supplies 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 files are opened + successfully. If the files fail to open, then the error returned + from the open routines are returned. ERROR_INALID_PARAMETER + otherwise. + +--*/ + +{ + DWORD Status; + + // + // See if we have enough arguments on the commmand line. + // + + if ( argc == 1 ) { + TpDiffUsage(); + return ERROR_INVALID_PARAMETER; + } else if (( argc != 4 ) && ( argc != 3 )) { + printf("\n\tTpDiff: ERROR - Invalid number of arguments\n"); + TpDiffUsage(); + return ERROR_INVALID_PARAMETER; + } + + // + // Is the first argument a LOG_FILE_NAME or the LOG_FILES_LIST switch ? + // + + if (!strcmp(argv[1],"-f")) { + + // + // It is the LOG_FILES_LIST switch. We need four arguments for + // this case, so make sure we have them. + + if ( argc != 4 ) { + printf("\n\tTpDiff: ERROR - Invalid number of arguments\n"); + TpDiffUsage(); + return ERROR_INVALID_PARAMETER; + } + + // + // It is the LOG_FILES_LIST switch. First set the flag indicating + // that there are possible more then one pair of files to diff. + // + + MoreFilesToDiff = TRUE; + + // + // We have a file containing the logfile/knownlogfile name pairs. + // Set up the name to be opened, and then open it now and read + // the contents. + // + + Status = TpDiffInitLogFileList( argv[2] ); + + if ( Status != NO_ERROR ) { + return Status; + } + + // + // Now read the first file pair from the list. The names + // will be stored in the global vars LogFileName and + // KnownLogFileName. + // + + Status = TpDiffLoadNextLogFilePair(); + + if ( Status != NO_ERROR ) { + return Status; + } + } else { + + // + // We have been passed two files to diff. set up the names to + // be opened. + // + + strcpy( LogFileName,argv[1] ); + strcpy( KnownLogFileName,argv[2] ); + } + + // + // Now open the first two log files to diff. The file handles will be + // stored in the global vars LogFileNameHandle and KnownLogFileNameHandle. + // + + Status = TpDiffOpenLogFiles(); + + if (( Status == ERROR_FILE_NOT_FOUND ) && + ( MoreFilesToDiff == TRUE )) { + + // + // We failed to open one of the logs files due to the fact + // that it did not exist, AND we are reading from a list of + // log/known log file pairs. We should get the next pair + // and try to open them. + // + + do { + + Status = TpDiffLoadNextLogFilePair(); + + if ( Status != NO_ERROR ) { + break; + } + + Status = TpDiffOpenLogFiles(); + + if (( Status != NO_ERROR ) && + ( Status != ERROR_FILE_NOT_FOUND )) { + break; + } + + } while (( MoreFilesToDiff == TRUE ) && + ( Status == ERROR_FILE_NOT_FOUND )); + + if ( Status != NO_ERROR ) { + return Status; + } + } else if ( Status != NO_ERROR ) { + return Status; + } + + // + // Finally setup the results file name and open it. This is the file + // any differences between the two log files will be written to. + // + + Status = TpDiffInitDiffFile( argv[3] ); + + if ( Status != NO_ERROR ) { + return Status; + } + + return NO_ERROR; +} + + +VOID +TpDiffFreeFiles( + VOID + ) + +/*++ + +Routine Description: + + This routine closes all open file handles and frees any corresponding + buffers. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + // + // Free the LOG_FILE_LIST resources. + // + + TpDiffFreeLogFileList(); + + // + // Free the LOG_FILE and KNOWN_LOG_FILE resources. + // + + TpDiffFreeLogFiles(); + + // + // Free the DIFF_FILE resources. + // + + TpDiffFreeDiffFile(); +} + + +DWORD +TpDiffInitLogFileList( + IN LPSTR LogFileList + ) + +/*++ + +Routine Description: + + This routine opens and reads the LOG_FILE_LIST file into a newly + allocated buffer. The handle, buffer and filename are all attached + to global LOG_FILE_LIST variables. + +Arguments: + + IN LPSTR LogFileList - Supplies the name of the LOG_FILE_LIST file + to open. + +Return Value: + + DWORD - If NO_ERROR the file was opened and read into the buffer. + otherwise there was a failure that will cause the application + to un-initialize and exit. + +--*/ + +{ + DWORD Status; + HANDLE LogFileListHandle = NULL; + HANDLE LogFileListMapHandle = NULL; + + // + // First Open the LOG_FILE_LIST file. + // + + strcpy( LogFileListName,LogFileList ); + + LogFileListHandle = CreateFile( + LogFileListName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if ( LogFileListHandle == (HANDLE)-1 ) { + Status = GetLastError(); + printf("\n\tTpDiff: Failed to open LOG_FILE_LIST \"%s\", returned %ld.\n", + LogFileListName,Status); + return Status; + } + + // + // then find its size. + // + + LogFileListSize = GetFileSize( LogFileListHandle,NULL ); + + if ( LogFileListSize == -1 ) { + Status = GetLastError(); + printf("\n\tTpDiff: failed find LOG_FILE_LIST size, returned %ld.\n",Status); + CloseHandle( LogFileListHandle ); + return Status; + } else if ( LogFileListSize == 0 ) { + printf("\n\tTpDiff: LOG_FILE_LIST is empty, nothing to compare.\n"); + CloseHandle( LogFileListHandle ); + return ERROR_FILE_NOT_FOUND; + } + + // + // and create a file mapping. + // + + LogFileListMapHandle = CreateFileMapping( + LogFileListHandle, + NULL, + PAGE_READONLY, + 0, + LogFileListSize, + NULL + ); + + if ( LogFileListMapHandle == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map LOG_FILE_LIST \"%s\", returned %d", + LogFileListName,Status); + CloseHandle( LogFileListHandle ); + return Status; + } + + // + // We're done with the file handle so close it now. + // + + CloseHandle( LogFileListHandle ); + + // + // Now create a View of the mapped file. + // + + LogFileListBuffer = MapViewOfFile( + LogFileListMapHandle, + FILE_MAP_READ, + 0, + 0, + LogFileListSize + ); + + if ( LogFileListBuffer == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map view of LOG_FILE_LIST \"%s\", returned %d", + LogFileListName,Status); + CloseHandle( LogFileListMapHandle ); + return Status; + } + + // + // We're done with the map handle so close it now. + // + + CloseHandle( LogFileListMapHandle ); + + return NO_ERROR; +} + + +VOID +TpDiffFreeLogFileList( + VOID + ) +{ + // + // Simply UnMap the log file list buffer and null it out. + // + + if ( LogFileListBuffer != NULL ) { + UnmapViewOfFile( LogFileListBuffer ); + LogFileListBuffer = NULL; + } +} + + +DWORD +TpDiffLoadNextLogFilePair( + VOID + ) + +/*++ + +Routine Description: + + This routine reads the next two log file names from the log file list + buffer and moves the log file list pointer past them. The format of + the log file list is pairs of LOG_FILE_NAME KNOWN_LOG_FILE_NAME with + each pair residing on the same line in the file. + +Arguments: + + None + +Return Value: + + DWORD - NO_ERROR if the next two files are found, ERROR_INVALID_PARAMETER + if the log file list is the wrong format. + +--*/ + +{ + DWORD TmpOffset; + DWORD Length; + + // + // If we are not reading files from a loglistfile the MoreFilesToDiff + // flag will be set to FALSE, so just return. + // + + if ( MoreFilesToDiff == FALSE ) { + return ERROR_NO_MORE_FILES; + } + + // + // Move the LOG_FILE_LIST pointer to the beginning of the next + // file name in the list. + // + + while ((((( LogFileListBuffer[LogFileListOffset] == ' ' ) || + ( LogFileListBuffer[LogFileListOffset] == '\t')) || + ( LogFileListBuffer[LogFileListOffset] == '\r')) || + ( LogFileListBuffer[LogFileListOffset] == '\n')) && + ( LogFileListOffset < LogFileListSize )) { + + LogFileListOffset++; + } + + if ( LogFileListOffset == LogFileListSize ) { + LogFileName[0] = '\0'; + KnownLogFileName[0] = '\0'; + return ERROR_NO_MORE_FILES; + } + + // + // then find the length of the next file name. + // + + Length = 0; + TmpOffset = LogFileListOffset; + + while ((((( LogFileListBuffer[TmpOffset] != ' ' ) && + ( LogFileListBuffer[TmpOffset] != '\t' )) && + ( LogFileListBuffer[TmpOffset] != '\r')) && + ( LogFileListBuffer[TmpOffset] != '\n')) && + ( TmpOffset < LogFileListSize )) { + + Length++; + TmpOffset++; + } + + // + // copy it to the global var LogFileName, and null terminate it. + // + + strncpy( LogFileName,&LogFileListBuffer[LogFileListOffset],Length ); + + LogFileName[Length] = '\0'; + + // + // then move the LOG_FILE_LIST pointer past the LogFileName + // + + LogFileListOffset = TmpOffset + 1; + + // + // and search to the beginning of the next file name + // + + while ((( LogFileListBuffer[LogFileListOffset] == ' ' ) || + ( LogFileListBuffer[LogFileListOffset] == '\t' )) && + ( LogFileListOffset < LogFileListSize )) { + + LogFileListOffset++; + + if (( LogFileListBuffer[LogFileListOffset] == '\n' ) || + ( LogFileListBuffer[LogFileListOffset] == '\r' )) { + + KnownLogFileName[0] = '\0'; + + MoreFilesToDiff = FALSE; + + printf("\tTpDiff: ERROR - LOG_FILE_LIST must have filename pairs on\n"); + printf("\t same line in file.\n"); + + return ERROR_INVALID_PARAMETER; + } + } + + // + // then find the length of the next file name. + // + + Length = 0; + TmpOffset = LogFileListOffset; + + while ((((( LogFileListBuffer[TmpOffset] != ' ' ) && + ( LogFileListBuffer[TmpOffset] != '\t' )) && + ( LogFileListBuffer[TmpOffset] != '\r')) && + ( LogFileListBuffer[TmpOffset] != '\n')) && + ( TmpOffset < LogFileListSize )) { + + Length++; + TmpOffset++; + } + + // + // copy it to the global var KnownLogFileName, and null terminate it. + // + + strncpy( KnownLogFileName,&LogFileListBuffer[LogFileListOffset],Length ); + + KnownLogFileName[Length] = '\0'; + + // + // then move the LOG_FILE_LIST pointer past the KnownLogFileName + // + + LogFileListOffset = TmpOffset + 1; + + return NO_ERROR; +} + + +DWORD +TpDiffOpenLogFiles( + VOID + ) + +/*++ + +Routine Description: + + This routine opens the file names stored in the global variables + LogFileName and KnownLogFile name, creates a buffer for each and + reads the file contents into the respective buffer. + +Arguments: + + None + +Return Value: + + DWORD - If NO_ERROR the files were opened and read into the buffers. + otherwise there was a failure that will cause the application + to un-initialize and exit. + +--*/ + +{ + DWORD Status; + HANDLE LogFileHandle = NULL; + HANDLE LogFileMapHandle = NULL; + HANDLE KnownLogFileHandle = NULL; + HANDLE KnownLogFileMapHandle = NULL; + + // + // First open the LOG_FILE file. + // + + if (( LogFileName[0] == '\0' ) || ( KnownLogFileName[0] == '\0' )) { + return ERROR_NO_MORE_FILES; + } + + LogFileHandle = CreateFile( + LogFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if ( LogFileHandle == (HANDLE)-1 ) { + Status = GetLastError(); + + if ( Status == ERROR_FILE_NOT_FOUND ) { + TpDiffWriteErrorToDiffFile( "Tpdiff: WARNING - Failed to open LOG_FILE \"" ); + TpDiffWriteErrorToDiffFile( LogFileName ); + TpDiffWriteErrorToDiffFile( "\".\n"); + } + + printf("\n\tTpDiff: Failed to open LOG_FILE \"%s\", returned %ld.\n", + LogFileName,Status); + return Status; + } + + // + // then find its size. + // + + LogFileSize = GetFileSize( LogFileHandle,NULL ); + + if ( LogFileSize == -1 ) { + Status = GetLastError(); + printf("\n\tTpDiff: failed find LOG_FILE size - returned %ld.\n",Status); + CloseHandle( LogFileHandle ); + return Status; + } else if ( LogFileSize == 0 ) { + printf("\n\tTpDiff: LOG_FILE \"%s\" is empty, nothing to compare.\n",LogFileName); + CloseHandle( LogFileHandle ); + return ERROR_NO_MORE_FILES; + + } + + // + // and create a file mapping. + // + + LogFileMapHandle = CreateFileMapping( + LogFileHandle, + NULL, + PAGE_READONLY, + 0, + LogFileSize, + NULL + ); + + if ( LogFileMapHandle == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map LOG_FILE \"%s\", returned %d", + LogFileName,Status); + CloseHandle( LogFileHandle ); + return Status; + } + + // + // We're done with the file handle so close it now. + // + + CloseHandle( LogFileHandle ); + + // + // Now create a View of the mapped file. + // + + LogFileBuffer = MapViewOfFile( + LogFileMapHandle, + FILE_MAP_READ, + 0, + 0, + LogFileSize + ); + + if ( LogFileBuffer == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map view of LOG_FILE \"%s\", returned %d", + LogFileName,Status); + CloseHandle( LogFileMapHandle ); + return Status; + } + + // + // We're done with the map handle so close it now. + // + + CloseHandle( LogFileMapHandle ); + + // + // Now reset the offset into the LogFilebuffer and the line number + // counter to zero. + // + + LogFileOffset = 0; + LogFileLineNumber = 1; + + // + // Then open the KNOWN_LOG_FILE file. + // + + KnownLogFileHandle = CreateFile( + KnownLogFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if ( KnownLogFileHandle == (HANDLE)-1 ) { + Status = GetLastError(); + + if ( Status == ERROR_FILE_NOT_FOUND ) { + TpDiffWriteErrorToDiffFile("TpDiff: WARNING Failed to open KNOWN_LOG_FILE \""); + TpDiffWriteErrorToDiffFile(KnownLogFileName); + TpDiffWriteErrorToDiffFile("\".\n"); + } + + printf("\n\tTpDiff: Failed to open KNOWN_LOG_FILE \"%s\", returned %ld.\n", + KnownLogFileName,Status); + return Status; + } + + // + // then find its size. + // + + KnownLogFileSize = GetFileSize( KnownLogFileHandle,NULL ); + + if ( KnownLogFileSize == -1 ) { + Status = GetLastError(); + printf("\n\tTpDiff: failed find KNOWN_LOG_FILE size - returned %ld.\n",Status); + CloseHandle( KnownLogFileHandle ); + return Status; + } else if ( KnownLogFileSize == 0 ) { + printf("\n\tTpDiff: KNOWN_LOG_FILE \"%s\" is empty, nothing to compare.\n",KnownLogFileName); + CloseHandle( KnownLogFileHandle ); + return ERROR_NO_MORE_FILES; + } + + // + // and create a file mapping. + // + + KnownLogFileMapHandle = CreateFileMapping( + KnownLogFileHandle, + NULL, + PAGE_READONLY, + 0, + KnownLogFileSize, + NULL + ); + + if ( KnownLogFileMapHandle == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map KNOWN_LOG_FILE \"%s\", returned %d", + KnownLogFileName,Status); + CloseHandle( KnownLogFileHandle ); + return Status; + } + + // + // We're done with the file handle so close it now. + // + + CloseHandle( KnownLogFileHandle ); + + // + // Now create a View of the mapped file. + // + + KnownLogFileBuffer = MapViewOfFile( + KnownLogFileMapHandle, + FILE_MAP_READ, + 0, + 0, + KnownLogFileSize + ); + + if ( KnownLogFileBuffer == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: Unable to map view of KNOWN_LOG_FILE \"%s\", returned %d", + KnownLogFileName,Status); + CloseHandle( KnownLogFileMapHandle ); + return Status; + } + + // + // We're done with the map handle so close it now. + // + + CloseHandle( KnownLogFileMapHandle ); + + // + // Now reset the offset into the KnownLogFilebuffer to zero. + // and return. + // + + KnownLogFileOffset = 0; + KnownLogFileLineNumber = 1; + + return NO_ERROR; +} + + +VOID +TpDiffFreeLogFiles( + VOID + ) + +/*++ + +Routine Description: + + This routine frees the LOG_FILE and KNOWN_LOG_FILE buffers and + nulls their respective pointers. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if ( LogFileBuffer != NULL ) { + UnmapViewOfFile( LogFileBuffer ); + LogFileBuffer = NULL; + } + + if ( KnownLogFileBuffer != NULL ) { + UnmapViewOfFile( KnownLogFileBuffer ); + KnownLogFileBuffer = NULL; + } +} + + +DWORD +TpDiffInitDiffFile( + IN LPSTR DiffFile + ) + +/*++ + +Routine Description: + + This routine opens the DIFF_FILE. The handle and file name are + attached to global DIFF_FILE variables. A buffer is also allocated + that is used to any output to the DIFF_FILE. + +Arguments: + + IN LPSTR DiffFile - Supplies the name of the DIFF_FILE to open. + +Return Value: + + DWORD - The Status of the OPEN. + +--*/ + +{ + DWORD Status; + + // + // If a Diff file name was passed in on the command line, + // Open the DIFF_FILE file. + // + + if ( DiffFile != NULL ) { + + strcpy( DiffFileName,DiffFile ); + + DiffFileHandle = CreateFile( + DiffFileName, + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if ( DiffFileHandle == (HANDLE)-1 ) { + Status = GetLastError(); + printf("\n\tTpDiff: Failed to open DIFFS_FILE \"%s\", returned %ld.\n", + DiffFileName,Status); + return Status; + } + + } else { // We will just write the DIFFS to the console. + + DiffFileHandle = GetStdHandle(STD_OUTPUT_HANDLE); + LoggingToScreen = TRUE; + } + + DiffBuffer = GlobalAlloc( + GMEM_FIXED | GMEM_ZEROINIT, + 0x1000 + ); + + if ( DiffBuffer == NULL ) { + Status = GetLastError(); + printf("\n\tTpDiff: failed to alloc DIFF_FILE buffer, returned %ld.\n", + Status); + + if ( strlen( DiffFile ) != 0 ) { // close the diff file + CloseHandle( DiffFileHandle ); + } + + DiffFileHandle = NULL; + return Status; + } + + return NO_ERROR; +} + + +DWORD +TpDiffWriteToDiffFile( + IN LPSTR Buffer + ) + +/*++ + +Routine Description: + + This routine simply writes a string to the DIFF_FILE. + +Arguments: + + IN LPSTR Buffer - Supplies the string to write to the DIFF_FILE. + +Return Value: + + DWORD - The Status of the call to WriteFile. + +--*/ + + +{ + DWORD Status; + DWORD BytesWritten; + + if ( !WriteFile( + DiffFileHandle, + DiffBuffer, + (Buffer-DiffBuffer), + &BytesWritten, + NULL + )) { + + Status = GetLastError(); + printf("\n\tTpDiff: Write to DIFFS_FILE failed, returned %ld\n",Status); + return Status; + } + + return NO_ERROR; +} + + +DWORD +TpDiffWriteErrorToDiffFile( + IN LPSTR Buffer + ) + +/*++ + +Routine Description: + + This routine simply writes a string to the DIFF_FILE. + +Arguments: + + IN LPSTR Buffer - Supplies the string to write to the DIFF_FILE. + +Return Value: + + DWORD - The Status of the call to WriteFile. + +--*/ + + +{ + DWORD Status; + DWORD BytesWritten; + DWORD BufLength = 0; + + BufLength = strlen( Buffer ); + + if ( !WriteFile( + DiffFileHandle, + Buffer, + BufLength, + &BytesWritten, + NULL + )) { + + Status = GetLastError(); + printf("\n\tTpDiff: Write to DIFFS_FILE failed, returned %ld\n",Status); + return Status; + } + + return NO_ERROR; +} + + +VOID +TpDiffFreeDiffFile( + VOID + ) +{ + // + // Close the DIFF_FILE, deallocate the diff buffer, and null out + // their pointers. + // + + if ( DiffFileHandle != NULL ) { + + if ( strlen( DiffFileName ) != 0 ) { + CloseHandle( DiffFileHandle ); + } + + DiffFileHandle = NULL; + } + + if ( DiffBuffer != NULL ) { + GlobalFree( DiffBuffer ); + DiffBuffer = NULL; + } +} + + +DWORD +TpDiffCompareLogFiles( + VOID + ) + +/*++ + +Routine Description: + + This is the main compare routine of the TpDiff utility. It compares the + log file and known log file line by line for diffences. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + DWORD Status; + DWORD Length; + DWORD KnownLength; + DWORD CmpLength; + LPSTR TmpBuf = DiffBuffer; + + printf("\n\tTpDiff: comparing %s and %s ...\n", + LogFileName,KnownLogFileName); + do { + + // + // Get the next line of the Log File. + // + + Length = TpDiffGetNextLine( + LogFileBuffer, + &LogFileOffset, + LogFileSize, + (PDWORD)&LogFileLineNumber, + (PBYTE)&LogFileLine + ); + + if ( Length != 0 ) { + + // + // Get the value of the Statitics results for that line, + // first storing away the last lines value. + // + + LastResultsValue = ResultsValue; + + ResultsValue = TpDiffGetResults( LogFileLine ); + } + + // + // And the next line of the Known Log File. + // + + KnownLength = TpDiffGetNextLine( + KnownLogFileBuffer, + &KnownLogFileOffset, + KnownLogFileSize, + (PDWORD)&KnownLogFileLineNumber, + (PBYTE)&KnownLogFileLine + ); + + // + // Compare them with respect to the length of the longer of the + // two lines. + // + + if ( Length >= KnownLength ) { + CmpLength = Length; + } else { + CmpLength = KnownLength; + } + + if (( CmpLength != 0 ) && + ( memcmp( LogFileLine,KnownLogFileLine,CmpLength ) != 0 )) { + + if (( TpDiffMayValuesDiffer( LogFileLine )) || + ( TpDiffMayValuesDiffer( KnownLogFileLine ))) { + + // + // The line contains a MAY_DIFFER flag, so ignore the + // differences. + // + + } else if (( TpDiffMustLastTwoValuesEqual( LogFileLine )) && + ( LastResultsValue == ResultsValue )) { + } else { + + LogFileDifferences++; + + // + // If lines did not match, and the line does not contain the + // MAY_DIFFER string, or It contained EQUAL_LAST, but the + // stats value weren't equal, then write the info to the + // diff file. + // + + TmpBuf += (BYTE)sprintf(TmpBuf,"Logfile: %s - Line Number: %ld\n", + LogFileName,LogFileLineNumber); + TmpBuf += (BYTE)sprintf(TmpBuf,"Found: %s\n",LogFileLine); + TmpBuf += (BYTE)sprintf(TmpBuf,"Expected: %s\n\n",KnownLogFileLine); + + if (( TpDiffMustLastTwoValuesEqual( LogFileLine )) && + ( LastResultsValue != ResultsValue )) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"TpDiff: ERROR - The last two test values (%ld) and (%ld) did not equal.\n\n", + LastResultsValue,ResultsValue); + } + + Status = TpDiffWriteToDiffFile( TmpBuf ); + + if ( Status != NO_ERROR ) { + printf("\n\tTpDiff: failed to write difference to logfile, return %d\n", + Status); + return Status; + } + + // + // and then reset the TmpBuf for the next go round. + // + + TmpBuf = DiffBuffer; + } + } + + } while (( Length != 0 ) || ( KnownLength != 0 )); + + // + // We have finished this log file, print the number of differences + // to the log, and to the screen, update the total errors counter, + // and reset the script error counter. + // + + printf("\n\tLogFile %s Contained %d Differences.\n", + LogFileName,LogFileDifferences); + + if ( LoggingToScreen == FALSE ) { + + TmpBuf += (BYTE)sprintf(TmpBuf,"\nLogFile %s Contained %d Differences.\n", + LogFileName,LogFileDifferences); + + Status = TpDiffWriteToDiffFile( TmpBuf ); + + if ( Status != NO_ERROR ) { + printf("\n\tTpDiff: failed to write statistics to logfile, return %d\n", + Status); + return Status; + } + } + + TotalDifferences += LogFileDifferences; + LogFileDifferences = 0; + + return NO_ERROR; +} + + +DWORD +TpDiffGetNextLine( + IN PBYTE Buffer, + IN PDWORD BufOffset, + IN DWORD BufSize, + IN PDWORD LineNumber, + OUT PBYTE Line + ) + +/*++ + +Routine Description: + + This routine take a file buffer and writes the next line of the + file into a line buffer. + +Arguments: + + IN PBYTE FileBuffer - Supplies the buffer to read the next line from. + IN PDWORD *BufOffset - Supplies the current offset in to the file buffer. + IN DWORD BufSize - Supplies the size of the file buffer. + OUT PBYTE FileLine - Returns the next line of the buffer. + +Return Value: + + DWORD - The length of the line written into the buffer. Zero if the + file is empty. + +--*/ + +{ + DWORD Length = 0; + DWORD i; + DWORD Offset = (DWORD)*BufOffset; + PBYTE TmpLine; + + TmpLine = Line; + + // + // Ignore any empty lines, and the last lines carriage + // returns/line feed pair. + // + + while (((( Buffer[Offset] == '\n' ) || + ( Buffer[Offset] == '\r' )) || + ( Buffer[Offset] == 0x1a )) && // my editor quirk + ( Offset < BufSize )) { + + if ( Buffer[Offset] == '\n' ) { + (*LineNumber)++; + } + + Offset++; + + if ( Offset >= BufSize ) { + + // + // We have run off the end of this log file. + // Null terminate the Line buffer. + // + + Line[0] = '\0'; + + // + // Update the Buffer Offset with the new offset value. + // + + *BufOffset = (DWORD)Offset; + + // + // and return a length of zero for the Line buffer. + // + + return Length; + } + } + + // + // while we are on the same line, copy the characters to the + // Line buffer. + // + + while ((((( Buffer[Offset] != EOF ) && + ( Buffer[Offset] != '\n' )) && + ( Buffer[Offset] != '\r' )) && + ( Buffer[Offset] != 0x1a )) && // my editor quirk + ( Offset <= BufSize )) { + + *Line++ = Buffer[Offset++]; + Length++; + } + + // + // Now Null terminate the Line buffer, and then null out any spaces, + // tabs or carriage returns and line feeds that may exist at the + // end of the string. + // + + *Line = '\0'; + i = Length; + + while ( --i > 0 ) { + + if (( TmpLine[i] == 0x20 ) || // Space + ( TmpLine[i] == 0x09 )) { // Tab + + TmpLine[i] = '\0'; + Length--; + } else { + break; + } + } + + // + // Update the Buffer Offset with the new offset value. + // + + *BufOffset = (DWORD)Offset; + + // + // and return the length of the Line buffer. + // + + return Length; +} + + +DWORD +TpDiffGetResults( + IN PBYTE Buffer + ) + +/*++ + +Routine Description: + + This routine finds the string result value in the buffer, converts + it to an integer, and returns the integer value. + +Arguments: + + IN PBYTE Buffer - Supplies a null terminated buffer containing + the possible string value. + +Return Value: + + DWORD - the integer result value found in the string. -1 otherwise. + +--*/ + +{ + DWORD Results = 0xFFFFFFFF; + LPSTR Char = (LPSTR)Buffer; + LPSTR NextChar = (LPSTR)Buffer; // Anything that isn't NULL. + + if ( Buffer == NULL ) { + return Results; + } + + NextChar = strpbrk( Char,"=" ); + + if ( NextChar != NULL ) { + *NextChar++; + } else { + return Results; + } + + while (( *NextChar == ' ' ) || ( *NextChar == '\t' )) { + *NextChar++; + } + + Results = atol( NextChar ) ; + + return Results; +} + + +BOOL +TpDiffMayValuesDiffer( + IN PBYTE Buffer + ) + +/*++ + +Routine Description: + +Arguments: + + IN PBYTE Buffer - Supplies a null terminated buffer containing the + possible text string "EQUAL_LAST" value. + +Return Value: + + BOOL - TRUE if "MAY_DIFFER" exists in the string, FALSE otherwise. + +--*/ + +{ + LPSTR String; + + String = strstr( Buffer,"MAY_DIFFER" ); + + if ( String == NULL ) { + return FALSE; + } + + return TRUE; +} + + + +BOOL +TpDiffMustLastTwoValuesEqual( + IN PBYTE Buffer + ) + +/*++ + +Routine Description: + +Arguments: + + IN PBYTE Buffer - Supplies a null terminated buffer containing the + possible text string "EQUAL_LAST" value. + +Return Value: + + BOOL - TRUE if "EQUAL_LAST" exists in the string, FALSE otherwise. + +--*/ + +{ + LPSTR String; + + String = strstr( Buffer,"EQUAL_LAST" ); + + if ( String == NULL ) { + return FALSE; + } + + return TRUE; +} + + +VOID +TpDiffUsage ( + VOID + ) + +/*++ + +Routine Description: + + This routine prints out the TpDiff Usage statement. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + printf("\n\tUSAGE: TPDIFF [LOG_FILE] [KNOWN_LOG_FILE] [DIFFS_FILE]\n\n"); + + printf("\tWhere:\n\n"); + + printf("\tLOG_FILE - is the log file that is to be verified\n"); + printf("\t for correctness.\n"); + + printf("\tKNOWN_LOG_FILE - is the known good log file that will be\n"); + printf("\t used to verify the log file.\n"); + + printf("\tDIFFS_FILE - is the file the differences, if any exist,\n"); + printf("\t between the log files and the known good log\n"); + printf("\t files will be written to. If no file name is\n"); + printf("\t given the differences will be printed to the\n"); + printf("\t console.\n"); + + printf("\t\t- OR -\n\n"); + + printf("\tTPDIFF -F [LOG_FILE_LIST] [DIFFS_FILE]\n\n"); + + printf("\tWhere:\n\n"); + + printf("\tLOG_FILE_LIST - is a file containing pairs of log file\n"); + printf("\t names and known good log file names. The\n"); + printf("\t pairs of file names must be on the same line\n"); + printf("\t in the file\n"); + + printf("\tDIFFS_FILE - is the file the differences, if any exist,\n"); + printf("\t between the log files and the known good log\n"); + printf("\t files will be written to.\n"); +} + + diff --git a/private/ntos/ndis/testprot/tpdrvr/buffer.c b/private/ntos/ndis/testprot/tpdrvr/buffer.c new file mode 100644 index 000000000..34ac561f8 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/buffer.c @@ -0,0 +1,313 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + buffer.c + +Abstract: + + This module implements the buffer manipulation routines for + Test Protocol. + +Author: + + Tom Adams (tomad) 15-Dec-1990 + +Environment: + + Kernel mode, FSD + +Revision History: + + Sanjeev Katariya (sanjeevk) 3-24-1993 + 1. Added function to free MDL's associated with Data block with the stress block + Effected Function: TpStressFreeDataBufferMdls() + 2. Changed functions TpStressInitDataBuffer() and TpStressFreeDataBuffers() to + handle two data buffer locations + +--*/ + +#include <ndis.h> +#include "tpdefs.h" +#include "tpprocs.h" + + +PNDIS_BUFFER +TpAllocateBuffer( + PUCHAR TmpBuf, + INT BufSize + ) + +/*++ + +Routine Description: + + This routine creates an NDIS_BUFFER. An NDIS_BUFFER is merely an + MDL that may be chained to other NDIS_BUFFERs to form an MDL chain. + This chain contains the actual contents of the NDIS frame that + will be sent on the wire. If the size of the buffer to be created + is zero, the size is temporarily set to one to be valid for + IoAllocateMdl. + +Arguments: + + TmpBuf - A pointer to the memory to be placed in the NDIS_BUFFER. + + BufSize - The size of TmpBuf. + +Return Value: + + PNDIS_BUFFER - A pointer to the new MDL that references the TmpBuf. + +--*/ + +{ + PMDL TmpMdl; + BOOLEAN Reset; + + Reset = FALSE; + + // + // IoAllocateMdl must be called with a positive value for the + // buffer size, so if TmpBuf is zero bytes long set the size to + // one temporarily. + // + + if ( BufSize == 0 ) { + BufSize = 1; + Reset = TRUE; + } + + // + // Allocate the MDL and set the various fields. + // + + TmpMdl = IoAllocateMdl( + TmpBuf, + BufSize, + TRUE, + FALSE, + NULL + ); + + if ( TmpMdl == NULL ) { + TpPrint0("TpAllocateBuffer: failed to allocate TmpMdl\n"); + return (PNDIS_BUFFER)NULL; + } + + MmBuildMdlForNonPagedPool( TmpMdl ); + + // + // if this is to be a zero by NDIS_BUFFER we must reset the MDL. + // + + if ( Reset == TRUE ) { + TmpMdl->ByteCount = 0; + } + + return (PNDIS_BUFFER)TmpMdl; +} + + +VOID +TpFreeBuffer( + PNDIS_BUFFER Buffer + ) + +/*++ + +Routine Description: + + This routine simply deallocates the MDL that was built in the routine + TpBuildBuffer. + +Arguments: + + Buffer - The PNDIS_BUFFER (PMDL) that is to be destroyed. + +Return Value: + + None. + +--*/ + +{ + IoFreeMdl( Buffer ); +} + + +VOID +TpStressInitDataBuffer( + POPEN_BLOCK OpenP, + INT BufferSize + ) + +/*++ + +Routine Description: + + This routine initializes the Data Buffers that will be referenced by + all packets as their data. It is twice as long as the maximum packet + allowable for the media in question, and contains an ascending sequence + of characters from 0x00 to 0xff repeating. This routine also allocates + the MDLs which reference these buffers. The MDLs are used by the packet + creation routines in the call IoBuildPartialMdl(); + +Arguments: + + OpenP - The Open Block to allocate the Data Buffer and MDL for. + + BufferSize - The size of the Data Buffer to allocate and initialize. + +Return Value: + + None - if successful two DataBuffers and two MDLs are referenced by this Open + Block + +--*/ + +{ + INT i, j; + + // + // Allocate the data buffers + // + NdisAllocateMemory( + (PVOID *)&OpenP->Stress->DataBuffer[0], + BufferSize, + 0, + HighestAddress + ); + NdisAllocateMemory( + (PVOID *)&OpenP->Stress->DataBuffer[1], + BufferSize, + 0, + HighestAddress + ); + + // + // Verify creation of data buffers + // + if ( OpenP->Stress->DataBuffer[0] == (PUCHAR)NULL || + OpenP->Stress->DataBuffer[1] == (PUCHAR)NULL ) { + TpPrint0("TpStressInitDataBuffer: failed to allocate Data Buffers\n"); + TpStressFreeDataBuffers( OpenP ); + return; + } + + + // + // Clear the two buffers + // + NdisZeroMemory( OpenP->Stress->DataBuffer[0],BufferSize ); + NdisZeroMemory( OpenP->Stress->DataBuffer[1],BufferSize ); + + + // + // And now initialize them 0x00 thru 0xff repeating + // + for ( j = 0; j < MAX_NUMBER_BUFFERS; j++ ) { + for ( i=0 ; i < BufferSize ; i++ ) { + OpenP->Stress->DataBuffer[j][i] = (UCHAR)(i % 256); + } + } + + // + // Now create the MDLs which reference these two data buffers + // + OpenP->Stress->DataBufferMdl[0] = (PMDL)TpAllocateBuffer( + OpenP->Stress->DataBuffer[0], + BufferSize + ); + OpenP->Stress->DataBufferMdl[1] = (PMDL)TpAllocateBuffer( + OpenP->Stress->DataBuffer[1], + BufferSize + ); + // + // Verify creation of the MDLs + // + if ( OpenP->Stress->DataBufferMdl[0] == NULL || + OpenP->Stress->DataBufferMdl[1] == NULL ) { + TpPrint0("TpStressInitDataBuffer: failed to create the DataBufferMdls\n"); + TpStressFreeDataBuffers( OpenP ); + TpStressFreeDataBufferMdls( OpenP ); + } + +} + + + +VOID +TpStressFreeDataBuffers( + POPEN_BLOCK OpenP + ) + +/*++ + +Routine Description: + + This routine simply frees the DataBuffers + +Arguments: + + OpenP - The Open to free the DataBuffers from. + +Return Value: + + None - if successful the data buffers are deallocated. + +--*/ + +{ + + // + // CHANGED: SanjeevK + // + + if ( OpenP->Stress->DataBuffer[0] != NULL ) NdisFreeMemory( OpenP->Stress->DataBuffer[0],0,0 ); + if ( OpenP->Stress->DataBuffer[1] != NULL ) NdisFreeMemory( OpenP->Stress->DataBuffer[1],0,0 ); + + OpenP->Stress->DataBuffer[0] = NULL; + OpenP->Stress->DataBuffer[1] = NULL; + +} + + +VOID +TpStressFreeDataBufferMdls( + POPEN_BLOCK OpenP + ) + +/*++ + +Routine Description: + + This routines simply frees DataBuffer MDLs. + +Arguments: + + OpenP - The Open to free the DataBuffer MDLs from. + +Return Value: + + None - if successful the data buffer MDLs are deallocated. + +--*/ + +{ + + // + // ADDED: SanjeevK + // + if( OpenP->Stress->DataBufferMdl[0] != (PMDL)NULL ) + TpFreeBuffer( (PNDIS_BUFFER)OpenP->Stress->DataBufferMdl[0] ); + + if( OpenP->Stress->DataBufferMdl[1] != (PMDL)NULL ) + TpFreeBuffer( (PNDIS_BUFFER)OpenP->Stress->DataBufferMdl[1] ); + + OpenP->Stress->DataBufferMdl[0] = NULL; + OpenP->Stress->DataBufferMdl[1] = NULL; + +} diff --git a/private/ntos/ndis/testprot/tpdrvr/makefile b/private/ntos/ndis/testprot/tpdrvr/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/testprot/tpdrvr/media.c b/private/ntos/ndis/testprot/tpdrvr/media.c new file mode 100644 index 000000000..8bdeff293 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/media.c @@ -0,0 +1,385 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + media.c + +Abstract: + + Functions used to determine information about a specific MAC, it's + packet size, and other media specifici information. + +Author: + + Tom Adams (tomad) 14-Jul-1990 + +Environment: + + Kernel mode, FSD + +Revision History: + + Tom Adams (tomad) 03-Jan-1991 Changed to support all MAC types. + + Sanjeev Katariya (sanjeevk) 04-6-1993 + Added native ARCNET support +--*/ + +#include <ndis.h> + +#include "tpdefs.h" +#include "media.h" + +// +// Medium array is used during NdisOpenAdapter to determine the +// media being supported by the card. +// + +// +// STARTCHANGE +// +NDIS_MEDIUM NdisMediumArray[NDIS_MEDIUM_ARRAY_SIZE] = { + NdisMedium802_3, + NdisMedium802_5, + NdisMediumDix, + NdisMediumFddi, + NdisMediumArcnet878_2 +}; +// +// STOPCHANGE +// + + +NDIS_STATUS +TpInitMedia( + POPEN_BLOCK OpenP, + ULONG FrameSize + ) + +/*++ + +Routine Description: + + TpInitMedia initializes the media data structure with information + specific to the media type that will be test on. The information + descibes the size of various elements of a packet for the media in + question, and is used when creating and destroying packets, etc. + +Arguments: + + MediumType - the specific NDIS Media that is being used in this test. + +Return Value: + + PTP_MEDIA_INFO - a pointer to the media information structure for + the Media being used in this test. + +--*/ + +{ + NDIS_STATUS Status; + + Status = NdisAllocateMemory( + (PVOID *)&OpenP->Media, + sizeof( TP_MEDIA_INFO ), + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpInitMedia: failed to allocate Media buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Media,sizeof( TP_MEDIA_INFO ) ); + } + + OpenP->Media->MediumType = NdisMediumArray[OpenP->MediumIndex]; + OpenP->Media->MaxPacketLen = FrameSize; + + switch( NdisMediumArray[OpenP->MediumIndex] ) + { + + case NdisMedium802_5: // TokenRing + + OpenP->Media->HeaderSize = TOKENRING_HEADER_SIZE; + OpenP->Media->Padding = TOKENRING_PADDING; + OpenP->Media->AddressLen = TOKENRING_ADDRESS_LEN; + OpenP->Media->DestAddrOffset = TOKENRING_DEST_ADDRESS_OFFSET; + OpenP->Media->SrcAddrOffset = TOKENRING_SRC_ADDRESS_OFFSET; + break; + + case NdisMedium802_3: // Ethernet + case NdisMediumDix: + + OpenP->Media->HeaderSize = ETHERNET_HEADER_SIZE; + OpenP->Media->Padding = ETHERNET_PADDING; + OpenP->Media->AddressLen = ETHERNET_ADDRESS_LEN; + OpenP->Media->DestAddrOffset = ETHERNET_DEST_ADDRESS_OFFSET; + OpenP->Media->SrcAddrOffset = ETHERNET_SRC_ADDRESS_OFFSET; + break; + + case NdisMediumFddi: + + OpenP->Media->HeaderSize = FDDI_HEADER_SIZE; + OpenP->Media->Padding = FDDI_PADDING; + OpenP->Media->AddressLen = FDDI_ADDRESS_LEN; + OpenP->Media->DestAddrOffset = FDDI_DEST_ADDRESS_OFFSET; + OpenP->Media->SrcAddrOffset = FDDI_SRC_ADDRESS_OFFSET; + break; + + // + // STARTCHANGE + // + + case NdisMediumArcnet878_2: + + OpenP->Media->HeaderSize = ARCNET_HEADER_SIZE; + OpenP->Media->Padding = ARCNET_PADDING; + OpenP->Media->AddressLen = ARCNET_ADDRESS_LEN; + OpenP->Media->DestAddrOffset = ARCNET_DEST_ADDRESS_OFFSET; + OpenP->Media->SrcAddrOffset = ARCNET_SRC_ADDRESS_OFFSET; + break; + // + // STOPCHANGE + // + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpInitMedia: Invalid media type.\n"); + } + + return NDIS_STATUS_NOT_SUPPORTED; + } + + return NDIS_STATUS_SUCCESS; +} + + +BOOLEAN +TpInitMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr, + PUCHAR SrcAddr, + INT PacketSize + ) +{ + PUCHAR p; + PUCHAR q; + USHORT DataSizeShort; + SHORT i; + +// DestAddr += (ADDRESS_LENGTH - Media->AddressLen); +// SrcAddr += (ADDRESS_LENGTH - Media->AddressLen); + + switch( Media->MediumType ) + { + case NdisMediumDix: + case NdisMedium802_3: + + p = (PUCHAR)&F1Packet->media.e.DestAddress[0]; + q = (PUCHAR)&F1Packet->media.e.SrcAddress[0]; + + for ( i = 0 ; i < Media->AddressLen ; i++ ) + { + *p++ = *DestAddr++; + *q++ = *SrcAddr++; + } + + DataSizeShort = (USHORT)( PacketSize - Media->HeaderSize ); + + F1Packet->media.e.PacketSize_Hi = (UCHAR)( DataSizeShort >> 8 ); + F1Packet->media.e.PacketSize_Lo = (UCHAR)DataSizeShort; + + break; + + + case NdisMedium802_5: + + F1Packet->media.tr.AC = 0x10; + F1Packet->media.tr.FC = 0x40; + + p = (PUCHAR)&F1Packet->media.tr.DestAddress[0]; + q = (PUCHAR)&F1Packet->media.tr.SrcAddress[0]; + + for ( i = 0 ; i < Media->AddressLen ; i++ ) + { + *p++ = *DestAddr++; + *q++ = *SrcAddr++; + } + + break; + + + case NdisMediumFddi: + + F1Packet->media.fddi.FC = 0x57; + + p = (PUCHAR)&F1Packet->media.fddi.DestAddress[0]; + q = (PUCHAR)&F1Packet->media.fddi.SrcAddress[0]; + + for ( i = 0 ; i < Media->AddressLen ; i++ ) + { + *p++ = *DestAddr++; + *q++ = *SrcAddr++; + } + + break; + + // + // STARTCHANGE + // + case NdisMediumArcnet878_2: + + F1Packet->media.a.ProtocolID = ARCNET_DEFAULT_PROTOCOLID; + + p = (PUCHAR)&F1Packet->media.a.DestAddress[0]; + q = (PUCHAR)&F1Packet->media.a.SrcAddress[0]; + + for ( i = 0 ; i < Media->AddressLen ; i++ ) + { + *p++ = *DestAddr++; + *q++ = *SrcAddr++; + } + + break; + // + // STOPCHANGE + // + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressInitPacketHeader: Unsupported MAC Type\n"); + } + return FALSE; + } + return TRUE; +} + + +VOID +TpInitPoolMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr + ) +{ + USHORT i; + +// DestAddr += (ADDRESS_LENGTH - Media->AddressLen); + + switch( Media->MediumType ) + { + case NdisMediumDix: + case NdisMedium802_3: + for ( i = 0 ; i < (USHORT)Media->AddressLen ; i++ ) + { + F1Packet->media.e.DestAddress[i] = *DestAddr++; + } + break; + case NdisMedium802_5: + for ( i = 0 ; i < (USHORT)Media->AddressLen ; i++ ) + { + F1Packet->media.tr.DestAddress[i] = *DestAddr++; + } + break; + case NdisMediumFddi: + for ( i = 0 ; i < (USHORT)Media->AddressLen ; i++ ) + { + F1Packet->media.fddi.DestAddress[i] = *DestAddr++; + } + break; + // + // STARTCHANGE + // + case NdisMediumArcnet878_2: + for ( i = 0 ; i < (USHORT)Media->AddressLen ; i++ ) + { + F1Packet->media.a.DestAddress[i] = *DestAddr++; + } + break; + // + // STOPCHANGE + // + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressSetPoolPacketInfo: Unsupported MAC Type\n"); + } + break; + } +} + + +VOID +TpInitTruncatedMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr, + INT PacketSize + ) +{ + USHORT DataSizeShort; + USHORT i; + +// DestAddr += (ADDRESS_LENGTH - Media->AddressLen); + + switch( Media->MediumType ) + { + case NdisMediumDix: + case NdisMedium802_3: + + DataSizeShort = (USHORT)( PacketSize - Media->HeaderSize ); + + F1Packet->media.e.PacketSize_Hi = (UCHAR)( DataSizeShort >> 8 ); + F1Packet->media.e.PacketSize_Lo = (UCHAR)DataSizeShort; + + for ( i=0;i<(USHORT)Media->AddressLen;i++ ) + { + F1Packet->media.e.DestAddress[i] = *DestAddr++; + } + break; + + case NdisMedium802_5: + for ( i=0;i<(USHORT)Media->AddressLen;i++ ) + { + F1Packet->media.tr.DestAddress[i] = *DestAddr++; + } + break; + + case NdisMediumFddi: + for ( i=0;i<(USHORT)Media->AddressLen;i++ ) + { + F1Packet->media.fddi.DestAddress[i] = *DestAddr++; + } + break; + // + // STARTCHANGE + // + case NdisMediumArcnet878_2: + for ( i = 0 ; i < (USHORT)Media->AddressLen ; i++ ) + { + F1Packet->media.a.DestAddress[i] = *DestAddr++; + } + break; + // + // STOPCHANGE + // + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressSetTruncatedPacketInfo: Unsupported MAC Type\n"); + } + break; + } +} diff --git a/private/ntos/ndis/testprot/tpdrvr/media.h b/private/ntos/ndis/testprot/tpdrvr/media.h new file mode 100644 index 000000000..8bc1e5677 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/media.h @@ -0,0 +1,350 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + media.h + +Abstract: + + Functions used to determine information about a specific MAC, it's + packet size, and other media specifici information. + +Author: + + Tom Adams (tomad) 14-Jul-1990 + +Environment: + + Kernel mode, FSD + +Revision History: + + Tom Adams (tomad) 03-Jan-1991 Changed to support all MAC types. + + SanjeevK (sanjeevk) 04-06-1993 + 1. Added Arcnet support + +--*/ + +// +// Medium array is used during NdisOpenAdapter to determine the +// media being supported by the card. +// +#define NDIS_MEDIUM_ARRAY_SIZE 5 + +extern NDIS_MEDIUM NdisMediumArray[NDIS_MEDIUM_ARRAY_SIZE]; + +// +// Media Specific Information used to describe the form of a packet and +// the device being used in this instance. +// +// The Media of interest are +// +// 802.3 +// 802.5 (TokenRing) +// FDDI +// ARCNET +// +// No special differentiation will be made between 802.3 and DIX +// + +typedef struct _TP_MEDIA_INFO { + NDIS_MEDIUM MediumType; // MAC type being used + USHORT HeaderSize; // Packet Header size if (exists) + USHORT Padding; // Pad to align TP_PACKET_HEADER + USHORT AddressLen; // Address length for the Media + USHORT SrcAddrOffset; + USHORT DestAddrOffset; + ULONG MaxPacketLen; // Maximum packet length for Media +} TP_MEDIA_INFO, *PTP_MEDIA_INFO; + +// +// Ethernet Specific Information +// +// The Ethernet Packet Header is constructed as follows: +// +// +------------------------------------------+ +// | Dest | Src | Sz | Data | +// +------------------------------------------+ +// +// The Src and Dest fields represent the source and destination addresses +// and are 6 bytes long each, the Sz field represents represents the size +// of the Data, and finally there is the Data area itself. +// + +#define ETHERNET_ADDRESS_LEN 6 + +#define ETHERNET_SRC_ADDRESS_OFFSET ETHERNET_ADDRESS_LEN + +#define ETHERNET_DEST_ADDRESS_OFFSET 0 + +#define ETHERNET_DATASIZE_LEN 2 + +#define ETHERNET_DATA_LEN 1500 + +#define ETHERNET_HEADER_SIZE (( ETHERNET_ADDRESS_LEN * 2 ) + \ + ETHERNET_DATASIZE_LEN ) + +#define ETHERNET_PACKET_SIZE ( ETHERNET_HEADER_SIZE + \ + ETHERNET_DATA_LEN ) + +#define ETHERNET_MIN_DATA_LEN 46 + +#define ETHERNET_MIN_PACKET_SIZE ( ETHERNET_HEADER_SIZE + \ + ETHERNET_MIN_DATA_LEN ) + +#define ETHERNET_PADDING 2 + +// +// Default Adapter name to be input from Configuration Manager +// +//#define ETHERNET_ADAPTER_NAME "\\device\\elnkii" + +// +// TokenRing Specific Information +// +// +// The Token Ring Packet Header is constructed as follows: +// +// +---------------------------------------------------+ +// | AC | FC | Dest | Src | Data | +// +---------------------------------------------------+ +// +// The AC and FC fields are used to store tokenring information, each is +// one byte long. The Src and Dest fields represent the source and +// destination addresses and are 6 bytes long each, and finally there +// is the Data area itself. +// + +#define TOKENRING_ACFC_SIZE 2 + +#define TOKENRING_ADDRESS_LEN 6 + +#define TOKENRING_SRC_ADDRESS_OFFSET ( TOKENRING_ADDRESS_LEN + \ + TOKENRING_ACFC_SIZE ) + +#define TOKENRING_DEST_ADDRESS_OFFSET TOKENRING_ACFC_SIZE + +#define TOKENRING_HEADER_SIZE (( TOKENRING_ADDRESS_LEN * 2) + \ + TOKENRING_ACFC_SIZE ) + +#define TOKENRING_DATA_LEN ( 8192 - TOKENRING_HEADER_SIZE ) +// 17K if 16MB or 8K if 4MB + +#define TOKENRING_PACKET_SIZE ( TOKENRING_HEADER_SIZE + \ + TOKENRING_DATA_LEN ) + +#define TOKENRING_PADDING 2 + +// +// FDDI Specific Information +// +// +// The FDDI Packet Header is constructed as follows: +// +// +----------------------------------------------+ +// | XX | Dest | Src | Data | +// +----------------------------------------------+ +// +// The XX field is used to store fddi information, it is one byte +// long. The Src and Dest fields represent the source and destination +// addresses and are 6 bytes long each, and finally there is the +// Data area itself. +// + +#define FDDI_XX_SIZE 1 + +#define FDDI_ADDRESS_LEN 6 + +#define FDDI_SRC_ADDRESS_OFFSET ( FDDI_ADDRESS_LEN + FDDI_XX_SIZE ) + +#define FDDI_DEST_ADDRESS_OFFSET FDDI_XX_SIZE + +#define FDDI_HEADER_SIZE (( FDDI_ADDRESS_LEN * 2) + FDDI_XX_SIZE ) + +#define FDDI_DATA_LEN 8192 // 17K if 16MB or 8K if 4MB + +#define FDDI_PACKET_SIZE ( FDDI_HEADER_SIZE + FDDI_DATA_LEN ) + +#define FDDI_PADDING 2 + + + +// +// STARTCHANGE +// + +// +// ARCNET Specific Information +// +// +// The ARCNET Software Packet Header is constructed as follows: +// +// +----------------------------------------------------------+ +// | Source | Destination | ProtocolID | Data | +// +----------------------------------------------------------+ +// 1 1 1 0 - 120*504 or 60480 +// +// CURRENT ARCNET SOFTWARE HEADER +// +// The ARCNET Software Packet Header is constructed as follows: +// +// +----------------------------------------------------------+ +// | Source | Destination | ProtocolID | Data | +// +----------------------------------------------------------+ +// 1 1 1 0 - 3*504 or 1512 +// +// +// The Src and Dest fields represent the source and destination +// addresses and are 1 byte long each. The ProtocolID represent +// the ID of the protocol communicating with the Arcnet MAC driver +// And finally there is Data area itself. +// +// An actual Arcnet Software packet looks like the following. The current provisions +// for the native ARCNET driver will be responsible for handling these type internally +// thereby providing ease of packet exchange between the MAC(N) and the layer above the MAC(N+1) +// +// SHORT PACKET (Octet) +// +---+ +// Source | 1 | +// +---+ +// Destination | 1 | +// +---+ +// ByteOffset | 1 | +// +---------+ +// Unused | 0 - 249 | PACKET CONSTANT LENGTH = 256 octets +// +---------+ MAXIMUM # of FRAGEMENTS = 120 +// ProcolID | 1 | +// +---+ +// Split Flag | 1 | +// +---+---+ +// Seqence # | 2 | +// +----------+ +// Data | 0 - 249 | +// +----------+ +// +// EXCEPTION PACKET (Octet) +// +---+ +// Source | 1 | +// +---+ +// Destination | 1 | +// +---+ +// Long Packet Flag | 1 | = 0 +// +---+ +// ByteOffset | 1 | +// +-----------+ +// Unused | 248 - 250 | PACKET CONSTANT LENGTH = 512 octets +// +-----------+ MAXIMUM # of FRAGEMENTS = 120 +// Pad1 ProcolID | 1 | +// +---+ +// Pad2 Split Flag | 1 | = FF +// +---+ +// Pad3 | 1 | +// +---+ +// Pad4 | 1 | +// +---+ +// ProcolID | 1 | +// +---+ +// Split Flag | 1 | +// +---+---+ +// Seqence # | 2 | +// +-----------+ +// Data | 250 - 252 | +// +-----------+ +// +// +// LONG PACKET (Octet) +// +---+ +// Source | 1 | +// +---+ +// Destination | 1 | +// +---+ +// Long Packet Flag | 1 | = 0 +// +---+ +// ByteOffset | 1 | +// +---------+ +// Unused | 0 - 251 | PACKET CONSTANT LENGTH = 512 octets +// +---------+ MAXIMUM # of FRAGEMENTS = 120 +// ProcolID | 1 | +// +---+ +// Split Flag | 1 | +// +---+---+ +// Seqence # | 2 | +// +-----------+ +// Data | 253 - 504 | +// +-----------+ +// +// The software packet is further broken down into 5 different categories on the wire +// The frame formats are: +// +// INVITATION TO TRANSMIT (ASCII EOT) +// FREE BUFFER ENQUIRY (ASCII ENQ) +// PACKET-DATA (ASCII SOH) +// ACK (ASCII ACK) +// NACK (ASCII NAK) +// The Destination octet is duplicated on the wire, the unused data buffer is not transmitted +// and a 2 octect CRC is generated with the PACKET-DATA format. +// + +#define ARCNET_ADDRESS_LEN 1 + +#define ARCNET_SRC_ADDRESS_OFFSET 0 + +#define ARCNET_DEST_ADDRESS_OFFSET ARCNET_ADDRESS_LEN + +#define ARCNET_PROTID_OFFSET ARCNET_DEST_ADDRESS_OFFSET + ARCNET_ADDRESS_LEN + +#define ARCNET_PROTID_LEN 1 + +#define ARCNET_HEADER_SIZE (( ARCNET_ADDRESS_LEN * 2) + ARCNET_PROTID_LEN ) + +#define ARCNET_DATA_LEN 1512 + +#define ARCNET_PACKET_SIZE ( ARCNET_HEADER_SIZE + ARCNET_DATA_LEN ) + +#define ARCNET_MIN_DATA_LEN 0 + +#define ARCNET_MIN_PACKET_SIZE ( ARCNET_HEADER_SIZE + ARCNET_MIN_DATA_LEN ) + +#define ARCNET_PADDING 0 + +// +// STOPCHANGE +// + + +// +// Media Initialization routine. +// + +NDIS_STATUS +TpInitMedia( + POPEN_BLOCK OpenP, + ULONG FrameSize + ); + +BOOLEAN +TpInitMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr, + PUCHAR SrcAddr, + INT PacketSize + ); + +VOID +TpInitPoolMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr + ); + +VOID +TpInitTruncatedMediaHeader( + PFUNC1_PACKET F1Packet, + PTP_MEDIA_INFO Media, + PUCHAR DestAddr, + INT PacketSize + ); diff --git a/private/ntos/ndis/testprot/tpdrvr/packet.c b/private/ntos/ndis/testprot/tpdrvr/packet.c new file mode 100644 index 000000000..72a27edef --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/packet.c @@ -0,0 +1,2164 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + packet.c + +Abstract: + + simple protocol to test the NDIS wrapper. + +Author: + + Tom Adams (tomad) 14-Jul-1990 + +Environment: + + Kernel mode, FSD + +Revision History: + + Sanjeev Katariya (sanjeevk) 3-24-1993 + 1. Corrected TpStressCreatePacket() to allocate the first buffer in a packet of correct + size. Added functionality to work with discontiguous physical data(Buffer chains) + 2. Changed functions to reflect the data structure change in + STRESS_BLOCK + a. TpStressCreateTruncatedPacket() + b. TpStressSetTruncatedPacketInfo() + +--*/ + +#include <ndis.h> +#include <stdlib.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + + + +VOID +TpSetRandom( + VOID + ) +{ + LARGE_INTEGER TmpTime; + + // + // Uses the system clock to return a random number. + // The randomness of the number is subject to some debate. + // The time increments in exact intervals; for example on + // a 386 it is 300000. We want to shift over enough that + // the LSB changes rapidly, but not too much so that we + // can only handle a small Range. + // + + KeQuerySystemTime( &TmpTime ); + srand( TmpTime.LowTime >> 10 ); +} + + +UINT +TpGetRandom( + IN UINT Low, + IN UINT High + ) +{ + UINT Range = High - Low + 1; + + return (UINT)(( rand() % Range ) + Low ); +} + + +PTP_PACKET +TpStressInitPacketHeader( + IN POPEN_BLOCK OpenP, + IN INT TmpBufSize, + IN INT PacketSize, + IN PUCHAR DestAddr, + IN PUCHAR SrcAddr, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType, + IN ULONG DataBufOffset, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN BOOLEAN DataChecking + ) +{ + NDIS_STATUS Status; + PTP_PACKET TmpBuffer; + + // + // Allocate a buffer to hold the packet header information. + // + + Status = NdisAllocateMemory( + (PVOID *)&TmpBuffer, + TmpBufSize, + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressInitPacketHeader: failed to allocate TmpBuffer\n"); + } + return NULL; + } else { + NdisZeroMemory( (PVOID)TmpBuffer,TmpBufSize ); + } + + // + // and stuff the packet header info into it. + // + + if ( !TpInitMediaHeader( + &TmpBuffer->u.S.hdr, + OpenP->Media, + DestAddr, + SrcAddr, + PacketSize + )) { + NdisFreeMemory( TmpBuffer,0,0 ); + return NULL; + } + + // + // initialize the Stress header information. + // + + TmpBuffer->u.S.hdr.info.Signature = STRESS_PACKET_SIGNATURE; + TmpBuffer->u.S.hdr.info.PacketSize = PacketSize; + TmpBuffer->u.S.hdr.info.DestInstance = DestInstance; + TmpBuffer->u.S.hdr.info.SrcInstance = SrcInstance; + TmpBuffer->u.S.hdr.info.PacketType = STRESS_PACKET_TYPE; + TmpBuffer->u.S.hdr.info.u.PacketProtocol = PacketProtocol; + TmpBuffer->u.S.hdr.info.CheckSum = 0xFFFFFFFF; + + TmpBuffer->u.S.sc.DataBufOffset = DataBufOffset; + TmpBuffer->u.S.sc.SequenceNumber = SequenceNumber; + TmpBuffer->u.S.sc.MaxSequenceNumber = MaxSequenceNumber; + TmpBuffer->u.S.sc.ResponseType = ResponseType; + TmpBuffer->u.S.sc.ClientReference = ClientReference; + TmpBuffer->u.S.sc.ServerReference = ServerReference; + TmpBuffer->u.S.sc.DataChecking = DataChecking; + + return TmpBuffer; +} + + +PNDIS_PACKET +TpStressCreatePacket( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE PacketHandle, + IN PACKET_MAKEUP PacketMakeUp, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType, + IN PUCHAR DestAddr, + IN INT PacketSize, + IN INT BufferSize, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN BOOLEAN DataChecking + ) + +{ + NDIS_STATUS Status ; + PNDIS_PACKET Packet ; + PNDIS_BUFFER Buffer ; + PPROTOCOL_RESERVED ProtRes ; + PUCHAR DataBufOffset1 ; + PUCHAR DataBufOffset2 ; + PUCHAR TmpBuf ; + PUCHAR TmpBufDataOffset ; + ULONG RandomOffset ; + INT TmpBufSize ; + INT TmpBufDataSize ; + INT MdlSize ; + INT NumBuffers ; + INT i ; + INT RemainingHdr ; + INT RemainingPkt ; + BOOLEAN FirstBuffer = TRUE ; + BOOLEAN Pulse = TRUE ; + + // + // Using a DISCONTIGUOUS allocation scheme in the CLIENT pool case + // + + // + // Comments : SanjeevK + // + // BRIEF WORKING + // + // This function simply allocates a packet from the packet pool and + // is reponsible for putting the packet together. The data portion of the + // packet is directly used from the the DataBuffers associated with the + // stress block. The packet creation is given the option of using + // a known buffer size mapping(which generates a definite number of buffers + // since the packet size is known) or can simply randomly choose how big + // or small it would like to make the buffer sizes. This option is characterized + // by the parameter KNOWN. + // The packet is created by created an initial header, setting the appropriate fields + // and then linking in the data buffers. The total length of the created packet is + // controlled by the PacketSize + // + // The variables and their boundary sizes are given below: + // + // <-------------------- PacketSize ------------------->[STRESS_PACKET,MAX_PACKET_LENGTH] + // + // <------ TmpBufSize ---->[STRESS_PACKET,max(2*STRESS_PACKET,PacketSize)] + // for PacketMakeUp != KNOWN + // + // MEDIA_FRAME,PacketSize] + // + // ---------------------------------------------------- + // | STRESS_PACKET+ | Additional DATA | + // | Random Data Size | | + // ----------------------- ---------------------------- + // + // ---.....-----....----....--- + // | | + // | + // ---.....-----....----....--- + // + // <-------- BufferSize -------->[MediaHeaderSize, max(STRESS_PACKET,PacketSize)] + // + // + + + + // + // Make sure that this is a legal packetsize, and buffersize if + // PacketMakeUp = KNOWN, if not use a default smallest or largest + // size allowable. + // + if ( PacketSize < sizeof( STRESS_PACKET )) { + PacketSize = sizeof( STRESS_PACKET ); + } else if ( PacketSize > (INT)OpenP->Media->MaxPacketLen ) { + PacketSize = OpenP->Media->MaxPacketLen; + } + + + // + // Check the condition for KNOWN packet type. + // If TRUE ensure that the BufferSize is between + // MediaHeaderSize and max(STRESS_PACKET,PacketSize). + // + if ( PacketMakeUp == KNOWN ) { + if ( BufferSize < OpenP->Media->HeaderSize ) { + BufferSize = OpenP->Media->HeaderSize ; + } else if ( BufferSize > PacketSize ) { + BufferSize = PacketSize; + } + } + + + + + // + // Allocate a PACKET out of the packet pool + // + NdisAllocatePacket( &Status,&Packet,PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + + if( OpenP->Stress->Arguments != NULL ) { + + // + // This is the special case where we realize that we will run out + // of packets very quickly since the packet pool is 200 only. ONLY + // in this case will we not issue a debug message to the screen + // + if ( (OpenP->Stress->Arguments->WindowEnabled == FALSE ) && + (OpenP->Stress->Arguments->ResponseType == ACK_10_TIMES ) + ) return NULL; + + } + + TpPrint1("TpStressCreatePacket: NdisAllocatePacket failed %s\n", + TpGetStatus( Status )); + + } + + return NULL; + + } + + + // + // Mark the Packet's protocol reserved section to NULL to indicate + // that this packet was not allocated from a TP_TRANSMIT_POOL, and set + // the InstanceCounters to NULL. TpStressCreateTransmitPool and the + // Packet Set Info routines will set them if applicable. + // + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.TransmitPool = NULL; + ProtRes->InstanceCounters = NULL; + + // + // Now select the random size of the header buffer which will be used to + // hold the Frame Header, the Test Protocol Packet Header, and a random + // chunk of the actual frame data. + // + // TmpBufSize = The random size of the header buffer + // where + // Header buffer = Frame Header + + // Test Protocol Packet Header + + // A random chunk of the actual frame data. + // + // + if ( PacketMakeUp != KNOWN ) { // ( PacketMakeUp == RAND|ONES|ZEROS|SMALL ) + + // + // Sanjeevk : Comment + // + // The TmpBufSize being within the bounds, STRESS_PACKET and 2*STRESS_PACKET + // will quite comfortably accomodate the MEDIA_HEADER. This restriction must + // be followed closely since this is the first buffer in the packet chain + // + + TmpBufSize = TpGetRandom( + sizeof( STRESS_PACKET ), + ( 2 * sizeof( STRESS_PACKET )) + ); + + if ( TmpBufSize > PacketSize ) { + TmpBufSize = PacketSize; + } + + + } else { + + // + // Packet_MakeUp is KNOWN, i.e. we can calculate the number of buffers + // from the size of the packet and the given buffersize + // We must however determine the number of buffers that + // will fit in the TP_PACKET_HEADER section of the packet, and how + // large that header will actually be. + // + // At this point BufferSize is between MediaHeaderSize + // and max(PacketSize,STRESS_PACKET) + // + if ( BufferSize >= sizeof( STRESS_PACKET ) ) { + + // + // If the BufferSize is greater than the size needed to fit the + // packet header then we will just allocate one chunk of memory + // of that size, and tack on some additional data at the the end. + // + + TmpBufSize = BufferSize; + RemainingPkt = PacketSize % BufferSize; + RemainingHdr = 0; + NumBuffers = 1; + + } else { + + // + // The BufferSize is smaller that then packet header, so we must + // determine the number of buffers that will fit in the header, + // and, if there is any remainder, how big it is. + // + + NumBuffers = sizeof( STRESS_PACKET ) / BufferSize; + RemainingHdr = sizeof( STRESS_PACKET ) % BufferSize; + RemainingPkt = PacketSize % BufferSize; + + // + // There are three possible cases here that must be handled. + // + // 1) only X buffers are needed to create the packet header + // + // 2) X buffers, and a remainder buffer are needed to create the + // packet header. + // a) the remainder is the rest of the actual packet. + // + // b) the remainder is the rest of the header. (and the + // packet) + // + // [-------------------------------------] + // packet header + // + // 1) [---------][---------][- -][---------] + // buf_1 buf_2 ... buf_X + // + // 2a) [-------][-------][- -][-------][--------------] + // buf_1 buf_2 ... buf_X remaining packet + // + // 2b) [-------][-------][- -][-------][---] + // buf_1 buf_2 ... buf_X remaining header + // + + if (((NumBuffers+1) * BufferSize) <= PacketSize ) { + + // + // The packet header can fit in NumBuffers+1 buffers. + // + + TmpBufSize = (( NumBuffers + 1 ) * BufferSize ); + NumBuffers++; + RemainingHdr = 0; + + } else if ((( NumBuffers * BufferSize ) + RemainingPkt ) == PacketSize ) { + + // + // The packet header can fit in a NumBuffers buffers plus the + // remainder of the packet. This is the entire packet. + // + + TmpBufSize = ( NumBuffers * BufferSize ) + RemainingPkt ; + RemainingHdr = RemainingPkt; + RemainingPkt = 0; + + } else { + + // + // The packet header can fit in a NumBuffers buffers plus the + // remainder of the header. This is the entire packet. + // + + TmpBufSize = (( NumBuffers * BufferSize ) + RemainingHdr ); + TP_ASSERT( RemainingHdr != RemainingPkt ); + RemainingPkt = 0; + } + } + } + + RandomOffset = TpGetRandom( 0,OpenP->Media->MaxPacketLen ); + + TmpBuf = (PUCHAR)TpStressInitPacketHeader( + OpenP, + TmpBufSize, + PacketSize, + DestAddr, + OpenP->StationAddress, + DestInstance, + SrcInstance, + PacketProtocol, + ResponseType, + RandomOffset, + SequenceNumber, + MaxSequenceNumber, + ClientReference, + ServerReference, + DataChecking + ); + + if ( TmpBuf == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to initialize Packet Header\n"); + } + return NULL; + } + + ((PTP_PACKET)TmpBuf)->u.S.sc.CheckSum = + + TpSetCheckSum( + (PUCHAR)&((PTP_PACKET)TmpBuf)->u.S.hdr.info, + sizeof( STRESS_PACKET ) - +// ( sizeof( ULONG ) + OpenP->Media->HeaderSize ) + ( sizeof(ULONG) + sizeof(MEDIA_HEADER)) + ); + + // + // Now setup the remainder of TmpBuf with a random amount of data + // from the data buffer. + // + // DataBufOffset1,2 is the random offset into the data buffer that will be + // used to fill the packet. + // + + DataBufOffset1 = OpenP->Stress->DataBuffer[0] + RandomOffset; + DataBufOffset2 = OpenP->Stress->DataBuffer[1] + RandomOffset; + + // + // TmpBufDataSize is the remainder of the TmpBuf that will be filled with + // data from the DataBuf + // + + TmpBufDataSize = TmpBufSize - sizeof( STRESS_PACKET ); + + if ( TmpBufDataSize > 0 ) { + + TmpBufDataOffset = TmpBuf + sizeof( STRESS_PACKET ); + + RtlMoveMemory( + TmpBufDataOffset, + DataBufOffset1, + TmpBufDataSize + ); + + DataBufOffset1 += TmpBufDataSize; + DataBufOffset2 += TmpBufDataSize; + + } else { + TP_ASSERT( TmpBufDataSize >= 0 ); + } + + + // + // Sanjeevk : Comment + // + // We now simply proceed to create the packet. We start of by using the TmpBuf we created + // and forming the header and then tack on the data buffer we allocated. MDL's are allocated + // as we go thru the data portions + // + // NOTE: To make the data discontiguous, we are using the following sheme + // + // We have allocated two data buffers and filled them in with identical contents + // + // LOC.A + // -------------------------------- + // BUFFER 1 | 00 01 02 03 .....FF 00 01 ..... | + // -------------------------------- + // LOC.B + // --------------------------------- + // BUFFER 2 | 00 01 02 03 .....FF 00 01 ..... | + // --------------------------------- + // ^ + // | + // COMMON OFFSET + // We now maintain a common offset into both buffers and simply switch between the two + // locations. + // + // LOGIC + // 1. Get location A at COMMON OFFSET from buffer 1. Take length Y. Obtain a MDL + // and chain than buffer onto the packet + // 2. Increment the COMMON OFFSET by length Y + // 3. Get location B at COMMON OFFSET from buffer 2. Take length X. Obtain a MDL + // and chain than buffer onto the packet + // 4. Increment the COMMON OFFSET by length X + // 5. Repeat steps 1,2,3 and 4 till you have reached the end of the total packet + // length to be mapped(ie. incremental length = 0 ) + // + // This makes the data verification an easy process since the sequence of data bytes + // stays the same although now the data areas are no longer contiguous. + // + switch( PacketMakeUp ) { + + case RAND: + + // + // Slice up the TmpBuf containing the Frame Header and the + // TP_PACKET_HEADER, and create the beginning of the PACKET. + // + + while ( TmpBufSize > 0 ) { + + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + + if ( MdlSize > TmpBufSize ) { + MdlSize = TmpBufSize; + } + + + // + // STARTCHANGE + // + // + // Ensure that the first buffer in the packet has length >= size + // of the media header. This is an NDIS 3.0 requirement for + // the sake of maintaining performance + // + if ( FirstBuffer ) { + if ( MdlSize < OpenP->Media->HeaderSize ) { + MdlSize = OpenP->Media->HeaderSize; + } + FirstBuffer = FALSE; + } + // + // STOPCHANGE + // + + Buffer = TpAllocateBuffer( TmpBuf,MdlSize ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + TmpBuf += MdlSize; + TmpBufSize -= MdlSize; + PacketSize -= MdlSize; + } + + // + // Now convert the data section of the into NDIS_BUFFERs and add to the + // end of the PACKET. + // + + while ( PacketSize > 0 ) { + + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + + if ( MdlSize > PacketSize ) { + MdlSize = PacketSize; + } + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize ); + Pulse = TRUE; + } + + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + PacketSize -= MdlSize; + DataBufOffset1 += (ULONG)MdlSize; + DataBufOffset2 += (ULONG)MdlSize; + } + break; + + case ZEROS: + + // + // Slice up the TmpBuf containing the Frame Header and the + // TP_PACKET_HEADER, and create the beginning of the PACKET. + // + + while (TmpBufSize > 0) { + + if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 0 ) { + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + } + if ( MdlSize > TmpBufSize ) { + MdlSize = TmpBufSize; + } + // + // STARTCHANGE + // + // + // Ensure that the first buffer in the pakcet has length >= size + // of the media header. This is an NDIS 3.0 requirement for + // the sake of maintaining performance + // + if ( FirstBuffer ) { + if ( MdlSize < OpenP->Media->HeaderSize ) { + MdlSize = OpenP->Media->HeaderSize; + } + FirstBuffer = FALSE; + } + // + // STOPCHANGE + // + Buffer = TpAllocateBuffer( TmpBuf,MdlSize ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + TmpBuf += MdlSize; + TmpBufSize -= MdlSize; + PacketSize -= MdlSize; + } + + // + // Now convert the data section of the into NDIS_BUFFERs and add to the + // end of the PACKET. + // + + while ( PacketSize > 0 ) { + + if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 0 ) { + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + } + + if ( MdlSize > PacketSize ) { + MdlSize = PacketSize; + } + + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize ); + Pulse = TRUE; + } + + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + PacketSize -= MdlSize; + DataBufOffset1 += (ULONG)MdlSize; + DataBufOffset2 += (ULONG)MdlSize; + } + break; + + case ONES: + + // + // Slice up the TmpBuf containing the Frame Header and the + // TP_PACKET_HEADER, and create the beginning of the PACKET. + // + + while ( TmpBufSize > 0 ) { + + if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 1 ) { + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + } + if ( MdlSize > TmpBufSize ) { + MdlSize = TmpBufSize; + } + + // + // STARTCHANGE + // + // + // Ensure that the first buffer in the pakcet has length >= size + // of the media header. This is an NDIS 3.0 requirement for + // the sake of maintaining performance + // + if ( FirstBuffer ) { + if ( MdlSize < OpenP->Media->HeaderSize ) { + MdlSize = OpenP->Media->HeaderSize; + } + FirstBuffer = FALSE; + } + // + // STOPCHANGE + // + + Buffer = TpAllocateBuffer( TmpBuf,MdlSize ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + TmpBuf += MdlSize; + TmpBufSize -= MdlSize; + PacketSize -= MdlSize; + } + + // + // Now convert the data section of the into NDIS_BUFFERs and add to the + // end of the PACKET. + // + + while ( PacketSize > 0 ) { + + if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 1 ) { + MdlSize = TpGetRandom( + 0, + OpenP->Media->MaxPacketLen / + ( 2 * OpenP->Environment->RandomBufferNumber ) + ); + } + + if ( MdlSize > PacketSize ) { + MdlSize = PacketSize; + } + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize ); + Pulse = TRUE; + } + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + PacketSize -= MdlSize; + DataBufOffset1 += (ULONG)MdlSize; + DataBufOffset2 += (ULONG)MdlSize; + + } + break; + + case SMALL: + + // + // Slice up the TmpBuf containing the Frame Header and the + // TP_PACKET_HEADER, and create the beginning of the PACKET. + // + + while ( TmpBufSize > 0 ) { + + MdlSize = TpGetRandom( 0,OpenP->Media->MaxPacketLen/50 ); + + if ( MdlSize > TmpBufSize ) { + MdlSize = TmpBufSize; + } + + // + // STARTCHANGE + // + // + // Ensure that the first buffer in the pakcet has length >= size + // of the media header. This is an NDIS 3.0 requirement for + // the sake of maintaining performance + // + if ( FirstBuffer ) { + if ( MdlSize < OpenP->Media->HeaderSize ) { + MdlSize = OpenP->Media->HeaderSize; + } + FirstBuffer = FALSE; + } + // + // STOPCHANGE + // + + Buffer = TpAllocateBuffer( TmpBuf,MdlSize ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + TmpBuf += MdlSize; + TmpBufSize -= MdlSize; + PacketSize -= MdlSize; + } + + // + // Now convert the data section of the into NDIS_BUFFERs and add to the + // end of the PACKET. + // + + while ( PacketSize > 0 ) { + + MdlSize = TpGetRandom( 0,OpenP->Media->MaxPacketLen/50 ); + + if ( MdlSize > PacketSize ) { + MdlSize = PacketSize; + } + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize ); + Pulse = TRUE; + } + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + PacketSize -= MdlSize; + DataBufOffset1 += (ULONG)MdlSize; + DataBufOffset2 += (ULONG)MdlSize; + } + break; + + case KNOWN: + + + for ( i=0;i<NumBuffers;i++ ) { + + Buffer = TpAllocateBuffer( TmpBuf,BufferSize ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + TmpBuf += BufferSize; + PacketSize -= BufferSize; + } + + if ( RemainingHdr > 0 ) { + + Buffer = TpAllocateBuffer( TmpBuf,RemainingHdr ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + PacketSize -= RemainingHdr; + } + + if ( PacketSize > 0 ) { + + // + // Determine the number of remaining buffers, and if it exists, + // the size of the last buffer. + // + + NumBuffers = PacketSize / BufferSize; + + for (i=0;i<NumBuffers;i++ ) { + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,BufferSize ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,BufferSize ); + Pulse = TRUE; + } + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + DataBufOffset1 += (ULONG)BufferSize; + DataBufOffset2 += (ULONG)BufferSize; + } + + if ( RemainingPkt > 0 ) { + + // + // Using DISCONTIGUITY + // + if ( Pulse ) { + Buffer = TpAllocateBuffer( DataBufOffset1,RemainingPkt ); + Pulse = FALSE; + } else { + Buffer = TpAllocateBuffer( DataBufOffset2,RemainingPkt ); + Pulse = TRUE; + } + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + } + } + break; + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: unknown packet makeup\n"); + } + return NULL; + } + return Packet; +} + + +PNDIS_PACKET +TpStressCreateTruncatedPacket( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE PacketHandle, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType + ) +{ + NDIS_STATUS Status; + PNDIS_PACKET Packet; + PNDIS_BUFFER Buffer; + PUCHAR TmpBuf; + PPROTOCOL_RESERVED ProtRes; + + // + // Using a CONTIGUOUS allocation scheme in the SERVER pool + // + NdisAllocatePacket( &Status,&Packet,PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint1("TpStressCreatePacket: NdisAllocatePacket failed %s\n", + TpGetStatus( Status )); + } + return NULL; + } + + // + // Mark the Protocol's reserved section to NULL to indicate that + // this packet was not allocated from a TP_TRANSMIT_POOL, and set + // the InstanceCounters to NULL. TpStressCreateTransmitPool and the + // Packet Set Info routines will set them if applicable. + // + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.TransmitPool = NULL; + ProtRes->InstanceCounters = NULL; + + TmpBuf = (PUCHAR)TpStressInitPacketHeader( + OpenP, + ( 2 * sizeof( STRESS_PACKET ) ), + sizeof( STRESS_PACKET ), + NULL_ADDRESS, + OpenP->StationAddress, + 0, //DestInstance + 0, //SrcInstance + PacketProtocol, + ResponseType, + 0, //RandomOffset + 0L, //SequenceNumber + 0L, //MaxSequenceNumber + 0, //ClientReference + 0, //ServerReference + FALSE // DataChecking + ); + + if ( TmpBuf == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreateTruncatedPacket: failed to initialize Packet Header\n"); + } + return NULL; + } + + Buffer = TpAllocateBuffer( TmpBuf,sizeof( STRESS_PACKET ) ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + Buffer = TpAllocateBuffer( + OpenP->Stress->DataBuffer[0], + OpenP->Media->MaxPacketLen*2 + ); + + if ( Buffer == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreatePacket: failed to create the MDL\n"); + } + TpStressFreePacket( Packet ); + return NULL; + } + + NdisChainBufferAtBack( Packet,Buffer ); + + // + // STOPCHANGE + // + + return Packet; +} + + +ULONG +TpGetPacketSignature( + IN PNDIS_PACKET Packet + ) + +{ + NDIS_STATUS Status; + PUCHAR TmpBuf; + PUCHAR TmpBuf1; + UINT TmpBufSize = sizeof( STRESS_PACKET ); + PNDIS_BUFFER Buffer; + PUCHAR Memory; + UINT MemoryLength; + ULONG Signature; + BOOLEAN GotWholeTpPacket; + + if ( Packet == NULL ) { + return 0xffffffff; + } + + Status = NdisAllocateMemory( + (PVOID *)&TmpBuf, + TmpBufSize, + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpGetPacketSignature: unable to allocate tmp buffer\n"); + } + return 0xffffffff; + } else { + NdisZeroMemory( TmpBuf,TmpBufSize ); + } + + TmpBuf1 = TmpBuf; + + NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL ); + + GotWholeTpPacket = FALSE; + + while ( Buffer != NULL ) { + + NdisQueryBuffer( + Buffer, + (PVOID *)&Memory, + &MemoryLength + ); + + if ( MemoryLength > TmpBufSize ) { + MemoryLength = TmpBufSize; + } + + RtlMoveMemory( TmpBuf1,Memory,MemoryLength ); + + TmpBufSize -= MemoryLength; + TmpBuf1 += MemoryLength; + + if (TmpBufSize == 0 ) { + GotWholeTpPacket = TRUE; + break; + } + + NdisGetNextBuffer( Buffer,&Buffer ); + } + + if ( GotWholeTpPacket == TRUE ) { + Signature = ((PSTRESS_PACKET)TmpBuf)->hdr.info.Signature; + } else { + Signature = 0xffffffff; + } + + NdisFreeMemory( TmpBuf,0,0 ); + + return Signature; +} + + +VOID +TpStressFreePacket( + IN PNDIS_PACKET Packet + ) +{ + PNDIS_BUFFER HeadBuffer; + PNDIS_BUFFER Buffer; + PPROTOCOL_RESERVED ProtRes; + + + if ( Packet == NULL ) { + return; + } + + NdisUnchainBufferAtFront( Packet,&HeadBuffer ); + + if ( HeadBuffer != NULL ) { + + NdisUnchainBufferAtFront( Packet,&Buffer ); + + while ( Buffer != NULL ) { + TpFreeBuffer( Buffer ); + NdisUnchainBufferAtFront( Packet,&Buffer ); + } + + // + // Due to the method used to create the header buffer this + // size is now invalid, but will work. + // + + HeadBuffer->ByteCount = ( sizeof( STRESS_PACKET ) * 2 ); + + NdisFreeMemory( MmGetMdlVirtualAddress( HeadBuffer ),0,0 ); + + TpFreeBuffer( HeadBuffer ); + } + + ProtRes = PROT_RES( Packet ); + + ProtRes->Pool.TransmitPool = NULL; + ProtRes->InstanceCounters = NULL; + + NdisFreePacket( Packet ); + + Packet = NULL; +} + + +PTP_TRANSMIT_POOL +TpStressCreateTransmitPool( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE PacketHandle, + IN PACKET_MAKEUP PacketMakeUp, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType, + IN INT PacketSize, + IN INT NumPackets, + IN BOOLEAN ServerPool + ) +{ + NDIS_STATUS Status; + PTP_TRANSMIT_POOL TmpPool; + PNDIS_PACKET Packet; + PPROTOCOL_RESERVED ProtRes; + ULONG SequenceNumber = 0; + ULONG MaxSequenceNumber = 0; + INT NextPacketSize; + INT i; + UCHAR DestInstance = 0; + UCHAR SrcInstance = 0; + UCHAR ClientReference = 0; + UCHAR ServerReference = 0; + + // + // Allocate the Packet Pool Structure + // + + Status = NdisAllocateMemory( + (PVOID *)&TmpPool, + sizeof( TP_TRANSMIT_POOL ), + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreateTransmitPool: failed to allocate TmpPool\n"); + } + return NULL; + } else { + NdisZeroMemory( TmpPool,sizeof( TP_TRANSMIT_POOL )); + } + + // + // and allocate it's SpinLock + // + + TmpPool->SpinLockAllocated = FALSE; + + NdisAllocateSpinLock( &TmpPool->SpinLock ); + + TmpPool->SpinLockAllocated = TRUE; + + // + // Set the Packet Pool Chain to empty + // + + TmpPool->Head = NULL; + TmpPool->Tail = NULL; + + for ( i=0;i<NumPackets-1;i++ ) { + + if ( ServerPool == TRUE ) { + + Packet = TpStressCreateTruncatedPacket( + OpenP, + PacketHandle, + PacketProtocol, + ResponseType + ); + } else { + + if ( OpenP->Stress->Arguments->PacketType == RANDOMSIZE ) { + + NextPacketSize = TpGetRandom( + sizeof( STRESS_PACKET ), + PacketSize + ); + + } else { // ( OpenP->Arguments->Packet_Size == FIXEDSIZE ) + + NextPacketSize = PacketSize; + } + + Packet = TpStressCreatePacket( + OpenP, + PacketHandle, + PacketMakeUp, + DestInstance, + SrcInstance, + PacketProtocol, + ResponseType, + NULL_ADDRESS, + NextPacketSize, + 0, // BufferSize + SequenceNumber, + MaxSequenceNumber, + ClientReference, + ServerReference, + FALSE + ); + } + + if ( Packet == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressCreateTransmitPool: could not allocate packet for pool.\n"); + } + TpStressFreeTransmitPool( TmpPool ); + return NULL; + } + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.NextPacket = TmpPool->Head; + TmpPool->Head = Packet; + + if ( i == 0 ) { + TmpPool->Tail = Packet; + } + } + + // + // Initialize the NumPackets var and the allocation counters + // + + TmpPool->Allocated = 0; + TmpPool->Deallocated = 0; + + return TmpPool; +} + + +VOID +TpStressFreeTransmitPool( + IN PTP_TRANSMIT_POOL TpTransmitPool + ) +{ + PNDIS_PACKET Packet; + PPROTOCOL_RESERVED ProtRes; + + if ( TpTransmitPool == NULL ) { + return; + } + + // + // If the spin lock was allocated free it. + // + + if ( TpTransmitPool->SpinLockAllocated == TRUE ) { + NdisFreeSpinLock( &TpTransmitPool->SpinLock ); + } + + // + // Unchain and destroy the packets chained in the Packet Pool. + // + + while ( TpTransmitPool->Head != NULL ) { + Packet = TpTransmitPool->Head; + + ProtRes = PROT_RES( TpTransmitPool->Head ); + TpTransmitPool->Head = ProtRes->Pool.NextPacket; + + TpStressFreePacket( Packet ); + } + + // + // And free the Packet Pool Structure. + // + + NdisFreeMemory( TpTransmitPool,0,0 ); +} + + +PNDIS_PACKET +TpStressAllocatePoolPacket( + IN PTP_TRANSMIT_POOL TpTransmitPool, + IN PINSTANCE_COUNTERS Counters + ) +{ + PPROTOCOL_RESERVED ProtRes; + PNDIS_PACKET Packet; + + NdisAcquireSpinLock( &TpTransmitPool->SpinLock ); + + if ( TpTransmitPool->Head == NULL ) { + NdisReleaseSpinLock( &TpTransmitPool->SpinLock ); + return NULL; + } + + Packet = TpTransmitPool->Head; + + ProtRes = PROT_RES( Packet ); + TpTransmitPool->Head = ProtRes->Pool.NextPacket; + + if ( TpTransmitPool->Head == NULL ) { + TpTransmitPool->Tail = NULL; + } + + TpTransmitPool->Allocated++; + + NdisReleaseSpinLock( &TpTransmitPool->SpinLock ); + + ProtRes->Pool.TransmitPool = TpTransmitPool; + ProtRes->InstanceCounters = Counters; + + return Packet; +} + + +VOID +TpStressSetPoolPacketInfo( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PUCHAR DestAddr, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference + ) +{ + PNDIS_BUFFER Buffer; + PUCHAR Memory; + UINT Length; + PSTRESS_PACKET StrPacket; + + NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL ); + + NdisQueryBuffer( Buffer,(PVOID *)&Memory,&Length ); + + StrPacket = (PSTRESS_PACKET)Memory; + + StrPacket->hdr.info.DestInstance = DestInstance; + StrPacket->hdr.info.SrcInstance = SrcInstance; + StrPacket->hdr.info.CheckSum = 0xFFFFFFFF; + + StrPacket->sc.SequenceNumber = SequenceNumber; + StrPacket->sc.MaxSequenceNumber = MaxSequenceNumber; + StrPacket->sc.ClientReference = ClientReference; + StrPacket->sc.ServerReference = ServerReference; + + TpInitPoolMediaHeader( &StrPacket->hdr,OpenP->Media,DestAddr ); + + + StrPacket->sc.CheckSum = TpSetCheckSum( + (PUCHAR)&StrPacket->hdr.info, + sizeof( STRESS_PACKET ) - + ( sizeof( ULONG ) + + OpenP->Media->HeaderSize ) + ); + +} + + +VOID +TpStressSetTruncatedPacketInfo( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PUCHAR DestAddr, + IN INT PacketSize, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN ULONG DataBufferOffset + ) +{ + PNDIS_BUFFER Buffer; + PNDIS_BUFFER NextBuffer; + PUCHAR Memory; + UINT Length; + LONG DataBufferSize; + PSTRESS_PACKET TpPacket; + BOOLEAN Reset; + static BOOLEAN IntroduceFalsePageInfo; + register UINT PageCount1; + register UINT PageCount2; + + Reset = FALSE; + + NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL ); + + NdisQueryBuffer( + Buffer, + (PVOID *)&Memory, + &Length + ); + + TpPacket = (PSTRESS_PACKET)Memory; + + TpPacket->hdr.info.PacketSize = PacketSize; + TpPacket->hdr.info.DestInstance = DestInstance; + TpPacket->hdr.info.SrcInstance = SrcInstance; + TpPacket->hdr.info.CheckSum = 0xFFFFFFFF; + + TpPacket->sc.SequenceNumber = SequenceNumber; + TpPacket->sc.MaxSequenceNumber = MaxSequenceNumber; + TpPacket->sc.ClientReference = ClientReference; + TpPacket->sc.ServerReference = ServerReference; + TpPacket->sc.DataBufOffset = DataBufferOffset; + + TpInitTruncatedMediaHeader( + &TpPacket->hdr, + OpenP->Media, + DestAddr, + PacketSize + ); + + TpPacket->sc.CheckSum = TpSetCheckSum( + (PUCHAR)&TpPacket->hdr.info, + sizeof( STRESS_PACKET ) - + ( sizeof( ULONG ) + + OpenP->Media->HeaderSize ) + ); + + NdisGetNextBuffer( Buffer,&NextBuffer ); + + DataBufferSize = PacketSize - sizeof( STRESS_PACKET ); + + TP_ASSERT( DataBufferSize >= 0 ); + + if ( DataBufferSize == 0 ) { + DataBufferSize = 1; + Reset = TRUE; + } + + // test + { + PMDL TmpMdl; + ULONG TmpSize; + PVOID VirtualAddress; + + TmpMdl = (PMDL)NextBuffer; + VirtualAddress = OpenP->Stress->DataBuffer[0]+DataBufferOffset; + + TmpSize = COMPUTE_PAGES_SPANNED(VirtualAddress, DataBufferSize); + if (((TmpMdl->Size - sizeof(MDL)) >> 2L) < TmpSize) + { + TpPrint0("TpStressSetTruncatePacketInfo: bad mdl size\n"); + TpPrint1("New Mdl size = %d\n", TmpMdl->Size); + TpPrint1("DataBufferSize = %d\n", DataBufferSize); + TpPrint1("PagesSpanned = %d\n", TmpSize); + TpPrint1("MdlPages = %d\n", (TmpMdl->Size - sizeof(MDL)) >> 2L); + TpBreakPoint(); + } + } + + IoBuildPartialMdl( + OpenP->Stress->DataBufferMdl[0], + (PMDL)NextBuffer, + (PVOID)(OpenP->Stress->DataBuffer[0]+DataBufferOffset), + DataBufferSize + ); + + if ( Reset == TRUE ) { + NextBuffer->ByteCount = 0; + } + + Packet->Private.TotalLength = PacketSize; + + + + + PageCount1 = ADDRESS_AND_SIZE_TO_SPAN_PAGES( MmGetMdlVirtualAddress( NextBuffer ), MmGetMdlByteCount( NextBuffer ) ); + PageCount2 = ADDRESS_AND_SIZE_TO_SPAN_PAGES( MmGetMdlVirtualAddress( Buffer ), MmGetMdlByteCount( Buffer ) ); + + + if ( IntroduceFalsePageInfo ) { + IntroduceFalsePageInfo = FALSE; + Packet->Private.PhysicalCount = (PageCount1 + PageCount2) | 0x08000000 ; + } else { + IntroduceFalsePageInfo = TRUE; + Packet->Private.PhysicalCount = PageCount1 + PageCount2; + } + +} + + + +VOID +TpStressFreePoolPacket( + IN OUT PNDIS_PACKET Packet + ) +{ + PPROTOCOL_RESERVED ProtRes; + PTP_TRANSMIT_POOL TpTransmitPool; + + // + // Determine the location of the Test Protocol Packet Pool to return + // this packet to. + // + + ProtRes = PROT_RES( Packet ); + TpTransmitPool = ProtRes->Pool.TransmitPool; + + // + // Null out the Packets NextPacket pointer. It will be placed the + // end of the Packet Pool chain. + // + + ProtRes->Pool.TransmitPool = NULL; + ProtRes->InstanceCounters = NULL; + + // + // Take the SpinLock which guards the Packet Pool + // + + NdisAcquireSpinLock( &TpTransmitPool->SpinLock ); + + // + // If the Packet Pool's Head pointer is NULL the poll is + // empty, and this packet is at the Head and the Tail. + // + + if ( TpTransmitPool->Head == NULL ) { + + // + // Chain the packet to the head of the Packet Pool Chain. + // + + TpTransmitPool->Head = Packet; + + } else { + + // + // Else chain the packet to the end of the Packet Pool Chain. + // + + ProtRes = PROT_RES( TpTransmitPool->Tail ); + ProtRes->Pool.NextPacket = Packet; + } + + // + // Finally point the Packet Pool Struct Tail pointer at this packet, + // and incremented the Deallocated Packets counter. + // + + TpTransmitPool->Tail = Packet; + TpTransmitPool->Deallocated++; + + // + // And release the Packet Pool SpinLock. + // + + NdisReleaseSpinLock( &TpTransmitPool->SpinLock ); +} + +// +// Functional Packet Routines +// + + +PTP_PACKET +TpFuncInitPacketHeader( + IN POPEN_BLOCK OpenP, + IN INT PacketSize + ) + +// --------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---------------- + +{ + NDIS_STATUS Status; + PTP_PACKET TmpBuffer; + PUCHAR DataField; + INT DataFieldSize; + USHORT i; + + Status = NdisAllocateMemory((PVOID *)&TmpBuffer, + PacketSize, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncInitPacketHeader: failed to allocate TmpBuffer\n"); + } + return NULL; + + } + else + { + NdisZeroMemory( (PVOID)TmpBuffer,PacketSize ); + } + + if ( !TpInitMediaHeader(&TmpBuffer->u.F2.hdr1, + OpenP->Media, + OpenP->Send->DestAddress, + OpenP->StationAddress, + PacketSize)) + { + NdisFreeMemory( TmpBuffer,0,0 ); + return NULL; + } + + + // + // initialize the packet information header + // + + TmpBuffer->u.F2.hdr1.info.Signature = FUNC1_PACKET_SIGNATURE; + TmpBuffer->u.F2.hdr1.info.DestInstance = OpenP->OpenInstance; + TmpBuffer->u.F2.hdr1.info.SrcInstance = 0; + TmpBuffer->u.F2.hdr1.info.PacketSize = PacketSize; + TmpBuffer->u.F2.hdr1.info.PacketType = FUNC1_PACKET_TYPE; + TmpBuffer->u.F2.hdr1.info.u.PacketNumber = (UCHAR)OpenP->Send->PacketsSent; + + // + // and set the checksum in the header. + // + + TmpBuffer->u.F2.hdr1.info.CheckSum =TpSetCheckSum((PUCHAR)&TmpBuffer->u.F2.hdr1.info, + sizeof( PACKET_INFO ) - sizeof( ULONG )); + + + if ( OpenP->Send->ResendPackets == TRUE ) + { + // + // We are building a resend packet, fill in the FUNC_PACKET info + // for the internal packet, and determine the start of the test + // data field. + // + + if ( !TpInitMediaHeader(&TmpBuffer->u.F2.hdr2, + OpenP->Media, + OpenP->Send->ResendAddress, + OpenP->Send->DestAddress, + ( PacketSize - sizeof( FUNC1_PACKET)))) + { + NdisFreeMemory( TmpBuffer,0,0 ); + return NULL; + } + + + TmpBuffer->u.F2.hdr2.info.Signature = FUNC2_PACKET_SIGNATURE; + TmpBuffer->u.F2.hdr2.info.DestInstance = OpenP->OpenInstance; + TmpBuffer->u.F2.hdr2.info.SrcInstance = 0; + TmpBuffer->u.F2.hdr2.info.PacketSize = PacketSize - sizeof( FUNC1_PACKET ); + TmpBuffer->u.F2.hdr2.info.PacketType = FUNC2_PACKET_TYPE; + TmpBuffer->u.F2.hdr2.info.u.PacketNumber = (UCHAR)OpenP->Send->PacketsSent; + + DataField = (PUCHAR)((PUCHAR)TmpBuffer + (ULONG)sizeof( FUNC2_PACKET )); + + // + // Now set the checksum value for the header. + // + + TmpBuffer->u.F2.hdr2.info.CheckSum = TpSetCheckSum((PUCHAR)&TmpBuffer->u.F2.hdr2.info, + sizeof( PACKET_INFO ) - sizeof( ULONG )); + + } + else + { + // + // Otherwise this is just a standard packet with no resend + // packet contained within. Mark it as such, a set the data field + // pointer to the beginning of the data field. + // + + DataField = (PUCHAR)((PUCHAR)TmpBuffer + (ULONG)sizeof( FUNC1_PACKET ) ); + + } + + DataFieldSize = PacketSize - (ULONG)( DataField - (PUCHAR)TmpBuffer ); + + for ( i = 0 ; i < (USHORT)DataFieldSize ; i++ ) + { + DataField[i] = (UCHAR)( i % 256 ); + } + + return TmpBuffer; +} + + +ULONG +TpSetCheckSum( + IN PUCHAR Buffer, + IN ULONG BufLen + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + PUCHAR TmpBuffer = Buffer; + ULONG TmpCheckSum = 0; + ULONG i; + + for ( i = 0 ; i < BufLen ; i++ ) { + TmpCheckSum += (ULONG)*TmpBuffer++; + } + + return ~TmpCheckSum; +} +/* + +VOID +TpSetCheckSum( + IN PUCHAR Buffer, + IN ULONG BufLen, + IN PULONG CheckSum + ) + +/ *++ + +Routine Description: + +Arguments: + +Return Value: + +--* / + +{ + PUCHAR TmpBuffer = Buffer; + ULONG TmpCheckSum = 0; + ULONG i; + + return; + + for ( i = 0 ; i < BufLen ; i++ ) { + TmpCheckSum += (ULONG)*TmpBuffer++; + } + + *CheckSum = ~TmpCheckSum; +} +*/ + + +BOOLEAN +TpCheckSum( + IN PUCHAR Buffer, + IN ULONG BufLen, + IN PULONG CheckSum + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + PUCHAR TmpBuffer = Buffer; + ULONG TmpCheckSum = 0; + ULONG i; + + return TRUE; + + for ( i = 0 ; i < BufLen ; i++ ) { + TmpCheckSum += (ULONG)*TmpBuffer++; + } + + if (( *CheckSum + TmpCheckSum ) != -1 ) { + TP_ASSERT( FALSE ); + return FALSE; + } + + return TRUE; +} + + +PNDIS_PACKET +TpFuncAllocateSendPacket( + IN POPEN_BLOCK OpenP + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + +--*/ + +{ + NDIS_STATUS Status; + PPROTOCOL_RESERVED ProtRes; + PNDIS_PACKET Packet; + PNDIS_BUFFER Buffer; + PUCHAR TmpBuf; + INT TmpBufSize; + INT MdlSize; + INT i; + + // + // Make sure that this is a legal packetsize, and if it isn't, + // then set it to the nearest valid size. + // + + if (( OpenP->Send->ResendPackets == FALSE ) && + ( OpenP->Send->PacketSize < sizeof( FUNC1_PACKET ))) { + + OpenP->Send->PacketSize = sizeof( FUNC1_PACKET ); + + TpPrint0("TpFuncAllocateSendPacket: PacketSize to small for packet type.\n"); + TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize); + + + } else if (( OpenP->Send->ResendPackets == TRUE ) && + ( OpenP->Send->PacketSize < sizeof( FUNC2_PACKET ))) { + + OpenP->Send->PacketSize = sizeof( FUNC2_PACKET ); + + TpPrint0("TpFuncAllocateSendPacket: Invalid PacketSize for packet type.\n"); + TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize); + + } else if ( OpenP->Send->PacketSize > + (ULONG)OpenP->Media->MaxPacketLen ) { + + OpenP->Send->PacketSize = (ULONG)OpenP->Media->MaxPacketLen; + + TpPrint0("TpFuncAllocateSendPacket: PacketSize to large for media.\n"); + TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize); + } + + NdisAllocatePacket( + &Status, + &Packet, + OpenP->Send->PacketHandle + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + + TpPrint1("TpFuncAllocateSendPacket: NdisAllocatePacket failed %s\n", + TpGetStatus( Status )); + return NULL; + } + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.PacketHandle = &OpenP->Send->PacketHandle; + ProtRes->InstanceCounters = OpenP->Send->Counters; + + TmpBufSize = OpenP->Send->PacketSize; + + TmpBuf = (PUCHAR)TpFuncInitPacketHeader( OpenP,TmpBufSize ); + + if ( TmpBuf == NULL ) { + TpPrint0("TpFuncAllocateSendPacket: failed to initialize Packet Header\n"); + return NULL; + } + + // + // Functional packets are made up of two small buffers at the beginning + // of the MDL chain followed by one large buffer at the end of the chain. + // If there is not enough room in the packet the buffer chain will be + // affected accordingly. + // + + for ( i=0;i<2;i++ ) { + + // + // Select the size of the first and second buffer. + // + + MdlSize = TpGetRandom( OpenP->Media->HeaderSize,0x64 ); + + if ( MdlSize > TmpBufSize ) { + + // + // If it is larger than the remaining packet size, then + // we will use only the remaining packet. + // + + MdlSize = TmpBufSize; + } + + // + // Create a buffer (MDL) using this portion of the packet. + // + + Buffer = TpAllocateBuffer( TmpBuf,MdlSize ); + + if ( Buffer == NULL ) { + TpPrint0("TpFuncAllocateSendPacket: failed to create the MDL\n"); + TpFuncFreePacket( Packet,OpenP->Send->PacketSize ); + return (PNDIS_PACKET)NULL; + } + + // + // And chain it to the back of the packet. + // + + NdisChainBufferAtBack( Packet,Buffer ); + + // + // reset the packet size counters and see if we are out of packet. + // + + TmpBuf += MdlSize; + TmpBufSize -= MdlSize; + + if ( TmpBufSize == 0 ) { + + // + // if so, then return the packet we have made. + // + + return Packet; + } + } + + // + // Otherwise tack on the remainder of the buffer as the last mdl + // in the chain. + // + + Buffer = TpAllocateBuffer( TmpBuf,TmpBufSize ); + + NdisChainBufferAtBack( Packet,Buffer ); + + if ( Buffer == NULL ) { + TpPrint0("TpFuncAllocateSendPacket: failed to create the MDL\n"); + TpFuncFreePacket( Packet,OpenP->Send->PacketSize ); + return NULL; + } + + return Packet; +} + + + +VOID +TpFuncFreePacket( + PNDIS_PACKET Packet, + ULONG PacketSize + ) + +{ + PNDIS_BUFFER HeadBuffer; + PNDIS_BUFFER Buffer; + + if ( Packet == NULL ) { + return; + } + + NdisUnchainBufferAtFront( Packet,&HeadBuffer ); + + if ( HeadBuffer != NULL ) { + + NdisUnchainBufferAtFront( Packet,&Buffer ); + + while ( Buffer != NULL ) { + TpFreeBuffer( Buffer ); + NdisUnchainBufferAtFront( Packet,&Buffer ); + } + + HeadBuffer->ByteCount = PacketSize; + + NdisFreeMemory( MmGetMdlVirtualAddress( HeadBuffer ),0,0 ); + + TpFreeBuffer( HeadBuffer ); + } + + NdisFreePacket( Packet ); +} diff --git a/private/ntos/ndis/testprot/tpdrvr/perf.c b/private/ntos/ndis/testprot/tpdrvr/perf.c new file mode 100644 index 000000000..255494430 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/perf.c @@ -0,0 +1,2162 @@ +// ------------------------------------------------ +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// perf.c +// +// Abstract: +// +// This file contains the source for the netcard performance tests +// +// Author: +// +// Tim Wynsma (timothyw) 4-27-1994 +// +// Environment: +// +// Kernel mode +// +// +// Changes: +// 5-18-1994 (timothyw) +// Requested changes to performance function and output (part 1) +// 6-08-1994 (timothyw) +// Changed perf tests to client/server model (part 2) +// +// -------------------------------------------------- + + +#include <ndis.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" +#include "string.h" + + +// +// local constants.. +// + +#define MINIMUM_PERF_PACKET 60 +#define PACKETS_PER_BURST 5 + +#define PERFMODE_SEND 0 // client sends to any address +#define PERFMODE_SENDTOSRV 1 // client sends to server +#define PERFMODE_SENDWITHACK 2 // client sends to server, server ACKS +#define PERFMODE_SENDANDRCV 3 // client sends to server, server sends to client +#define PERFMODE_RECEIVE 4 // server sends to client +#define PERFMODE_REQANDRCV 5 // server sends to client when get REQ message +#define PERFMODE_SHUTDOWN 6 // client shuts down server + +#define REQ_DATA 0 +#define REQ_INITGO 1 +#define REQ_ACK 2 +#define REQ_RES 3 + +// +// defines for the packet signature of each type, and for the packet +// types themselves +// + +// "ID" portion of packet signature. This is added to base to get actual signature + +#define PERF_DATA_ID 0x00000000 // test data message +#define PERF_ACKREQ_ID 0x00000001 // ACK or REQ message +#define PERF_START_ID 0x00000002 // INIT or GO message +#define PERF_DONE_ID 0x00000003 // REQRES or SRVDONE message +#define PERF_STOP_ID 0x00000004 // STOPSRV or SRVDOWN message +#define PERF_NOGO_ID 0x00000005 // NOGO message +#define PERF_RESULTS_ID 0x00000006 // RETRES message +#define PERF_ID_MASK 0x00000007 // mask for ID + +#define PERF_BASE 0x76543210 // base signature +#define PERF_SERVER 0x00000008 // offset from base of server ids + +// signatures used by client (messages sent to server) + +#define PERF_CLTDATA_SIGNATURE (PERF_BASE + PERF_DATA_ID) +#define PERF_REQ_SIGNATURE (PERF_BASE + PERF_ACKREQ_ID) +#define PERF_INIT_SIGNATURE (PERF_BASE + PERF_START_ID) +#define PERF_REQRES_SIGNATURE (PERF_BASE + PERF_DONE_ID) +#define PERF_STOPSRV_SIGNATURE (PERF_BASE + PERF_STOP_ID) + +// signatures used by server (messages sent to client) + +#define PERF_SRVDATA_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_DATA_ID) +#define PERF_ACK_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_ACKREQ_ID) +#define PERF_GO_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_START_ID) +#define PERF_SRVDONE_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_DONE_ID) +#define PERF_SRVDOWN_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_STOP_ID) +#define PERF_NOGO_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_NOGO_ID) +#define PERF_RETRES_SIGNATURE (PERF_BASE + PERF_SERVER + PERF_RESULTS_ID) + +// +// structures of special (info) packet types used by performance tests +// structures MUST be packed + +#include <packon.h> + +typedef struct _INFO_PACKET_INFO +{ + ULONG Signature; + ULONG PacketSize; + ULONG Mode; + ULONG Length; + ULONG Count; + ULONG Delay; + UCHAR Address[ADDRESS_LENGTH]; + ULONG CheckSum; +} INFO_PACKET_INFO; + +typedef INFO_PACKET_INFO UNALIGNED *PINFO_PACKET_INFO; + + +typedef struct _RESULTS_PACKET_INFO +{ + ULONG Signature; + ULONG PacketSize; + ULONG PacketsSent; + ULONG SendErrors; + ULONG PacketsReceived; + ULONG ElapsedTime; + ULONG SelfReceives; + ULONG Restarts; + ULONG CheckSum; +} RESULTS_PACKET_INFO; +typedef RESULTS_PACKET_INFO UNALIGNED *PRESULTS_PACKET_INFO; + + +typedef struct _DATA_PACKET_INFO +{ + ULONG Signature; + ULONG PacketSize; + ULONG CheckSum; +} DATA_PACKET_INFO; + +typedef DATA_PACKET_INFO UNALIGNED *PDATA_PACKET_INFO; + +typedef struct _PERF_PACKET +{ + MEDIA_HEADER media; + union + { + INFO_PACKET_INFO info; + DATA_PACKET_INFO data; + RESULTS_PACKET_INFO results; + } u; +} PERF_PACKET; +typedef PERF_PACKET UNALIGNED *PPERF_PACKET; + +#include <packoff.h> + +// +// local functions +// + +PTP_REQUEST_HANDLE +TpPerfAllocatePacket( IN POPEN_BLOCK OpenP, + IN ULONG PacketSize ); + +NDIS_STATUS +TpPerfInitialize( IN OUT POPEN_BLOCK OpenP); + +VOID +TpPerfDeallocate( IN OUT POPEN_BLOCK OpenP); + + +NDIS_STATUS +TpPerfSend( IN POPEN_BLOCK OpenP ); + +VOID +TpPerfSendDpc( IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 ); + +VOID +TpPerfRestart( IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 ); + +VOID +TpPerformEndDpc( IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 ); + +VOID +TpPerfWriteResults( IN PPERF_BLOCK Perform, + IN PRESULTS_PACKET_INFO Info); + + +VOID +TpPerfSetPacketData(POPEN_BLOCK OpenP, + PUCHAR TmpBuf, + ULONG Signature, + PUCHAR DestAddr, + ULONG PacketSize); + +VOID +TpPerfTestCompleted(PPERF_BLOCK Perform); + + +NDIS_STATUS +TpPerfLowPriorityReceive( POPEN_BLOCK OpenP, + PINFO_PACKET_INFO ReceivePacketInfo, + ULONG MessageId); + + +// --------------------------------------------------------------- +// +// Function: TpPerfServer +// +// Arguments: OpenP -- pointer to open block for instance +// +// Returns: Completion status +// +// Descript: This function starts up the PerformServer command +// +// --------------------------------------------------------------- + +NDIS_STATUS +TpPerfServer( POPEN_BLOCK OpenP ) +{ + NDIS_STATUS Status; + PTP_REQUEST_HANDLE RequestHandle; + + // + // Allocate the performance structure, and do necessary initializations + // + + Status = TpPerfInitialize(OpenP); + if (Status != NDIS_STATUS_SUCCESS) + { + return Status; + } + OpenP->Perform->IsServer = TRUE; + OpenP->Perform->MaskId = PERF_BASE; + + // + // yes, I know that OpenP->Perform->ServerAddress is 00-00-00-00-00-00 + // at this point + // + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + OpenP->Perform->GoInitReq = RequestHandle; + + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + OpenP->Perform->AckReq = RequestHandle; + + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + OpenP->Perform->ResReq = RequestHandle; + + TpAddReference( OpenP ); + + return NDIS_STATUS_PENDING; +} + + +// --------------------------------------------------------------- +// +// Function: TpPerfClient +// +// Arguments: OpenP -- pointer to open block for instance +// CmdArgs -- Arguments given in tpctl to PerformClient command +// +// Returns: Completion status +// +// Descript: This function starts up the PerformClient command +// +// --------------------------------------------------------------- + + +NDIS_STATUS +TpPerfClient( POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs ) +{ + PUCHAR p, q, s, t; + ULONG i; + PTP_REQUEST_HANDLE RequestHandle; + NDIS_STATUS Status; + PPERF_BLOCK Perform; + PPERF_RESULTS OutputBuffer; + + // + // Allocate the performance structure, and do necessary initializations + // + + Status = TpPerfInitialize(OpenP); + if (Status != NDIS_STATUS_SUCCESS) + { + return Status; + } + Perform = OpenP->Perform; + Perform->IsServer = FALSE; + Perform->MaskId = PERF_BASE + PERF_SERVER; + + // + // set so no data is avail if aborted + // + OutputBuffer = MmGetSystemAddressForMdl( Perform->PerformIrp->MdlAddress ); + OutputBuffer->ResultsExist = FALSE; + + // Now, deal with the arguments.. + + Perform->NumberOfPackets = CmdArgs->ARGS.TPPERF.PerfNumPackets; + Perform->PacketDelay = CmdArgs->ARGS.TPPERF.PerfDelay; + Perform->PerformMode = CmdArgs->ARGS.TPPERF.PerfMode; + + if ( CmdArgs->ARGS.TPPERF.PerfPacketSize > OpenP->Media->MaxPacketLen ) + { + Perform->PacketSize = OpenP->Media->MaxPacketLen; + IF_TPDBG ( TP_DEBUG_IOCTL_ARGS ) + { + TpPrint1("TpPerfClient: Invalid PacketSize, using %d\n", Perform->PacketSize); + } + } + else if ( CmdArgs->ARGS.TPPERF.PerfPacketSize < MINIMUM_PERF_PACKET ) + { + Perform->PacketSize = MINIMUM_PERF_PACKET; + IF_TPDBG ( TP_DEBUG_IOCTL_ARGS ) + { + TpPrint1("TpPerfClient: Invalid PacketSize, using %d\n", Perform->PacketSize); + } + } + else + { + Perform->PacketSize = CmdArgs->ARGS.TPPERF.PerfPacketSize; + } + + p = Perform->ServerAddress; + q = CmdArgs->ARGS.TPPERF.PerfServerAddr; + s = Perform->ClientAddress; + t = CmdArgs->ARGS.TPPERF.PerfSendAddr; + + + for ( i=0 ; i < OpenP->Media->AddressLen; i++ ) + { + *p++ = *q++; + *s++ = *t++; + } + + // + // only PERFMODE_SEND does not use a info packet (it assumes its sending to + // never-never land) + // + + if (Perform->PerformMode != PERFMODE_SEND) + { + // + // NULL_ADDRESS is not a valid server address + // + if ( RtlCompareMemory( Perform->ServerAddress, + NULL_ADDRESS, + OpenP->Media->AddressLen ) == OpenP->Media->AddressLen ) + { + TpPrint0("TpPerfClient: server address may not equal NULL_ADDRESS\n"); + TpPerfDeallocate(OpenP); + return NDIS_STATUS_FAILURE; + } + + Perform->WhichReq = REQ_INITGO; + + // + // Set up the info send packet and request. + // + + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + Perform->GoInitReq = RequestHandle; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + ((Perform->PerformMode < PERFMODE_SHUTDOWN) + ? PERF_INIT_SIGNATURE + : PERF_STOPSRV_SIGNATURE), + Perform->ServerAddress, + MINIMUM_PERF_PACKET); + + // + // if needed, Set up the data request send packet and request. + // + if (Perform->PerformMode == PERFMODE_REQANDRCV) + { + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + Perform->AckReq = RequestHandle; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + PERF_REQ_SIGNATURE, + Perform->ServerAddress, + MINIMUM_PERF_PACKET); + } + + // + // If needed, set up the request server results send packet and request. + // + + if (Perform->PerformMode < PERFMODE_SHUTDOWN) + { + RequestHandle = TpPerfAllocatePacket( OpenP, MINIMUM_PERF_PACKET); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + Perform->ResReq = RequestHandle; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + PERF_REQRES_SIGNATURE, + Perform->ServerAddress, + MINIMUM_PERF_PACKET); + } + } + else + { + Perform->WhichReq = REQ_DATA; + } + + // + // if necessary, set up the data send packet and request + // + + if (Perform->PerformMode <= PERFMODE_SENDANDRCV) + { + RequestHandle = TpPerfAllocatePacket( OpenP, Perform->PacketSize); + if (RequestHandle == NULL) + { + TpPerfDeallocate(OpenP); + return NDIS_STATUS_RESOURCES; + } + Perform->DataReq = RequestHandle; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + PERF_CLTDATA_SIGNATURE, + Perform->ServerAddress, + Perform->PacketSize); + + if (Perform->PerformMode == PERFMODE_SENDWITHACK) + { + Perform->SendBurstCount = PACKETS_PER_BURST; + } + else + { + Perform->SendBurstCount = Perform->NumberOfPackets+1; + } + Perform->ReceiveBurstCount = Perform->NumberOfPackets+1; + } + else if (Perform->PerformMode == PERFMODE_REQANDRCV) + { + Perform->ReceiveBurstCount = PACKETS_PER_BURST; + } + else + { + Perform->ReceiveBurstCount = Perform->NumberOfPackets+1; + } + + TpAddReference( OpenP ); + + // + // We will be probably be sending more than one packet, so queue TpPerfSendDpc + // and return Pending to the user, the DPC will send the packets, + // and after all the packets have been sent complete the request. + // + + if ( !KeInsertQueueDpc( &Perform->PerformSendDpc, NULL, NULL )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpPerfSend failed to queue the TpPerfSendDpc.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( Perform->PerformIrp != NULL ) + { + Perform->PerformIrp->IoStatus.Status = NDIS_STATUS_FAILURE; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + TpPerfDeallocate(OpenP); + return NDIS_STATUS_FAILURE; + } + return NDIS_STATUS_PENDING; +} + + + +// --------------------------------------------- +// +// Function: TpPerfInitialize +// +// Arguments: OpenP -- ptr to current open instance +// +// Returns: Status +// +// Descript: This function allocates the PERF_BLOCK structure, and initializes +// necessary components of it.. +// +// --------------------------------------------- + +NDIS_STATUS +TpPerfInitialize( IN OUT POPEN_BLOCK OpenP) +{ + NDIS_STATUS Status; + + // Sanity check + + IF_TPDBG (TP_DEBUG_RESOURCES) + { + if (OpenP->Perform != NULL) + { + TpPrint0("TpPerfInitialize: OpenP->Perform is not NULL !\n"); + TpBreakPoint(); + return STATUS_INSUFFICIENT_RESOURCES; + } + } + + // + // First allocate the Performance struct. + // + + if ( (NdisAllocateMemory( (PVOID *)&OpenP->Perform, + sizeof( PERF_BLOCK ), + 0, + HighestAddress) ) != NDIS_STATUS_SUCCESS) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpPerfInitialize: failed to allocate PERF_BLOCK struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // zero everything for starters.. + // + + NdisZeroMemory( OpenP->Perform, sizeof( PERF_BLOCK )); + + // + // Allocate the Send PacketPool. + // + + NdisAllocatePacketPool( &Status, + &OpenP->Perform->PacketHandle, + NUMBER_OF_POOL_PACKETS, + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpPerfInitialize: could not allocate Packet Pool\n"); + } + NdisFreeMemory( OpenP->Perform,0,0 ); + OpenP->Perform = NULL; + return Status; + } + + // + // Initialize the Perform DPCs + // + + KeInitializeDpc(&OpenP->Perform->PerformSendDpc, // performance send + TpPerfSendDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Perform->PerformEndDpc, + TpPerformEndDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Perform->PerformRestartDpc, + TpPerfRestart, + (PVOID)OpenP); + + + KeInitializeTimer( &OpenP->Perform->PerformTimer ); + + // + // other things we can initialize here + // + + OpenP->Perform->PerformIrp = OpenP->Irp; + OpenP->Irp = NULL; + + OpenP->Perform->Active = TRUE; + OpenP->PerformanceTest = TRUE; + + return NDIS_STATUS_SUCCESS; +} + + + +// ------------------------------------------------- +// +// Function: TpPerfDeallocate +// +// Arguments: OpenP -- ptr to current open instance +// +// Returns: none +// +// Descript: This function frees up everything if allocations fail, or when +// we are ending performance testing +// +// ------------------------------------------------- + + +VOID +TpPerfDeallocate( IN OUT POPEN_BLOCK OpenP) +{ + OpenP->PerformanceTest = FALSE; + + if (OpenP->Perform->GoInitReq) + { + TpFuncFreePacket( OpenP->Perform->GoInitReq->u.SEND_REQ.Packet, + OpenP->Perform->GoInitReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( OpenP->Perform->GoInitReq,0,0 ); + } + + if (OpenP->Perform->AckReq) + { + TpFuncFreePacket( OpenP->Perform->AckReq->u.SEND_REQ.Packet, + OpenP->Perform->AckReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( OpenP->Perform->AckReq,0,0 ); + } + + if (OpenP->Perform->ResReq) + { + TpFuncFreePacket( OpenP->Perform->ResReq->u.SEND_REQ.Packet, + OpenP->Perform->ResReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( OpenP->Perform->ResReq,0,0 ); + } + + if (OpenP->Perform->DataReq) + { + TpFuncFreePacket( OpenP->Perform->DataReq->u.SEND_REQ.Packet, + OpenP->Perform->DataReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( OpenP->Perform->DataReq,0,0 ); + } + + NdisFreePacketPool( OpenP->Perform->PacketHandle ); + + NdisFreeMemory( OpenP->Perform,0,0 ); + OpenP->Perform = NULL; +} + + + + +// --------------------------------------------- +// +// Function: TpPerfAllocatePacket +// +// Arguments: OpenP -- ptr to current open instance +// PacketSize -- size of packet being allocated -- +// range is checked by caller +// +// Returns: ptr to request structure for packet if successful, else NULL +// +// Descript: This function allocates all send packets used in performance tests +// +// --------------------------------------------- + + +PTP_REQUEST_HANDLE +TpPerfAllocatePacket( IN POPEN_BLOCK OpenP, + IN ULONG PacketSize ) + +{ + NDIS_STATUS Status; + PPROTOCOL_RESERVED ProtRes; + PNDIS_PACKET Packet; + PNDIS_BUFFER Buffer; + PUCHAR TmpBuf; + PTP_REQUEST_HANDLE RequestHandle; + + // + // first, check to make sure media type is ok. + // This makes sure that this check is done in "main" thread, not + // in a DPC somewhere + + switch( OpenP->Media->MediumType ) + { + case NdisMediumDix: + case NdisMedium802_3: + case NdisMedium802_5: + case NdisMediumFddi: + case NdisMediumArcnet878_2: + break; + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpPerfAllocatePacket: Unsupported MAC Type\n"); + } + return (PTP_REQUEST_HANDLE)NULL; + } + + + NdisAllocatePacket( &Status, + &Packet, + OpenP->Perform->PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint1("TpPerfAllocatePacket: NdisAllocatePacket failed %s\n", TpGetStatus( Status )); + return (PTP_REQUEST_HANDLE)NULL; + } + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.PacketHandle = &OpenP->Perform->PacketHandle; + ProtRes->InstanceCounters = NULL; + + // + // start of things partially copied from TpFuncInitPacketHeader + // + + + Status = NdisAllocateMemory((PVOID *)&TmpBuf, + PacketSize, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncInitPacketHeader: failed to allocate TmpBuf\n"); + } + return (PTP_REQUEST_HANDLE)NULL; + } + NdisZeroMemory( (PVOID)TmpBuf,PacketSize ); + + // data is in 2 or three buffers. The first is always 14 bytes, and the second is + // always 46 bytes. (giving a total of 60 bytes). If Packetsize > 60 bytes, the + // third buffer is created with a size of (Packetsize-60) bytes + + // first, the "media header" = 14 bytes + + NdisAllocateBuffer( &Status, + &Buffer, + NULL, // pool handle, not currently used in NT + TmpBuf, + sizeof (MEDIA_HEADER)); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpPerfAllocatePacket: failed to create the MDL\n"); + TpFuncFreePacket( Packet, PacketSize ); + return (PTP_REQUEST_HANDLE)NULL; + } + + // + // And chain it to the back of the packet. + // + + NdisChainBufferAtBack( Packet,Buffer ); + + // next, the "protocol" info (plus some data) = 46 bytes (46+14=60) + + NdisAllocateBuffer( &Status, + &Buffer, + NULL, // pool handle, not currently used in NT + TmpBuf+sizeof(MEDIA_HEADER), + MINIMUM_PERF_PACKET - sizeof(MEDIA_HEADER)); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpPerfAllocatePacket: failed to create the MDL\n"); + TpFuncFreePacket( Packet, PacketSize ); + return (PTP_REQUEST_HANDLE)NULL; + } + + // + // And chain it to the back of the packet. + // + + NdisChainBufferAtBack( Packet,Buffer ); + + // finally, if we need more than 60 bytes, add a buffer with the rest.. + + if (PacketSize > MINIMUM_PERF_PACKET) + { + NdisAllocateBuffer( &Status, + &Buffer, + NULL, // pool handle, not currently used in NT + TmpBuf+MINIMUM_PERF_PACKET, + PacketSize-MINIMUM_PERF_PACKET); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpPerfAllocatePacket: failed to create the MDL\n"); + TpFuncFreePacket( Packet, PacketSize ); + return (PTP_REQUEST_HANDLE)NULL; + } + + // + // And chain it to the back of the packet. + // + + NdisChainBufferAtBack( Packet,Buffer ); + } + + Status = NdisAllocateMemory((PVOID *)&RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpPerfAllocatePacket: unable to allocate Request Handle.\n"); + return (PTP_REQUEST_HANDLE)NULL; + } + else + { + NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE )); + } + + RequestHandle->Signature = SEND_REQUEST_HANDLE_SIGNATURE; + RequestHandle->Open = OpenP; + RequestHandle->RequestPended = TRUE; + RequestHandle->Irp = OpenP->Perform->PerformIrp; + + RequestHandle->u.PERF_REQ.Packet = Packet; + RequestHandle->u.PERF_REQ.PacketSize = PacketSize; + RequestHandle->u.PERF_REQ.SendPacket = TRUE; + RequestHandle->u.PERF_REQ.Buffer = TmpBuf; + + ProtRes = PROT_RES( Packet ); + ProtRes->RequestHandle = RequestHandle; + + // + // Set the check sum in the PROTOCOL RESERVED Section of the + // packet header to ensure it is not touched while the packet + // is in the hands of the MAC. + // + + ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) ); + + return RequestHandle; + +} + +// ----------------------------------------------------- +// +// Function: TpPerfSetPacketData +// +// Arguments: OpenP -- ptr to current open instance +// TmpBuf -- ptr to memory allocated for packet data +// Signature -- packet type signature to use +// DestAddr -- address to which packet will be sent +// PacketSize -- bytes allocated for packet +// +// Returns: None +// +// Descript: stuffs data into a packet +// +// ----------------------------------------------------- + +VOID +TpPerfSetPacketData(POPEN_BLOCK OpenP, + PUCHAR TmpBuf, + ULONG Signature, + PUCHAR DestAddr, + ULONG PacketSize) +{ + PPERF_PACKET TmpBuffer = (PPERF_PACKET)TmpBuf; + PUCHAR p; + PUCHAR q; + PUCHAR SrcAddr = OpenP->StationAddress; + USHORT DataSizeShort; + USHORT i; + PPERF_BLOCK Perform = OpenP->Perform; + + + if (DestAddr != NULL) // only do this on first pass + { + switch( OpenP->Media->MediumType ) + { + case NdisMediumDix: + case NdisMedium802_3: + p = TmpBuffer->media.e.DestAddress; + q = TmpBuffer->media.e.SrcAddress; + DataSizeShort = (USHORT)( PacketSize - OpenP->Media->HeaderSize ); + TmpBuffer->media.e.PacketSize_Hi = (UCHAR)( DataSizeShort >> 8 ); + TmpBuffer->media.e.PacketSize_Lo = (UCHAR)DataSizeShort; + break; + + case NdisMedium802_5: + TmpBuffer->media.tr.AC = 0x10; + TmpBuffer->media.tr.FC = 0x40; + p = TmpBuffer->media.tr.DestAddress; + q = TmpBuffer->media.tr.SrcAddress; + break; + + case NdisMediumFddi: + TmpBuffer->media.fddi.FC = 0x57; + p = TmpBuffer->media.fddi.DestAddress; + q = TmpBuffer->media.fddi.SrcAddress; + break; + + case NdisMediumArcnet878_2: + TmpBuffer->media.a.ProtocolID = ARCNET_DEFAULT_PROTOCOLID; + p = TmpBuffer->media.a.DestAddress; + q = TmpBuffer->media.a.SrcAddress; + break; + + default: + TpBreakPoint(); + } + + for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ ) + { + *p++ = *DestAddr++; + *q++ = *SrcAddr++; + } + } + + // + // initialize the packet information header + // + + if ((Signature == PERF_SRVDATA_SIGNATURE) || (Signature == PERF_CLTDATA_SIGNATURE)) + { + ULONG DataFieldSize; + PUCHAR DataField; + + TmpBuffer->u.data.Signature = Signature; + TmpBuffer->u.data.PacketSize = PacketSize; + TmpBuffer->u.data.CheckSum = TpSetCheckSum( (PUCHAR)&TmpBuffer->u.data, + sizeof(DATA_PACKET_INFO) - sizeof(ULONG) ); + DataField = TmpBuf + sizeof (MEDIA_HEADER) + sizeof (DATA_PACKET_INFO); + DataFieldSize = PacketSize - (sizeof (MEDIA_HEADER) + sizeof (DATA_PACKET_INFO) ); + for ( i = 0 ; i < DataFieldSize ; i++ ) + { + *DataField++ = (UCHAR)i; + } + } + else if (Signature == PERF_RETRES_SIGNATURE) + { + TmpBuffer->u.results.Signature = PERF_RETRES_SIGNATURE; + TmpBuffer->u.results.PacketSize = PacketSize; + TmpBuffer->u.results.PacketsSent = Perform->SendCount; + TmpBuffer->u.results.SendErrors = Perform->SendFailCount; + TmpBuffer->u.results.PacketsReceived = Perform->ReceiveCount; + TmpBuffer->u.results.ElapsedTime = Perform->PerfSendTotalTime.LowPart; + TmpBuffer->u.results.SelfReceives = Perform->SelfReceiveCount; + TmpBuffer->u.results.Restarts = Perform->RestartCount; + + TmpBuffer->u.results.CheckSum = TpSetCheckSum( (PUCHAR)&TmpBuffer->u.results, + sizeof(RESULTS_PACKET_INFO) - sizeof(ULONG) ); + } + else + { + + TmpBuffer->u.info.Signature = Signature; + if (DestAddr != NULL) + { + ULONG i; + PUCHAR r,s; + + TmpBuffer->u.info.PacketSize = PacketSize; + TmpBuffer->u.info.Mode = Perform->PerformMode; + TmpBuffer->u.info.Length = Perform->PacketSize; + TmpBuffer->u.info.Count = Perform->NumberOfPackets; + TmpBuffer->u.info.Delay = Perform->PacketDelay; + r = TmpBuffer->u.info.Address; + s = Perform->ClientAddress; + for (i=0; i < ADDRESS_LENGTH; i++) + { + *r++ = *s++; + } + } + TmpBuffer->u.info.CheckSum = TpSetCheckSum( (PUCHAR)&TmpBuffer->u.info, + sizeof(INFO_PACKET_INFO) - sizeof(ULONG) ); + } +} + + + + +// ------------------------------------------ +// +// Function: TpPerfSendDpc +// +// Arguments: Dpc -- ignored +// DeferredContext -- actually ptr to open instance +// SysArg1 -- ignored +// SysArg2 -- ignored +// +// Returns: none +// +// Descript: This function is used to start the sending of packets +// Further packets are sent via TpPerfSendComplete +// +// ------------------------------------------- + + +VOID +TpPerfSendDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + NDIS_STATUS Status; + PTP_REQUEST_HANDLE RequestHandle; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + + switch(OpenP->Perform->WhichReq) + { + case REQ_DATA: + RequestHandle = OpenP->Perform->DataReq; + ++OpenP->Perform->SendCount; + OpenP->Perform->PerfSendTotalTime = + RtlLargeIntegerNegate(KeQueryPerformanceCounter(NULL)); + break; + case REQ_INITGO: + RequestHandle = OpenP->Perform->GoInitReq; + break; + case REQ_ACK: + RequestHandle = OpenP->Perform->AckReq; + break; + case REQ_RES: + RequestHandle = OpenP->Perform->ResReq; + break; + } + + ++OpenP->Perform->PacketsPending; + + NdisSend( &Status,OpenP->NdisBindingHandle, RequestHandle->u.PERF_REQ.Packet ); + + if ( Status != NDIS_STATUS_PENDING ) + { + TpPerfSendComplete( OpenP, RequestHandle->u.PERF_REQ.Packet, Status ); + } + +} + + + + +// ----------------------------------------------- +// +// Function: TpPerfSendComplete +// +// Arguments: ProtocolBindingContext -- actually ptr to open instance +// Packet -- the packet that was just sent +// Status -- final status of the send operation +// +// Returns: none +// +// Descript: This function is called after the netcard driver actually +// sends the packet. It is responsible for sending the next +// packet (if there is one to be sent) +// +// ----------------------------------------------- + + +VOID +TpPerfSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ) + + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPERF_BLOCK Perform = OpenP->Perform; + PPROTOCOL_RESERVED ProtRes; + PTP_REQUEST_HANDLE RequestHandle; + PNDIS_BUFFER Buffer; + LARGE_INTEGER DueTime; + ULONG MessageId; + + + + ProtRes = PROT_RES( Packet ); + RequestHandle = ProtRes->RequestHandle; + +senddidnotpend: + + if ( Perform->Active == TRUE ) + { + // + // Make sure it is one of our packets + // + if (( RequestHandle->Signature == SEND_REQUEST_HANDLE_SIGNATURE ) && + ( RequestHandle->u.PERF_REQ.SendPacket == TRUE )) + { + // + // Packet was sent by the PERF command, decrement the + // counter tracking the number of outstanding functional packets, + // and if the send succeeded increment the completion counter. + // + + --Perform->PacketsPending; + + // + // doesn't do any good to reverse logic here (at least for x86) + // so just put up with the 1 jump + // + + if (Status != NDIS_STATUS_SUCCESS) + { + // + // If we are running on TokenRing the following two "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + // SanjeevK : Even FDDI returns the same errors as 802.5 + // + + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++Perform->SendFailCount; + } + } + else + { + ++Perform->SendFailCount; + } + } + + // + // not checking the checksum of the PROTOCOL_RESERVED section + // here, because that stuff was done in functional testing + // + + MessageId = ((PPERF_PACKET)RequestHandle->u.PERF_REQ.Buffer)->u.info.Signature + - PERF_BASE; + + // + // deal with performance test messages first + // + + if ((MessageId & PERF_ID_MASK) == PERF_DATA_ID) + { + if ( ++Perform->PacketsSent < Perform->NumberOfPackets ) + { + // + // if in a mode where never wait for ack or req, don't + // bother with spin-lock, etc, even though this causes + // repetitious code... + // + if ((Perform->PerformMode != PERFMODE_SENDWITHACK) && + (Perform->PerformMode != PERFMODE_REQANDRCV)) + { + ++Perform->PacketsPending; + ++Perform->SendCount; + + if (!Perform->PacketDelay) + { + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status == NDIS_STATUS_PENDING ) + { + return; + } + goto senddidnotpend; // avoid recursion + } + // + // delay code + // + else + { + KeStallExecutionProcessor(10 * Perform->PacketDelay); + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status == NDIS_STATUS_PENDING ) + { + return; + } + goto senddidnotpend; // avoid recursion + } + } + + // + // send another packet if SendBurstCount has not run out + // otherwise, wait for REQ or ACK (and setup timeout?) + // + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (--Perform->SendBurstCount != 0) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + ++Perform->PacketsPending; + ++Perform->SendCount; + + if (!Perform->PacketDelay) + { + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status == NDIS_STATUS_PENDING ) + { + return; + } + goto senddidnotpend; // avoid recursion + } + // + // delay code + // + else + { + KeStallExecutionProcessor(10 * Perform->PacketDelay); + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status == NDIS_STATUS_PENDING ) + { + return; + } + goto senddidnotpend; // avoid recursion + } + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_TENTH_SECOND)); + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + &Perform->PerformRestartDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( + "TpPerfSendComplete: set PerformTimer while timer existed(4).\n"); + } + } + } + } + else + { + TpPerfTestCompleted(Perform); + } + return; + } + + // + // deal with all other messages + // + switch ( MessageId) + { + // + // info messages sent by server. Nothing special to do + // when send is complete + // + case PERF_ACKREQ_ID: // client: REQ message + case (PERF_ACKREQ_ID + PERF_SERVER): // server: ACK message + case PERF_START_ID: // client: INIT message + case PERF_DONE_ID: // client: REQRES message + case (PERF_DONE_ID + PERF_SERVER): // server: SRVDONE message + case PERF_STOP_ID: // client: STOPSRV message + case (PERF_NOGO_ID + PERF_SERVER): // server: NOGO message + return; // client waits for server message + // server waits for client response + + // + // we are a server, and we just got done sending a GO message + // if we are a sender, send the first performance packet + // + case (PERF_START_ID + PERF_SERVER): // server: GO message + if (Perform->PerformMode >= PERFMODE_SENDANDRCV) + { + // + // server needs to send data to client. start it up + // + Perform->WhichReq = REQ_DATA; + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_HUNDREDTH_SECOND*2)); + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + &Perform->PerformSendDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( + "TpPerfSendComplete: set PerformTimer while timer existed(1).\n"); + } + } + } + return; + + // + // we are a server, and we just got done sending the final results + // to the client. finish shutting down from this test + // + + case (PERF_RESULTS_ID + PERF_SERVER): // server: sent results + if (Perform->DataReq) // clean up, then wait for INIT message + { + TpFuncFreePacket( Perform->DataReq->u.SEND_REQ.Packet, + Perform->DataReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( Perform->DataReq,0,0 ); + Perform->DataReq = NULL; + } + return; + + // + // we are a server, and we just got done acknowledging a shut-down request + // from the client. finish up with the shutdown. + // + case (PERF_STOP_ID + PERF_SERVER): // server: acknowledged shutdown + // request cleansup, then exit + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + &Perform->PerformEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( + "TpPerfSendComplete: set PerformTimer while timer existed(2).\n"); + } + } + return; + + default: // illegal message + TpPrint0("TpPerfSendComplete: unknown message\n"); + TpBreakPoint(); + return; + + + } + } // if (RequestSignature == .. + + else + { + // + // this is not one of ours. we should never, ever get here... + // + TpPrint0("TpPerfSendComplete: Not one of ours--why are we here?"); + NdisUnchainBufferAtFront( Packet,&Buffer ); + NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 ); + TpFreeBuffer( Buffer ); + NdisFreePacket( Packet ); + NdisFreeMemory( RequestHandle,0,0 ); + return; + } + } // if (Perform->Active) + +} + + +// ----------------------------------------------------------- +// +// TpPerfTestCompleted +// +// Arguments: OpenP -- ptr to current open instance +// +// Returns: none +// +// Descript: This code deals with cleanup that needs to be done at the +// end of a send test +// +// ---------------------------------------------------------- + +VOID +TpPerfTestCompleted(PPERF_BLOCK Perform) +{ + LARGE_INTEGER scale; + LARGE_INTEGER ltemp; + LARGE_INTEGER DueTime; + PKDPC DpcPtr; + + Perform->PerfSendTotalTime = RtlLargeIntegerAdd( Perform->PerfSendTotalTime, + KeQueryPerformanceCounter(&scale)); + + Perform->PerfSendTotalTime = RtlExtendedIntegerMultiply(Perform->PerfSendTotalTime, 1000); + Perform->PerfSendTotalTime = RtlLargeIntegerDivide(Perform->PerfSendTotalTime, + scale, <emp); + + if (Perform->IsServer) + { + DpcPtr = &Perform->PerformSendDpc; + Perform->WhichReq = REQ_ACK; // SRVDONE message + } + + // + // must be client.. + // + else if (Perform->PerformMode == PERFMODE_SEND) + { + // + // Write the statistics to the send results outputbuffer. + // + + TpPerfWriteResults( Perform, NULL ); + DpcPtr = &Perform->PerformEndDpc; + } + + else + { + if (Perform->PerformMode == PERFMODE_SENDANDRCV) + { + if (!Perform->Testing) + { + Perform->Testing = TRUE; + return; + } + } + Perform->WhichReq = REQ_RES; + DpcPtr = &Perform->PerformSendDpc; + } + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + DpcPtr )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( "TpPerfTestCompleted: set PerformTimer while timer existed.\n"); + } + } +} + +// ------------------------------------------------------- +// +// Function: TpPerfReceive +// +// Arguments: ProtocolBindingContext -- actually ptr to current open instance +// LookaheadBuffer -- ptr to actual data received (after header) +// LookaheadBufferSize -- valid bytes in LookaheadBuffer +// PacketSize -- total size of packet (excluding header) +// +// Returns: Status +// +// Descript: This function deals with packets received by this netcard open instance +// Some packets are counted, some just thrown away, some result in other +// packets being sent +// +// ------------------------------------------------------- + + + +NDIS_STATUS +TpPerfReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ) + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPERF_BLOCK Perform = OpenP->Perform; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PINFO_PACKET_INFO ReceivePacketInfo; + PNDIS_PACKET Packet; + ULONG MessageId; + + // + // if we are not active (ie, shutting down) skip everything + // + + if (Perform->Active) + { + // + // The LookAhead Buffer has been adjusted to point to the beginning of the + // PACKET_INFO structure + // + ReceivePacketInfo = (PINFO_PACKET_INFO)LookaheadBuffer; + + // + // All valid messages have a signature of 0x7654321X. + // Using the MaskId, convert all valid messages to 0x0000000X. + // invalid messages will have other bits set. Messages that we + // managed to send to ourselves will be in range 0x08 to 0x0f. + // messages we expect will be in range 0x00 to 0x07 + // + MessageId = ReceivePacketInfo->Signature ^ Perform->MaskId; + // + // trivially discard all unrecognized messages + // + if (MessageId < (PERF_SERVER + PERF_ID_MASK)) + { + // + // first, deal with performance test messages which were received + // + if ( MessageId == PERF_DATA_ID) + { + ++Perform->ReceiveCount; + + // + // Check to see if we need to send an ACK (or a REQ ) + // note that the info packet will already be set up correctly + // + if (--Perform->ReceiveBurstCount != 0) + { + return NDIS_STATUS_SUCCESS; + } + else + { + Perform->ReceiveBurstCount = PACKETS_PER_BURST; + Packet = Perform->AckReq->u.PERF_REQ.Packet; + ++Perform->PacketsPending; + + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status == NDIS_STATUS_PENDING ) + { + return NDIS_STATUS_SUCCESS; + } + TpPerfSendComplete( OpenP, Packet, Status ); + return NDIS_STATUS_SUCCESS; + } + } + // + // second, deal with ACK and REQ messages + // + else if (MessageId == PERF_ACKREQ_ID) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (Perform->SendBurstCount == 0) + { + Perform->SendBurstCount = PACKETS_PER_BURST; + NdisReleaseSpinLock( &OpenP->SpinLock ); + KeCancelTimer(&Perform->PerformTimer); + + Packet = Perform->DataReq->u.PERF_REQ.Packet; + ++Perform->SendCount; + ++Perform->PacketsPending; + + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + if ( Status != NDIS_STATUS_PENDING ) + { + TpPerfSendComplete( OpenP, Packet, Status ); + } + } + else + { + Perform->SendBurstCount += PACKETS_PER_BURST; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + return NDIS_STATUS_SUCCESS; + } + // + // deal with other valid messages + // + else if ((MessageId & PERF_SERVER) == 0) // check other valid messages + { + return TpPerfLowPriorityReceive(OpenP, ReceivePacketInfo, MessageId); + } + // + // deal with messages that we probably sent to ourselves + // while it it POSSIBLE that we got a random message that will + // fit this criteria, we are ignoring that for now + // + else + { + Perform->SelfReceiveCount++; + return NDIS_STATUS_SUCCESS; + } + } + } + return NDIS_STATUS_SUCCESS; // don't fail.. +} + + +// ------------------------------------------------ +// +// Function: TpPerfLowPriorityReceive +// +// Arguments: OpenP -- ptr to current open instance +// ReceivePacketInfo -- data received from other end of wire +// MessageId -- which message we received +// +// Returns: Status +// +// Descript: This function does the initialization required +// when the server receives the PERF_INIT message +// +// ------------------------------------------------- + +NDIS_STATUS +TpPerfLowPriorityReceive( POPEN_BLOCK OpenP, + PINFO_PACKET_INFO ReceivePacketInfo, + ULONG MessageId) +{ + PPERF_BLOCK Perform = OpenP->Perform; + PUCHAR r,s; + ULONG i; + PTP_REQUEST_HANDLE RequestHandle; + PNDIS_PACKET Packet; + LARGE_INTEGER DueTime; + PKDPC DpcPtr; + + + switch(MessageId) + { + case PERF_DONE_ID: // REQRES or SRVDONE message + if (Perform->IsServer) + { + // + // client sent request for final results of test (on server side) + // test had better be complete. Shut down test and send message + // to client with those results + // + TpPerfSetPacketData(OpenP, + Perform->ResReq->u.PERF_REQ.Buffer, + PERF_RETRES_SIGNATURE, + NULL, + MINIMUM_PERF_PACKET); + + Perform->WhichReq = REQ_RES; + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + Perform->Testing = FALSE; + } + else + { + // + // server is done sending data. if only server was sending, get + // stats now . if both were sending, get stats now if we are also + // done. Otherwise, set flags to get data when we are done sending + // + if (Perform->PerformMode == PERFMODE_SENDANDRCV) + { + if (!Perform->Testing) + { + Perform->Testing = TRUE; + return NDIS_STATUS_SUCCESS; + } + } + Perform->WhichReq = REQ_RES; + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + } + break; + + + case PERF_STOP_ID: // STOPSRV or SRVDOWN message + if (Perform->IsServer) + { + // + // client just sent message to server telling server to + // shut down, and go back to tpctl for next command + // + TpPerfSetPacketData(OpenP, + Perform->GoInitReq->u.PERF_REQ.Buffer, + PERF_SRVDOWN_SIGNATURE, + ReceivePacketInfo->Address, + MINIMUM_PERF_PACKET); + + Perform->WhichReq = REQ_INITGO; + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + } + else + { + // + // server is shutting down. We need to do the same + // + DpcPtr = &Perform->PerformEndDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + } + break; + + + case PERF_NOGO_ID: // NOGO message + // + // server just sent message that it is unable to perform the + // requested test. Clean up and exit (to tpctl) + // + DpcPtr = &Perform->PerformEndDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + break; + + + case PERF_RESULTS_ID: // RETRES message + // + // just received final results of this test from the server + // send data to tpctl, cleanup, and exit + // + // + // Write the statistics to the send results outputbuffer. + // + + TpPerfWriteResults( Perform, (PRESULTS_PACKET_INFO)ReceivePacketInfo); + DpcPtr = &Perform->PerformEndDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + break; + + case PERF_START_ID: // INIT or GO message + if (!Perform->IsServer) + { + if (Perform->DataReq) + { + Perform->WhichReq = REQ_DATA; + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_HUNDREDTH_SECOND)); + break; + } + return NDIS_STATUS_SUCCESS; + } + else + { + if (Perform->Testing) // Got 2nd request, not done with 1st + { + TpPrint0("TpPerfReceive: Server got INIT while already running!\n"); + if (Perform->DataReq) + { + TpFuncFreePacket( Perform->DataReq->u.SEND_REQ.Packet, + Perform->DataReq->u.SEND_REQ.PacketSize ); + NdisFreeMemory( Perform->DataReq,0,0 ); + } + } + // + // copy info we will need from message + // + Perform->PerformMode = ReceivePacketInfo->Mode; + Perform->PacketSize = ReceivePacketInfo->Length; + Perform->NumberOfPackets = ReceivePacketInfo->Count; + Perform->PacketDelay = ReceivePacketInfo->Delay; + r = Perform->ClientAddress; + s = ReceivePacketInfo->Address; + for (i=0; i < ADDRESS_LENGTH; i++) + { + *r++ = *s++; + } + // + // initialize counters + // + Perform->SendCount = 0; + Perform->SendFailCount = 0; + Perform->ReceiveCount = 0; + Perform->PacketsSent = 0; + Perform->PerformEndDpcCount = 0; + Perform->PacketsPending = 0; + Perform->Testing = FALSE; + Perform->SelfReceiveCount = 0; + Perform->SendBurstCount = 0; + Perform->ReceiveBurstCount = 0; + Perform->RestartCount = 0; + // + // if we will be sending test data (not just info messages), then + // set up the necessary buffer. If it fails, send a NOGO message + // + if (Perform->PerformMode >= PERFMODE_SENDANDRCV) + { + RequestHandle = TpPerfAllocatePacket( OpenP, Perform->PacketSize); + if (RequestHandle == NULL) + { + TpPrint0("TpPerfReceive: Server unable to allocate data packet\n"); + RequestHandle = Perform->GoInitReq; + Packet = RequestHandle->u.PERF_REQ.Packet; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + PERF_NOGO_SIGNATURE, + Perform->ClientAddress, + MINIMUM_PERF_PACKET); + + Perform->WhichReq = REQ_INITGO; + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + break; + } + Perform->DataReq = RequestHandle; + + TpPerfSetPacketData(OpenP, + RequestHandle->u.PERF_REQ.Buffer, + PERF_SRVDATA_SIGNATURE, + Perform->ClientAddress, + Perform->PacketSize); + + if (Perform->PerformMode == PERFMODE_REQANDRCV) + { + Perform->SendBurstCount = PACKETS_PER_BURST; + } + else + { + Perform->SendBurstCount = Perform->NumberOfPackets+1; + } + Perform->ReceiveBurstCount = Perform->NumberOfPackets+1; + } + + else if (Perform->PerformMode == PERFMODE_SENDWITHACK) + { + Perform->ReceiveBurstCount = PACKETS_PER_BURST; + } + else + { + Perform->ReceiveBurstCount = Perform->NumberOfPackets+1; + } + + // + // all set--initialize the AckReq message, and + // send the client the GO message + // + Perform->Testing = TRUE; + + switch(Perform->PerformMode) + { + case PERFMODE_SENDTOSRV: + case PERFMODE_SENDWITHACK: + TpPerfSetPacketData(OpenP, + Perform->AckReq->u.PERF_REQ.Buffer, + PERF_ACK_SIGNATURE, + Perform->ClientAddress, + MINIMUM_PERF_PACKET); + break; + default: + TpPerfSetPacketData(OpenP, + Perform->AckReq->u.PERF_REQ.Buffer, + PERF_SRVDONE_SIGNATURE, + Perform->ClientAddress, + MINIMUM_PERF_PACKET); + break; + } + TpPerfSetPacketData(OpenP, + Perform->ResReq->u.PERF_REQ.Buffer, + PERF_RETRES_SIGNATURE, + Perform->ClientAddress, + MINIMUM_PERF_PACKET); + + TpPerfSetPacketData(OpenP, + Perform->GoInitReq->u.PERF_REQ.Buffer, + PERF_GO_SIGNATURE, + Perform->ClientAddress, + MINIMUM_PERF_PACKET); + + DpcPtr = &Perform->PerformSendDpc; + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + Perform->WhichReq = REQ_INITGO; + break; + } + + default: + TpPrint0("TpPerfReceive: Client received unrecognized message\n"); + return NDIS_STATUS_NOT_RECOGNIZED; + } + + // + // drop thru to here if need to fire something off with the timer... + // + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + DpcPtr )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( "TpPerfLowPriorityReceive: set PerformTimer while timer existed.\n"); + } + } + return NDIS_STATUS_SUCCESS; +} + + +// -------------------------------------------- +// +// Function: TpPerformEndDpc +// +// Arguments: Dpc -- not used +// DeferredContext -- actually ptr to current open instance +// SysArg1 -- not used +// SysArg2 -- not used +// +// Returns: none +// +// Descript: This function is called when it is time to shut down +// the current performance command +// +// ------------------------------------------- + +VOID +TpPerformEndDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PPERF_BLOCK Perform = OpenP->Perform; + LARGE_INTEGER DueTime; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + // + // See if we have any outstanding packets left to complete. If we do, + // then we will reset the time to queue this dpc routine again in one + // second, if after ten requeue the packet has still no completed we + // assume it will never complete and return the results and finish. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ((( Perform->PerformIrp != NULL ) && + ( Perform->PerformIrp->Cancel == FALSE )) && + (( Perform->PacketsPending != 0 ) && + ( Perform->PerformEndDpcCount++ < 10 ))) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + &Perform->PerformEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpPerformEndDpc: set PerformTimer while timer existed.\n"); + } + } + return; + } + + + // + // and if the IoStatus.Status has not been set, then set it. + // + + if ( (Perform->PerformIrp != NULL) && + (Perform->PerformIrp->IoStatus.Status == NDIS_STATUS_PENDING )) + { + Perform->PerformIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Now set the sending flag to indicate that we are no longer + // SENDing packets. + // + + Perform->Active = FALSE; + + // + // and decrement the reference count on the OpenBlock stating this + // instance of an async test is no longer running, and the adapter + // may be closed if requested. + // + + + if (Perform->PerformIrp != NULL) + { + TpRemoveReference( OpenP ); + IoMarkIrpPending( Perform->PerformIrp ); + + IoAcquireCancelSpinLock( &Perform->PerformIrp->CancelIrql ); + IoSetCancelRoutine( Perform->PerformIrp,NULL ); + IoReleaseCancelSpinLock( Perform->PerformIrp->CancelIrql ); + + IoCompleteRequest( Perform->PerformIrp,IO_NETWORK_INCREMENT ); + + Perform->PerformIrp = NULL; + } + TpPerfDeallocate(OpenP); +} + +// -------------------------------------------- +// +// Function: TpPerfRestart +// +// Arguments: Dpc -- not used +// DeferredContext -- actually ptr to current open instance +// SysArg1 -- not used +// SysArg2 -- not used +// +// Returns: none +// +// Descript: This function is called when it is necessary to restart +// a send without there having been a REQ or ACK received +// +// ------------------------------------------- + +VOID +TpPerfRestart( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PPERF_BLOCK Perform = OpenP->Perform; + NDIS_STATUS Status; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (Perform->SendBurstCount == 0) + { + Perform->SendBurstCount = 1; + NdisReleaseSpinLock( &OpenP->SpinLock ); + Perform->RestartCount++; + ++Perform->SendCount; + ++Perform->PacketsPending; + + NdisSend( &Status,OpenP->NdisBindingHandle, Perform->DataReq->u.PERF_REQ.Packet ); + if ( Status != NDIS_STATUS_PENDING ) + { + TpPerfSendComplete( OpenP, Perform->DataReq->u.PERF_REQ.Packet, Status ); + } + } +} + + +// ----------------------------------------------------------------- +// +// Function: TpPerfWriteResults +// +// Arguments: Perform -- ptr to perform block structure +// Info -- ptr to data received from server (may be NULL) +// +// Returns: none +// +// Descript: This function writes the Performance test statistics into the +// output buffer passed in by the ioctl call. NOTE: the +// OpenP->SpinLock must be held when making this call +// +// ------------------------------------------------------------------ + + +VOID +TpPerfWriteResults( IN PPERF_BLOCK Perform, + IN PRESULTS_PACKET_INFO Info) +{ + PPERF_RESULTS OutputBuffer; + + // + // Get the output buffer out of the MDL stored in the IRP, and map + // it so we may write the statistics to it. + // + + if (( Perform->PerformIrp != NULL ) && + ( Perform->PerformIrp->Cancel == FALSE )) + { + OutputBuffer = MmGetSystemAddressForMdl( Perform->PerformIrp->MdlAddress ); + + // + // Write the statistics to the outbuffer + // + + OutputBuffer->Signature = PERF_RESULTS_SIGNATURE; + OutputBuffer->ResultsExist = TRUE; + OutputBuffer->Mode = Perform->PerformMode; + OutputBuffer->PacketSize = Perform->PacketSize; + OutputBuffer->PacketCount = Perform->NumberOfPackets; + OutputBuffer->Milliseconds = Perform->PerfSendTotalTime.LowPart; + OutputBuffer->Sends = Perform->SendCount; + OutputBuffer->SendFails = Perform->SendFailCount; + OutputBuffer->Receives = Perform->ReceiveCount; + OutputBuffer->SelfReceives = Perform->SelfReceiveCount; + OutputBuffer->Restarts = Perform->RestartCount; + + if (Info != NULL) + { + OutputBuffer->S_Milliseconds = Info->ElapsedTime; + OutputBuffer->S_Sends = Info->PacketsSent; + OutputBuffer->S_SendFails = Info->SendErrors; + OutputBuffer->S_Receives = Info->PacketsReceived; + OutputBuffer->S_SelfReceives = Info->SelfReceives; + OutputBuffer->S_Restarts = Info->Restarts; + } + } +} + + +NDIS_STATUS +TpPerfAbort(POPEN_BLOCK OpenP) +{ + LARGE_INTEGER DueTime; + PPERF_BLOCK Perform = OpenP->Perform; + + // + // We want to stop any active client and/or server on this open + // instance from running the performance routines, so clear the + // Active flag, queue up the EndDpc function, and wait for it + // to finish + // + + Perform->Active = FALSE; + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + for(;;) + { + KeCancelTimer(&Perform->PerformTimer); + if ( KeSetTimer(&Perform->PerformTimer, + DueTime, + &Perform->PerformEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0( "TpPerfAbort: set PerformTimer while timer existed.\n"); + } + } + else + { + break; + } + } + + // + // And wait for them to finish. + // + + while ( OpenP->PerformanceTest == TRUE ) + { + /* NULL */ ; + } + return NDIS_STATUS_SUCCESS; +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/protocol.c b/private/ntos/ndis/testprot/tpdrvr/protocol.c new file mode 100644 index 000000000..e45f71b2c --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/protocol.c @@ -0,0 +1,442 @@ +// ---------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// protocol.c +// +// Abstract: +// +// Test Protocol Indication and Completion routines called by a MAC. +// +// Author: +// +// Tom Adams (tomad) 19-Nov-1991 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Tim Wynsma (timothyw) 4-27-94 +// Performance tests +// 5-18-94 +// Enhancements/improvements to performance tests +// 6-08-94 +// Perf tests chgd to client/server model +// +// --------------------------- + +#include <ndis.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + + + +VOID +TestProtocolOpenComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ) +{ + TpFuncOpenComplete( ProtocolBindingContext,Status,OpenErrorStatus ); +} + + + +VOID +TestProtocolCloseComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ) +{ + TpFuncCloseComplete( ProtocolBindingContext,Status ); +} + + + +VOID +TestProtocolSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + ULONG PacketSignature; + + if (OpenP->PerformanceTest) + { + TpPerfSendComplete( ProtocolBindingContext,Packet,Status ); + } + else + { + // + // First get the signature out of the packet if it is a test prot + // packet. + // + + PacketSignature = TpGetPacketSignature( Packet ); + + if ((( OpenP->Stress->Stressing == TRUE ) && + ( OpenP->Stress->StressEnded == FALSE )) && + ( PacketSignature == STRESS_PACKET_SIGNATURE )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + OpenP->GlobalCounters->SendComps++; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // If this is a stress packet, then let the stress send complete + // routine handle it. + // + + TpStressSendComplete( ProtocolBindingContext,Packet,Status ); + } + else + { + TpFuncSendComplete( ProtocolBindingContext,Packet,Status ); + } + } +} + + + +VOID +TestProtocolTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPROTOCOL_RESERVED ProtRes; + + ProtRes = PROT_RES( Packet ); + + if (OpenP->PerformanceTest) + { + TpPrint0("TestProtocolTransferDataComplete: called while in performance test\n"); + return; + } + + if ((( OpenP->Stress->Stressing == TRUE ) && + ( OpenP->Stress->StressEnded == FALSE )) && + ( ProtRes->RequestHandle->Signature == STRESS_REQUEST_HANDLE_SIGNATURE )) + { + // + // The transfer data was called by the stress routines, so + // let them complete it. + // + + TpStressTransferDataComplete( ProtocolBindingContext, + Packet, + Status, + BytesTransferred ); + } + else + { + TpFuncTransferDataComplete( ProtocolBindingContext, + Packet, + Status, + BytesTransferred ); + } +} + + + +VOID +TestProtocolResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + + if ( OpenP->Stress->Resetting == TRUE ) + { + TpStressResetComplete( ProtocolBindingContext,Status ); + } + else + { + TpFuncResetComplete( ProtocolBindingContext,Status ); + } +} + + + +VOID +TestProtocolRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PTP_REQUEST_HANDLE ReqHndl; + BOOLEAN StressRequest = FALSE; + + if ((( OpenP->Stress->Stressing == TRUE ) && + ( OpenP->Stress->StressEnded == FALSE )) && + ( OpenP->StressReqHndl != NULL )) + { + if ( OpenP->StressReqHndl->u.STRESS_REQ.Request == NdisRequest ) + { + StressRequest = TRUE; + } + else + { + ReqHndl = OpenP->StressReqHndl; + + do + { + if ( ReqHndl->u.STRESS_REQ.NextReqHndl->u.STRESS_REQ.Request == NdisRequest ) + { + StressRequest = TRUE; + break; + } + else + { + ReqHndl = ReqHndl->u.STRESS_REQ.NextReqHndl; + } + } while ( ReqHndl->u.STRESS_REQ.NextReqHndl != NULL ); + } + + if ( StressRequest == TRUE ) + { + TpStressRequestComplete( ProtocolBindingContext,NdisRequest,Status ); + } + else + { + TpFuncRequestComplete( ProtocolBindingContext,NdisRequest,Status ); + } + } + else + { + TpFuncRequestComplete( ProtocolBindingContext,NdisRequest,Status ); + } +} + + + +NDIS_STATUS +TestProtocolReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PUCHAR Lookahead = (PUCHAR)LookaheadBuffer; + PPACKET_INFO PacketInfo; + // + // STARTCHANGE + // + UINT HeaderVariance = sizeof(MEDIA_HEADER)- HeaderBufferSize; + // + // STOPCHANGE + // + + + // + // SPECIAL ENTRY. THIS MUST BE REMOVED IF WE CREATE + // AND TEST FOR TRUE MAC FRAMES AND OTHER RESERVED TYPES + // + switch( OpenP->Media->MediumType ) + { + case NdisMedium802_5: + // + // If the Frame Control indicates that this frames is anything other than + // an LLC frame, we will not accept since we are not responsible for + // generating this frame and this is not part of our control environment + // + // In Token Ring the bit Frame Control field + // F F Z Z Z Z Z Z + // where FF must be 0 1 for an LLC PDU + // + + if ( (((PTR_802_5)HeaderBuffer)->FC & 0xC0) != 0x40 ) + { + IF_TPDBG( TP_DEBUG_INFOLEVEL_2 ) + { + TpPrint1( + "TestProtocolReceive: Dropping 802.5 frame as we received FC Control Frame set to : 0x%2.2x\n", + ((PTR_802_5)HeaderBuffer)->FC ); + } + return NDIS_STATUS_NOT_RECOGNIZED; + } + break; + + case NdisMediumFddi: + // + // If the Frame Control indicates that this frames is anything other than + // an LLC frame, we will not accept since we are not responsible for + // generating this frame and this is not part of our control environment + // + // In FDDI the bit Frame Control field + // C L F F Z Z Z Z + // where FF must be 0 1 for an LLC PDU + // + + if ( (((PFDDI)HeaderBuffer)->FC & 0x30) != 0x10 ) + { + IF_TPDBG( TP_DEBUG_INFOLEVEL_2 ) + { + TpPrint1( + "TestProtocolReceive: Dropping FDDI frame as we received FC Control Frame set to : 0x%2.2x\n", + ((PFDDI)HeaderBuffer)->FC ); + } + return NDIS_STATUS_NOT_RECOGNIZED; + } + break; + + default: + break; + + } + + // + // STARTCHANGE + // + // Adjust the look ahead buffer so that it points to + // the beginning of PACKET_INFO structure + // + LookaheadBuffer = (PVOID)( (PUCHAR)LookaheadBuffer + HeaderVariance ); + LookaheadBufferSize -= HeaderVariance; + // + // STOPCHANGE + // + + if (OpenP->PerformanceTest) + { + return TpPerfReceive( ProtocolBindingContext, + LookaheadBuffer, + LookaheadBufferSize, + PacketSize ); + } + + PacketInfo = LookaheadBuffer; + + if ((( OpenP->Stress->Stressing == TRUE ) && + ( OpenP->Stress->StressEnded == FALSE )) && + ( PacketInfo->Signature == STRESS_PACKET_SIGNATURE )) + { + // + // if so pass it to the stress receive routine. + // + + return TpStressReceive( ProtocolBindingContext, + MacReceiveContext, + HeaderBuffer, + HeaderBufferSize, + LookaheadBuffer, + LookaheadBufferSize, + PacketSize ); + + } + else + { + // + // otherwise let the functional receive routine handle it. + // + return TpFuncReceive( ProtocolBindingContext, + MacReceiveContext, + HeaderBuffer, + HeaderBufferSize, + LookaheadBuffer, + LookaheadBufferSize, + PacketSize ); + } +} + + + +VOID +TestProtocolReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + + if (OpenP->PerformanceTest) + { + return; + } + + if (( OpenP->Stress->Stressing == TRUE ) && + ( OpenP->Stress->StressEnded == FALSE )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + OpenP->GlobalCounters->ReceiveComps++; + NdisReleaseSpinLock( &OpenP->SpinLock ); + TpStressReceiveComplete( ProtocolBindingContext ); + } + else + { + TpFuncReceiveComplete( ProtocolBindingContext ); + } +} + + + +VOID +TestProtocolStatus( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + + if ( OpenP->Stress->Stressing == FALSE ) + { + UINT SpecificStatus; + + // + // XXX: add an expecting flag for tpstressreset. + // + // ADAMBA: Assume the buffer has a four-byte specific status. + // + + if ( StatusBufferSize == sizeof( SpecificStatus )) + { + SpecificStatus = *(PULONG)StatusBuffer; + + TpFuncStatus( ProtocolBindingContext, + GeneralStatus, + StatusBuffer, + StatusBufferSize ); + } + } +} + + + +VOID +TestProtocolStatusComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + + if ( OpenP->Stress->Stressing == FALSE ) + { + // XXX: add an expecting flag for tpstressreset. + + TpFuncStatusComplete( ProtocolBindingContext ); + } +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/sources b/private/ntos/ndis/testprot/tpdrvr/sources new file mode 100644 index 000000000..36f776cdf --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/sources @@ -0,0 +1,57 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=tpdrvr +TARGETPATH=obj +TARGETTYPE=DRIVER + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib \ + ..\tplib\obj\*\tplib.lib \ + $(BASEDIR)\public\sdk\lib\*\ntdll.lib + +INCLUDES=..\inc;..\..\..\inc;..\..\..\..\inc + +SOURCES=tpdrvr.c \ + tpreq.c \ + protocol.c \ + tpfunc.c \ + stress.c \ + strrcv.c \ + strfunc.c \ + tputils.c \ + media.c \ + packet.c \ + perf.c \ + buffer.c + +RELATIVE_DEPTH=..\..\.. + +!IFNDEF 386_WARNING_LEVEL +386_WARNING_LEVEL=/W3 +!ENDIF + +UMTYPE=nt diff --git a/private/ntos/ndis/testprot/tpdrvr/stress.c b/private/ntos/ndis/testprot/tpdrvr/stress.c new file mode 100644 index 000000000..c19e6a0e3 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/stress.c @@ -0,0 +1,2503 @@ +// ***************************** +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpstress.c +// +// Abstract: +// +// This module implements the Test Protocol Stress routines and the +// basic controls for stressing the MAC. +// +// Author: +// +// Tom Adams (tomad) 15-Dec-1990 +// +// Environment: +// +// Kernel mode +// +// Revision History: +// +// Sanjeev Katariya(sanjeevk) +// 3-16-93 Bug#2874: TpStressFreeResources(). +// 4-8-93 Bug#2874: Added routine TpStressFreePostResetResources() to be able to +// call it thru the routine and its associated completion routine. +// 4-8-1993 Added ARCNET Support +// 5-14-1993 Bug#6583 Re-arranged and cleaned up TpStressDpc for CYCLICAL testing +// +// Tim Wynsma (timothyw) +// 5-18-94 Fixed warnings; general cleanup +// +// **************************** + +#include <ndis.h> +#include <string.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + +// +// Forward references +// + +VOID +TpStressDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpStressServerDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpStressStatsDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpStressEndReqDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpStressFinalDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpStressFreeClient( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressFreeServer( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressFreePostResetResources( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressRegister2Dpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +// +// ******************** +// + + +NDIS_STATUS +TpStressStart( + IN POPEN_BLOCK OpenP, + IN PSTRESS_ARGUMENTS StressArguments + ) + +// -------------------- +// +// Routine Description: +// +// This is the main routine of the NDIS 3.0 Stress Tool. This routine +// opens the proper MAC adapter, creates the data structures used to +// control the test, runs the specific test, and then cleans up. +// +// The flow of an actual test is controlled through a series of packet +// protocols sent from a Client machine to any responding Server machines. +// Initially the Client sends a REGISTER_REQ packet to an agreed upon +// address that all servers have registered as a multicast address. Any +// Server receiving this packet responds directly to the Client with a +// REGISTER_RESP packet stating that the Server will participate in the +// test. At this point the Client begins to send the actual test packets, +// TEST_REQ, to each registered Server, who in turn responds with a +// TEST_RESP packet. At the end of a test run the Client sends each +// Server a STATS_REQ packet requesting that the Server print it's test +// statistic. Finally the Client sends a TEST_END packet which causes +// each Server to tear down it's test control data structures and end +// the test. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +// ---------------------- + +{ + NDIS_STATUS Status; + PNDIS_PACKET Packet = NULL; + PSTRESS_ARGUMENTS Args = NULL; + PSERVER_INFO Server = NULL; + INT i, j; + INT ClientNumPackets = 100; // put in environment. + INT ServerNumPackets = 100; + UINT PacketFilter; + LARGE_INTEGER DueTime; + PPENDING PPend; + + // + // Set the StartStarted flag to true indicating that we are running + // a stress test, it will be set to false later if the initialization + // fails. Set the stress cleanup flags Final and Ended to false. + // This will disable any early unexpected cleanup. + // + + OpenP->Stress->StressStarted = TRUE; + OpenP->Stress->StressFinal = FALSE; + OpenP->Stress->StressEnded = FALSE; + + // + // Increment the reference count on the OpenBlock stating that an async + // test is running and must be ended prior to closing the adapter on this + // open. + // + + TpAddReference( OpenP ); + + // + // Initialize the test arguments structure using the arguments passed + // in from the command line. + // + + OpenP->Stress->Arguments = StressArguments; + + // + // Set up new Args pointer for easier access to the arguments. + // + + Args = OpenP->Stress->Arguments; + + // + // Initialize the random number generator. + // + + TpSetRandom(); + + // + // Initialize the data buffer used for the data in each packet. + // + + TpStressInitDataBuffer( OpenP,2 * OpenP->Media->MaxPacketLen ); + + if ( OpenP->Stress->DataBuffer[0] == NULL || + OpenP->Stress->DataBuffer[1] == NULL || + OpenP->Stress->DataBufferMdl[0] == NULL || + OpenP->Stress->DataBufferMdl[1] == NULL ) + { + TpPrint0("TpStressStart: failed to init Data Buffer\n"); + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + + // + // Allocate the global counter storage and zero the counters. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->GlobalCounters, + sizeof( GLOBAL_COUNTERS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressStart: failed to allocate counters.\n"); + } + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + else + { + NdisZeroMemory((PVOID)OpenP->GlobalCounters,sizeof( GLOBAL_COUNTERS )); + } + + NdisAllocatePacketPool( &Status, + &OpenP->Stress->PacketHandle, + 50, + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpStressStart: could not allocate OpenP packet pool\n"); + goto clean_up; + } + else + { + OpenP->Stress->PoolInitialized = TRUE; + } + + // + // Then initialize the PPENDING buffer. + // + + TpInitializePending( OpenP->Stress->Pend ); + + if (( Args->MemberType == TP_SERVER ) || ( Args->MemberType == BOTH )) + { + // + // Allocate memory for the server storage and packet pool, initialize + // it and the CLIENT_INFO array contained. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Server, + sizeof( SERVER_STORAGE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpStressStart: could not allocate Server storage memory\n"); + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + else + { + NdisZeroMemory( OpenP->Stress->Server,sizeof( SERVER_STORAGE )); + } + + OpenP->Stress->Server->NumClients = 0 ; + OpenP->Stress->Server->ActiveClients = 0; + OpenP->Stress->Server->PoolInitialized = FALSE; + OpenP->Stress->Server->PadByte = 0xFF; + OpenP->Stress->Server->PacketHandle = NULL; + OpenP->Stress->Server->TransmitPool = NULL; + OpenP->Stress->Server->PadLong = 0xFFFFFFFF; + + for ( i=0 ; i < MAX_CLIENTS ; i++ ) + { + OpenP->Stress->Server->Clients[i].ClientInstance = 0xFF; + OpenP->Stress->Server->Clients[i].ClientReference = 0xFF; + OpenP->Stress->Server->Clients[i].DataChecking = FALSE; + OpenP->Stress->Server->Clients[i].TestEnding = FALSE; + OpenP->Stress->Server->Clients[i].ServerResponseType = -1; + OpenP->Stress->Server->Clients[i].LastSequenceNumber = 0; + OpenP->Stress->Server->Clients[i].Counters = NULL; + } + + NdisAllocatePacketPool( &Status, + &OpenP->Stress->Server->PacketHandle, + 200, // should be environment.server... + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpStressStart: could not allocate server packet pool\n"); + goto clean_up; + } + else + { + OpenP->Stress->Server->PoolInitialized = TRUE; + } + + // + // The server always gets it's TEST_RESP packets from a transmit + // pool, so create it now. + // + + OpenP->Stress->Server->TransmitPool = + TpStressCreateTransmitPool( OpenP, + OpenP->Stress->Server->PacketHandle, + Args->PacketMakeUp, + TEST_RESP, + Args->ResponseType, + Args->PacketSize, + ServerNumPackets, + TRUE ); + + if ( OpenP->Stress->Server->TransmitPool == NULL ) + { + TpPrint0("TpStressStart: could not create server transmit pool\n"); + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + + // + // Set the stressing flag, thus enabling the TpStress protocol + // handler routines, and the stopstress flag to allow the TpStress + // Dpc to be queued. + // + + OpenP->Stress->Stressing = TRUE; + OpenP->Stress->StopStressing = FALSE; + + // + // Now setup the card to receive packets. + // + + // + // STARTCHANGE + // + if ( OpenP->Media->MediumType == NdisMedium802_5 ) // Tokenring + { + // + // add the stress functional address "C0-00-00-01-00-00" + // + + Status = TpStressSetFunctionalAddress( OpenP, + (PUCHAR)&OpenP->Environment->StressAddress[2], + FALSE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + TpPrint0("TpStressStart: failed to set Functional Address.\n"); + goto clean_up; + } + + PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_FUNCTIONAL; + + } + else if (OpenP->Media->MediumType == NdisMedium802_3) // Ethernet + { + // + // or the stress multicast address "07-07-07-07-07-07" + // + + Status = TpStressAddMulticastAddress( OpenP, + (PUCHAR)OpenP->Environment->StressAddress, + FALSE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + TpPrint0("TpStressStart: failed to add Test Multicast address.\n"); + goto clean_up; + } + + PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST; + + } + else if (OpenP->Media->MediumType == NdisMediumFddi) // Fddi + { + // + // or the stress multicast address "07-07-07-07-07-07" + // + + Status = TpStressAddLongMulticastAddress( OpenP, + (PUCHAR)OpenP->Environment->StressAddress, + FALSE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + TpPrint0("TpStressStart: failed to add Test Multicast address.\n"); + goto clean_up; + } + + PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST; + + } + else if (OpenP->Media->MediumType == NdisMediumArcnet878_2) // ARCNET + { + // + // ARCNET does not support the concept of multicast(group) addressing. + // It works it two modes only, either directed or broadcast. So will use + // the broadcast for setting up client server connections and thereafter + // use the directed addresses + // + PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST; + } + // + // STOPCHANGE + // + + + // + // Set the packet filter to accept the following packet types. + // + + Status = TpStressSetPacketFilter( OpenP,PacketFilter ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + TpPrint0("TpStressStart: failed to set packet filter.\n"); + goto clean_up; + } + + if ( Args->MemberType == TP_SERVER ) + { + // + // Initialize the DPC used to call TpStressServerDpc, and + // TpStressFinalDpc. + // + + KeInitializeDpc(&OpenP->Stress->TpStressDpc, + TpStressServerDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Stress->TpStressFinalDpc, + TpStressFinalDpc, + (PVOID)OpenP ); + + // + // and then set the flag allowing the receive handler to + // accept and process test packets. + // + + Args->BeginReceives = TRUE; + + // + // The Server's main body of work is performed in the receive + // handler, TpStressReceive, and the receive completion routine, + // TpStressReceiveComplete. Once the Client sends the END_REQ + // packet the server will break out of the busy loop, clean up and + // exit. So, for now the server simply queues a DPC at which time + // the server examines the stop flags, and if true, cleans up and + // exits. + // + + // + // Queue the first instance of the DPC and return. + // + + if ( !KeInsertQueueDpc( &OpenP->Stress->TpStressDpc, NULL, NULL) ) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressStart failed to queue the TpStressServerDpc.\n"); + } + Status = NDIS_STATUS_FAILURE; + goto clean_up; + } + } + } + + if (( Args->MemberType == TP_CLIENT ) || ( Args->MemberType == BOTH )) + { + // + // Allocate memory for the client storage and packet pool, initialize + // it and the SERVER_INFO array contained. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Client, + sizeof( CLIENT_STORAGE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpStressStart: could not allocate client storage.\n"); + goto clean_up; + } + else + { + NdisZeroMemory( OpenP->Stress->Client,sizeof( CLIENT_STORAGE )); + } + + OpenP->Stress->Client->NumServers = 0 ; + OpenP->Stress->Client->NextServer = 0 ; + OpenP->Stress->Client->ActiveServers = 0; + OpenP->Stress->Client->PoolInitialized = FALSE; + OpenP->Stress->Client->PacketHandle = NULL; + OpenP->Stress->Client->TransmitPool = NULL; + OpenP->Stress->Client->PacketSize = sizeof( STRESS_PACKET ); + OpenP->Stress->Client->BufferSize = 1; + OpenP->Stress->Client->SizeIncrease = OpenP->Media->MaxPacketLen/150; + + for ( i=0 ; i < MAX_SERVERS ; i++ ) + { + OpenP->Stress->Client->Servers[i].ServerInstance = 0xFF; + OpenP->Stress->Client->Servers[i].ClientReference = 0xFF; + OpenP->Stress->Client->Servers[i].ServerReference = 0xFF; + OpenP->Stress->Client->Servers[i].ServerActive = FALSE; + OpenP->Stress->Client->Servers[i].WindowReset = 0; + OpenP->Stress->Client->Servers[i].SequenceNumber = 1; + + if ( Args->WindowEnabled == TRUE ) + { + OpenP->Stress->Client->Servers[i].MaxSequenceNumber = + OpenP->Environment->WindowSize; + } + else + { + OpenP->Stress->Client->Servers[i].MaxSequenceNumber = 0xFFFFFFFF; + } + + OpenP->Stress->Client->Servers[i].LastSequenceNumber = 0; + OpenP->Stress->Client->Servers[i].PacketDelay = 0; + OpenP->Stress->Client->Servers[i].DelayLength = Args->DelayLength; + OpenP->Stress->Client->Servers[i].WindowReset = 0; + } + + NdisAllocatePacketPool( &Status, + &OpenP->Stress->Client->PacketHandle, + 200, // 1000, // should 200 be environment... + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + TpPrint0("TpStressStart: could not allocate client packet pool\n"); + goto clean_up; + } + else + { + OpenP->Stress->Client->PoolInitialized = TRUE; + } + + if ( Args->PacketsFromPool == TRUE ) + { + OpenP->Stress->Client->TransmitPool = + TpStressCreateTransmitPool( OpenP, + OpenP->Stress->Client->PacketHandle, + Args->PacketMakeUp, + TEST_REQ, + Args->ResponseType, + Args->PacketSize, + ClientNumPackets, + FALSE ); + + if ( OpenP->Stress->Client->TransmitPool == NULL ) + { + TpPrint0("TpStressStart: could not create TP packet pool\n"); + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + } + + // + // Initialize the DPCs to call TpStressDpc, TpStressReg2Dpc, + // TpStressStatsDpc, TpStressEndReqDpc and TpStressFinalDpc. + // + + KeInitializeDpc(&OpenP->Stress->TpStressDpc, + TpStressDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Stress->TpStressReg2Dpc, + TpStressRegister2Dpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Stress->TpStressStatsDpc, + TpStressStatsDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Stress->TpStressEndReqDpc, + TpStressEndReqDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Stress->TpStressFinalDpc, + TpStressFinalDpc, + (PVOID)OpenP ); + + // + // and then set the flag to enable packets being received + // to be handled. + // + + Args->BeginReceives = TRUE; + + // + // Set the stressing flag, thus enabling the TpStress protocol + // handler routines, and the stopstress flag to allow the + // TpStress Dpc to be queued. + // + + OpenP->Stress->Stressing = TRUE; + OpenP->Stress->StopStressing = FALSE; + + if ( Args->MemberType == TP_CLIENT ) + { + // + // Set the packet filter to accept directed packets only. + // + + PacketFilter = NDIS_PACKET_TYPE_DIRECTED; + + Status = TpStressSetPacketFilter( OpenP,PacketFilter ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + TpPrint0("TpStressStart: failed to set packet filter.\n"); + goto clean_up; + } + } + + // + // We are now ready to begin the test, send several instances + // of the REGISTER_REQ packet to the STRESS_MULTICAST/FUNCTIONAL + // address. + // + + TpPrint0("TpStress: starting search for servers\n"); + + PPend = OpenP->Stress->Pend; + + for ( j=0;j<10;j++ ) + { + // + // Construct the REGISTER_REQ packet and send it. + // + + Packet = TpStressCreatePacket( OpenP, + OpenP->Stress->Client->PacketHandle, + Args->PacketMakeUp, + 0, // ServerInstance + OpenP->OpenInstance, + REGISTER_REQ, + Args->ResponseType, + OpenP->Environment->StressAddress, + sizeof( STRESS_PACKET ), + sizeof( STRESS_PACKET ), + (ULONG)j, + 0L,0,0, + Args->DataChecking ); + + if ( Packet == NULL ) + { + TpPrint1("TpStressStart: failed to build REGISTER_REQ packet #%d\n",j); + Status = NDIS_STATUS_RESOURCES; + goto clean_up; + } + + TpStressSend( OpenP,Packet,NULL ); + + // + // Pause momentarily before sending the next packet. + // + + for (;;) + { + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-4 * ONE_HUNDREDTH_SECOND ); + KeDelayExecutionThread(KernelMode, TRUE, &DueTime); + + NdisAcquireSpinLock( &PPend->SpinLock ); + if (PPend->PendingPackets) + { + NdisReleaseSpinLock( &PPend->SpinLock ); + } + else + { + NdisReleaseSpinLock( &PPend->SpinLock ); + break; + } + } + + } + TpPrint0("TpStress: done with search for servers\n"); + + // + // If no servers have registered there is no point in running + // the test, clean up and return. + // + + if ( OpenP->Stress->Client->NumServers == 0 ) + { + TpPrint0("TpStressStart: No servers registered, exiting\n"); + Status = TP_STATUS_NO_SERVERS; + goto clean_up; + } + + // + // Show what servers are registered. + // + + for ( i=0;i<(INT)OpenP->Stress->Client->NumServers;i++ ) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint2("\nServer %d: open %d, ", + i, OpenP->Stress->Client->Servers[i].ServerInstance); + + // + // STARTCHANGE + // + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("address %02X\n", OpenP->Stress->Client->Servers[i].Address[0]); + } + else + { + TpPrint6("address %02X-%02X-%02X-%02X-%02X-%02X\n", + OpenP->Stress->Client->Servers[i].Address[0], + OpenP->Stress->Client->Servers[i].Address[1], + OpenP->Stress->Client->Servers[i].Address[2], + OpenP->Stress->Client->Servers[i].Address[3], + OpenP->Stress->Client->Servers[i].Address[4], + OpenP->Stress->Client->Servers[i].Address[5]); + } + // + // STOPCHANGE + // + } + } + + // + // Initialize the multi-purpose counter used for the up-for-air + // delay, stats dpc and end dpc, and the Register_Req2 counter. + // + + OpenP->Stress->FirstIteration = TRUE; + OpenP->Stress->Counter = 0; + OpenP->Stress->Reg2Counter = 0; + + // + // Queue the first instance of the Stress DPC. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressStart failed to queue the TpStressDpc.\n"); + } + Status = NDIS_STATUS_FAILURE; + goto clean_up; + } + + // + // Queue the first instance of the Register2 DPC and return. + // + + if ( !KeInsertQueueDpc( &OpenP->Stress->TpStressReg2Dpc, + NULL, + NULL )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressStart failed to queue the TpStressReg2Dpc.\n"); + } + Status = NDIS_STATUS_FAILURE; + goto clean_up; + } + } + return NDIS_STATUS_PENDING; + + +clean_up: + + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpStressStart failed to start: returned %s\n", TpGetStatus( Status )); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Stress->StressIrp != NULL ) + { + OpenP->Stress->StressIrp->IoStatus.Status = Status; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + return Status; +} + + + +VOID +TpStressDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PSTRESS_ARGUMENTS Args; + PCLIENT_STORAGE Client; + NDIS_STATUS Status; + UCHAR ServerNum; + PSERVER_INFO Server; + BOOLEAN ContinueSending = TRUE; + LARGE_INTEGER DueTime; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + Args = OpenP->Stress->Arguments; + Client = OpenP->Stress->Client; + + // + // This is the main loop of a stress test, in this loop RANDOM or + // FIXED size packets are sent to each server depending on the delay + // intervals and window size. Packets are sent one to a server, as + // the client loops through each server, and then repeats, if a + // window is closed for a given server, or the packet delay has not + // been reached that server will be skipped over. The client will + // continue to loop thru the servers sending packets until either + // all the packets have been sent, or all the iterations have been + // iterated. NOTE: setting the ServerActive flag to false on all + // the servers will also result in the test ending. + // + + // + // If this is the beginning of the test, get the Start Time + // for later statistics computation. + // + + if ( OpenP->Stress->FirstIteration == TRUE ) + { + KeQuerySystemTime( &OpenP->Stress->StartTime ); + OpenP->Stress->FirstIteration = FALSE; + } + + // + // If the Stress Irp has been cancelled then clean up and leave. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StressIrp == NULL ) || + ( OpenP->Stress->StressIrp->Cancel == TRUE )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + OpenP->Stress->StopStressing = TRUE; + } + else if ( Client->ActiveServers <= 0 ) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // There are no more active servers so just end the test here. + // + + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint1("TpStressDpc: WARNING - Client Open Instance %d ending test.\n", + OpenP->OpenInstance); + TpPrint0("\tNo remaining active stress servers\n"); + } + + OpenP->Stress->StopStressing = TRUE; + } + else if (( Args->PacketType == RANDOMSIZE ) || + ( Args->PacketType == FIXEDSIZE )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Start looping sending packets until one of the conditions + // is met for stopping and requeueing a new DPC to send later. + // The possible conditions are Packet Delay not met, Window for + // a given server is closed or there are no available packets. + // + + while ( ContinueSending == TRUE ) + { + // + // As long as there are still packets to send or loops to + // iterate continue sending packets. + // + + if (( Args->Iterations++ >= Args->TotalIterations ) || + ( Args->AllPacketsSent == TRUE )) + { + break; + } + else + { + // + // Set the packets sent flag to true, it will be reset to + // false later in the loop if there are really packets left + // to send. + // + + Args->AllPacketsSent = TRUE; + + // + // Now loop through each of the servers starting with the + // server we left of with at the end of the last DPC. + // + + for ( ServerNum = Client->NextServer; + ServerNum < Client->NumServers; + ServerNum++ ) + { + Server = &Client->Servers[ServerNum]; + + // + // If this server is still active and we have not sent all + // the packets required to this it, then continue with + // the send process. + // + + if (( Server->ServerActive == TRUE ) && + ( Server->SequenceNumber <= Args->TotalPackets )) + { + // + // Set the flag indicating there are more packets + // to be sent. + // + + Args->AllPacketsSent = FALSE; + + // + // Now check if the Client has waited long enough to + // send another packet to this server. + // + + if (( Server->PacketDelay++ >= Server->DelayLength ) && + ( Server->SequenceNumber <= Server->MaxSequenceNumber )) + { + // + // And if so, allocate a packet and send it to + // the server. + // + + Status = TpStressClientSend(OpenP, + Client->PacketHandle, + Client->TransmitPool, + Server->Address, + OpenP->OpenInstance, + Server->ServerInstance, + TEST_REQ, + Server->SequenceNumber, + 0, // MaxSeqNum: not used in TEST_REQ pkts. + Server->ClientReference, + Server->ServerReference, + Client->PacketSize, + Client->BufferSize ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + Server->SequenceNumber++; + Server->PacketDelay = 0; + if ( Args->DelayType == RANDOMDELAY ) + { + Server->DelayLength = TpGetRandom(0,Args->DelayLength); + } + } + else + { + // + // No packets available to send now. + // Queue a new DPC and exit. + // + + ContinueSending = FALSE; + break; + } + + // + // If the window is not open, check to see if the + // server is presumed dead. + // + + } + else if (( Args->WindowEnabled == TRUE ) && + ( Server->PacketDelay > MAX_PACKET_DELAY )) + { // Put MaxPacketDelay in environment? + // + // We have reset this servers window the maximum + // number of times and it still is not responding + // so we will remove it from the active servers. + // + + if ( Server->WindowReset >= MAX_WINDOW_RESETS ) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint2( + "TpStressDpc: WARNING - Client Open Instance %d marking Server %d as Inactive.\n", + OpenP->OpenInstance,Server->ServerInstance); + } + + Server->ServerActive = FALSE; + Client->ActiveServers--; + + // + // This server may still be alive, so reset the + // window to the initial state causing WINDOW_SIZE + // more packets to be sent to the server on the + // next pass through the loop. + // + + } + else + { + // + // The packet delay for this server has exceeded + // the maximum packet delay, and we are sending + // with windowing enabled, so blast out Window + // Size more packets. + // + + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint1("TpStressDpc: WARNING - Client Open Instance %d\n", + OpenP->OpenInstance); + TpPrint2("\tincreasing Server %d MaxSequenceNumber to %d\n", + Server->ServerInstance, + Server->MaxSequenceNumber + + OpenP->Environment->WindowSize ); + } + + Server->MaxSequenceNumber += OpenP->Environment->WindowSize; + + Server->PacketDelay = 0; + Server->WindowReset++; + Client->NextServer++; + + ContinueSending = FALSE; + break; + } + Client->NextServer++; + break; + } + else + { + // + // Either the window for this server is closed, + // or the delay has not expired. Queue a new DPC, + // and exit. We will start with the next server + // with the next DPC. + // + + Client->NextServer++; + ContinueSending = FALSE; + break; + } + } + } + + // + // We have come to the end of the server array, start again + // at the beginning on the next FOR loop. + // + + Client->NextServer = 0; + } + } + } + else // PacketType == CYCLICAL + { + // + // STARTCHANGE + // + // SanjeevK + // + // This piece of code contain one too many nested loops. It needs to be cleaned + // The cleanup will be instituted at a later date. For the time being the + // loop control will be clearly marked with entry and exit conditions + // + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if ( Client->PacketSize == 0 ) + { + // + // We have just started the test, so set the PacketSize and + // BufferSize to their minimum startimg sizes. + // + + Client->PacketSize = sizeof( STRESS_PACKET ); + Client->BufferSize = 1; + } + + // + // SanjeevK + // + // MARK EXTERIOR CONTROL + // + // NOTE + // + // All loops have control exit conditions. The code has been semi-cleaned + // for recognizable operation. Breaks of jumping between control loops + // has been minimized + // + + // + // This condition if valid gets executed once. If the total iteration count + // is greater than 1, the work is DPCd and on re-entering takes on the + // values set in the control global arguments. That is why it is very important + // to not set the global control values on entry but on exit of a control + // since work can be DPC'd from any part within the control loops. + // + + if ( Args->Iterations < Args->TotalIterations ) + { + // + // FIRST CONTROL LOOP. + // Execute until we exceed MAX_PACKET_LENGTH. + // + while ( Client->PacketSize <= OpenP->Media->MaxPacketLen ) + { + // + // SECOND CONTROL LOOP. + // Execute till the buffer size has gone + // thru a cycle of ( 1,Current Packet Size ) + // + while ( Client->BufferSize <= Client->PacketSize ) + { + // + // Disable the above while loop if... + // + + if ( Args->PacketMakeUp != KNOWN ) + { + Client->BufferSize = Client->PacketSize; + Client->SizeIncrease = 1; + } + + // + // THIRD CONTROL LOOP + // Execute the same code path for all registered/valid stress servers + // + for (ServerNum=Client->NextServer;ServerNum < Client->NumServers;ServerNum++) + { + Server = &Client->Servers[ServerNum]; + + // + // If this server is still active then + // continue with the send process. + // + + if ( Server->ServerActive == TRUE ) + { + if (( Server->PacketDelay++ >= Server->DelayLength ) && + ( Server->SequenceNumber <= Server->MaxSequenceNumber )) + { + Status = TpStressClientSend(OpenP, + Client->PacketHandle, + Client->TransmitPool, + Server->Address, + OpenP->OpenInstance, + Server->ServerInstance, + TEST_REQ, + Server->SequenceNumber, + 0, // MaxSeqNum: not used in TEST_REQ. + Server->ClientReference, + Server->ServerReference, + Client->PacketSize, + Client->BufferSize ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + Server->SequenceNumber++; + Server->PacketDelay = 0; + + if (Args->DelayType == RANDOMDELAY) + { + Server->DelayLength = TpGetRandom(0,Args->DelayLength); + } + } + else + { + // + // No packets are available to send now, + // So set the flag to queue a new DPC + // and exit. + // + goto breakout; + } // END of if ( Status == NDIS_STATUS_SUCCESS ) + } + else if (( Args->WindowEnabled == TRUE ) && + ( Server->PacketDelay > MAX_PACKET_DELAY )) + { + // + // We have reset this servers window the maximum + // number of times and it still is not responding + // so we will remove it from the active servers. + // + + if ( Server->WindowReset >= MAX_WINDOW_RESETS ) + { + // + // Since the window size for the server has exceeded + // the maximum times it could have been reset, mark this + // server as inactive and decrement the number of + // active servers by one + // + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint2( + "TpStressDpc: WARNING - Client Open Instance %d marking Server %d as Inactive.\n", + OpenP->OpenInstance,Server->ServerInstance); + } + + Server->ServerActive = FALSE; + Client->ActiveServers--; + } + else + { + // + // This server may still be alive, so reset the + // window to the initial state causing WINDOW_SIZE + // more packets to be sent to the server on the + // next pass through the loop. + + // + // The packet delay for this server has exceeded + // the maximum packet delay, and we are sending + // with windowing enabled, so blast out + // WindowSize more packets. + // + + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint1("TpStressDpc: WARNING - Client Open Instance %d\n", + OpenP->OpenInstance); + TpPrint2("\tincreasing Server %d MaxSequenceNumber to %d\n", + Server->ServerInstance, + Server->MaxSequenceNumber + + OpenP->Environment->WindowSize ); + } + + Server->MaxSequenceNumber += OpenP->Environment->WindowSize; + + Server->PacketDelay = 0; + Server->WindowReset++; + + } // END of if ( Server->WindowReset >= MAX_WINDOW_RESETS ) + + Client->NextServer++; + goto breakout; + } + else + { + // + // Either the window for this server is closed + // or the delay has not expired yet. Queue a + // new DPC and exit. We will start with the + // next server with the next DPC. + // + + Client->NextServer++; + ContinueSending = FALSE; + goto breakout; + + } // END of if (( Args->WindowEnabled == TRUE ) && + // ( Server->PacketDelay > MAX_PACKET_DELAY )) + } // END of if ( Server->ServerActive == TRUE ) + } // END of FOR loop. Indicates we have dealt with all servers in the list + + // + // CONTROL EXIT CONDITION + // + Client->NextServer = 0; + + // + // SanjeevK + // + // NOTE + // + // This code section was badly nested within another looping section + // This simply needs to reside outside the loop + // + // ORIGINAL COMMENT + // + // If we have succesfully sent this packet + // to the last server in the list, then + // move on to the next packetsize/buffersize + // combination. + // + // + Client->BufferSize += Client->SizeIncrease; + + } // END of while ( Client->BufferSize <= Client->PacketSize ) + + // + // CONTROL EXIT CONDITION + // + Client->BufferSize = 1; + Client->PacketSize += Client->SizeIncrease; + + } // END of while ( Client->PacketSize <= OpenP->Media->MaxPacketLen ) + + // + // CONTROL EXIT CONDITION + // + Client->PacketSize = sizeof( STRESS_PACKET); + + // + // We have completed one full iteration of CYCLICAL + // packets, inc the counter. + // + + Args->Iterations++; + + } // END of if ( Args->Iterations < Args->TotalIterations ) + + } // END of the else PacketType == CYCLICAL + +breakout: + + // + // If the StopStress flag has been set by a command line call, or + // we have sent all the packets requested or completed the required + // number of iterations, then end the stress routine and clean up. + // + + if (( OpenP->Stress->StopStressing == TRUE ) || + ( Args->AllPacketsSent == TRUE ) || + ( Args->Iterations >= Args->TotalIterations )) + { + // + // Set the stop stress flag to halt the Register2Dpc routine + // now, if it was already set this will do nothing. + // + + OpenP->Stress->StopStressing = TRUE; + OpenP->Stress->Counter = 0; + + // + // Set the time for when to queue the TpStressStatsDpc routine. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressStatsDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n"); + } + } + } + else + { + // + // Otherwise the test should continue, so insert the next timer in + // the timer queue and exit. This will queue the next instance of + // the TpStressDpc routine when the timer goes off. + // + + if ( OpenP->Stress->Counter == OpenP->Environment->StressDelayInterval ) + { + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG) (- ((LONG) OpenP->Environment->UpForAirDelay )); + OpenP->Stress->Counter = 0; + } + else + { + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ((LONG) OpenP->Environment->StandardDelay )); + OpenP->Stress->Counter++; + } + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set Stress timer while timer existed.\n"); + } + } + } +} + + + +VOID +TpStressServerDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// --------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + LARGE_INTEGER DueTime; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + DueTime.HighPart = -1; // relative time. + DueTime.LowPart = (ULONG)(- ( ONE_SECOND )); + + // + // If the Stress Irp has been cancelled then clean up and leave. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StressIrp == NULL ) || + ( OpenP->Stress->StressIrp->Cancel == TRUE )) + { + OpenP->Stress->StopStressing = TRUE; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Stress->StopStressing == TRUE ) + { + // + // Either we have received an END_TEST packet from the last + // Client we are stressing, or we have received a command from + // the user interface to stop the test, set the IoStatusBlock + // status field, and end it. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Stress->StressIrp != NULL ) + { + OpenP->Stress->StressIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressFinalDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressServerDpc set Stress timer while timer existed.\n"); + } + } + } + else + { + // + // Otherwise the test should continue, so insert the next timer in + // the timer queue and exit. This will queue the next instance of + // the TpStressServerDpc routine when the timer goes off. + // + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressServerDpc set Stress timer while timer existed.\n"); + } + } + } +} + + + +VOID +TpStressStatsDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PSTRESS_ARGUMENTS Args; + PCLIENT_STORAGE Client; + UCHAR ServerNum; + LARGE_INTEGER DueTime; + PNDIS_PACKET Packet; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + Args = OpenP->Stress->Arguments; + Client = OpenP->Stress->Client; + + // + // If the Stress Irp has been cancelled then skip the stats requesting. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StressIrp != NULL ) && + ( OpenP->Stress->StressIrp->Cancel == FALSE )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Write the client statistics to the Results buffer, and send + // STATS_REQ packets to each server request the servers test stats. + // + + if ( OpenP->Stress->Counter == 0 ) + { + KeQuerySystemTime( &OpenP->Stress->EndTime ); + TpCopyClientStatistics( OpenP ); + TpPrintClientStatistics( OpenP ); + } + + for ( ServerNum=0 ; ServerNum < Client->NumServers ; ServerNum++ ) + { + Packet = TpStressCreatePacket( OpenP, + Client->PacketHandle, + Args->PacketMakeUp, + Client->Servers[ServerNum].ServerInstance, + OpenP->OpenInstance, + STATS_REQ, + Args->ResponseType, + Client->Servers[ServerNum].Address, + 64, 32, + OpenP->Stress->Counter, + OpenP->Stress->Counter, + Client->Servers[ServerNum].ClientReference, + Client->Servers[ServerNum].ServerReference, + Args->DataChecking ); + + if ( Packet == NULL ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressDpc: failed to create STATS_REQ Packet\n"); + } + } + else + { + TpStressSend( OpenP,Packet,NULL ); + } + } + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + OpenP->Stress->StopStressing = TRUE; + } + + if ( OpenP->Stress->Counter++ < 10 ) + { + // + // requeue the StatsDpc. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( ONE_TENTH_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressStatsDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n"); + } + } + } + else + { + // + // reset the multipurpose counter. + // + + OpenP->Stress->Counter = 0; + + // + // Then set the next timer for the EndDpc. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressEndReqDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set Stress timer while timer existed.\n"); + } + } + } +} + + + +VOID +TpStressEndReqDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PSTRESS_ARGUMENTS Args; + PCLIENT_STORAGE Client; + UCHAR ServerNum; + LARGE_INTEGER DueTime; + PNDIS_PACKET Packet; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + Args = OpenP->Stress->Arguments; + Client = OpenP->Stress->Client; + + // + // If the Stress Irp has been cancelled then skip the stats requesting. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StressIrp != NULL ) && + ( OpenP->Stress->StressIrp->Cancel == FALSE )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Send an end request packet to each of the servers. + // + + for ( ServerNum=0;ServerNum<Client->NumServers;ServerNum++ ) + { + Packet = TpStressCreatePacket( OpenP, + Client->PacketHandle, + Args->PacketMakeUp, + Client->Servers[ServerNum].ServerInstance, + OpenP->OpenInstance, + END_REQ, + Args->ResponseType, + Client->Servers[ServerNum].Address, + 64, 32, + OpenP->Stress->Counter, + OpenP->Stress->Counter, + Client->Servers[ServerNum].ClientReference, + Client->Servers[ServerNum].ServerReference, + Args->DataChecking ); + + if ( Packet == NULL ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressDpc: failed to create END_REQ Packet\n"); + } + } + else + { + TpStressSend( OpenP,Packet,NULL ); + } + } + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + OpenP->Stress->StopStressing = TRUE; + } + + if ( OpenP->Stress->Counter++ < 10 ) + { + // + // requeue the StatsDpc. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( ONE_TENTH_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressEndReqDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n"); + } + } + } + else + { + // + // reset the multi-purpose counter. + // + + OpenP->Stress->Counter = 0; + + // + // Then set the next timer for the EndDpc. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( 10 * ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressFinalDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set Stress timer while timer existed.\n"); + } + } + } +} + + + +VOID +TpStressFinalDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// -------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + NDIS_STATUS Status; + PSTRESS_ARGUMENTS Args = NULL; + PSERVER_INFO Server = NULL; + UINT i; + LARGE_INTEGER DueTime; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + Args = OpenP->Stress->Arguments; + + // + // Check to see if all packets sent on this open have completed, + // If they have not all completed see if we have waited long + // enough. long enough being 10 one second delayed cycles + // through TpStressEndDcp. + // + + if ((((( Args->MemberType == TP_CLIENT ) && + ( Args->PacketsFromPool == FALSE )) && + ( OpenP->Stress->Pend->PendingPackets != 0 )) + + // + // We are a Client getting each packet from the NdisPacketPool and + // all the packets from the NdisPacketPool have not completed, or ... + // + + || + + (( Args->PacketsFromPool == TRUE ) && + ( OpenP->Stress->Pend->PacketPendNumber != + OpenP->Stress->Pend->PacketCompleteNumber ))) + + // + // We are getting the packets from the TP_PACKET_POOL, and + // all the TpPoolPackets that pended have not completed and ... + // + + && + + ( OpenP->Stress->Counter++ < 10 )) + { + + // + // We have not waited through 10 cycles of TpStressFinalDpc + // Then reset the timer for this dpc to try again later. + // + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(- ( 1 * ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressTimer, + DueTime, + &OpenP->Stress->TpStressFinalDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressDpc set Stress timer while timer existed.\n"); + } + } + } + else + { + // + // Time to clean up, so first check if there are any packets + // still in the pending queue representing packets that were + // sent, pended, and have not completed. We only do this if + // we are a Client, the server only part is handled at the + // End_Req packet receipt time. + // + + if (( Args->MemberType != TP_SERVER ) && + ( OpenP->Stress->Pend->PendingPackets != 0 )) + { + // + // There are packets in the pend queue, so print out there + // addresses, and break. + // + + IF_TPDBG( TP_DEBUG_DPC ) + { + TpPrint1("TpStressFinalDpc: The following %d packets are still in the\n", + OpenP->Stress->Pend->PendingPackets); + TpPrint1(" Client's Pend Queue for Open Instance %d.\n", + OpenP->OpenInstance); + TpPrint1(" Pend Queue = %lX\n\n", OpenP->Stress->Pend); + + for ( i=0 ; i<NUM_PACKET_PENDS ; i++ ) + { + if (( OpenP->Stress->Pend->Packets[i] != NULL ) && + ( OpenP->Stress->Pend->Packets[i] != (PNDIS_PACKET)-1 )) + { + TpPrint1("\t\t%lX\n", OpenP->Stress->Pend->Packets[i]); + } + } +// TpBreakPoint(); + } + TpInitializePending( OpenP->Stress->Pend ); + } + + // + // Write the stress results into the ioctl buffer to be passed + // back to the user application. + // + + TpStressWriteResults( OpenP ); + + // + // if we have set a functional address or added a multicast + // address then clear it now. + // + + if ( Args->MemberType != TP_CLIENT ) + { + if ( OpenP->Media->MediumType == NdisMedium802_5 ) // Token Ring + { + Status = TpStressSetFunctionalAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to clear Functional Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } + else if (OpenP->Media->MediumType == NdisMedium802_3) // Ethernet + { + Status = TpStressAddMulticastAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } + else if (OpenP->Media->MediumType == NdisMediumFddi) // Fddi + { + Status = TpStressAddLongMulticastAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } // And if you are Arcnet, do nothing + } + + OpenP->Stress->StressFinal = TRUE; + + // + // And clear the packet filter on the card by setting it + // to null. + // + + Status = TpStressSetPacketFilter( OpenP,0 ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint0("TpStressFinalDpc: failed to reset packet filter.\n"); + } + } + } +} + + + +VOID +TpStressCleanUp( + IN POPEN_BLOCK OpenP + ) + +// ------ +// +// Routine Description: +// +// This routine is used to clean up after a failed attempt to start a +// stress test. +// +// Arguments: +// +// OpenP - a pointer to the OPEN_BLOCK containing the structures to be +// deallocated. +// +// Return Value: +// +// None. +// +// ------ + +{ + PSTRESS_ARGUMENTS Args = NULL; + PSERVER_INFO Server = NULL; + NDIS_STATUS Status; + + Args = OpenP->Stress->Arguments; + + // + // Set the stop stress flag to halt the Register2Dpc routine + // now, if it was already set this will do nothing. + // + + OpenP->Stress->StopStressing = TRUE; + OpenP->Stress->Stressing = FALSE; + + // + // if we have set a functional address or added a multicast + // address then clear it now. + // + + if ( Args->MemberType != TP_CLIENT ) + { + if ( OpenP->Media->MediumType == NdisMedium802_5 ) + { + Status = TpStressSetFunctionalAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to clear Functional Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } + else if (OpenP->Media->MediumType == NdisMedium802_3) + { + Status = TpStressAddMulticastAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } + else if (OpenP->Media->MediumType == NdisMediumFddi) + { + Status = TpStressAddLongMulticastAddress( OpenP, + (PUCHAR)NULL_ADDRESS, + TRUE ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n", + TpGetStatus(Status)); + } + } + } // And if you are ARCNET do nothing + } + + // + // And clear the packet filter on the card by setting it + // to null. + // + + Status = TpStressSetPacketFilter( OpenP,0 ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint0("TpStressFinalDpc: failed to reset packet filter.\n"); + } + } + + OpenP->Stress->StressFinal = TRUE; + + // + // Clean up the various data structures allocated during initialization + // + + TpStressFreeResources( OpenP ); + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Stress->StressIrp != NULL ) + { + OpenP->Stress->StressIrp->IoStatus.Status = NDIS_STATUS_FAILURE; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); +} + + + +VOID +TpStressFreeResources( + IN POPEN_BLOCK OpenP + ) + +// ------------- +// +// Changes in functionality: SanjeevK +// +// The RESET should occur prior to resource de-allocation. This is because +// all requests to the adapter in question working over the OPEN_BLOCK should +// be completed since they use the resources allocated by the open block in question. +// After the RESET has completed, the resources are de-allocated +// +// Assumption +// +// OpenP cannot be a NULL at this point and time +// +// Descrption +// +// This function is responsible for clearing the adapter followed by dis-associating +// any resources(memory blocks) which have been associated with an OPEN_BLOCK. +// +// ------------- + +{ + NDIS_STATUS Status; + + + // Sanjeevk : STARTCHANGE + + // + // Initialize the Open block pointer for RESET + // + Status = NdisAllocateMemory((PVOID *)&OpenP->ResetReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressFreeResources: unable to allocate Reset Request Handle.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + else + { + // + // Perform the RESET on the adapter + // + NdisZeroMemory( OpenP->ResetReqHndl,sizeof( TP_REQUEST_HANDLE )); + + // + // And initialize the Reset Request block + // + OpenP->ResetReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + OpenP->ResetReqHndl->Open = OpenP; + OpenP->ResetReqHndl->RequestPended = TRUE; + + // + // Indicate that cleanup is required once the RESET completes + // This is to ensure that the either this routine or the completion + // routine will take care of the cleanup + OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup = TRUE; + + // + // And now issue the RESET + // + OpenP->Stress->Resetting = TRUE; + + Status = TpStressReset( OpenP ); + + } + + + // + // If the RESET has not gotten pended in which case there is the possibility + // of a reset failure we will still proceed and free up the resources + // + + if ( Status != NDIS_STATUS_PENDING ) + { + // + // Indicate that we will take care of the post reset cleanup + // and that the completion routine does not have to take care of it + // + OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup = FALSE; + + TpStressResetComplete( OpenP,Status ); + + // + // Free up the various data structures allocated during the + // initialization phase. + // + + OpenP->Stress->StressEnded = TRUE; + + // + // Free up the resources associated with this instance of the stress test + // + TpStressFreePostResetResources( OpenP ); + + + // + // Decrement the reference count on the OpenBlock stating this + // instance of an async test is no longer running, and the adapter + // may be closed if requested. + // + TpRemoveReference( OpenP ); + } + // Sanjeevk : STOPCHANGE +} + + + +VOID +TpStressFreeClient( + IN POPEN_BLOCK OpenP + ) +{ + UCHAR i; + + if ( OpenP->Stress->Client != NULL ) + { + if ( OpenP->Stress->Arguments->PacketsFromPool == TRUE ) + { + TpStressFreeTransmitPool( OpenP->Stress->Client->TransmitPool ); + } + + if ( OpenP->Stress->Client->PoolInitialized == TRUE ) + { + NdisFreePacketPool( OpenP->Stress->Client->PacketHandle ); + OpenP->Stress->Client->PoolInitialized = FALSE; + } + + for ( i=0;i<OpenP->Stress->Client->NumServers;i++ ) + { + if ( OpenP->Stress->Client->Servers[i].Counters != NULL ) + { + NdisFreeMemory( (PVOID)OpenP->Stress->Client->Servers[i].Counters,0,0 ); + } + } + + NdisFreeMemory( OpenP->Stress->Client,0,0 ); + OpenP->Stress->Client = NULL; + } +} + + + +VOID +TpStressFreeServer( + IN POPEN_BLOCK OpenP + ) +{ + UCHAR i; + + if ( OpenP->Stress->Server != NULL ) + { + TpStressFreeTransmitPool( OpenP->Stress->Server->TransmitPool ); + + if ( OpenP->Stress->Server->PoolInitialized == TRUE ) + { + NdisFreePacketPool( OpenP->Stress->Server->PacketHandle ); + OpenP->Stress->Server->PoolInitialized = FALSE; + } + + for ( i=0;i<OpenP->Stress->Server->NumClients;i++ ) + { + if ( OpenP->Stress->Server->Clients[i].Counters != NULL ) + { + NdisFreeMemory( (PVOID)OpenP->Stress->Server->Clients[i].Counters,0,0 ); + } + } + + NdisFreeMemory( OpenP->Stress->Server,0,0 ); + OpenP->Stress->Server = NULL; + } +} + + + +VOID +TpStressFreePostResetResources( + IN POPEN_BLOCK OpenP + ) +{ + + if (( OpenP != NULL ) && ( OpenP->Stress->Arguments != NULL )) + { + if (( OpenP->Stress->Arguments->MemberType == TP_CLIENT ) || + ( OpenP->Stress->Arguments->MemberType == BOTH )) + { + TpStressFreeClient( OpenP ); + } + + if (( OpenP->Stress->Arguments->MemberType == TP_SERVER ) || + ( OpenP->Stress->Arguments->MemberType == BOTH )) + { + TpStressFreeServer( OpenP ); + } + + if (OpenP->Stress->PoolInitialized == TRUE ) + { + NdisFreePacketPool( OpenP->Stress->PacketHandle ); + OpenP->Stress->PoolInitialized = FALSE; + } + + + // + // SanjeevK: Free up the data buffer and associated MDL resources + // + TpStressFreeDataBuffers( OpenP ); + TpStressFreeDataBufferMdls( OpenP ); + + + NdisFreeMemory( OpenP->Stress->Arguments,0,0 ); + OpenP->Stress->Arguments = NULL; + + // + // Deallocate the global counters, and their spinlock. + // + + if ( OpenP->GlobalCounters != NULL ) + { + NdisFreeMemory( (PVOID)OpenP->GlobalCounters,0,0 ); + OpenP->GlobalCounters = NULL; + } + } +} + + + +VOID +TpStressRegister2Dpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PSTRESS_ARGUMENTS Args; + LARGE_INTEGER DueTime; + PNDIS_PACKET Packet; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + // + // If the Stress Irp has been cancelled then clean up and leave. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StressIrp == NULL ) || + ( OpenP->Stress->StressIrp->Cancel == TRUE )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + OpenP->Stress->StopStressing = TRUE; + return; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if (( OpenP->Stress->StopStressing == FALSE ) && + ( OpenP->Stress->Client->NumServers < MAX_SERVERS )) + { + Args = OpenP->Stress->Arguments; + + if (( OpenP->Stress->Reg2Counter < 60 ) || + (( OpenP->Stress->Reg2Counter % 60 ) == 0 )) + { + // + // We are now ready to begin the test, send a REGISTER_REQ + // packet to the STRESS_MULTICAST/FUNCTIONAL address. + // + // Construct the REGISTER_REQ2 packet and send it. + // + + Packet = TpStressCreatePacket( OpenP, + OpenP->Stress->Client->PacketHandle, + Args->PacketMakeUp, + 0, // ServerInstance + OpenP->OpenInstance, + REGISTER_REQ2, + Args->ResponseType, + OpenP->Environment->StressAddress, + sizeof( STRESS_PACKET ), + sizeof( STRESS_PACKET ), + 0,0L,0,0, + Args->DataChecking ); + + if ( Packet == NULL ) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressRegister2Dpc: failed to build REGISTER_REQ2 packet\n"); + } + } + else + { + TpStressSend( OpenP,Packet,NULL ); + } + } + + // + // We will continue requeueing this Dpc for 6 minutes. The first + // minute we will send once every second then for the next five + // minutes send only one request each minute. + // + + if ( OpenP->Stress->Reg2Counter++ < 360 ) + { + // + // Now requeue the Dpc to run try again next time. + // + + DueTime.HighPart = -1; + DueTime.LowPart = (ULONG)(- ( ONE_SECOND )); + + if ( KeSetTimer(&OpenP->Stress->TpStressReg2Timer, + DueTime, + &OpenP->Stress->TpStressReg2Dpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpStressRegister2Dpc set TpStressReg2Timer while timer existed.\n"); + } + } + } + } +} + + diff --git a/private/ntos/ndis/testprot/tpdrvr/strfunc.c b/private/ntos/ndis/testprot/tpdrvr/strfunc.c new file mode 100644 index 000000000..c9721cc42 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/strfunc.c @@ -0,0 +1,1858 @@ +// ********************** +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// strfunc. +// +// Abstract: +// +// Tests to drive the NDIS wrapper and NDIS 3.0 MACs. +// +// Author: +// +// Tom Adams (tomad) 26-Nov-1990 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Sanjeev Katariya(sanjeevk) +// 3-16-1993 Change TpStressResetComplete() to accomodate for bug #2874 +// 4-14-1993 Changed error count check for Fddi also within TpStressSendComplete since +// both 802.5 and Fddi work on tokens and hence the FS bits are the same +// 5-10-1993 Fixed TpStressTransferDataComplete to not check the data in the event +// that the transfer data failed. Bug#9244 +// +// Tim Wynsma (timothyw) +// 5-18-1994 Fixed warnings, improved debug, cleanup +// +// ****************** + +#include <ndis.h> + +#include <string.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + +// +// Forward references +// +extern VOID +TpStressFreePostResetResources( + IN POPEN_BLOCK OpenP + ); + + + +NDIS_STATUS +TpStressAddMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN BOOLEAN SetZeroTableSize + ) + +// ----- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---- + +{ + NDIS_STATUS Status; + PNDIS_REQUEST Request; + PTP_REQUEST_HANDLE ReqHndl; + ULONG OidIndex; + PUCHAR InformationBuffer; + + + Status = NdisAllocateMemory((PVOID *)&ReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate ReqHndl.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( ReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + ReqHndl->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ReqHndl->Open = OpenP; + ReqHndl->RequestPended = TRUE; + ReqHndl->u.STRESS_REQ.NextReqHndl = NULL; + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate Request.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = NdisRequestSetInformation; + + OidIndex = TpLookUpOidInfo( OID_802_3_MULTICAST_LIST ); + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + OidArray[OidIndex].Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate Information Buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length ); + } + + Request->DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + if ( SetZeroTableSize ) + { + Request->DATA.SET_INFORMATION.InformationBufferLength = 0; + } + else + { + Request->DATA.SET_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + } + + RtlMoveMemory( InformationBuffer,MulticastAddress,ADDRESS_LENGTH ); + + ReqHndl->u.STRESS_REQ.Request = Request; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + ReqHndl->u.STRESS_REQ.NextReqHndl = OpenP->StressReqHndl; + OpenP->StressReqHndl = ReqHndl; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + ++OpenP->Stress->Pend->PendingRequests; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + TP_ASSERT( Request->DATA.SET_INFORMATION.BytesRead <= + Request->DATA.SET_INFORMATION.InformationBufferLength ); + } + + // + // If the request did not pend, then free up the memory now. + // + + if ( Status != NDIS_STATUS_PENDING ) + { + TpStressRequestComplete( OpenP,Request,Status ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressAddMulticastAddress: NdisRequest returned %s\n", + TpGetStatus(Status)); + } + } + } + + return Status; +} + + + +NDIS_STATUS +TpStressAddLongMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN BOOLEAN SetZeroTableSize + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------ + +{ + NDIS_STATUS Status; + PNDIS_REQUEST Request; + PTP_REQUEST_HANDLE ReqHndl; + ULONG OidIndex; + PUCHAR InformationBuffer; + + + Status = NdisAllocateMemory((PVOID *)&ReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate ReqHndl.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( ReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + ReqHndl->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ReqHndl->Open = OpenP; + ReqHndl->RequestPended = TRUE; + ReqHndl->u.STRESS_REQ.NextReqHndl = NULL; + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate Request.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = NdisRequestSetInformation; + + OidIndex = TpLookUpOidInfo( OID_FDDI_LONG_MULTICAST_LIST ); + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + OidArray[OidIndex].Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressAddMulticastAddress: unable to allocate Information Buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length ); + } + + Request->DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + + if ( SetZeroTableSize ) + { + Request->DATA.SET_INFORMATION.InformationBufferLength = 0; + } + else + { + Request->DATA.SET_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + } + + RtlMoveMemory( InformationBuffer,MulticastAddress,ADDRESS_LENGTH ); + + ReqHndl->u.STRESS_REQ.Request = Request; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + ReqHndl->u.STRESS_REQ.NextReqHndl = OpenP->StressReqHndl; + OpenP->StressReqHndl = ReqHndl; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + ++OpenP->Stress->Pend->PendingRequests; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + TP_ASSERT( Request->DATA.SET_INFORMATION.BytesRead <= + Request->DATA.SET_INFORMATION.InformationBufferLength ); + } + + // + // If the request did not pend, then free up the memory now. + // + + if ( Status != NDIS_STATUS_PENDING ) + { + TpStressRequestComplete( OpenP,Request,Status ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressAddMulticastAddress: NdisRequest returned %s\n", + TpGetStatus(Status)); + } + } + } + + return Status; +} + + + +NDIS_STATUS +TpStressSetFunctionalAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR FunctionalAddress, + IN BOOLEAN SetZeroTableSize + ) + +// ------ +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------ + +{ + NDIS_STATUS Status; + PTP_REQUEST_HANDLE ReqHndl; + PNDIS_REQUEST Request; + ULONG OidIndex; + PUCHAR InformationBuffer; + + + Status = NdisAllocateMemory((PVOID *)&ReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetFunctionalAddress: unable to allocate ReqHndl.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( ReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + ReqHndl->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ReqHndl->Open = OpenP; + ReqHndl->RequestPended = TRUE; + ReqHndl->u.STRESS_REQ.NextReqHndl = NULL; + + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetFunctionalAddress: unable to allocate Request.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = NdisRequestSetInformation; + + OidIndex = TpLookUpOidInfo( OID_802_5_CURRENT_FUNCTIONAL ); + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + OidArray[OidIndex].Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetFunctionalAddress: unable to allocate Information Buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length); + } + + Request->DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + +// Wrapper requires information buffer length to be 4 here--zero is not allowed + +// if ( SetZeroTableSize ) +// { +// Request->DATA.SET_INFORMATION.InformationBufferLength = 0; +// } +// else +// { + Request->DATA.SET_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; +// } + + RtlMoveMemory( InformationBuffer, + FunctionalAddress, + FUNCTIONAL_ADDRESS_LENGTH ); + + ReqHndl->u.STRESS_REQ.Request = Request; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + ReqHndl->u.STRESS_REQ.NextReqHndl = OpenP->StressReqHndl; + OpenP->StressReqHndl = ReqHndl; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + ++OpenP->Stress->Pend->PendingRequests; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + // + // If the request did not pend, then free up the memory now. + // + + if ( Status != NDIS_STATUS_PENDING ) + { + TpStressRequestComplete( OpenP,Request,Status ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressSetFunctionalAddress: NdisRequest returned %s\n", + TpGetStatus(Status)); + } + } + } + return Status; +} + + + +NDIS_STATUS +TpStressSetPacketFilter( + IN POPEN_BLOCK OpenP, + IN UINT PacketFilter + ) + +// ------ +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------ + +{ + NDIS_STATUS Status; + PTP_REQUEST_HANDLE ReqHndl; + PNDIS_REQUEST Request; + ULONG OidIndex; + PUCHAR InformationBuffer; + + + Status = NdisAllocateMemory((PVOID *)&ReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetPacketFilter: unable to allocate ReqHndl.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( ReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + ReqHndl->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ReqHndl->Open = OpenP; + ReqHndl->RequestPended = TRUE; + ReqHndl->u.STRESS_REQ.NextReqHndl = NULL; + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetPacketFilter: unable to allocate Request.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = NdisRequestSetInformation; + + OidIndex = TpLookUpOidInfo( OID_GEN_CURRENT_PACKET_FILTER ); + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + OidArray[OidIndex].Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSetPacketFilter: unable to allocate Information Buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length); + } + + Request->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.SET_INFORMATION.InformationBufferLength = + OidArray[OidIndex].Length; + + *((PULONG)InformationBuffer) = (ULONG)PacketFilter; + + ReqHndl->u.STRESS_REQ.Request = Request; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + ReqHndl->u.STRESS_REQ.NextReqHndl = OpenP->StressReqHndl; + OpenP->StressReqHndl = ReqHndl; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + ++OpenP->Stress->Pend->PendingRequests; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + // + // If the request did not pend, then free up the memory now. + // + + if ( Status != NDIS_STATUS_PENDING ) + { + TpStressRequestComplete( OpenP,Request,Status ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressSetPacketFilter: NdisRequest returned %s\n", + TpGetStatus(Status)); + } + } + } + + return Status; +} + + + +VOID +TpStressRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// --------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PTP_REQUEST_HANDLE CorrectReqHndl = NULL; + PTP_REQUEST_HANDLE RH; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + TP_ASSERT( OpenP->StressReqHndl != NULL ); + + if ( OpenP->StressReqHndl->u.STRESS_REQ.Request == NdisRequest ) + { + CorrectReqHndl = OpenP->StressReqHndl; + OpenP->StressReqHndl = OpenP->StressReqHndl->u.STRESS_REQ.NextReqHndl; + } + else + { + RH = OpenP->StressReqHndl; + + do + { + if ( RH->u.STRESS_REQ.NextReqHndl->u.STRESS_REQ.Request == NdisRequest ) + { + CorrectReqHndl = RH->u.STRESS_REQ.NextReqHndl; + + RH->u.STRESS_REQ.NextReqHndl = + RH->u.STRESS_REQ.NextReqHndl->u.STRESS_REQ.NextReqHndl; + + break; + } + else + { + RH = RH->u.STRESS_REQ.NextReqHndl; + } + } while ( RH->u.STRESS_REQ.NextReqHndl != NULL ); + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + TP_ASSERT( CorrectReqHndl != NULL ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_NDIS_ERROR ) + { + TpPrint2("TpStressRequestComplete returned %s, request type %d\n", + TpGetStatus( Status ), NdisRequest->RequestType); + } + } + + if ( NdisRequest->RequestType == NdisRequestSetInformation ) + { + NdisFreeMemory( NdisRequest->DATA.SET_INFORMATION.InformationBuffer,0,0 ); + + } + else // NdisRequestQueryInformation + { + NdisFreeMemory( NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,0,0 ); + } + + NdisFreeMemory( NdisRequest,0,0 ); + NdisFreeMemory( CorrectReqHndl,0,0 ); + + // + // Decrement the Pending Requests and set the stressing flag to + // stop all stressing if the time is right counter. + // + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + --OpenP->Stress->Pend->PendingRequests; + + if (((( OpenP->Stress->StopStressing == TRUE ) && + ( OpenP->Stress->StressFinal == TRUE )) && + ( OpenP->Stress->Pend->PendingRequests == 0 )) && + ( OpenP->Stress->Pend->PendingPackets == 0 )) + { + OpenP->Stress->Stressing = FALSE; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + TpStressFreeResources( OpenP ); + } + else + { + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + } + + return; +} + + + +NDIS_STATUS +TpStressReset( + POPEN_BLOCK OpenP + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------- + +{ + NDIS_STATUS Status; + + NdisReset( &Status,OpenP->NdisBindingHandle ); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressReset: NdisReset returned %s\n", + TpGetStatus(Status)); + } + } + return Status; +} + + + +VOID +TpStressResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// -------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + ULONG NextEvent; + + // + // Indicate RESET is over + // + OpenP->Stress->Resetting = FALSE; + + + // Sanjeevk : STARTCHANGE + + if (( OpenP->ResetReqHndl != NULL ) && + (( OpenP->ResetReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) && + ( OpenP->ResetReqHndl->Open == OpenP ))) + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint1("TpStressResetComplete Status = %s\n", TpGetStatus( Status )); + } + + // + // Check if any stress cleanup is required + // + if ( OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup ) + { + OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup = FALSE; + + // + // Free up the resources associated with this instance of the stress test + // + TpStressFreePostResetResources( OpenP ); + + // + // Decrement the reference count on the OpenBlock stating this + // instance of an async test is no longer running, and the adapter + // may be closed if requested. + // + TpRemoveReference( OpenP ); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Stress->StressIrp != NULL ) + { + OpenP->Stress->StressIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; + + IoAcquireCancelSpinLock( &OpenP->Stress->StressIrp->CancelIrql ); + IoSetCancelRoutine( OpenP->Stress->StressIrp,NULL ); + IoReleaseCancelSpinLock( OpenP->Stress->StressIrp->CancelIrql ); + + if ( OpenP->Stress->StressStarted == TRUE ) + { + IoCompleteRequest( OpenP->Stress->StressIrp,IO_NETWORK_INCREMENT ); + } + + OpenP->Stress->StressIrp = NULL; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Free up the request handle block + // + NdisFreeMemory( OpenP->ResetReqHndl,0,0 ); + OpenP->ResetReqHndl = NULL; + } + else + { + // + // We are not expecting any requests to complete at this + // point, so stick this on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteReset; + + OpenP->EventQueue->Head = NextEvent; + + // we should also stick some interesting info like requesttype. + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } + + // Sanjeevk : STOPCHANGE +} + + + +NDIS_STATUS +TpStressClientSend( + POPEN_BLOCK OpenP, + NDIS_HANDLE PacketHandle, + PTP_TRANSMIT_POOL TpTransmitPool, + PUCHAR DestAddr, + UCHAR SrcInstance, + UCHAR DestInstance, + UCHAR PacketProtocol, + ULONG SequenceNumber, + ULONG MaxSequenceNumber, + UCHAR ClientReference, + UCHAR ServerReference, + INT PacketSize, + INT BufferSize + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// --------- + +{ + PNDIS_PACKET Packet; + PSTRESS_ARGUMENTS Args; + PINSTANCE_COUNTERS Counters; + + Args = OpenP->Stress->Arguments; + Counters = OpenP->Stress->Client->Servers[ServerReference].Counters; + + if ( Args->PacketsFromPool == TRUE ) + { + Packet = TpStressAllocatePoolPacket(TpTransmitPool, + Counters ); + + if ( Packet != NULL ) + { + TpStressSetPoolPacketInfo( OpenP, + Packet, + DestAddr, + DestInstance, + SrcInstance, + SequenceNumber, + MaxSequenceNumber, + ClientReference, + ServerReference ); + } + else + { + return NDIS_STATUS_RESOURCES; + } + } + else + { + if ( Args->PacketType == RANDOMSIZE ) + { + PacketSize = TpGetRandom( sizeof( STRESS_PACKET ), + Args->PacketSize ); + } + else if (Args->PacketType == FIXEDSIZE) + { + PacketSize = Args->PacketSize; + } // else Args->PacketType == CYCLICAL + + Packet = TpStressCreatePacket( OpenP, + PacketHandle, + Args->PacketMakeUp, + DestInstance, + SrcInstance, + PacketProtocol, + Args->ResponseType, + DestAddr, + PacketSize, + BufferSize, + SequenceNumber, + MaxSequenceNumber, + ClientReference, + ServerReference, + Args->DataChecking ); + + if ( Packet != NULL ) + { + TpInitProtocolReserved( Packet,Counters ); + } + else + { + return NDIS_STATUS_RESOURCES; + } + } + + TpStressSend( OpenP,Packet,Counters ); + + return NDIS_STATUS_SUCCESS; +} + + + +VOID +TpStressServerSend( + POPEN_BLOCK OpenP, + PTP_TRANSMIT_POOL TpTransmitPool, + PUCHAR DestAddr, + UCHAR DestInstance, + UCHAR SrcInstance, + ULONG SequenceNumber, + ULONG MaxSequenceNumber, + UCHAR ClientReference, + UCHAR ServerReference, + INT PacketSize, + ULONG DataBufferOffset + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// -------- + +{ + PNDIS_PACKET Packet; + PINSTANCE_COUNTERS Counters; + + Counters = OpenP->Stress->Server->Clients[ClientReference].Counters; + +// ------- +// This does not work correctly if you are under severe stress +// because we run out of packets and loop forever. However, there +// needs to be done some work to handle the less severe case of +// lower stress say for instance when the window is enabled, or +// there is a large inter packet delay, giving the sends time to +// complete and put the used packets back in the transmitpool. +// Maybe if this fails here it should be handled in the completion +// routine where it is allowed to loop continuously. +// +// do +// { +// Packet = TpStressAllocatePoolPacket( TpTransmitPool,Counters ); +// } while ( Packet == NULL ); +// +// ------- + + Packet = TpStressAllocatePoolPacket( TpTransmitPool,Counters ); + + if ( Packet == NULL ) + { + return; + } + + + TpStressSetTruncatedPacketInfo( OpenP, + Packet, + DestAddr, + PacketSize, + DestInstance, + SrcInstance, + SequenceNumber, + MaxSequenceNumber, + ClientReference, + ServerReference, + DataBufferOffset & 0x07FF ); + + TpStressSend( OpenP,Packet,Counters ); +} + + + +VOID +TpStressSend( + POPEN_BLOCK OpenP, + PNDIS_PACKET Packet, + PINSTANCE_COUNTERS Counters OPTIONAL + ) + +// ----- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----- + +{ + NDIS_STATUS Status; + PPROTOCOL_RESERVED ProtRes; + PPENDING PPend; + PSTRESS_ARGUMENTS Args; + ULONG TmpPendNumber; + + Args = OpenP->Stress->Arguments; + ProtRes = PROT_RES( Packet ); + + // + // First allocate the Request Handle. + // + + Status = NdisAllocateMemory((PVOID *)&ProtRes->RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + // + // If we can't allocate the memory, then fail the send. + // + + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpStressSend: unable to allocate RequestHandle\n"); + } + Status = NDIS_STATUS_RESOURCES; + } + else + { + // + // Otherwise zero the memory, and fill in the fields + // + + NdisZeroMemory( ProtRes->RequestHandle,sizeof( TP_REQUEST_HANDLE )); + + ProtRes->RequestHandle->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ProtRes->RequestHandle->Open = OpenP; + ProtRes->RequestHandle->RequestPended = TRUE; + ProtRes->RequestHandle->u.SEND_REQ.Packet = Packet; + + // + // Then Set the CheckSum in the Protocol Reserved section of the + // packet header. + // + + ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) ); + + // + // and put the packet in the pending queue. + // + + PPend = OpenP->Stress->Pend; + + NdisAcquireSpinLock( &PPend->SpinLock ); + + // + // If the windowing mechanism is enabled, then add the packet + // to the pend queue. We don't add the packet to the pend queue + // when we are not windowing because a fast machine can quickly + // overrun the queue, and we don't support dynamically increasing + // the size of the queue yet. + // + if ( Args->WindowEnabled == TRUE ) + { + TmpPendNumber = PPend->PacketPendNumber; + + while ( PPend->Packets[TmpPendNumber] != NULL ) + { + NdisReleaseSpinLock( &PPend->SpinLock ); + +// IF_TPDBG ( TP_DEBUG_DPC ) +// { +// TpPrint2("TpStressSend: Found packet 0x%lX at slot %d of Pendbuffer\n", +// PPend->Packets[TmpPendNumber], +// TmpPendNumber); +// TpBreakPoint(); +// } + ++TmpPendNumber; + TmpPendNumber &= (NUM_PACKET_PENDS-1); // 2**n - 1 + + if (TmpPendNumber == PPend->PacketPendNumber) + { + TpPrint0("PPend buffer full -- no empty slots!\n"); + TpBreakPoint(); + } + NdisAcquireSpinLock( &PPend->SpinLock ); + } + + PPend->Packets[TmpPendNumber] = Packet; + + PPend->PacketPendNumber = (TmpPendNumber + 1) & (NUM_PACKET_PENDS - 1); // 2**n - 1 + } + + // + // We will also increment the Pending Packets counter now in + // case the packet pends and completes before the actual call + // to ndis send returns. if the send does not pend, the counter + // will be decremented later. + // + + ++PPend->PendingPackets; + + NdisReleaseSpinLock( &PPend->SpinLock ); + + // + // Then send then packet + // + + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + + // + // and count the send. + // + + if ( ARGUMENT_PRESENT( Counters )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->Sends; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + + if ( Status != NDIS_STATUS_PENDING ) + { + TpStressSendComplete(OpenP, Packet, Status); + } + else // ( Status == NDIS_STATUS_PENDING ) + { + // + // Otherwise the SEND pended so all of the clean up + // will be done in the Send Completion routine. Simply + // count the pend here. + // + + if ( ARGUMENT_PRESENT( Counters )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->SendPends; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + } + } +} + + + +VOID +TpStressSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPROTOCOL_RESERVED ProtRes; + PTP_REQUEST_HANDLE SendReqHndl; + ULONG TmpCompleteNumber; + ULONG MaxCompleteNumber; + BOOLEAN CompletePacketCleared; + PPENDING PPend; + PSTRESS_ARGUMENTS Args; + + TP_ASSERT( Packet != NULL ); + + Args = OpenP->Stress->Arguments; + ProtRes = PROT_RES( Packet ); + SendReqHndl = ProtRes->RequestHandle; + + TP_ASSERT( SendReqHndl->Signature == STRESS_REQUEST_HANDLE_SIGNATURE ); + TP_ASSERT( SendReqHndl->Open == OpenP ); + TP_ASSERT( SendReqHndl->RequestPended == TRUE ); + TP_ASSERT( Packet == SendReqHndl->u.SEND_REQ.Packet ); + + // + // Now check the PROTOCOL_RESERVED section of the Packet header + // to ensure that it was not corrupted while in the hands of + // the MAC. + // + + if ( !TpCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ), + &ProtRes->CheckSum )) + { + // + // This could cause an access violation because we have + // just found that the PROTOCOL_RESERVED section of this + // packet header has been corrupted, and we are about to + // attempt to dereference a pointer stored in it. This + // should be changed to a try except. + // + + if ( ARGUMENT_PRESENT( ProtRes->InstanceCounters )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++ProtRes->InstanceCounters->SendFails; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + } + + PPend = OpenP->Stress->Pend; + + NdisAcquireSpinLock( &PPend->SpinLock ); + + // + // If the windowing mechinism is enabled, then find the packet in the + // pend queue and remove it. + // + + if ( Args->WindowEnabled == TRUE ) + { + TmpCompleteNumber = PPend->PacketCompleteNumber; + MaxCompleteNumber = TmpCompleteNumber; + CompletePacketCleared = FALSE; + + do + { + if (CompletePacketCleared) + { + if (PPend->Packets[TmpCompleteNumber] != NULL) + { + break; + } + } + else + { + if ( Packet == PPend->Packets[TmpCompleteNumber] ) + { + PPend->Packets[TmpCompleteNumber] = NULL; + CompletePacketCleared = TRUE; + TmpCompleteNumber = PPend->PacketCompleteNumber; + MaxCompleteNumber = PPend->PacketPendNumber; + continue; + } + } + + ++TmpCompleteNumber; + TmpCompleteNumber &= (NUM_PACKET_PENDS - 1); // 2**n - 1 + } + while ( TmpCompleteNumber != MaxCompleteNumber ); + + if (CompletePacketCleared) + { + PPend->PacketCompleteNumber = TmpCompleteNumber; + } + else + { + IF_TPDBG( TP_DEBUG_DPC ) + { + TpPrint0("TpStressSendComplete: Pending Packet not found!!\n"); + TpPrint2("Packet: 0x%lX, list: 0x%lX\n",Packet,PPend->Packets ); + TpBreakPoint(); + } + } + } + + NdisReleaseSpinLock( &PPend->SpinLock ); + + if ( ARGUMENT_PRESENT( ProtRes->InstanceCounters )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + + ++ProtRes->InstanceCounters->SendComps; + + if ( Status != NDIS_STATUS_SUCCESS ) + { + // + // If we are running on TokenRing the following to "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + + // + // STARTCHANGE: Added FDDI problem catching + // + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++ProtRes->InstanceCounters->SendFails; + } + } + else + { + ++ProtRes->InstanceCounters->SendFails; + } + // + // STOPCHANGE + // + + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + + if ( ProtRes->Pool.TransmitPool != NULL ) + { + TpStressFreePoolPacket( (PNDIS_PACKET)Packet ); + } + else + { + TpStressFreePacket( (PNDIS_PACKET)Packet ); + } + + // + // Decrement the counter representing the number of packets pending + // on this open instance. + // + + NdisAcquireSpinLock( &PPend->SpinLock ); + --PPend->PendingPackets; + + if (((( OpenP->Stress->StopStressing == TRUE ) && + ( OpenP->Stress->StressFinal == TRUE )) && + ( OpenP->Stress->Pend->PendingRequests == 0 )) && + ( OpenP->Stress->Pend->PendingPackets == 0 )) + { + OpenP->Stress->Stressing = FALSE; + NdisReleaseSpinLock( &PPend->SpinLock ); + TpStressFreeResources( OpenP ); + } + else + { + NdisReleaseSpinLock( &PPend->SpinLock ); + } + + // + // And free the Request Handle memory + // + + NdisFreeMemory( SendReqHndl,0,0 ); +} + + + +VOID +TpStressCheckPacketData( + POPEN_BLOCK OpenP, + NDIS_HANDLE MacReceiveContext, + ULONG DataOffset, + UINT PacketSize, + PINSTANCE_COUNTERS Counters + ) + +// ------------ +// +// Routine Description: +// +// TpStressCheckPacketData is used to verify the data of a stress packet. +// It calls NdisTransferData to copy the packet into a NDIS_PACKET structure +// and then verifies the data in the packet's buffer. +// +// Arguments: +// +// OpenP - The Open Instance that received this packet. We will use this +// open instances resources. +// +// MacReceiveContext - Passed to NdisTransferData, the MAC way of +// recognizing this Open Instance. +// +// DataOffset - the offset into the DataBuffer where the packet's data +// should begin. +// +// PacketSize - The size of data of this packet to be verified. +// +// Counters - The specific client or server's counters used to track the +// results of the data checking. +// +// Return Value: +// +// None. +// +// ------------ + +{ + NDIS_STATUS Status; + PNDIS_PACKET TransferPacket; + PNDIS_BUFFER TransferBuffer; + PUCHAR Memory; + PPROTOCOL_RESERVED ProtRes; + UINT BytesTransferred; + UINT DataStart; + UINT DataSize; + UINT i, j; + + // + // Allocate a packet, and a buffer to use in the call to transfer + // the packet into. + // + + NdisAllocatePacket( &Status,&TransferPacket,OpenP->Stress->PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressCheckPacketData: NdisAllocatePacket failed: %s\n", + TpGetStatus(Status)); + } + return; + } + + // + // STARTCHANGE + // + + // + // We are only going to transfer the data portion of the packet. + // NOTE: + // The PacketSize being used here is the COMPLETE packet size + // = HEADER + DATA + // + DataSize = PacketSize - sizeof(STRESS_PACKET); + DataStart = (UINT)sizeof( STRESS_PACKET ) - OpenP->Media->HeaderSize; + + // + // STOPCHANGE + // + + Status = NdisAllocateMemory((PVOID *)&Memory,DataSize,0,HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressCheckPacketData: failed to allocate TransferBuffer\n"); + } + NdisFreePacket( TransferPacket ); + return; + } + else + { + NdisZeroMemory( Memory,DataSize ); + } + + TransferBuffer = IoAllocateMdl( Memory,DataSize,TRUE,FALSE,NULL ); + + if ( TransferBuffer == NULL ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressCheckPacketData: failed to allocate TransferBuffer Mdl\n"); + } + NdisFreeMemory( Memory,0,0 ); + NdisFreePacket( TransferPacket ); + return; + } + + MmBuildMdlForNonPagedPool((PMDL)TransferBuffer ); + + NdisChainBufferAtFront( TransferPacket,TransferBuffer ); + + // + // Now allocate a request handle structure and reference it in + // the packets protocol reserved section to pass info to the + // completion routine. + // + + ProtRes = PROT_RES( TransferPacket ); + + Status = NdisAllocateMemory((PVOID *)&ProtRes->RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpStressCheckPacketData: unable to allocate RequestHandle\n"); + } + IoFreeMdl( TransferBuffer ); + NdisFreeMemory( Memory,0,0 ); + NdisFreePacket( TransferPacket ); + return; + } + else + { + NdisZeroMemory( ProtRes->RequestHandle,sizeof( TP_REQUEST_HANDLE )); + } + + // + // and initialize the information in the request handle. + // + + ProtRes->RequestHandle->Signature = STRESS_REQUEST_HANDLE_SIGNATURE; + ProtRes->RequestHandle->u.TRANS_REQ.Packet = TransferPacket; + ProtRes->RequestHandle->u.TRANS_REQ.DataOffset = DataOffset; + ProtRes->RequestHandle->u.TRANS_REQ.DataSize = DataSize; + ProtRes->RequestHandle->u.TRANS_REQ.InstanceCounters = Counters; + + // + // Increment the transfer data counter, and make the call. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->XferData; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + ++OpenP->Stress->Pend->PendingRequests; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + + NdisTransferData( &Status, + OpenP->NdisBindingHandle, + MacReceiveContext, + DataStart, + DataSize, + TransferPacket, + &BytesTransferred ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + // + // if the call succeeded, then verify the data now. + // + + TP_ASSERT( BytesTransferred == DataSize ); + + i = 0; + j = DataOffset; + + while ( i < DataSize ) + { + if ( Memory[i++] != (UCHAR)(j++ % 256) ) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->CorruptRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + IF_TPDBG ( TP_DEBUG_DATA ) + { + TpPrint1("TpStressCheckPacketData1: Data Error at offset %d in packet data\n", + i-1); + TpPrint2(" Found %02x, Expected %02x\n\n", + Memory[i-1],(( j - 1 ) % 256 )); + TpBreakPoint(); + } + break; + } + } + } + else if ( Status != NDIS_STATUS_PENDING ) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressCheckPacketData: NdisTransferData returned %s\n",TpGetStatus(Status)); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->XferDataFails; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + else // (Status == NDIS_STATUS_PENDING) + { + // + // The call to NdisTransferData pended, the completion routine will + // verify the data. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Counters->XferDataPends; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + + if ( Status != NDIS_STATUS_PENDING ) + { + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + + --OpenP->Stress->Pend->PendingRequests; + + if (((( OpenP->Stress->StopStressing == TRUE ) && + ( OpenP->Stress->StressFinal == TRUE )) && + ( OpenP->Stress->Pend->PendingRequests == 0 )) && + ( OpenP->Stress->Pend->PendingPackets == 0 )) + { + OpenP->Stress->Stressing = FALSE; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + TpStressFreeResources( OpenP ); + } + else + { + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + } + + // + // If the routine did not pend, then deallocate the various resources, + // otherwise the completion routine will do this later. + // + IoFreeMdl( TransferBuffer ); + NdisFreeMemory( Memory,0,0 ); + NdisFreeMemory( ProtRes->RequestHandle,0,0 ); + NdisFreePacket( TransferPacket ); + } +} + + + +VOID +TpStressTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ) + +// ----- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPROTOCOL_RESERVED ProtRes; + PTP_REQUEST_HANDLE XferReqHndl; + PNDIS_BUFFER TransferBuffer; + PUCHAR Memory; + UINT i = 0; + + TP_ASSERT( Packet != NULL ); + + ProtRes = PROT_RES( Packet ); + XferReqHndl = ProtRes->RequestHandle; + + TP_ASSERT( XferReqHndl->Signature == STRESS_REQUEST_HANDLE_SIGNATURE ); + TP_ASSERT( Packet == XferReqHndl->u.SEND_REQ.Packet ); + + // + // Increment the NdisTransferData completion counter. + // + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++XferReqHndl->u.TRANS_REQ.InstanceCounters->XferDataComps; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Now unchain the buffer from the packet... + // + + NdisUnchainBufferAtFront( Packet,&TransferBuffer ); + + // + // get the actual packet data from the buffer... + // + + Memory = MmGetMdlVirtualAddress( TransferBuffer ); + + + // + // SanjeevK + // + // Fix for Bug# 9244 + // + + if ( ( Status != NDIS_STATUS_SUCCESS ) || + ( BytesTransferred != XferReqHndl->u.TRANS_REQ.DataSize ) ) + { + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpStressTransferDataComplete: NdisTransferData failed: Returned %s\n", + TpGetStatus(Status)); + } + } + else + { + IF_TPDBG ( TP_DEBUG_DATA ) + { + TpPrint0("TpStressCheckPacketData: Data bytes transfered were incorrect: "); + TpPrint2("Expected: %ld\tTransfered:%ld\n", + XferReqHndl->u.TRANS_REQ.DataSize, BytesTransferred ); + } + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++XferReqHndl->u.TRANS_REQ.InstanceCounters->XferDataFails; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + else + { + // + // NdisTransferData completed successfully and thus proceed with + // checking the received data and see if it was corrupted. + // + + while ( i < XferReqHndl->u.TRANS_REQ.DataSize ) + { + if ( Memory[i++] != (UCHAR)( XferReqHndl->u.TRANS_REQ.DataOffset++ % 256 )) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++XferReqHndl->u.TRANS_REQ.InstanceCounters->CorruptRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + IF_TPDBG ( TP_DEBUG_DATA ) + { + TpPrint1("TpStressCheckPacketData2: Data Error at offset %d in packet data\n", + i-1); + TpPrint2(" Found %02x, Expected %02x\n\n", + Memory[i-1],(( XferReqHndl->u.TRANS_REQ.DataOffset - 1 ) % 256 )); + TpBreakPoint(); + } + break; + } // End of the if + } // End of the while + } // End of the if-else + + // + // Finally Free up the packet, buffer memory and finally the RequestHandle. + // + + NdisFreeMemory( Memory,0,0 ); + IoFreeMdl( TransferBuffer ); + NdisFreePacket( Packet ); + NdisFreeMemory( XferReqHndl,0,0 ); + + // + // Decrement the Pending Requests and set the stressing flag to + // stop all stressing if the time is right counter. + // + + NdisAcquireSpinLock( &OpenP->Stress->Pend->SpinLock ); + --OpenP->Stress->Pend->PendingRequests; + + if (((( OpenP->Stress->StopStressing == TRUE ) && + ( OpenP->Stress->StressFinal == TRUE )) && + ( OpenP->Stress->Pend->PendingRequests == 0 )) && + ( OpenP->Stress->Pend->PendingPackets == 0 )) + { + OpenP->Stress->Stressing = FALSE; + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + TpStressFreeResources( OpenP ); + } + else + { + NdisReleaseSpinLock( &OpenP->Stress->Pend->SpinLock ); + } +} + + + +VOID +TpStressDoNothing( + VOID + ) +{ +// +// This function is used to ensure that busy loops don't +// get completely optimized out by the compiler. +// + + return; +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/strrcv.c b/private/ntos/ndis/testprot/tpdrvr/strrcv.c new file mode 100644 index 000000000..e7e8f1209 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/strrcv.c @@ -0,0 +1,1280 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + tpstress.c + +Abstract: + + This module implements the Test Protocol Stress routines and the + basic controls for stressing the MAC. + +Author: + + Tom Adams (tomad) 15-Dec-1990 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include <ndis.h> +#include <string.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + + + +NDIS_STATUS +TpStressReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PNDIS_PACKET Packet; + PCLIENT_STORAGE Client; + PSERVER_STORAGE Server; + PSTRESS_ARGUMENTS Args; + PPACKET_INFO pi; + PSTRESS_CONTROL sc; + UCHAR NextClient; + UCHAR NextServer; + INT NewPacketSize; + INT NumResponses; + BOOLEAN NewClient; + BOOLEAN NewServer; + PUCHAR DestAddr; + PUCHAR SrcAddr; + + DestAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->DestAddrOffset; + SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset; + + // + // pi is the packet information section of the test prot packet header, + // sc is the stress control section of the testprot packet header. We + // will us pi and sc to quickly reference info in the header. + // + + pi = (PPACKET_INFO)LookaheadBuffer; + + sc = (PSTRESS_CONTROL)((PUCHAR)LookaheadBuffer + + (ULONG)sizeof( PACKET_INFO )); + + if ( !TpCheckSum( + (PUCHAR)pi, + sizeof( STRESS_PACKET ) - + ( sizeof( ULONG ) + OpenP->Media->HeaderSize ), + (PULONG)&sc->CheckSum + )) { + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->CorruptRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + Status = NDIS_STATUS_NOT_RECOGNIZED; + } + + Client = OpenP->Stress->Client; + Server = OpenP->Stress->Server; + Args = OpenP->Stress->Arguments; + + switch( pi->u.PacketProtocol ) { + + // + // A REGISTER_REQ(2) packet is a request from a TP_CLIENT to + // participate in a stress test. If this packet is from a new + // client then a response packet will be set back to the client, + // the client will be added to the Clients array, and its counters + // and control structures for the test will be reset. If this is + // an old client, then we will just reset the counters and control + // structures. + // + + case REGISTER_REQ: + case REGISTER_REQ2: + + // + // Is this packet really destined for us, check that the + // destination address matches the stress address. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->Environment->StressAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the stress + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a request from a Client to register. + // Are we a Server? + // + + } else if ( Args->MemberType == TP_CLIENT ) { + + // + // No! We are not a Server, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + // + // If there is room, see if this is a new client and if so + // register it, and send a REGISTER_RESP packet. + // + + if ( Server->NumClients < MAX_CLIENTS ) { + + NextClient = 0; + NewClient = TRUE; + + // + // See if we have already registered this client. + // + + while ( NextClient < Server->NumClients ) { + + // + // If the Src Address matches a previously registered + // Client, and the Open Instance of that Client matches + // the Src Instance then we have already registered + // this Client, reset the counters, send a response, + // but ignore it. Otherwise this is a new Client so + // register it properly. + // + + if (( RtlCompareMemory( + SrcAddr, + Server->Clients[NextClient].Address, + OpenP->Media->AddressLen ) == + (ULONG)OpenP->Media->AddressLen ) + + && + + ( pi->SrcInstance == + Server->Clients[NextClient].ClientInstance )) { + + // + // We have already registered with this client. + // + + NewClient = FALSE; + break; + + } else { + + // + // This is not a match , try the next one. + // + + NextClient++; + } + } + } + + // + // This REGISTER_REQ(2) packet is from a New Client, and we + // have room for it, so register it. + // + + if ( NewClient == TRUE ) { + + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("TpStressReceive: REGISTER_REQ(2) - Registering Client\n"); + } + + // + // set up the CLIENT_INFO data structure and initialize it. + // + + NextClient = Server->NumClients++; + ++Server->ActiveClients; + Server->Clients[NextClient].ClientReference = NextClient; + Server->Clients[NextClient].ClientInstance = pi->SrcInstance; + Server->Clients[NextClient].ServerResponseType = sc->ResponseType; + Server->Clients[NextClient].DataChecking = sc->DataChecking; + Server->Clients[NextClient].LastSequenceNumber = 0; + + RtlMoveMemory( + Server->Clients[NextClient].Address, + SrcAddr, + OpenP->Media->AddressLen + ); + + // + // Now allocate and initialize the instances counter + // + + Status = NdisAllocateMemory( + (PVOID *)&Server->Clients[NextClient].Counters, + sizeof( INSTANCE_COUNTERS ), + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG (TP_DEBUG_RESOURCES) { + TpPrint0("TpStressReceive: failed to allocate counters.\n"); + } + + Status = NDIS_STATUS_RESOURCES; + break; + + } else { + + NdisZeroMemory( + (PVOID)Server->Clients[NextClient].Counters, + sizeof( INSTANCE_COUNTERS ) + ); + } + } else if ( pi->u.PacketProtocol == REGISTER_REQ ) { + + NdisZeroMemory( + (PVOID)Server->Clients[NextClient].Counters, + sizeof( INSTANCE_COUNTERS ) + ); + + Server->Clients[NextClient].ServerResponseType = sc->ResponseType; + Server->Clients[NextClient].DataChecking = sc->DataChecking; + Server->Clients[NextClient].LastSequenceNumber = 0; + } + + if (( pi->u.PacketProtocol == REGISTER_REQ ) || + ( NewClient == TRUE )) { + + // + // Then build a REGISTER_RESP packet to register with, and + // send it to the Client. + // + + do { + Packet = TpStressCreatePacket( + OpenP, + Server->PacketHandle, + Args->PacketMakeUp, + pi->SrcInstance, + OpenP->OpenInstance, + REGISTER_RESP, + Args->ResponseType, + SrcAddr, + sizeof( STRESS_PACKET ), + sizeof( STRESS_PACKET ), + sc->SequenceNumber, + sc->SequenceNumber + + OpenP->Environment->WindowSize, + NextClient, + 0, + Args->DataChecking + ); + + if ( Packet == NULL ) { + IF_TPDBG ( TP_DEBUG_RESOURCES ) { + TpPrint0("TpStressReceive: failed to create REGISTER_RESP Packet\n"); + } + } + } while ( Packet == NULL ); + + // + // And send it. + // + + TpStressSend( OpenP,Packet,NULL ); + } + } + + break; + + // + // A REGISTER_RESP packet is a response from a TP_SERVER to a + // previously sent REGISTER_REQ(2) that the server will be + // participating in the next stress test. If this packet is from + // a new server then the server will be added to the Server array, + // and its counters and control structures for the test will be + // reset. If the response packet is from an old client, then we + // will just reset the counters. + // + + case REGISTER_RESP: + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a response from a Server to register. Are we a Client? + // + + } else if ( Args->MemberType == TP_SERVER ) { + + // + // No! We are not a Client, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + if ( Client->NumServers < MAX_SERVERS ) { + + NextServer = 0; + NewServer = TRUE; + + // + // See if this is a new server. + // + + while ( NextServer < Client->NumServers ) { + + if (( RtlCompareMemory( + SrcAddr, + Client->Servers[NextServer].Address, + OpenP->Media->AddressLen) == + (ULONG)OpenP->Media->AddressLen ) + + && + + ( pi->SrcInstance == + Client->Servers[NextServer].ServerInstance )) { + + // + // This server has already registered, ignore it. + // + + NewServer = FALSE; + break; + + } else { + + // + // Not this server, try the next one. + // + + NextServer++; + } + } + } + + if ( NewServer == TRUE ) { + + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("TpStressReceive: REGISTER_RESP - Registering Server\n"); + } + + // + // set up the SERVER_INFO data structure and initialize it. + // + + NextServer = Client->NumServers++; + NextServer = Client->ActiveServers++; + + Client->Servers[NextServer].ServerReference = NextServer; + Client->Servers[NextServer].ClientReference = sc->ClientReference; + Client->Servers[NextServer].ServerInstance = pi->SrcInstance; + Client->Servers[NextServer].ServerActive = TRUE; + Client->Servers[NextServer].LastSequenceNumber = 0; + + RtlMoveMemory( + Client->Servers[NextServer].Address, + SrcAddr, + OpenP->Media->AddressLen + ); + + // + // Now allocate and initialize the instances counter + // + + Status = NdisAllocateMemory( + (PVOID *)&Client->Servers[NextServer].Counters, + sizeof( INSTANCE_COUNTERS ), + 0, + HighestAddress + ); + + if ( Status != NDIS_STATUS_SUCCESS ) { + IF_TPDBG (TP_DEBUG_RESOURCES) { + TpPrint0("TpStressReceive: failed to allocate counters.\n"); + } + + Status = NDIS_STATUS_RESOURCES; + break; + + } else { + + NdisZeroMemory( + (PVOID)Client->Servers[NextServer].Counters, + sizeof( INSTANCE_COUNTERS ) + ); + } + + } else { + + // + // Old Server, reset the statistics counters. + // + + NdisZeroMemory( + (PVOID)Client->Servers[NextServer].Counters, + sizeof( INSTANCE_COUNTERS ) + ); + + Client->Servers[NextServer].LastSequenceNumber = 0; + } + } + + break; + + // + // A TEST_REQ packet is the standard test packet sent from a the + // client to each of the servers participating in the test. This + // packet is evaluated for data integrity, counted, and the required + // response packet is returned to the client. + // + + case TEST_REQ: + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a test request from a Client. Are we a Server?, + // + + } else if ( Args->MemberType == TP_CLIENT ) { + + // + // No! We are not a Server, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this a client we have previously registered with? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen) != + (ULONG)OpenP->Media->AddressLen ) + + || + + ( pi->SrcInstance != + Server->Clients[sc->ClientReference].ClientInstance )) { + + // + // No! We should ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this packet destined for our open instance or another + // open instance of the same card? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen) == + (ULONG)OpenP->Media->AddressLen) + + && + + ( pi->DestInstance != OpenP->OpenInstance )) { + + // + // No, this packet is for some other open instance. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + if ( Args->BeginReceives == FALSE ) { + + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("TpStressReceive: received TEST_REQ packet, not initialized\n"); + } + // Increment receive counter for accounting purposes. + break; + } + + // + // Has this packet arrived out of order? + // + + if ( sc->SequenceNumber <= Server->Clients[sc->ClientReference].LastSequenceNumber ) { + IF_TPDBG ( TP_DEBUG_NDIS_ERROR ) { + TpPrint0("\nTpStressReceive: PACKET ARRIVED OUT OF ORDER, OR ARRIVED TWICE !!!\n"); + TpPrint3("TEST_REQ Packet: Sequence Number %d @ 0x%lX, expected greater than %d.\n\n", + sc->SequenceNumber, HeaderBuffer, + Server->Clients[sc->ClientReference].LastSequenceNumber); + TpBreakPoint(); + } + } else { + Server->Clients[sc->ClientReference].LastSequenceNumber = sc->SequenceNumber; + } + + if ( Server->Clients[sc->ClientReference].DataChecking == TRUE ) { + + if (( pi->PacketSize - sizeof( STRESS_PACKET )) > 0 ) { + + TpStressCheckPacketData( + OpenP, + MacReceiveContext, + sc->DataBufOffset, + pi->PacketSize, + Server->Clients[sc->ClientReference].Counters + ); + } + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Server->Clients[sc->ClientReference].Counters->Receives; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + switch( Server->Clients[sc->ClientReference].ServerResponseType ) { + + case NO_RESPONSE: + + NumResponses = 0; + break; + + case FULL_RESPONSE: + + NumResponses = 1; + NewPacketSize = pi->PacketSize; + break; + + case ACK_EVERY: + + NumResponses = 1; + NewPacketSize = sizeof( STRESS_PACKET ); + break; + + case ACK_10_TIMES: + + NumResponses = 10; + NewPacketSize = sizeof( STRESS_PACKET ); + break; + + default: + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("TpStressReceive: Unknown Response Type\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->CorruptRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + Status = NDIS_STATUS_NOT_RECOGNIZED; + break; + } + + while ( NumResponses-- > 0 ) { + + // + // if send now, build and send a TEST_RESP packet + // + + TpStressServerSend( + OpenP, + Server->TransmitPool, + SrcAddr, + pi->SrcInstance, + OpenP->OpenInstance, + sc->SequenceNumber, + sc->SequenceNumber + + OpenP->Environment->WindowSize, + sc->ClientReference, + sc->ServerReference, + NewPacketSize, + sc->DataBufOffset + ); + } + + // + // else queue send for TpStressReceiveComplete send + // + } + + break; + + // + // A TEST_RESP packet is the response from a server to a client's + // TEST_REQ packet. This packet is checked for data integrity, + // counted, and discarded. + // + + case TEST_RESP: + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a test response from a Server. Are we a Client? + // + + } else if ( Args->MemberType == TP_SERVER ) { + + // + // No! We are not a Client, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this a Server that has previously registered with us? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Client->Servers[sc->ServerReference].Address, + OpenP->Media->AddressLen) != + (ULONG)OpenP->Media->AddressLen ) + + || + + ( pi->SrcInstance != + Client->Servers[sc->ServerReference].ServerInstance )) { + + // + // No! We should ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this packet destined for this open instance or another + // open instance of the same card? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Client->Servers[sc->ServerReference].Address, + OpenP->Media->AddressLen) == + (ULONG)OpenP->Media->AddressLen) + + && + + ( pi->DestInstance != OpenP->OpenInstance )) { + + // + // This packet is for some other open instance, ignore it. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + // + // Has this packet arrived out of order? + // + + if ( sc->SequenceNumber <= Client->Servers[sc->ServerReference].LastSequenceNumber ) { + + if (( Args->ResponseType == ACK_10_TIMES ) && + ( sc->SequenceNumber == Client->Servers[sc->ServerReference].LastSequenceNumber )) { + ; // This is okay, we expect 10 packets with same + // number ignore packet. + } else { + + // + // A Packet has arrived out or order, PANIC! + // + + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("\nTpStressReceive: PACKET ARRIVED OUT OF ORDER, OR ARRIVED TWICE !!!\n"); + TpPrint3("TEST_RESP Packet: Sequence Number %d @ 0x%lX, expected greater than %d.\n\n", + sc->SequenceNumber, HeaderBuffer, + Client->Servers[sc->ServerReference].LastSequenceNumber); + TpBreakPoint(); + } + } + } else { + Client->Servers[sc->ServerReference].LastSequenceNumber = sc->SequenceNumber; + } + + if ( Args->WindowEnabled == TRUE ) { + Client->Servers[sc->ServerReference].MaxSequenceNumber = sc->MaxSequenceNumber; + } else { + Client->Servers[sc->ServerReference].MaxSequenceNumber = 0xFFFFFFFF; + } + + // + // We have received a packet from this server so zero its + // window resetting counter in case it has any strikes + // against it. + // + + Client->Servers[sc->ServerReference].WindowReset = 0; + + // + // Update the instance receive counters for the Server + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++Client->Servers[sc->ServerReference].Counters->Receives; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if ( Args->DataChecking == TRUE ) { + + if (( pi->PacketSize - sizeof( STRESS_PACKET )) > 0 ) { + + TpStressCheckPacketData( + OpenP, + MacReceiveContext, + sc->DataBufOffset, + pi->PacketSize, + Client->Servers[sc->ServerReference].Counters + ); + } + } + } + + break; + + // + // A STATS_REQ packet is a request by the client at the end of + // a stress test for the server to return the statistics. + // + + case STATS_REQ: + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a Statistics request from a Client. + // Are we a Server?, + // + + } else if ( Args->MemberType == TP_CLIENT ) { + + // + // No! We are not a Server, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this a client we have previously registered with? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen ) != + (ULONG)OpenP->Media->AddressLen ) + + || + + ( pi->SrcInstance != + Server->Clients[sc->ClientReference].ClientInstance )) { + + // + // No! We should ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this packet destined for our open instance or another + // open instance on the same card? + // + + } else if (( pi->DestInstance != OpenP->OpenInstance ) + + && + + ( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen ) == + (ULONG)OpenP->Media->AddressLen )) { + + // + // This packet is for some other open instance, ignore it. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + // + // We need to respond to the client's request for the + // test statistics, so create a STATS_RESP packet, + // + + Packet = TpStressCreatePacket( + OpenP, + Server->PacketHandle, + KNOWN, + pi->SrcInstance, + OpenP->OpenInstance, + STATS_RESP, + Args->ResponseType, + SrcAddr, + + sizeof( STRESS_PACKET ) + + sizeof( INSTANCE_COUNTERS ) + + sizeof( GLOBAL_COUNTERS ), // PacketSize + + sizeof( STRESS_PACKET ) + + sizeof( INSTANCE_COUNTERS ) + + sizeof( GLOBAL_COUNTERS ), // BufferSize + + sc->SequenceNumber, + sc->SequenceNumber, + sc->ClientReference, + sc->ServerReference, + FALSE + ); + + if ( Packet == NULL ) { + IF_TPDBG(TP_DEBUG_RESOURCES) { + TpPrint0("TpStressReceive: failed to create STATS_RESP Packet\n"); + } + } else { + + // + // Write the statistics into the packet, + // + + TpWriteServerStatistics( + OpenP, + Packet, + &Server->Clients[sc->ClientReference] + ); + + if ( sc->SequenceNumber == 0 ) { + + // + // Maybe instead of checking the SequenceNumber is + // zero, the first packet, we should have a flag in + // the server for this in case we miss the first + // STATS_REQ packet. + // + + TpPrintServerStatistics( + OpenP, + &Server->Clients[sc->ClientReference] + ); + } + + // + // And send it back to the Client. + // + + TpStressSend( OpenP,Packet,NULL ); + } + } + + break; + + // + // A STATS_RESP packet is the server responding to a clients + // request for stress statistics. The stats a bundled in the + // data field of the packet. The client will read them into + // the local buffer and discard the packet. + // + + case STATS_RESP: + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is a Statistics response from a Server. + // Are we a Client? + // + + } else if ( Args->MemberType == TP_SERVER ) { + + // + // No! We are not a Client, ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this a Server that has previously registered with us? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Client->Servers[sc->ServerReference].Address, + OpenP->Media->AddressLen) != + (ULONG)OpenP->Media->AddressLen ) + + || + + ( pi->SrcInstance != + Client->Servers[sc->ServerReference].ServerInstance )) { + + // + // No! We should ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this packet destined for our open instance or another + // open instance on the same card? + // + + } else if (( pi->DestInstance != OpenP->OpenInstance ) && + ( RtlCompareMemory( + SrcAddr, + Client->Servers[sc->ServerReference].Address, + OpenP->Media->AddressLen) == + (ULONG)OpenP->Media->AddressLen )) { + + // + // This packet is for some other open instance, ignore it. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + // + // Copy the server's stats to the Stress Results buffer. + // + + TpCopyServerStatistics( + OpenP, + LookaheadBuffer, + sc->ServerReference + ); + } + + break; + + // + // AN END_REQ packet is a notification by a client that the stress + // test has completed. The server decrements the number of clients, + // and discards the packet. + // + + case END_REQ: + { + UINT i; + + // + // Is this packet really destined for us, check that the + // destination address matches the local card address we + // queried and stored in the OPEN_BLOCK. + // + + if ( RtlCompareMemory( + DestAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen ) != + OpenP->Media->AddressLen ) { + + // + // the destination address does not match the local card + // address, we should never have received this packet! + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->InvalidPacketRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // This packet is an end request from a Client. Are we a Server?, + // + + } else if ( Args->MemberType == TP_CLIENT ) { + + // + // No! We are not a Server, ignote this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this a client we have previously registered with? + // + + } else if (( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen) != + (ULONG)OpenP->Media->AddressLen ) + + || + + ( pi->SrcInstance != + Server->Clients[sc->ClientReference].ClientInstance )) { + + // + // No! We should ignore this packet. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + // + // Is this packet destined for our open instance or another + // open instance on the same card? + // + + } else if (( pi->DestInstance != OpenP->OpenInstance ) + + && + + ( RtlCompareMemory( + SrcAddr, + Server->Clients[sc->ClientReference].Address, + OpenP->Media->AddressLen) == + (ULONG)OpenP->Media->AddressLen)) { + + // + // This packet is for some other open instance, ignore it. + // + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } else { + + if ( Server->Clients[sc->ClientReference].TestEnding == FALSE ) { + Server->Clients[sc->ClientReference].TestEnding = TRUE; + --Server->ActiveClients; + } + + // + // If we are running as only a server, and there are packets + // remaining in the Pend Queue, display them to the debug + // screen. + // + + if (( Args->MemberType == TP_SERVER ) && + ( OpenP->Stress->Pend->PendingPackets != 0 )) { + + // + // There are packets in the pend queue, so print out + // the packet addresses and break. + // + + IF_TPDBG( TP_DEBUG_DPC ) { + + TpPrint1("TpStressEndDpc: The following %d packets are still in the\n", + OpenP->Stress->Pend->PendingPackets); + TpPrint1(" Server's Pend Queue for Open Instance %d.\n", + OpenP->OpenInstance); + TpPrint1(" Pend Queue = %lX\n\n", + OpenP->Stress->Pend); + + for ( i=0 ; i<NUM_PACKET_PENDS ; i++ ) { + + if (( OpenP->Stress->Pend->Packets[i] != NULL ) && + ( OpenP->Stress->Pend->Packets[i] != (PNDIS_PACKET)-1 )) { + + TpPrint1("\t\t%lX\n", OpenP->Stress->Pend->Packets[i]); + } + } + + TpBreakPoint(); + + // + // And set the PendingPackets counter to zero, so + // we will not print this message on the remainder + // of the END_REQ packets that we receive. + // + + OpenP->Stress->Pend->PendingPackets = 0; + } + + TpInitializePending( OpenP->Stress->Pend ); + } + } + break; + } + default: + IF_TPDBG ( TP_DEBUG_DPC ) { + TpPrint0("TpStressReceive: Unknown Packet Protocol\n"); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->GlobalCounters->CorruptRecs; + NdisReleaseSpinLock( &OpenP->SpinLock ); + + Status = NDIS_STATUS_NOT_RECOGNIZED; + } + + return Status; +} + + +VOID +TpStressReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + ULONG i; + + if (( OpenP->Stress != NULL ) && + ( OpenP->Stress->Client != NULL )) { + + for ( i=0;i<MAX_SERVERS;i++ ) { + + if ( OpenP->Stress->Client->Servers[i].Counters != NULL ) { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->Stress->Client->Servers[i].Counters->ReceiveComps; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + } + } + + if (( OpenP->Stress != NULL ) && + ( OpenP->Stress->Server != NULL )) { + + for ( i=0;i<MAX_CLIENTS;i++ ) { + + if ( OpenP->Stress->Server->Clients[i].Counters != NULL ) { + NdisAcquireSpinLock( &OpenP->SpinLock ); + ++OpenP->Stress->Server->Clients[i].Counters->ReceiveComps; + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + } + } + + return; +} diff --git a/private/ntos/ndis/testprot/tpdrvr/tpdefs.h b/private/ntos/ndis/testprot/tpdrvr/tpdefs.h new file mode 100644 index 000000000..82ee3ce83 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tpdefs.h @@ -0,0 +1,769 @@ +// ----------------------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpdefs.h +// +// Abstract: +// +// Definitions for stress and test sections of the Test Protocol. +// +// Author: +// +// Tom Adams (tomad) 16-Jul-1990 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// +// Tom Adams (tomad) 27-Nov-1990 +// Divided the procedures and defintions into two seperate include files. +// Added definitions for TpRunTest and support routines. +// +// Tom Adams (tomad) 30-Dec-1990 +// Added defintions for TpStress and support routines. +// +// Sanjeev Katariya 3-16-1993 +// Added structure for async RESET processing: Bug #2874 +// Added support for native ARCNET +// +// Tim Wynsma (timothyw) 4-27-94 +// Added performance tests +// Chgs for performance tests -- 5-18-94 +// Chgd perf tests to client server -- 6-08-94 +// +// Notes: +// +// 1. ARCNET Support. Most stress and other functional structures have fields +// describing the addresses of lengths = ADDRESS_LENGTH(6 octects). This does +// not need to be changed for arcnet since we will use only the first octect. +// The rest can simply be set to 0 or any other preferred pad value. This is true +// however for the tests formats and NOT the media header +// +// ----------------------------------------- + +#include "common.h" + +struct _TP_MEDIA_INFO; + +// +// Define the various packet protocols used in TpStress. +// +// REGISTER REQ and REQ2 are used to request Servers to assist in running +// a test, REGISTER RESP is used to respond to a Client's register request. +// TEST REQ and RESP are the actual test packets, STATS REQ and RESP are the +// method of asking for and collecting statistics from all Servers. Finally +// END REQ and RESP are the packets used to tell all Servers that the test +// is over, and to clean up and end. +// + +#define REGISTER_REQ 0x00 +#define REGISTER_REQ2 0x01 +#define REGISTER_RESP 0x02 +#define TEST_REQ 0x03 +#define TEST_RESP 0x04 +#define STATS_REQ 0x05 +#define STATS_RESP 0x06 +#define END_REQ 0x07 +#define END_RESP 0x08 + +// +// Test Packet headers used to describe the contents of the three seperate +// types of packets; FUNC1_PACKET, FUNC2_PACKET, and STRESS_PACKET. +// + +// +// These structures need to be packed, and the pointers need to be +// defined as UNALIGNED for MIPS. +// + +#include <packon.h> + +// +// Ethernet packet header description +// + +typedef struct _E_802_3 { + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; + UCHAR PacketSize_Hi; + UCHAR PacketSize_Lo; +} E_802_3; +typedef E_802_3 UNALIGNED *PE_802_3; + +// +// Token Ring packet header description +// + +typedef struct _TR_802_5 { + UCHAR AC; + UCHAR FC; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; +} TR_802_5; +typedef TR_802_5 UNALIGNED *PTR_802_5; + +// +// FDDI packet header description +// + +typedef struct _FDDI { + UCHAR FC; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; +} FDDI; +typedef FDDI UNALIGNED *PFDDI; + +// +// STARTCHANGE +// Arcnet packet header description +// +typedef struct _ARCNET { + UCHAR SrcAddress[ADDRESS_LENGTH_1_OCTET] ; + UCHAR DestAddress[ADDRESS_LENGTH_1_OCTET]; + UCHAR ProtocolID ; +} ARCNET; +typedef ARCNET UNALIGNED *PARCNET; + +// +// All combined media into the all encompassing header +// +typedef union _MEDIA_HEADER { + E_802_3 e; + TR_802_5 tr; + FDDI fddi; + ARCNET a; +} MEDIA_HEADER ; +typedef MEDIA_HEADER UNALIGNED *PMEDIA_HEADER; +// +// STOPCHANGE +// + +// +// Defines for the packet signatures of each packet, and the packet type. +// + +#define STRESS_PACKET_SIGNATURE 0x81818181 +#define FUNC1_PACKET_SIGNATURE 0x72727272 +#define FUNC2_PACKET_SIGNATURE 0x63636363 +#define GO_PACKET_SIGNATURE 0x54545454 + +#define STRESS_PACKET_TYPE 0 +#define FUNC1_PACKET_TYPE 1 +#define FUNC2_PACKET_TYPE 2 + +// +// Test Protocol packet header info shared amongst each of the four +// types of packets. +// + +typedef struct _PACKET_INFO { + ULONG Signature; + ULONG PacketSize; // the total size of the packet + UCHAR DestInstance; // instance of the packet's dest ndis binding + UCHAR SrcInstance; // instance of the packet's src ndis binding + UCHAR PacketType; // type of packet; STRESS or FUNC + union { + UCHAR PacketProtocol; // for STRESS packets the actual protocol type. + UCHAR PacketNumber; // ranges from 0x00 to 0xff, for tracking FUNCs. + } u; + ULONG CheckSum; // functional packet header check sum +} PACKET_INFO; +typedef PACKET_INFO UNALIGNED *PPACKET_INFO; + +// +// Control information for STRESS test packets. +// + +typedef struct _STRESS_CONTROL { + ULONG DataBufOffset; // offset into databuf used to generate packet data + ULONG SequenceNumber; // packet's sequence in order of sending + ULONG MaxSequenceNumber; // server window sequence number + UCHAR ResponseType; // how the server should respond. + UCHAR ClientReference; // the number of the Client sending the packet + UCHAR ServerReference; // the number of the Server sending the packet + BOOLEAN DataChecking; // + ULONG CheckSum; // stress packet header check sum +} STRESS_CONTROL; +typedef STRESS_CONTROL UNALIGNED *PSTRESS_CONTROL; + +// +// FUNC1_PACKET type format +// + +// +// STARTCHANGE +// +typedef struct _FUNC1_PACKET { + MEDIA_HEADER media; + PACKET_INFO info; +} FUNC1_PACKET; +typedef FUNC1_PACKET UNALIGNED *PFUNC1_PACKET; +// +// STOPCHANGE +// + + +// +// FUNC2_PACKET type format, or the RESEND packet. +// + +typedef struct _FUNC2_PACKET { + FUNC1_PACKET hdr1; + FUNC1_PACKET hdr2; +} FUNC2_PACKET; +typedef FUNC2_PACKET UNALIGNED *PFUNC2_PACKET; + +// +// STRESS_PACKET format +// + +typedef struct _STRESS_PACKET { + FUNC1_PACKET hdr; + STRESS_CONTROL sc; +} STRESS_PACKET; +typedef STRESS_PACKET UNALIGNED *PSTRESS_PACKET; + +typedef struct _TP_PACKET { + union { + FUNC1_PACKET F1; + FUNC2_PACKET F2; + STRESS_PACKET S; + } u; +} TP_PACKET; +typedef TP_PACKET UNALIGNED *PTP_PACKET; + +// +// GO PAUSE protocol packet header info. +// + +typedef struct _GO_PACKET_INFO { + ULONG Signature; // GO_PACKET_SIGNATURE + ULONG TestSignature; // Test Signature + ULONG UniqueSignature; // Unique Signature for this GO PAUSE instance + UCHAR PacketType; // type of packet; STRESS or FUNC + ULONG CheckSum; // functional packet header check sum +} GO_PACKET_INFO; +typedef GO_PACKET_INFO UNALIGNED *PGO_PACKET_INFO; + +// +// STARTCHANGE +// +typedef struct _GO_PACKET { + MEDIA_HEADER go_media; + GO_PACKET_INFO info; +} GO_PACKET; +typedef GO_PACKET UNALIGNED *PGO_PACKET; +// +// STOPCHANGE +// + +#include <packoff.h> + +// +// Transmit Pool Header. +// + +typedef struct _TP_TRANSMIT_POOL { + NDIS_SPIN_LOCK SpinLock; + BOOLEAN SpinLockAllocated; + ULONG Allocated; + ULONG Deallocated; + PNDIS_PACKET Head; + PNDIS_PACKET Tail; +} TP_TRANSMIT_POOL, * PTP_TRANSMIT_POOL; + +// +// Define the Request Handle structure used to track memory handed off +// to the MAC. +// + +struct _OPEN_BLOCK; + +typedef struct _TP_REQUEST_HANDLE { + ULONG Signature; + struct _OPEN_BLOCK * Open; + BOOLEAN RequestPended; + PIRP Irp; + + union { + + struct _OPEN_REQ { + NTSTATUS RequestStatus; + KEVENT OpenEvent; + } OPEN_REQ; + +// +// SanjeevK : Bug #2874 +// + + struct _RESET_REQ { + NTSTATUS RequestStatus; + BOOLEAN PostResetStressCleanup; + } RESET_REQ; + + struct _INFO_REQ { + ULONG IoControlCode; + NDIS_REQUEST_TYPE NdisRequestType; + NDIS_OID OID; + PVOID InformationBuffer; + UINT InformationBufferLength; + } INFO_REQ; + + struct _SEND_REQ { + PNDIS_PACKET Packet; + ULONG PacketSize; + BOOLEAN SendPacket; + } SEND_REQ; + + struct _PERF_REQ { + PNDIS_PACKET Packet; + ULONG PacketSize; + BOOLEAN SendPacket; + PUCHAR Buffer; + } PERF_REQ; + + struct _TRANS_REQ { + PNDIS_PACKET Packet; + ULONG DataOffset; + UINT DataSize; + PINSTANCE_COUNTERS InstanceCounters; + } TRANS_REQ; + + struct _STRESS_REQ { + struct _TP_REQUEST_HANDLE * NextReqHndl; + PNDIS_REQUEST Request; + } STRESS_REQ; + + } u; + +} TP_REQUEST_HANDLE, *PTP_REQUEST_HANDLE; + +// +// The protocol's reserved section in the NDIS_PACKET header used to +// store information about where the packet came from, and/or what +// stress counters to increment. +// + +typedef struct _PROTOCOL_RESERVED { + union { + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + PNDIS_PACKET NextPacket; + } Pool; + PTP_REQUEST_HANDLE RequestHandle; + PINSTANCE_COUNTERS InstanceCounters; + ULONG CheckSum; +} PROTOCOL_RESERVED, * PPROTOCOL_RESERVED; + + +// +// Retrieve the PROT_RESERVED structure from a packet. +// + +#define PROT_RES(Packet) ((PPROTOCOL_RESERVED)((Packet)->ProtocolReserved)) + +// +// Macro used to initialize the fields in the protocol reserved structure +// of a packet that will be linked into a transmit pool. +// + +// --- +// +// VOID +// TpInitProtocolReserved( +// PNDIS_PACKET Packet, +// PINSTANCE_COUNTERS Counters +// ); +// +// --- + +#define TpInitProtocolReserved(_Packet,_Counters) { \ + PPROTOCOL_RESERVED ProtRes; \ + ProtRes = PROT_RES( Packet ); \ + ProtRes->Pool.TransmitPool = NULL; \ + ProtRes->InstanceCounters = Counters; \ +} + + +// +// A client has one of these per server registered (up to MAX_SERVERS). +// +// The ServerReference is as assigned by the client; for each test +// they will be numbered sequentially in the order that they register +// themselves (therefore, ServerNumber is just this SERVER_INFOs +// index in Client->Servers). Address is the Ethernet that this server +// is at, and within addresses the OpenInstance is used to distinguish +// between servers (in the case of two servers on the same card). +// Responses and PacketStatus track which DIR_REQ packets have +// had RESPONSE packets sent back for them. +// + +typedef struct _SERVER_INFO { + UCHAR ServerInstance; + UCHAR ClientReference; + UCHAR ServerReference; + UCHAR Address[ADDRESS_LENGTH]; // will be the same for a given ServerReference + BOOLEAN ServerActive; + UCHAR WindowReset; + ULONG SequenceNumber; + ULONG MaxSequenceNumber; + ULONG LastSequenceNumber; + ULONG PacketDelay; + ULONG DelayLength; + PINSTANCE_COUNTERS Counters; +} SERVER_INFO, * PSERVER_INFO; + +// +// The structure a client references in OpenBlock->Client. +// +// NumServers is how many servers are registered, the number of +// valid entries in Servers. NumPackets is how many packets are +// being sent in this test. +// + +typedef struct _CLIENT_STORAGE { + UCHAR NumServers; + UCHAR NextServer; + UCHAR ActiveServers; + BOOLEAN PoolInitialized; + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + ULONG PacketSize; + ULONG BufferSize; + ULONG SizeIncrease; + SERVER_INFO Servers[MAX_SERVERS]; +} CLIENT_STORAGE, * PCLIENT_STORAGE; + +// +// A server has one of these per client registered (up to MAX_CLIENTS). +// +// Address is the Card Address that this client is at +// and within addresses the OpenInstance is used to distinguish +// between client (in the case of two clients on the same card). +// + +typedef struct _CLIENT_INFO { + UCHAR ClientInstance; + UCHAR ClientReference; + UCHAR Address[ADDRESS_LENGTH]; + BOOLEAN DataChecking; + BOOLEAN TestEnding; // TRUE denotes that an END_REQ packet has been + // received, and to ignore any more END_REQ packets. + RESPONSE_TYPE ServerResponseType; + ULONG LastSequenceNumber; + PINSTANCE_COUNTERS Counters; +} CLIENT_INFO, * PCLIENT_INFO; + +// +// The structure a server reference in OpenBlock->Server. +// +// Each server has a packet pool, with the actual storage +// pointed to by PacketPool and the result of InitializePacketPool +// in PacketHandle. BufferHandle points to the "buffer pool" +// that we create (a linked list of MDLs). +// + +#define MAX_CLIENTS 10 + +typedef struct _SERVER_STORAGE { + UCHAR NumClients; + UCHAR ActiveClients; + BOOLEAN PoolInitialized; + UCHAR PadByte; + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + ULONG PadLong; + CLIENT_INFO Clients[MAX_CLIENTS]; +} SERVER_STORAGE, * PSERVER_STORAGE; + +// +// +// + +typedef struct _STRESS_ARGUMENTS { + MEMBER_TYPE MemberType; + PACKET_TYPE PacketType; + INT PacketSize; + PACKET_MAKEUP PacketMakeUp; + + UCHAR ResponseType; + INTERPACKET_DELAY DelayType; + ULONG DelayLength; + ULONG Iterations; + + ULONG TotalIterations; + ULONG TotalPackets; + BOOLEAN AllPacketsSent; + BOOLEAN WindowEnabled; + BOOLEAN DataChecking; + BOOLEAN PacketsFromPool; + BOOLEAN BeginReceives; + BOOLEAN ServerContinue; +} STRESS_ARGUMENTS, * PSTRESS_ARGUMENTS; + +// +// PENDING is used to track NDIS routines which pend, and their +// subsequent completions, there must be a one to one relationship +// between the number of pends for a specific calls and the number +// of completions. +// + +// Note that size is a power of 2, so can & with x-1 to deal with wrapping + +#define NUM_PACKET_PENDS 2048 + +typedef struct _PENDING { + ULONG PendingPackets; + ULONG PendingRequests; + ULONG PacketPendNumber; + ULONG PacketCompleteNumber; + BOOLEAN PendingSpinLockAllocated; + NDIS_SPIN_LOCK SpinLock; + PNDIS_PACKET Packets[NUM_PACKET_PENDS]; +} PENDING, * PPENDING; + +// +// The Stress Block holds the flags counters, and pointers to the client +// storage, server storage and other control structures for the STRESS command. +// + +#define MAX_NUMBER_BUFFERS 2 + +typedef struct _STRESS_BLOCK { + volatile BOOLEAN Stressing; + BOOLEAN StressStarted; + BOOLEAN StopStressing; + BOOLEAN StressFinal; + BOOLEAN StressEnded; + BOOLEAN Resetting; + BOOLEAN FirstIteration; + PCLIENT_STORAGE Client; + PSERVER_STORAGE Server; + + LARGE_INTEGER StartTime; + LARGE_INTEGER EndTime; + + ULONG PacketsPerSecond; + PSTRESS_ARGUMENTS Arguments; + PPENDING Pend; + + // + // Added buffers for allowing discontigous allocations + // + PUCHAR DataBuffer[MAX_NUMBER_BUFFERS]; + PMDL DataBufferMdl[MAX_NUMBER_BUFFERS]; + + BOOLEAN PoolInitialized; + NDIS_HANDLE PacketHandle; + PSTRESS_RESULTS Results; + + PIRP StressIrp; + ULONG Counter; + ULONG Reg2Counter; + KTIMER TpStressTimer; + KTIMER TpStressReg2Timer; + KDPC TpStressDpc; + KDPC TpStressReg2Dpc; + KDPC TpStressStatsDpc; + KDPC TpStressEndReqDpc; + KDPC TpStressFinalDpc; +} STRESS_BLOCK, * PSTRESS_BLOCK; + + +typedef struct _SEND_BLOCK { + volatile BOOLEAN Sending; + BOOLEAN StopSending; + BOOLEAN ResendPackets; + UCHAR PadByte; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR ResendAddress[ADDRESS_LENGTH]; + ULONG PacketSize; + ULONG NumberOfPackets; + ULONG PacketsSent; + ULONG PacketsPending; + ULONG SendEndDpcCount; + NDIS_HANDLE PacketHandle; + PINSTANCE_COUNTERS Counters; + PIRP SendIrp; + KTIMER SendTimer; + KDPC SendDpc; + KDPC SendEndDpc; +} SEND_BLOCK, * PSEND_BLOCK; + +#define NUMBER_OF_POOL_PACKETS 30 + + +typedef struct _RECEIVE_BLOCK { + volatile BOOLEAN Receiving; + BOOLEAN StopReceiving; + ULONG PacketsPending; + ULONG ReceiveEndDpcCount; + NDIS_HANDLE PacketHandle; + PINSTANCE_COUNTERS Counters; + PIRP ReceiveIrp; + KTIMER ReceiveTimer; + KDPC ReceiveDpc; + KDPC ReceiveEndDpc; + + ULONG ResendType; // 0 = normal, 1 = resending self-directed packet + KDPC ResendDpc; + PTP_REQUEST_HANDLE ResendReq; // request handle for resend packet + KTIMER ResendTimer; +} RECEIVE_BLOCK, * PRECEIVE_BLOCK; + +typedef struct _PERF_BLOCK +{ + ULONG PerformMode; + PIRP PerformIrp; + ULONG NumberOfPackets; + ULONG PacketSize; + UCHAR ServerAddress[ADDRESS_LENGTH]; + UCHAR ClientAddress[ADDRESS_LENGTH]; + ULONG PacketDelay; + BOOLEAN IsServer; + ULONG WhichReq; + PTP_REQUEST_HANDLE GoInitReq; // req hand for GO, NOGO, or SRVDOWN(srv) and + // INIT or SHUTDOWN(cliet) packet + PTP_REQUEST_HANDLE AckReq; // req hand for ACK, HBEAT, or SRVDONE(srv) and + // REQ(client) packet + PTP_REQUEST_HANDLE ResReq; // req hand for RETRES(srv) and REQRES(clt) packet + PTP_REQUEST_HANDLE DataReq; // request handle for test data packet + ULONG SendCount; + ULONG SendFailCount; + ULONG ReceiveCount; + BOOLEAN Active; + ULONG PacketsSent; + ULONG PerformEndDpcCount; + KDPC PerformSendDpc; + KTIMER PerformTimer; + KDPC PerformEndDpc; + ULONG PacketsPending; + NDIS_HANDLE PacketHandle; + LARGE_INTEGER PerfSendTotalTime; + BOOLEAN Testing; + ULONG SelfReceiveCount; + ULONG SendBurstCount; + ULONG ReceiveBurstCount; + ULONG RestartCount; + KDPC PerformRestartDpc; + ULONG MaskId; +} PERF_BLOCK, * PPERF_BLOCK; + + +#define TP_GO 0x0 +#define TP_GO_ACK 0x1 + +typedef struct _PAUSE_BLOCK { + volatile BOOLEAN GoReceived; + BOOLEAN PoolAllocated; + NDIS_HANDLE PacketHandle; + UCHAR RemoteAddress[ADDRESS_LENGTH]; + ULONG TestSignature; + ULONG UniqueSignature; + UCHAR PacketType; + ULONG TimeOut; + NDIS_SPIN_LOCK SpinLock; +} PAUSE_BLOCK, * PPAUSE_BLOCK; + + +typedef struct _EVENTS { + TP_EVENT_TYPE TpEventType; + NDIS_STATUS Status; + BOOLEAN Overflow; + PVOID EventInfo; +} EVENTS, * PEVENTS; + +#define MAX_EVENT 20 + +typedef struct _EVENT_QUEUE { + NDIS_SPIN_LOCK SpinLock; + ULONG ReceiveIndicationCount; + ULONG StatusIndicationCount; + BOOLEAN ExpectReceiveComplete; + BOOLEAN ExpectStatusComplete; + ULONG Head; + ULONG Tail; + ULONG PadUlong; + EVENTS Events[MAX_EVENT]; +} EVENT_QUEUE, * PEVENT_QUEUE; + +// +// Open Block used to desribe each open instance of an adapter +// + +typedef struct _OPEN_BLOCK { + NDIS_HANDLE NdisBindingHandle; + NDIS_HANDLE NdisProtocolHandle; + UCHAR OpenInstance; + BOOLEAN Closing; + UCHAR StationAddress[ADDRESS_LENGTH]; + PSZ AdapterName; + NDIS_SPIN_LOCK SpinLock; + volatile UCHAR ReferenceCount; + UINT MediumIndex; + struct _TP_MEDIA_INFO *Media; + PGLOBAL_COUNTERS GlobalCounters; + PENVIRONMENT_VARIABLES Environment; + PSTRESS_BLOCK Stress; + PSEND_BLOCK Send; + PRECEIVE_BLOCK Receive; + volatile BOOLEAN PerformanceTest; + PPERF_BLOCK Perform; + PEVENT_QUEUE EventQueue; + PPAUSE_BLOCK Pause; + PTP_REQUEST_HANDLE OpenReqHndl; + PTP_REQUEST_HANDLE CloseReqHndl; + PTP_REQUEST_HANDLE ResetReqHndl; + PTP_REQUEST_HANDLE RequestReqHndl; + PTP_REQUEST_HANDLE StressReqHndl; + BOOLEAN IrpCancelled; + PIRP Irp; + ULONG Signature; +} OPEN_BLOCK, * POPEN_BLOCK; + +POPEN_BLOCK TpOpen; + +#define OPEN_BLOCK_SIGNATURE 0x12345678 + +// +// Device Driver data struct definition +// +// Device Context - hanging off the end of the DeviceObject for the +// driver the device context contains the control structures used +// to administer the ndis tests. +// + +typedef struct _DEVICE_CONTEXT { + DEVICE_OBJECT DeviceObject; // the I/O system's device object. + PNDIS_PROTOCOL_CHARACTERISTICS ProtChars; // protocol characteristics + NDIS_HANDLE NdisProtocolHandle; + BOOLEAN Initialized; // TRUE if TP Init succeeded; FALSE otherwise + BOOLEAN Opened; // TRUE if device is opened; + ULONG OpenSignature; + OPEN_BLOCK Open[NUM_OPEN_INSTANCES]; +} DEVICE_CONTEXT, * PDEVICE_CONTEXT; + +// +// Unique Signatures for Test Protocol data structures. +// + +#define OPEN_REQUEST_HANDLE_SIGNATURE 0x81818181 +#define FUNC_REQUEST_HANDLE_SIGNATURE 0x18181818 +#define SEND_REQUEST_HANDLE_SIGNATURE 0x45454545 +#define STRESS_REQUEST_HANDLE_SIGNATURE 0x54545454 +#define GO_REQUEST_HANDLE_SIGNATURE 0x39393939 + +// +// Address argument passed to NdisAllocateMemory. +// + +extern NDIS_PHYSICAL_ADDRESS HighestAddress; + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c b/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c new file mode 100644 index 000000000..a40b385bc --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c @@ -0,0 +1,1656 @@ +// ------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpdrvr.c +// +// Abstract: +// +// This module contains code which defines the Test Protocol +// device object. +// +// Author: +// +// Tom Adams (tomad) 19-Apr-1991 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Sanjeev Katariya Forced unload of driver thru the control panel was not working +// Effected function : TpUnloadDriver() +// +// Tim Wynsma (timothyw) 4-27-94 +// Added performance tests +// Tim Wynsma (timothyw) 6-08-94 +// Chgd perf tests to use client/server model +// +// -------------- + +#include <ndis.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + +// the following function is prototyped in public\oak\inc\zwapi.h, but including that file +// produces MANY compile errors. + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateSymbolicLinkObject( + OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING LinkTarget + ); + + +POPEN_BLOCK TpOpen = NULL; +HANDLE SymbolicLinkHandle; + +// +// The debugging longword, containing a bitmask as defined in common.h +// If a bit is set, then debugging is turned on for that component. +// + +#if DBG + +ULONG TpDebug = TP_DEBUG_NDIS_CALLS|TP_DEBUG_NDIS_ERROR|TP_DEBUG_STATISTICS| + TP_DEBUG_DATA|TP_DEBUG_DISPATCH|TP_DEBUG_IOCTL_ARGS| + TP_DEBUG_NT_STATUS|TP_DEBUG_DPC|TP_DEBUG_INITIALIZE| + TP_DEBUG_RESOURCES|TP_DEBUG_BREAKPOINT|TP_DEBUG_INFOLEVEL_1; + +BOOLEAN TpAssert = TRUE; + +#endif // DBG + +NDIS_PHYSICAL_ADDRESS HighestAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + +// +// Driver Entry function +// + + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) + +// ---------- +// +// Routine Description: +// +// This routine performs initialization of the Test Protocol driver. +// It creates the device objects for the driver and performs +// other driver initialization. +// +// Arguments: +// +// DriverObject - Pointer to driver object created by the system. +// +// Return Value: +// +// The function value is the final status from the initialization operation. +// +// ---------- + +{ + STRING nameString; + PDEVICE_CONTEXT DeviceContext; + NTSTATUS Status; + + // + // General Version Information + // + IF_TPDBG( TP_DEBUG_ALL ) + { + TpPrint0("\nMAC NDIS 3.0 Tester - Test Driver Version 1.5.1\n\n"); + } + + // + // First initialize the DeviceContext struct, + // + + RtlInitString( &nameString, DD_TP_DEVICE_NAME ); + + Status = TpCreateDeviceContext (DriverObject, + nameString, + &DeviceContext ); + + if (!NT_SUCCESS (Status)) + { + TpPrint1 ("TPDRVR: failed to create device context: Status = %s\n", + TpGetStatus(Status)); + return Status; + } + else + { + TpOpen = &DeviceContext->Open[0]; + } + + // + // Create symbolic link between the Dos Device name and Nt + // Device name for the test protocol driver. + // + + Status = TpCreateSymbolicLinkObject( ); + + if (!NT_SUCCESS (Status)) + { + TpPrint1 ("TPDRVR: failed to create symbolic link. Status = %s\n", TpGetStatus(Status)); + return Status; + } + + // + // then set up the EventQueue for any spurious event, indications, + // or completions. This should be ready at all times, from the + // time the test protocol is registered to the time it is unloaded. + // + + Status = TpInitializeEventQueue( DeviceContext ); + + if (!NT_SUCCESS (Status)) { + TpPrint1 ("TPDRVR: failed to create initialize Event Queue. Status = %s\n", + TpGetStatus(Status)); + return Status; + } + + // + // make ourselves known to the NDIS wrapper. + // + + Status = TpRegisterProtocol ( DeviceContext, &nameString ); + + if (!NT_SUCCESS(Status)) + { + DeviceContext->Initialized = FALSE; + + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint1("TPDRVR: TpRegisterProtocol failed. Status= %s\n", TpGetStatus(Status)); + } + } + return Status; +} + + + +NTSTATUS +TpCreateDeviceContext( + IN PDRIVER_OBJECT DriverObject, + IN STRING DeviceName, + PDEVICE_CONTEXT *DeviceContext + ) + +// ----------- +// +// Routine Description: +// +// This routine creates and initializes a device context structure. +// +// Arguments: +// +// DriverObject - pointer to the IO subsystem supplied driver object. +// +// DeviceContext - Pointer to a pointer to a transport device context object. +// +// DeviceName - pointer to the name of the device this device object points to. +// +// Return Value: +// +// STATUS_SUCCESS if all is well; STATUS_INSUFFICIENT_RESOURCES otherwise. +// +// ------------ + +{ + NTSTATUS Status; + UNICODE_STRING unicodeString; + PDEVICE_OBJECT deviceObject; + PDEVICE_CONTEXT deviceContext; + + // + // Convert the input name string to Unicode until it is actually + // passed as a Unicode string. + // + + Status = RtlAnsiStringToUnicodeString( &unicodeString, + &DeviceName, + TRUE ); + if ( !NT_SUCCESS( Status )) + { + return Status; + } + + // + // Create the device object for Test Protocol. + // + + Status = IoCreateDevice(DriverObject, + sizeof (DEVICE_CONTEXT) - sizeof (DEVICE_OBJECT), + &unicodeString, + FILE_DEVICE_TRANSPORT, + 0, + FALSE, + &deviceObject ); + + RtlFreeUnicodeString( &unicodeString ); + + if ( !NT_SUCCESS( Status )) + { + return Status; + } + + deviceObject->Flags |= DO_DIRECT_IO; + + // + // Initialize the driver object with this driver's entry points. + // + + DriverObject->MajorFunction [IRP_MJ_CREATE] = TpDispatch; + DriverObject->MajorFunction [IRP_MJ_CLOSE] = TpDispatch; + DriverObject->MajorFunction [IRP_MJ_CLEANUP] = TpDispatch; + DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = TpDispatch; + DriverObject->DriverUnload = TpUnloadDriver; + + deviceContext = (PDEVICE_CONTEXT)deviceObject; + + // + // Now initialize the Device Context structure Signatures. + // + + deviceContext->OpenSignature = OPEN_BLOCK_SIGNATURE; + + deviceContext->Initialized = TRUE; + + *DeviceContext = deviceContext; + + return STATUS_SUCCESS; +} + + + +NTSTATUS +TpCreateSymbolicLinkObject( + VOID + ) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttr; + STRING DosString; + STRING NtString; + UNICODE_STRING DosUnicodeString; + UNICODE_STRING NtUnicodeString; + + RtlInitAnsiString( &DosString, "\\DosDevices\\Tpdrvr" ); + + Status = RtlAnsiStringToUnicodeString( &DosUnicodeString, + &DosString, + TRUE ); + if ( !NT_SUCCESS( Status )) + { + return Status; + } + + RtlInitAnsiString( &NtString, DD_TP_DEVICE_NAME ); + + Status = RtlAnsiStringToUnicodeString( &NtUnicodeString, + &NtString, + TRUE ); + if ( !NT_SUCCESS( Status )) + { + return Status; + } + + // + // Removed the OBJ_PERMANENT attribute since we should be able to load and + // unload this driver and create the necessary links at will. Buf Fix# 13183 + // + InitializeObjectAttributes( &ObjectAttr, + &DosUnicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + Status = ZwCreateSymbolicLinkObject(&SymbolicLinkHandle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttr, + &NtUnicodeString ); + + if ( Status != STATUS_SUCCESS ) + { + return Status; + } + + RtlFreeUnicodeString( &DosUnicodeString ); + RtlFreeUnicodeString( &NtUnicodeString ); + + return STATUS_SUCCESS; +} + + + +NTSTATUS +TpInitializeEventQueue( + IN PDEVICE_CONTEXT DeviceContext + ) +{ + NTSTATUS Status; + ULONG i, j; + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + // + // Finally, allocate Event Queue header struct, and its spin lock. + // + + Status = NdisAllocateMemory((PVOID *)&DeviceContext->Open[i].EventQueue, + sizeof( EVENT_QUEUE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpInitializeEventQueue: failed to allocate EVENT_QUEUE struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( (PVOID)DeviceContext->Open[i].EventQueue, + sizeof( EVENT_QUEUE ) ); + } + + NdisAllocateSpinLock( &DeviceContext->Open[i].EventQueue->SpinLock ); + + // + // Initialize the Event Queue header, and each of the seperate events + // in the Event Queue array. + // + + DeviceContext->Open[i].EventQueue->ReceiveIndicationCount = 0; + DeviceContext->Open[i].EventQueue->StatusIndicationCount = 0; + DeviceContext->Open[i].EventQueue->ExpectReceiveComplete = FALSE; + DeviceContext->Open[i].EventQueue->ExpectStatusComplete = FALSE; + DeviceContext->Open[i].EventQueue->Head = 0; + DeviceContext->Open[i].EventQueue->Tail = 0; + + for ( j=0;j<MAX_EVENT;j++ ) + { + DeviceContext->Open[i].EventQueue->Events[j].TpEventType = Unknown; + DeviceContext->Open[i].EventQueue->Events[j].Status = NDIS_STATUS_SUCCESS; + DeviceContext->Open[i].EventQueue->Events[j].Overflow = FALSE; + DeviceContext->Open[i].EventQueue->Events[j].EventInfo = NULL; + } + } + return STATUS_SUCCESS; +} + + + +NTSTATUS +TpRegisterProtocol ( + IN PDEVICE_CONTEXT DeviceContext, + IN STRING *NameString + ) + +// ----- +// +// Routine Description: +// +// This routine introduces this transport to the NDIS interface. +// +// Arguments: +// +// DeviceObject - Pointer to the device object for this driver. +// +// NameString - The name of the device to be registered. +// +// Return Value: +// +// The function value is the status of the operation. +// STATUS_SUCCESS if all goes well, +// STATUS_UNSUCCESSFUL if we tried to register and couldn't, +// STATUS_INSUFFICIENT_RESOURCES if we couldn't even try to register. +// +// ------------- + +{ + NDIS_STATUS Status; + USHORT i; + + // + // Set up the characteristics of this protocol + // + + + Status = NdisAllocateMemory((PVOID *)&DeviceContext->ProtChars, + sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) + NameString->Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_INITIALIZE) + { + TpPrint0 ("TpRegisterProtocol: insufficient memory to allocate Protocol descriptor.\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( DeviceContext->ProtChars, + sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) ); + } + + // + // Setup the Characteristics Block and register the protocol with + // the NDIS Wrapper. + // + + DeviceContext->ProtChars->MajorNdisVersion = 3; + DeviceContext->ProtChars->MinorNdisVersion = 0; + DeviceContext->ProtChars->Name.Length = NameString->Length; + DeviceContext->ProtChars->Name.Buffer = (PVOID)NameString->Buffer; + + DeviceContext->ProtChars->OpenAdapterCompleteHandler = + TestProtocolOpenComplete; + DeviceContext->ProtChars->CloseAdapterCompleteHandler = + TestProtocolCloseComplete; + DeviceContext->ProtChars->SendCompleteHandler = TestProtocolSendComplete; + DeviceContext->ProtChars->TransferDataCompleteHandler = + TestProtocolTransferDataComplete; + DeviceContext->ProtChars->ResetCompleteHandler = + TestProtocolResetComplete; + DeviceContext->ProtChars->RequestCompleteHandler = + TestProtocolRequestComplete; + DeviceContext->ProtChars->ReceiveHandler = TestProtocolReceive; + DeviceContext->ProtChars->ReceiveCompleteHandler = + TestProtocolReceiveComplete; + DeviceContext->ProtChars->StatusHandler = TestProtocolStatus; + DeviceContext->ProtChars->StatusCompleteHandler = + TestProtocolStatusComplete; + + NdisRegisterProtocol ( &Status, + &DeviceContext->NdisProtocolHandle, + DeviceContext->ProtChars, + (UINT)sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) + NameString->Length ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_INITIALIZE) + { + TpPrint1("TpRegisterProtocol: NdisRegisterProtocol failed: %s\n", + TpGetStatus( Status )); + } + NdisFreeMemory( DeviceContext->ProtChars,0,0 ); + return STATUS_UNSUCCESSFUL; + } + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + DeviceContext->Open[i].NdisProtocolHandle = DeviceContext->NdisProtocolHandle; + } + return STATUS_SUCCESS; +} + + + +NTSTATUS +TpDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +// ------- +// +// Routine Description: +// +// This routine is the main dispatch routine for the Test Protocol +// driver. It accepts an I/O Request Packet, performs the request, +// and then returns with the appropriate status. +// +// Arguments: +// +// DeviceObject - Pointer to the device object for this driver. +// +// Irp - Pointer to the request packet representing the I/O request. +// +// Return Value: +// +// The function value is the status of the operation. +// +// ------- + +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + PDEVICE_CONTEXT DeviceContext; + + // + // Check to see if TP has been initialized; if not, don't allow any use. + // + + DeviceContext = (PDEVICE_CONTEXT)DeviceObject; + if ( !DeviceContext->Initialized ) + { + return STATUS_UNSUCCESSFUL; + } + + // + // Make sure status information is consistent every time. + // + + Irp->IoStatus.Status = NDIS_STATUS_PENDING; + Irp->IoStatus.Information = 0; + + // + // Get a pointer to the current stack location in the IRP. This is where + // the function codes and parameters are stored. + // + + IrpSp = IoGetCurrentIrpStackLocation( Irp ); + + // + // Case on the function that is being performed by the requestor. If the + // operation is a valid one for this device, then make it look like it was + // successfully completed, where possible. + // + + switch ( IrpSp->MajorFunction ) + { + // + // The Create function opens the Test Protocol driver and initializes + // the OpenBlock and its various data structures used to control the + // tests. Only one instance of TPCTL.EXE may have the driver open at + // any given time, all other open requests will fail with the error + // STATUS_DEVICE_ALREADY_ATTACHED + // + case IRP_MJ_CREATE: + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint0("TpDispatch: IRP_MJ_CREATE.\n"); + } + Status = TpOpenDriver( DeviceContext ); + Irp->IoStatus.Status = Status; + break; + + // + // The Close function closes the Test Protocol driver and deallocates + // the various data structures attached to the OpenBlock. + // + case IRP_MJ_CLOSE: + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint0("TpDispatch: IRP_MJ_CLOSE.\n"); + } + TpCloseDriver( DeviceContext ); + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + // + // The DeviceControl function is the main path to the test protocol + // driver interface. Every Test Protocol request is has an Io Control + // code that is used by this function to determine the routine to + // call. + // + case IRP_MJ_DEVICE_CONTROL: + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint0("TpDispatch: IRP_MJ_DEVICE_CONTROL.\n"); + } + Status = TpIssueRequest( DeviceContext,Irp,IrpSp ); + break; + + // + // Handle the two stage IRP for a file close operation. When the first + // stage hits, + // + case IRP_MJ_CLEANUP: + IF_TPDBG( TP_DEBUG_DISPATCH ) + { + TpPrint0("TpDispatch: IRP_MJ_CLEANUP.\n"); + } + Status = TpCleanUpDriver( DeviceContext,Irp ); + Irp->IoStatus.Status = Status; + break; + + default: + IF_TPDBG( TP_DEBUG_DISPATCH ) + { + TpPrint0("TpDispatch: OTHER (DEFAULT).\n"); + } + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + Status = STATUS_INVALID_DEVICE_REQUEST; + + } // major function switch + + // + // If the request did not pend, the complete it now, otherwise it + // will be completed when the pending routine finishes. + // + + if ( Status == STATUS_PENDING ) + { + IF_TPDBG( TP_DEBUG_DISPATCH ) + { + TpPrint0("TpDispatch: request PENDING in handler.\n"); + } + } + else if ( Status == STATUS_CANCELLED ) + { + IF_TPDBG( TP_DEBUG_DISPATCH ) + { + TpPrint0("TpDispatch: request CANCELLED by handler.\n"); + } + } + else + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint0("TpDispatch: request COMPLETED by handler.\n"); + } + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + IoSetCancelRoutine( Irp,NULL ); + IoReleaseCancelSpinLock( Irp->CancelIrql ); + + IoCompleteRequest( Irp,IO_NETWORK_INCREMENT ); + } + + // + // Return the immediate status code to the caller. + // + + return Status; +} + + + +NTSTATUS +TpOpenDriver( + IN PDEVICE_CONTEXT DeviceContext + ) + +{ + NTSTATUS Status; + USHORT i; + + // + // If the Device did not successfully initialize at boot time than + // fail this open. + // + + if( DeviceContext->Initialized != TRUE ) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + // + // if the device has already been opened by an instance of TPCTL.EXE + // then fail this open. + // + + if ( DeviceContext->Opened == TRUE ) + { + return STATUS_DEVICE_ALREADY_ATTACHED; + } + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + // + // Allocate each of the instances of the OpenBlock. + // + + Status = TpAllocateOpenArray( &DeviceContext->Open[i] ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint1("TpCreateDeviceContext: failed to allocate Open Array. Status = %s\n", + TpGetStatus(Status)); + } + + // + // If one of the allocation calls fails deallocate any of + // the structs that were just successfully allocated. + // + + while ( i >= 0 ) + { + TpDeallocateOpenArray( &DeviceContext->Open[i--] ); + } + return Status; + } + } + DeviceContext->Opened = TRUE; + + return STATUS_SUCCESS; +} + + + +NTSTATUS +TpCleanUpDriver( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp + ) + +// ---- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// ---- + +{ + NDIS_STATUS Status; + USHORT i; + + // + // Make this Irp Cancellable + // + + NdisAcquireSpinLock( &DeviceContext->Open[0].SpinLock ); + + DeviceContext->Open[0].Irp = Irp; + DeviceContext->Open[0].IrpCancelled = FALSE; + + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + + if ( Irp->Cancel ) + { + Irp->IoStatus.Status = STATUS_CANCELLED; + return STATUS_CANCELLED; + } + + IoSetCancelRoutine( Irp,(PDRIVER_CANCEL)TpCancelIrp ); + + IoReleaseCancelSpinLock( Irp->CancelIrql ); + + NdisReleaseSpinLock( &DeviceContext->Open[0].SpinLock ); + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + if ( DeviceContext->Open[i].OpenInstance != (UCHAR)-1 ) + { + // + // Set the open instance's closing flag to true, then signal + // all the async test protocol routines to end. + // + + DeviceContext->Open[i].Closing = TRUE; + + if ( DeviceContext->Open[i].Stress->Stressing == TRUE ) + { + DeviceContext->Open[i].Stress->StopStressing = TRUE; + } + + if ( DeviceContext->Open[i].Send->Sending == TRUE ) + { + DeviceContext->Open[i].Send->StopSending = TRUE; + } + + if ( DeviceContext->Open[i].Receive->Receiving == TRUE ) + { + DeviceContext->Open[i].Receive->StopReceiving = TRUE; + } + + if ( DeviceContext->Open[i].PerformanceTest == TRUE) + { + DeviceContext->Open[i].Perform->Active = FALSE; + } + + // + // Wait for all of the four asynchronous routines STRESS, + // SEND, PERFORMANCE, and RECEIVE to finish, then close the adapter. + // + + while (( DeviceContext->Open[i].ReferenceCount > 0 ) && + ( DeviceContext->Open[0].IrpCancelled != TRUE )) + { + /* NULL */ ; + } + + // + // Now close each of the existing OpenInstances. + // + + NdisCloseAdapter( &Status, + DeviceContext->Open[i].NdisBindingHandle ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_NDIS_ERROR ) + { + TpPrint2( + "TpCleanUpDriver: failed to close adapter for instance #%d. Status = %s\n", + i, TpGetStatus(Status)); + } + } + else + { + // XXX: handle the close pending. + + DeviceContext->Open[i].NdisBindingHandle = NULL; + DeviceContext->Open[i].OpenInstance = (UCHAR)-1; + DeviceContext->Open[i].Closing = FALSE; + + NdisFreeMemory( DeviceContext->Open[i].AdapterName,0,0 ); + DeviceContext->Open[i].AdapterName = NULL; + + // + // We will also free the media block at this point because + // the info it contains may not hold for the next adapter + // open on this instance. + // + + NdisFreeMemory( DeviceContext->Open[i].Media,0,0 ); + DeviceContext->Open[i].Media = NULL; + } + } + } + + // + // If this Irp has been cancelled return now, otherwise make it + // non cancellable. + // + + NdisAcquireSpinLock( &DeviceContext->Open[0].SpinLock ); + + if ( DeviceContext->Open[0].IrpCancelled == TRUE ) + { + return STATUS_CANCELLED; + } + else + { + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + IoSetCancelRoutine( Irp,NULL ); + IoReleaseCancelSpinLock( Irp->CancelIrql ); + } + + NdisReleaseSpinLock( &DeviceContext->Open[0].SpinLock ); + + // + // Deallocate each of the instances of the OpenBlock. + // + + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + TpDeallocateOpenArray( &DeviceContext->Open[i] ); + } + + return STATUS_SUCCESS; +} + + + +VOID +TpCloseDriver( + IN PDEVICE_CONTEXT DeviceContext + ) + +// ---- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// ---- + +{ + DeviceContext->Opened = FALSE; +} + + + +VOID +TpUnloadDriver( + IN PDRIVER_OBJECT DriverObject + ) +{ + USHORT i; + PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)DriverObject->DeviceObject; + + TpPrint0("TpUnloadDriver called.\n"); + + // + // Fixed error for deallocation of memory contigent to having been opened + // Bug# 13183 + // + if ( DeviceContext->Opened == TRUE ) + { + // + // for each of the open instances in the open array. + // + for ( i=0;i<NUM_OPEN_INSTANCES;i++ ) + { + // + // Deallocate each of the instances of the OpenBlock. + // + TpDeallocateOpenArray( &DeviceContext->Open[i] ); + } + } + + // + // Close the Dos Symbolic link to remove traces of the device + // + ZwClose( SymbolicLinkHandle ); + + // + // Then delete the device object from the system. Fixed for Bug#: 13183 + // + IoDeleteDevice( (PDEVICE_OBJECT)DeviceContext ); + + TpPrint0("TpUnloadDriver completed.\n"); +} + + + +BOOLEAN +TpAddReference( + IN POPEN_BLOCK OpenP + ) + +// --- +// +// Routine Description: +// +// Add a reference to an open block, to prevent it being removed +// by TpCloseDriver. +// +// Arguments: +// +// OpenP - The open block holding the adapter information to add the +// reference to. +// +// Return Value: +// +// TRUE if the reference is added. +// FALSE if the open is already closing. +// +// ---- + +{ + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Closing ) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + return FALSE; + } + ++OpenP->ReferenceCount; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + return TRUE; +} + + + +VOID +TpRemoveReference( + IN POPEN_BLOCK OpenP + ) + +// -- +// +// Routine Description: +// +// Remove a reference to an adapter. If the count goes to +// zero, then the adapter may be closed if requested. +// +// Arguments: +// +// Argument - The open block holding the adapter information to +// remove the reference from. +// +// Return Value: +// +// None. +// +// -- + +{ + NdisAcquireSpinLock( &OpenP->SpinLock ); + --OpenP->ReferenceCount; + NdisReleaseSpinLock( &OpenP->SpinLock ); +} + + + +NTSTATUS +TpAllocateOpenArray( + POPEN_BLOCK OpenP + ) + +// ----- +// +// Routine Description: +// +// This routine allocates the various data structures and spinlocks +// in the OpenBlock. +// +// Arguments: +// +// OpenP - a pointer to the OpenBlock containing the data structures which +// will be allocated during this routine. +// +// Return Value: +// +// NTSTATUS - STATUS_SUCCESS if all the memory and spinlocks are allocated +// else STATUS_INSUFFICIENT_RESOURCES if an allocation of memory +// fails. +// +// ---------- + +{ + NDIS_STATUS Status; + ULONG i; + + // + // Initialize the Open Block fields, + // + + OpenP->NdisBindingHandle = NULL; + OpenP->OpenInstance = (UCHAR)-1; + OpenP->Closing = FALSE; + OpenP->AdapterName = NULL; + OpenP->ReferenceCount = 0; + OpenP->MediumIndex = 0xFFFFFFFF; + + OpenP->Media = NULL; + OpenP->GlobalCounters = NULL; + OpenP->Environment = NULL; + + OpenP->Stress = NULL; + OpenP->Send = NULL; + OpenP->Receive = NULL; + + OpenP->OpenReqHndl = NULL; + OpenP->CloseReqHndl = NULL; + OpenP->ResetReqHndl = NULL; + OpenP->RequestReqHndl = NULL; + OpenP->StressReqHndl = NULL; + + OpenP->IrpCancelled = FALSE; + OpenP->Irp = NULL; + + OpenP->Signature = OPEN_BLOCK_SIGNATURE; + OpenP->PerformanceTest = FALSE; + + + // + // and set the station address for this open instance to nulls. + // + + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + OpenP->StationAddress[i] = 0x00; + } + + // + // Allocate the Environment struct + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Environment, + sizeof( ENVIRONMENT_VARIABLES ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate Environment struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Environment,sizeof( ENVIRONMENT_VARIABLES )); + } + + // + // Then initialize the Environment Variables to the default settings. + // + + OpenP->Environment->WindowSize = WINDOW_SIZE; + OpenP->Environment->RandomBufferNumber = BUFFER_NUMBER; + OpenP->Environment->StressDelayInterval = DELAY_INTERVAL; + OpenP->Environment->UpForAirDelay = UP_FOR_AIR_DELAY; + OpenP->Environment->StandardDelay = STANDARD_DELAY; + + // + // Allocate the Stress struct and the pend counters and stress results + // counters attached to it. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Stress, + sizeof( STRESS_BLOCK ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate STRESS_BLOCK struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Stress,sizeof( STRESS_BLOCK )); + } + + // + // Initialize the Stress Block and set the request pending counters + // and the stress results structs to null. + // + + OpenP->Stress->Stressing = FALSE; + OpenP->Stress->StressStarted = FALSE; + OpenP->Stress->StopStressing = TRUE; + OpenP->Stress->StressFinal = FALSE; + OpenP->Stress->StressEnded = TRUE; + OpenP->Stress->Client = NULL; + OpenP->Stress->Server = NULL; + OpenP->Stress->Arguments = NULL; + OpenP->Stress->DataBuffer[0] = NULL; + OpenP->Stress->DataBuffer[1] = NULL; + OpenP->Stress->DataBufferMdl[0] = NULL; + OpenP->Stress->DataBufferMdl[1] = NULL; + OpenP->Stress->PoolInitialized = FALSE; + OpenP->Stress->PacketHandle = NULL; + OpenP->Stress->StressIrp = NULL; + + // + // allocate the pend counter, we need to create this here because + // it will be used in starting all instances of the stress test. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Pend, + sizeof( PENDING ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate PEND_COUNTER struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Stress->Pend,sizeof( PENDING )); + } + + NdisAllocateSpinLock( &OpenP->Stress->Pend->SpinLock ); + + TpInitializePending( OpenP->Stress->Pend ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Results, + sizeof( STRESS_RESULTS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate Stress Results struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Stress->Results,sizeof( STRESS_RESULTS )); + TpInitializeStressResults( OpenP->Stress->Results ); + } + + // + // Initialize the timer to regulate when to call each of the routines. + // + + KeInitializeTimer( &OpenP->Stress->TpStressTimer ); + KeInitializeTimer( &OpenP->Stress->TpStressReg2Timer ); + + // + // Now allocate the Send and Receive structs. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Send, + sizeof( SEND_BLOCK ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate SEND_BLOCK struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->Send,sizeof( SEND_BLOCK )); + } + + // + // Initialize the Send Block fields and set the SEND destination + // address and resend address to nulls. + // + + OpenP->Send->Sending = FALSE; + OpenP->Send->StopSending = TRUE; + OpenP->Send->ResendPackets = FALSE; + OpenP->Send->PacketSize = 0; + OpenP->Send->NumberOfPackets = 0; + OpenP->Send->PacketsSent = 0; + OpenP->Send->PacketsPending = 0; + OpenP->Send->PacketHandle = NULL; + OpenP->Send->Counters = NULL; + OpenP->Send->SendIrp = NULL; + + KeInitializeTimer( &OpenP->Send->SendTimer ); + + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + OpenP->Send->DestAddress[i] = 0x00; + OpenP->Send->ResendAddress[i] = 0x00; + } + + // + // Allocate the Send PacketPool. + // + + NdisAllocatePacketPool( &Status, + &OpenP->Send->PacketHandle, + NUMBER_OF_POOL_PACKETS, + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: could not allocate Packet Pool\n"); + } + return Status; + } + + // + // Now allocate the SEND Counters and initialize them to zero. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Send->Counters, + sizeof( INSTANCE_COUNTERS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate counters.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( (PVOID)OpenP->Send->Counters, + sizeof( INSTANCE_COUNTERS ) ); + } + + // + // Initialize the DPC used to call SendDpc, and SendEndDpc. + // + + KeInitializeDpc(&OpenP->Send->SendDpc, + TpFuncSendDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Send->SendEndDpc, + TpFuncSendEndDpc, + (PVOID)OpenP ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->Receive, + sizeof( RECEIVE_BLOCK ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate RECEIVE_BLOCK struct\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory((PVOID)OpenP->Receive,sizeof( RECEIVE_BLOCK )); + } + + // + // Initialize the Receive Block fields. + // + + OpenP->Receive->Receiving = FALSE; + OpenP->Receive->StopReceiving = TRUE; + OpenP->Receive->PacketsPending = 0; + OpenP->Receive->PacketHandle = NULL; + OpenP->Receive->Counters = NULL; + OpenP->Receive->ReceiveIrp = NULL; + + KeInitializeTimer( &OpenP->Receive->ReceiveTimer ); + KeInitializeTimer( &OpenP->Receive->ResendTimer); + + // + // Create a PacketPool, and initialize it, we will need this in case + // we receive any RESEND packets (FUNC2_PACKET). + // + + NdisAllocatePacketPool( &Status, + &OpenP->Receive->PacketHandle, + NUMBER_OF_POOL_PACKETS, + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint1("TpAllocateOpenArray: could not allocate Packet Pool: return %s.\n", + TpGetStatus(Status)); + } + return Status; + } + + // + // Now allocate the COUNTERS structure and set the counters to zero. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Receive->Counters, + sizeof( INSTANCE_COUNTERS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpAllocateOpenArray: failed to allocate counters.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( (PVOID)OpenP->Receive->Counters, + sizeof( INSTANCE_COUNTERS ) ); + } + + // + // Initialize the DPCs used to call ReceiveDpc and ReceiveEndDpc. + // + + KeInitializeDpc(&OpenP->Receive->ReceiveDpc, + TpFuncReceiveDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Receive->ReceiveEndDpc, + TpFuncReceiveEndDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Receive->ResendDpc, + TpFuncResendDpc, + (PVOID)OpenP ); + + // + // the performance structure is not allocated here, but is allocated and freed + // within the performance functions themselves + // + +// OpenP->Perform = NULL; + + // + // now deal with the PAUSE Block + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->Pause, + sizeof( PAUSE_BLOCK ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: failed to allocate PAUSE_BLOCK struct.\n"); + } + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NdisZeroMemory( (PVOID)OpenP->Pause, + sizeof( PAUSE_BLOCK ) ); + } + + // + // Initialize the Pause Block fields. + // + + OpenP->Pause->GoReceived = FALSE; + + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + OpenP->Pause->RemoteAddress[i] = 0x00; + } + + OpenP->Pause->TestSignature = 0xFFFFFFFF; + OpenP->Pause->PacketType = (UCHAR)-1; + OpenP->Pause->UniqueSignature = 0xFFFFFFFF; + OpenP->Pause->TimeOut = 0; + + NdisAllocateSpinLock( &OpenP->Pause->SpinLock ); + OpenP->Pause->PoolAllocated = FALSE; + + // + // and Allocate the PacketPool. + // + + NdisAllocatePacketPool( &Status, + &OpenP->Pause->PacketHandle, + 10, + sizeof( PROTOCOL_RESERVED ) ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpAllocateOpenArray: could not allocate Packet Pool.\n"); + } + return Status; + } + else + { + OpenP->Pause->PoolAllocated = TRUE; + } + + // + // Then allocate the Open Blocks open spin lock. + // + + NdisAllocateSpinLock( &OpenP->SpinLock ); + + return STATUS_SUCCESS; +} + + + +VOID +TpDeallocateOpenArray( + POPEN_BLOCK OpenP + ) + +// ------- +// +// Routine Description: +// +// This routine deallocates the various data structures and spinlocks +// in the OpenBlock that are used to control the tests. +// +// Arguments: +// +// OpenP - a pointer to the OpenBlock containing the data structures which +// will be deallocated during this routine. +// +// Return Value: +// +// None. +// +// ------- + +{ + NdisFreeSpinLock( &OpenP->SpinLock ); + + if ( OpenP->AdapterName != NULL ) + { + NdisFreeMemory( OpenP->AdapterName,0,0 ); + } + + if ( OpenP->Environment != NULL ) + { + NdisFreeMemory( OpenP->Environment,0,0 ); + } + + if ( OpenP->Stress->Pend != NULL ) + { + NdisFreeMemory( OpenP->Stress->Pend,0,0 ); + NdisFreeSpinLock( &OpenP->Stress->Pend->SpinLock ); + } + + if ( OpenP->Stress->Results != NULL ) + { + NdisFreeMemory( OpenP->Stress->Results,0,0 ); + } + + if ( OpenP->Send != NULL ) + { + NdisFreePacketPool( OpenP->Send->PacketHandle ); + NdisFreeMemory( (PVOID)OpenP->Send->Counters,0,0 ); + NdisFreeMemory( OpenP->Send,0,0 ); + } + + if ( OpenP->Receive != NULL ) + { + NdisFreePacketPool( OpenP->Receive->PacketHandle ); + NdisFreeMemory( (PVOID)OpenP->Receive->Counters,0,0 ); + NdisFreeMemory( OpenP->Receive,0,0 ); + } + + if ( OpenP->Pause != NULL ) + { + if ( OpenP->Pause->PoolAllocated == TRUE ) + { + NdisFreePacketPool( OpenP->Pause->PacketHandle ); + } + NdisFreeSpinLock( &OpenP->Pause->SpinLock ); + NdisFreeMemory( OpenP->Pause,0,0 ); + } +} + + + +VOID +TpCancelIrp( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp + ) + +// ---------- +// +// Routine Description: +// +// Arguments: +// +// DeviceObject - Pointer to device object for this driver. +// +// Irp - Pointer to the request packet representing the I/O request +// to cancel. +// +// Return Value: +// +// None. +// +// ---------- + +{ + POPEN_BLOCK OpenP; + PIO_STACK_LOCATION IrpSp; + + IrpSp = IoGetCurrentIrpStackLocation( Irp ); + + OpenP = (POPEN_BLOCK)Irp->IoStatus.Information; + + IoSetCancelRoutine( Irp,NULL ); + + IoReleaseCancelSpinLock( Irp->CancelIrql ); + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ((( Irp == OpenP->Stress->StressIrp ) || + ( Irp == OpenP->Send->SendIrp )) || + ( Irp == OpenP->Receive->ReceiveIrp ) || + ( OpenP->PerformanceTest && (Irp == OpenP->Perform->PerformIrp))) + { + // + // These Irps will handle the cancel and clean up themselves + // so just return + // + + NdisReleaseSpinLock( &OpenP->SpinLock ); + return; + } + else if ( Irp == OpenP->Irp ) + { + // + // We have found one of the General Case Irp to be cancelled. + // first set the flag that this Irp has been cancelled, them + // complete it. + // + + OpenP->IrpCancelled = TRUE; + OpenP->Irp = NULL; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + } +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/tpfunc.c b/private/ntos/ndis/testprot/tpdrvr/tpfunc.c new file mode 100644 index 000000000..d94998c87 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tpfunc.c @@ -0,0 +1,4639 @@ +// ------------------------ +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpfunc.c +// +// Abstract: +// +// +// Author: +// +// Tom Adams (tomad) 9-Jul-1991 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Sanjeev Katariya (sanjeevk) +// +// 4-6-1993 Bug #5203: Changed the routine TpFuncOpenAdapter() to fill in the information +// of the media type for use by the TPCTL. This was done in order +// for TPCTL to make a decision on the OID to use when submitting +// requests to add/change mulicast addresses. +// +// 4-9-1993 Bug #5886: Changed TpFuncSendComplete() to zero out the private section of the +// NDIS_PACKET. Should the MAC access this section now after having made +// a call and to NdisSendComplete(), it will be forced to deal with +// or incorrect data +// +// 4-12-1993 Added ARCNET support +// +// Tim Wynsma (timothyw) +// 4-27-94 Added performance tests +// 5-18-94 Got rid of warnings; added some debug +// 6-08-94 Chgd perf test to client/server +// +// ----------------------------- + + +#include <ndis.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" +#include "string.h" + + +VOID +TpFuncResend(POPEN_BLOCK OpenP, + PTP_REQUEST_HANDLE SendReqHndl); + + + +NDIS_STATUS +TpFuncOpenAdapter( + IN POPEN_BLOCK OpenP, + IN UCHAR OpenInstance, + IN PCMD_ARGS CmdArgs + ) + +// ------------ +// +// Routine Description: +// +// This routine opens the request NDIS adapter and sets up the OpenBlock +// accordingly. If the call to NdisOpenAdapter does not pend, then a call +// will be made to TpFuncRequestComplete to complete the request and +// signal the application that it has finished, otherwise this call will +// be made the MAC itself once the request has finished. +// +// Arguments: +// +// +// Return Value: +// +// NDIS_STATUS - This routine always returns NDIS_STATUS_PENDING as it +// will either really pend and be completed later, or we +// will fake a completion request that will complete it +// at that time. +// +// ------------------ + + +{ + NTSTATUS Status = STATUS_SUCCESS; + NDIS_STATUS DriverStatus = NDIS_STATUS_SUCCESS; + NDIS_STATUS RequestStatus = NDIS_STATUS_SUCCESS; + STRING AdapterString; + NDIS_STRING NdisAdapterString; + NDIS_STATUS OpenErrorStatus; + UINT NameLength; + PNDIS_REQUEST Request = NULL; + PUCHAR InformationBuffer = NULL; + ULONG OidIndex; + PUCHAR p, q; + ULONG i; + PREQUEST_RESULTS OutputBuffer; + BOOLEAN GotCardAddress = FALSE; + ULONG MediaArraySize; + + + // + // Determine determine whether this instance of the Adapter is already + // opened. + // + + if ( OpenP->OpenInstance != (UCHAR)-1 ) + { + // + // If it has, then we will fail this request, and continue. We will + // not create a new Open Instance overwriting an existing one. + // + + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: An open already exists for this Open Instance %d\n", + OpenInstance); + } + Status = NDIS_STATUS_OPEN_FAILED; + } + else + { + // + // First allocate the request handle and set it up as if the request + // pended. If it does not pend we will reset the flags later; before + // calling the completion routine. + // + + TP_ASSERT ( OpenP->OpenReqHndl == NULL ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->OpenReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncOpenAdapter: unable to allocate Request Handle.\n"); + } + Status = NDIS_STATUS_RESOURCES; + goto cleanup; + } + else + { + NdisZeroMemory( OpenP->OpenReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + OpenP->OpenReqHndl->Signature = OPEN_REQUEST_HANDLE_SIGNATURE; + OpenP->OpenReqHndl->Open = OpenP; + OpenP->OpenReqHndl->RequestPended = FALSE; + + KeInitializeEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + SynchronizationEvent, + FALSE ); + // + // Otherwise initialize the adapter string for the call ... + // + + TP_ASSERT( OpenP->AdapterName == NULL ); + + NameLength = strlen( CmdArgs->ARGS.OPEN_ADAPTER.AdapterName ) + 1; + + Status = NdisAllocateMemory((PVOID *)&OpenP->AdapterName, + 8 + NameLength, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncOpenAdapter: failed to allocate adapter name buffer.\n"); + } + Status = NDIS_STATUS_RESOURCES; + goto cleanup; + } + else + { + NdisZeroMemory( OpenP->AdapterName,8 + NameLength ); + } + + NdisMoveMemory( OpenP->AdapterName,"\\Device\\",8 ); + + NdisMoveMemory( OpenP->AdapterName + 8, + CmdArgs->ARGS.OPEN_ADAPTER.AdapterName, + NameLength ); + + RtlInitString( &AdapterString,(PSZ)OpenP->AdapterName ); + + Status = RtlAnsiStringToUnicodeString( (PUNICODE_STRING)&NdisAdapterString, + (PANSI_STRING)&AdapterString, + TRUE ); + + TP_ASSERT( NT_SUCCESS( Status )); + + // + // And make the actual NdisOpenAdapter Call. + // + + if (CmdArgs->ARGS.OPEN_ADAPTER.NoArcNet) // force encapsulated ethernet + { + MediaArraySize = NDIS_MEDIUM_ARRAY_SIZE - 1; + } + else + { + MediaArraySize = NDIS_MEDIUM_ARRAY_SIZE; + } + + + NdisOpenAdapter(&DriverStatus, + &OpenErrorStatus, + &OpenP->NdisBindingHandle, + &OpenP->MediumIndex, + NdisMediumArray, + MediaArraySize, + OpenP->NdisProtocolHandle, + (NDIS_HANDLE)OpenP, + &NdisAdapterString, + 0, + NULL ); + + RtlFreeUnicodeString( &NdisAdapterString ); + + if ( DriverStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n", + TpGetStatus(Status) ); + } + goto cleanup; + } + + DriverStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( DriverStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisOpenAdapter returned %s\n", + TpGetStatus( DriverStatus )); + } + goto cleanup; + } + } + else if ( DriverStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisOpenAdapter returned %s\n", + TpGetStatus( DriverStatus )); + } + goto cleanup; + } + + // + // The open was a success, so set the open instance on + // the open block. + // + + OpenP->OpenInstance = OpenInstance; + + // + // and initialize the stress address depending on the medium type + // of the adapter opened. + // + + switch ( NdisMediumArray[OpenP->MediumIndex] ) + { + case NdisMedium802_5: + for ( i=0 ; i < ADDRESS_LENGTH ; i++ ) + { + OpenP->Environment->StressAddress[i] = STRESS_FUNCTIONAL[i]; + } + break; + + case NdisMediumFddi: + case NdisMediumDix: + case NdisMedium802_3: + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + OpenP->Environment->StressAddress[i] = STRESS_MULTICAST[i]; + } + break; + // + // STARTCHANGE + // + case NdisMediumArcnet878_2: + TP_ASSERT (MediaArraySize == NDIS_MEDIUM_ARRAY_SIZE) + + for ( i=0;i<ADDRESS_LENGTH;i++ ) + { + OpenP->Environment->StressAddress[i] = STRESS_ARCNET_BROADCAST[i]; + } + break; + // + // STOPCHANGE + // + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncOpenAdapter: Unsupported MAC Type\n"); + } + DriverStatus = NDIS_STATUS_UNSUPPORTED_MEDIA; + goto cleanup; + } + + // + // Now allocate the Ndis Request structure to hold the query + // information requests in. + // + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncOpenAdapter: unable to allocate Ndis Request buffer.\n"); + } + Status = NDIS_STATUS_RESOURCES; + goto cleanup; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = NdisRequestQueryInformation; + + // + // Now query the card address and the maximum frame size + // from the MAC. Determine the necessary size of the + // information buffer to fit the station address, and + // allocate it. + // + + // + // STARTCHANGE + // + if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 ) + { + OidIndex = TpLookUpOidInfo( OID_802_3_CURRENT_ADDRESS ); + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) + { + OidIndex = TpLookUpOidInfo( OID_802_5_CURRENT_ADDRESS ); + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) + { + OidIndex = TpLookUpOidInfo( OID_FDDI_LONG_CURRENT_ADDR ); + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2 ) + { + OidIndex = TpLookUpOidInfo( OID_ARCNET_CURRENT_ADDRESS ); + } + // + // STOPCHANGE + // + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + OidArray[OidIndex].Length, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncOpenAdapter: unable to allocate Information Buffer.\n"); + } + Status = NDIS_STATUS_RESOURCES; + goto cleanup; + } + else + { + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length); + } + + Request->DATA.QUERY_INFORMATION.Oid = OidArray[OidIndex].Oid; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + goto cleanup; + } + + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest Query Station Address failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest Query Station Address failed returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + + GotCardAddress = TRUE; + + p = OpenP->StationAddress; + q = (PUCHAR)InformationBuffer; + + // + // STARTCHANGE + // + for ( i=0;i<OidArray[OidIndex].Length;i++ ) + { + *p++ = *q++; + } + // + // STOPCHANGE + // + + // + // Then determine the necessary size of the information buffer + // to allocate, and allocate it. + // + + OidIndex = TpLookUpOidInfo( OID_GEN_MAXIMUM_TOTAL_SIZE ); + + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length ); + + Request->RequestType = NdisRequestQueryInformation; + + Request->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + goto cleanup; + } + + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + + Status = TpInitMedia( OpenP,*(PULONG)InformationBuffer ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_INITIALIZE ) + { + TpPrint1("TpFuncOpenAdapter: TpInitMedia failed. returned %s\n", + TpGetStatus( Status )); + } + goto cleanup; + } + + + // + // SANJEEVK: NEW: BUG#2930 NTRAID\NTBUG + // + + // + // Set the lookahead size to the max supported by the card + // Later on if we don't like it we can change it + // + + // + // QUERY the OID_GEN_MAXIMUM_LOOKAHEAD + // + OidIndex = TpLookUpOidInfo( OID_GEN_MAXIMUM_LOOKAHEAD ); + + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length ); + + Request->RequestType = NdisRequestQueryInformation; + + Request->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_LOOKAHEAD; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + + goto cleanup; + } + + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest QueryMaxLookAhead failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisRequest QueryMaxLookAhead failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + + + // + // And now set the card with the maximum value + // + OidIndex = TpLookUpOidInfo( OID_GEN_CURRENT_LOOKAHEAD ); + + Request->RequestType = NdisRequestSetInformation; + + Request->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_LOOKAHEAD; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.SET_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + goto cleanup; + } + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest SetCurrentLookAhead to MAXLOOKAHEAD failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest SetCurrentLookAhead to MAXLOOKAHEAD failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + + // + // ENDNEW + // + + // + // If we are on ethernet query the multicast list size for + // use in later tests. + // + + if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 ) + { + OidIndex = TpLookUpOidInfo( OID_802_3_MAXIMUM_LIST_SIZE ); + + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length); + + Request->RequestType = NdisRequestQueryInformation; + + Request->DATA.QUERY_INFORMATION.Oid = OID_802_3_MAXIMUM_LIST_SIZE; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + goto cleanup; + } + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + OpenP->Environment->MulticastListSize = *(PULONG)InformationBuffer; + } + + if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) + { + OidIndex = TpLookUpOidInfo( OID_FDDI_LONG_MAX_LIST_SIZE ); + + NdisZeroMemory( InformationBuffer,OidArray[OidIndex].Length); + + Request->RequestType = NdisRequestQueryInformation; + + Request->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LONG_MAX_LIST_SIZE; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = OidArray[OidIndex].Length; + + // + // and then make the request + // + + NdisRequest( &RequestStatus,OpenP->NdisBindingHandle,Request ); + + if ( RequestStatus == NDIS_STATUS_PENDING ) + { + Status = KeWaitForSingleObject( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent, + Executive, + KernelMode, + FALSE, + NULL ); + + if ( Status != STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NT_STATUS ) + { + TpPrint1("TpFuncOpenAdapter: KeWaitForSingleObject returned %s\n",Status ); + } + goto cleanup; + } + + RequestStatus = OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1( + "TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + } + else if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncOpenAdapter: NdisRequest Max Frame Size failed: returned %s\n", + TpGetStatus( RequestStatus )); + } + goto cleanup; + } + OpenP->Environment->MulticastListSize = *(PULONG)InformationBuffer; + } + } + + +cleanup: + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress ); + + OutputBuffer->Signature = OPEN_RESULTS_SIGNATURE; + OutputBuffer->RequestPended = OpenP->OpenReqHndl->RequestPended; + OutputBuffer->RequestStatus = DriverStatus; + + if (( Status == STATUS_SUCCESS ) && + ( DriverStatus == NDIS_STATUS_SUCCESS )) + { + OutputBuffer->OpenRequestStatus = RequestStatus; + + if ( RequestStatus != NDIS_STATUS_SUCCESS ) + { + OutputBuffer->OID = Request->DATA.QUERY_INFORMATION.Oid; + + OutputBuffer->BytesReadWritten = Request->DATA.QUERY_INFORMATION.BytesWritten; + + OutputBuffer->BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded; + + // + // Since a portion of the call failed, i.e. one of the query + // info calls, we are failing the whole call, and need to + // reset the card open info. + // + + OpenP->OpenInstance = 0xFF; + + if ( OpenP->Media != NULL ) + { + NdisFreeMemory( OpenP->Media,0,0 ); + OpenP->Media = NULL; + } + + } + else if ( GotCardAddress == TRUE ) + { + PNDIS_MEDIUM MediumType = (PNDIS_MEDIUM)OutputBuffer->InformationBuffer; + // + // Sanjeevk: Bug #5203 + // + // Comment + // + // This is where the user provided buffer thru the IOCTL + // is filled out with the address and the media type + // + + // + // Copy the Media type into the buffer. The media type + // has been initialized by a call to TpInitMedia() earlier + // on in this function. + // + *MediumType = OpenP->Media->MediumType; + + // + // Copy the adapter address into the buffer + // + p = OutputBuffer->InformationBuffer + sizeof( NDIS_MEDIUM ); + q = OpenP->StationAddress; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = *q++; + } + + } + } + } + + OpenP->Irp->IoStatus.Status = Status; + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + if ( OpenP->OpenReqHndl != NULL ) + { + NdisFreeMemory( OpenP->OpenReqHndl,0,0 ); + OpenP->OpenReqHndl = NULL; + } + + if ((( DriverStatus != NDIS_STATUS_SUCCESS ) || + ( RequestStatus != NDIS_STATUS_SUCCESS )) && + ( OpenP->AdapterName != NULL )) + { + + NdisFreeMemory( OpenP->AdapterName,0,0 ); + OpenP->AdapterName = NULL; + } + + if ( Request != NULL ) + { + NdisFreeMemory( Request,0,0 ); + } + + if ( InformationBuffer != NULL ) + { + NdisFreeMemory( InformationBuffer,0,0 ); + } + + return Status; +} + + + +VOID +TpFuncOpenComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ) + +{ + POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext; + ULONG NextEvent; + + TP_ASSERT( OpenP != NULL ); + + if (( OpenP->OpenReqHndl != NULL ) && + (( OpenP->OpenReqHndl->Signature == OPEN_REQUEST_HANDLE_SIGNATURE ) && + ( OpenP->OpenReqHndl->Open == OpenP ))) + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint1("TpFuncOpenComplete Status = %s\n", TpGetStatus( Status )); + } + + OpenP->OpenReqHndl->RequestPended = TRUE; + OpenP->OpenReqHndl->u.OPEN_REQ.RequestStatus = Status; + + KeSetEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,0,FALSE ); + + } + else + { + // + // We are not expecting any Open requests to complete at this + // point, so stick this on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteOpen; + OpenP->EventQueue->Head = NextEvent; + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } +} + + + +NDIS_STATUS +TpFuncCloseAdapter( + IN POPEN_BLOCK OpenP + ) + +// -------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// ------ + +{ + NDIS_STATUS Status; + LARGE_INTEGER TimeOut; + + TP_ASSERT( OpenP->CloseReqHndl == NULL ); + + // + // First determine whether this instance of the Adapter is currently + // opened. + // + + if ( OpenP->OpenInstance == (UCHAR)-1 ) + { + // + // It is not already opened, so we will fail this call. + // + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint0("TpFuncCloseAdapter: An open does not exists for this Open Instance\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OpenP->Irp->IoStatus.Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + return NDIS_STATUS_ADAPTER_NOT_FOUND; + } + else + { + // + // Otherwise allocate the request handle and set it up as if + // the request pended. If it does not pend we will reset the + // flags later before calling the completion routine. + // + + Status = NdisAllocateMemory((PVOID *)&OpenP->CloseReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncOpenAdapter: unable to allocate Request Handle.\n"); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->CloseReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + OpenP->CloseReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + OpenP->CloseReqHndl->Open = OpenP; + OpenP->CloseReqHndl->RequestPended = TRUE; + OpenP->CloseReqHndl->Irp = OpenP->Irp; + + // + // Then we will attempt to close it. First set the + // open instance's closing flag to true, then signal all + // the async test protocol routines that are currently + // running to end. + // + + OpenP->Closing = TRUE; + + if ( OpenP->Stress->Stressing == TRUE ) + { + OpenP->Stress->StopStressing = TRUE; + } + + if ( OpenP->Send->Sending == TRUE ) + { + OpenP->Send->StopSending = TRUE; + } + + if ( OpenP->Receive->Receiving == TRUE ) + { + OpenP->Receive->StopReceiving = TRUE; + } + + // + // Then wait for all of the three asynchronous routines; + // STRESS, SEND and RECEIVE to finish. + // + + TimeOut.HighPart = -1; // so it will be relative. + TimeOut.LowPart = (ULONG)(-(ONE_TENTH_SECOND)); + + while ( OpenP->ReferenceCount > 0 ) + { + // Status = KeDelayExecutionThread( KernelMode,FALSE,&TimeOut ); + /* NULL */ ; + } + + // + // finally we will attempt to close it. + // + + NdisCloseAdapter( &Status,OpenP->NdisBindingHandle ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncCloseAdapter: NdisCloseAdapter returned %s\n", TpGetStatus(Status)); + } + } + + if ( Status != NDIS_STATUS_PENDING ) + { + // + // If the request did not pend, we should reset the pend flag, + // and the status flag in the OpenP->CloseReqHndl, and then + // call the completion handler ourselves. + // + + OpenP->CloseReqHndl->RequestPended = FALSE; + TpFuncCloseComplete( OpenP,Status ); + } + } + return NDIS_STATUS_PENDING; +} + + + +VOID +TpFuncCloseComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext; + PREQUEST_RESULTS OutputBuffer; + USHORT i; + ULONG NextEvent; + + TP_ASSERT( OpenP != NULL ); + + if (( OpenP->CloseReqHndl != NULL ) && + (( OpenP->CloseReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) && + ( OpenP->CloseReqHndl->Open == OpenP ))) + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint1("TpFuncCloseComplete Status = %s\n", TpGetStatus( Status )); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->CloseReqHndl->Irp != NULL ) + { + OutputBuffer = MmGetSystemAddressForMdl( OpenP->CloseReqHndl->Irp->MdlAddress ); + + OutputBuffer->Signature = CLOSE_RESULTS_SIGNATURE; + OutputBuffer->RequestPended = OpenP->CloseReqHndl->RequestPended; + OutputBuffer->RequestStatus = Status; + + if ( Status == NDIS_STATUS_SUCCESS ) + { + // + // The close of the adapter was a success so set the flags + // in the OpenBlock back to the initial state, and reset + // the StationAddress to NULL. + // + + OpenP->NdisBindingHandle = NULL; + OpenP->OpenInstance = 0xFF; + OpenP->Closing = FALSE; + + if ( OpenP->AdapterName != NULL ) + { + NdisFreeMemory( OpenP->AdapterName,0,0 ); + OpenP->AdapterName = NULL; + } + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + OpenP->StationAddress[i] = 0x00; + } + + // + // We will also free the media block at this point because + // the info it contains may not hold for the next adapter + // open on this instance. + // + + if ( OpenP->Media != NULL ) + { + NdisFreeMemory( OpenP->Media,0,0 ); + OpenP->Media = NULL; + } + } + + TP_ASSERT(Status != NDIS_STATUS_PENDING); + + OpenP->CloseReqHndl->Irp->IoStatus.Status = Status; + + IoMarkIrpPending( OpenP->CloseReqHndl->Irp ); + + IoAcquireCancelSpinLock( &OpenP->CloseReqHndl->Irp->CancelIrql ); + IoSetCancelRoutine( OpenP->CloseReqHndl->Irp,NULL ); + IoReleaseCancelSpinLock( OpenP->CloseReqHndl->Irp->CancelIrql ); + + IoCompleteRequest( OpenP->CloseReqHndl->Irp,IO_NETWORK_INCREMENT ); + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisFreeMemory( OpenP->CloseReqHndl,0,0 ); + OpenP->CloseReqHndl = NULL; + } + else + { + // + // We are not expecting any requests to complete at this + // point, so stick this on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteClose; + + OpenP->EventQueue->Head = NextEvent; + + // we should also stick some interesting info likje requesttype. + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } +} + + + +NDIS_STATUS +TpFuncReset( + IN POPEN_BLOCK OpenP + ) + +// ------------ +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// Change history: +// +// SanjeevK : During initial allocation during the reset, should the allocation fail, the spin +// lock for the OPEN_BLOCK was being acquired twice instead of being acquired +// and then released. Bug #3109 +// +// ------------ + +{ + NDIS_STATUS Status; + + TP_ASSERT( OpenP->ResetReqHndl == NULL ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->ResetReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncReset: unable to allocate Request Handle.\n"); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->ResetReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + OpenP->ResetReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + OpenP->ResetReqHndl->Open = OpenP; + OpenP->ResetReqHndl->RequestPended = TRUE; + OpenP->ResetReqHndl->Irp = OpenP->Irp; + + // + // Then make the call to RESET the adapter. + // + + NdisReset( &Status,OpenP->NdisBindingHandle ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG(TP_DEBUG_NDIS_ERROR) + { + TpPrint1("TpFuncReset: NdisReset failed: returned %s\n", + TpGetStatus( Status )); + } + } + + if ( Status != NDIS_STATUS_PENDING ) + { + // + // If the request did not pend, we should reset the pend flag, + // and the status flag in the RequestHandle, and call the + // completion handler ourselves. + // + + OpenP->ResetReqHndl->RequestPended = FALSE; + TpFuncResetComplete( OpenP,Status ); + } + return NDIS_STATUS_PENDING; +} + + + +VOID +TpFuncResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext; + PREQUEST_RESULTS OutputBuffer; + ULONG NextEvent; + + TP_ASSERT( OpenP != NULL ); + + if (( OpenP->ResetReqHndl != NULL ) && + (( OpenP->ResetReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) && + ( OpenP->ResetReqHndl->Open == OpenP ))) + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint1("TpFuncResetComplete Status = %s\n", + TpGetStatus( Status )); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->ResetReqHndl->Irp != NULL ) + { + OutputBuffer = MmGetSystemAddressForMdl( OpenP->ResetReqHndl->Irp->MdlAddress ); + + OutputBuffer->Signature = RESET_RESULTS_SIGNATURE; + OutputBuffer->RequestPended = OpenP->ResetReqHndl->RequestPended; + OutputBuffer->RequestStatus = Status; + + OpenP->ResetReqHndl->Irp->IoStatus.Status = Status; + + TP_ASSERT( Status != NDIS_STATUS_PENDING ); + + IoMarkIrpPending( OpenP->ResetReqHndl->Irp ); + + IoAcquireCancelSpinLock( &OpenP->ResetReqHndl->Irp->CancelIrql ); + IoSetCancelRoutine( OpenP->ResetReqHndl->Irp,NULL ); + IoReleaseCancelSpinLock( OpenP->ResetReqHndl->Irp->CancelIrql ); + + IoCompleteRequest( OpenP->ResetReqHndl->Irp,IO_NETWORK_INCREMENT ); + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + NdisFreeMemory( OpenP->ResetReqHndl,0,0 ); + OpenP->ResetReqHndl = NULL; + } + else + { + // + // We are not expecting any requests to complete at this + // point, so stick this on the Event Queue. + // + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteReset; + OpenP->EventQueue->Head = NextEvent; + + // we should also stick some interesting info likje requesttype. + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } +} + + + +NDIS_STATUS +TpFuncRequestQueryInfo( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN OUT PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) +{ + NDIS_STATUS Status; + PNDIS_REQUEST Request; + PUCHAR InformationBuffer; + ULONG OidIndex; + ULONG InfoBufLength; + + // + // First allocate a request handle structure to hold the + // test information in. + // + + TP_ASSERT( OpenP->RequestReqHndl == NULL ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->RequestReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestQueryInfo: unable to allocate Request Handle.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->RequestReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + OpenP->RequestReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + OpenP->RequestReqHndl->Open = OpenP; + OpenP->RequestReqHndl->RequestPended = TRUE; + OpenP->RequestReqHndl->Irp = Irp; + + OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode = + IrpSp->Parameters.DeviceIoControl.IoControlCode; + + // + // Now allocate the Ndis Request structure to hold the + // query information request in. + // + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestQueryInfo: unable to allocate Request.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType = + Request->RequestType = NdisRequestQueryInformation; + + // + // Then determine the necessary size of the information buffer + // to allocate, and allocate it. + // + + OidIndex = TpLookUpOidInfo( CmdArgs->ARGS.TPQUERY.OID ); + + // + // If the OID we are going to call is for the Multicast List, then + // we will need a buffer of size MaxMulticastList * sizeof(Multicast) + // + + if (( CmdArgs->ARGS.TPQUERY.OID == OID_802_3_MULTICAST_LIST ) || + ( CmdArgs->ARGS.TPQUERY.OID == OID_FDDI_LONG_MULTICAST_LIST )) + { + InfoBufLength = OpenP->Environment->MulticastListSize * ADDRESS_LENGTH; + } + else + { + InfoBufLength = OidArray[OidIndex].Length; + } + + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + InfoBufLength, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestQueryInfo: unable to allocate Information Buffer.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,InfoBufLength ); + } + + Request->DATA.QUERY_INFORMATION.Oid = CmdArgs->ARGS.TPQUERY.OID; + Request->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.QUERY_INFORMATION.InformationBufferLength = InfoBufLength; + + OpenP->RequestReqHndl->u.INFO_REQ.OID = CmdArgs->ARGS.TPQUERY.OID; + OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer = InformationBuffer; + OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength = InfoBufLength; + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_NDIS_ERROR ) + { + TpPrint1("TpFuncRequestQueryInfo: NdisRequest failed: returned %s\n", + TpGetStatus(Status)); + } + } + + if ( Status != NDIS_STATUS_PENDING ) + { + // + // If the request did not pend, we should reset the pend flag, + // and the status flag in the OpenP->RequestReqHndl, and call the + // completion handler ourselves. + // + + OpenP->RequestReqHndl->RequestPended = FALSE; + TpFuncRequestComplete( OpenP,Request,Status ); + } + return NDIS_STATUS_PENDING; +} + + + +NDIS_STATUS +TpFuncRequestSetInfo( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN OUT PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) + +// ----------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// -------- + +{ + NDIS_STATUS Status; + PNDIS_REQUEST Request; + ULONG OidIndex; + PUCHAR InformationBuffer = NULL; + ULONG InfoBufLength = 0; + + // + // First allocate a request handle structure to hold the + // test information in. + // + + TP_ASSERT( OpenP->RequestReqHndl == NULL ); + + Status = NdisAllocateMemory((PVOID *)&OpenP->RequestReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestSetInfo: unable to allocate Request Handle.\n"); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( OpenP->RequestReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + OpenP->RequestReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + OpenP->RequestReqHndl->Open = OpenP; + OpenP->RequestReqHndl->RequestPended = TRUE; + OpenP->RequestReqHndl->Irp = Irp; + + OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode = + IrpSp->Parameters.DeviceIoControl.IoControlCode; + + // + // Now allocate the Ndis Request structure to hold the request + // information in. + // + + Status = NdisAllocateMemory((PVOID *)&Request, + sizeof( NDIS_REQUEST ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestSetInfo: unable to allocate Request.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Request,sizeof( NDIS_REQUEST )); + } + + Request->RequestType = OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType + = NdisRequestSetInformation; + + OidIndex = TpLookUpOidInfo( CmdArgs->ARGS.TPSET.OID ); + + if (( CmdArgs->ARGS.TPSET.OID == OID_802_3_MULTICAST_LIST ) || + ( CmdArgs->ARGS.TPSET.OID == OID_FDDI_LONG_MULTICAST_LIST)) + { + InfoBufLength = OidArray[OidIndex].Length * CmdArgs->ARGS.TPSET.NumberMultAddrs; + } + else + { + InfoBufLength = OidArray[OidIndex].Length; + } + + // + // Now if the infobuffer is larger than zero bytes allocate it. + // With a multicast list size of zero we will just pass a null + // pointer. + // + + if ( InfoBufLength > 0 ) + { + Status = NdisAllocateMemory((PVOID *)&InformationBuffer, + InfoBufLength, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncRequestSetInfo: unable to allocate Information Buffer.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( InformationBuffer,InfoBufLength); + } + } + + // + // Now set the generic setinfo information in both the Request + // Handle, and in the SET_INFO portion of the Request struct. + // + + OpenP->RequestReqHndl->u.INFO_REQ.OID = CmdArgs->ARGS.TPSET.OID; + OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer = InformationBuffer; + OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength = InfoBufLength; + + Request->DATA.SET_INFORMATION.Oid = CmdArgs->ARGS.TPSET.OID; + Request->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; + Request->DATA.SET_INFORMATION.InformationBufferLength = InfoBufLength; + + switch( CmdArgs->ARGS.TPSET.OID ) + { + // + // and then add the OID specific information to the information + // section of the OVB for this request. + // + case OID_GEN_CURRENT_PACKET_FILTER: + *((PULONG)InformationBuffer) = (ULONG)CmdArgs->ARGS.TPSET.U.PacketFilter; + break; + + case OID_802_3_MULTICAST_LIST: + case OID_FDDI_LONG_MULTICAST_LIST: + // + // Initialize the multicast address string to pass to the request. + // + + NdisMoveMemory( InformationBuffer, + CmdArgs->ARGS.TPSET.U.MulticastAddress, + ADDRESS_LENGTH * CmdArgs->ARGS.TPSET.NumberMultAddrs ); + break; + + case OID_802_5_CURRENT_FUNCTIONAL: + case OID_802_5_CURRENT_GROUP: + // + // This is only valid if Driver Type is 802.5, should it be + // allowed if we are not working with a token ring driver ???? + // + + NdisMoveMemory( InformationBuffer, + &CmdArgs->ARGS.TPSET.U.FunctionalAddress, + FUNCTIONAL_ADDRESS_LENGTH ); + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + *((PULONG)InformationBuffer) = (ULONG)CmdArgs->ARGS.TPSET.U.LookaheadSize; + break; + + default: + IF_TPDBG(TP_DEBUG_NDIS_CALLS) + { + TpPrint0("TpFuncRequestSetInfo: invalid OID to be passed to NdisRequest\n"); + } + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Irp != NULL ) + { + Irp->IoStatus.Status = NDIS_STATUS_INVALID_OID; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_INVALID_OID; + + } // switch + + + // + // Now that the Request is set, make the actual call. + // + + NdisRequest( &Status,OpenP->NdisBindingHandle,Request ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG(TP_DEBUG_NDIS_ERROR) + { + TpPrint1("TpFuncRequestSetInfo: NdisRequest failed: returned %s\n", + TpGetStatus(Status)); + } + } + + if ( Status != NDIS_STATUS_PENDING ) + { + // + // If the request did not pend, we should reset the pend flag, + // and the status flag in the OpenP->RequestReqHndl, and call the + // completion handler ourselves. + // + + OpenP->RequestReqHndl->RequestPended = FALSE; + TpFuncRequestComplete( OpenP,Request,Status ); + } + return NDIS_STATUS_PENDING; +} + + + +VOID +TpFuncRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ) +{ + POPEN_BLOCK OpenP = (POPEN_BLOCK)ProtocolBindingContext; + PREQUEST_RESULTS OutputBuffer; + ULONG NextEvent; + + TP_ASSERT( OpenP != NULL ); + TP_ASSERT( NdisRequest != NULL ); + TP_ASSERT( Status != NDIS_STATUS_PENDING ); + + if (( OpenP->RequestReqHndl != NULL ) && + (( OpenP->RequestReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) && + ( OpenP->RequestReqHndl->Open == OpenP ))) + { + IF_TPDBG(TP_DEBUG_DISPATCH) + { + TpPrint2("TpFuncRequestComplete RequestType = %d, Status = %s\n", + NdisRequest->RequestType, TpGetStatus( Status)); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Irp != NULL ) + { + OutputBuffer = MmGetSystemAddressForMdl( OpenP->RequestReqHndl->Irp->MdlAddress ); + + OutputBuffer->Signature = REQUEST_RESULTS_SIGNATURE; + OutputBuffer->IoControlCode = OpenP->RequestReqHndl->u.INFO_REQ.IoControlCode; + OutputBuffer->RequestPended = OpenP->RequestReqHndl->RequestPended; + OutputBuffer->RequestStatus = Status; + + TP_ASSERT( NdisRequest->RequestType == + OpenP->RequestReqHndl->u.INFO_REQ.NdisRequestType ); + + OutputBuffer->NdisRequestType = NdisRequest->RequestType; + + if ( NdisRequest->RequestType == NdisRequestQueryInformation ) + { + TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.Oid == + OpenP->RequestReqHndl->u.INFO_REQ.OID ); + + TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer == + OpenP->RequestReqHndl->u.INFO_REQ.InformationBuffer ); + + OutputBuffer->OID = NdisRequest->DATA.QUERY_INFORMATION.Oid; + + TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.BytesWritten <= + OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + // + // Then we must copy the information returned into the + // OutputBuffer. + // + + OutputBuffer->InformationBufferLength = + OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength; + +// TP_ASSERT( NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength <= +// IOCTL_BUFFER_SIZE - sizeof( REQUEST_RESULTS )); + + NdisMoveMemory( OutputBuffer->InformationBuffer, + (PUCHAR)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, + NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength ); + } + + OutputBuffer->BytesReadWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten; + OutputBuffer->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded; + } + else if ( NdisRequest->RequestType == NdisRequestSetInformation ) + { + OutputBuffer->OID = OpenP->RequestReqHndl->u.INFO_REQ.OID; + + TP_ASSERT( NdisRequest->DATA.SET_INFORMATION.BytesRead <= + OpenP->RequestReqHndl->u.INFO_REQ.InformationBufferLength ); + + OutputBuffer->BytesReadWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead; + OutputBuffer->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded; + } + else + { + TP_ASSERT( FALSE ); + } + + // + // Now set the return status to SUCCESS and complete the request. + // + OpenP->RequestReqHndl->Irp->IoStatus.Status = NDIS_STATUS_SUCCESS; + + IoMarkIrpPending( OpenP->RequestReqHndl->Irp ); + + IoAcquireCancelSpinLock( &OpenP->RequestReqHndl->Irp->CancelIrql ); + IoSetCancelRoutine( OpenP->RequestReqHndl->Irp,NULL ); + IoReleaseCancelSpinLock( OpenP->RequestReqHndl->Irp->CancelIrql ); + + IoCompleteRequest( OpenP->RequestReqHndl->Irp,IO_NETWORK_INCREMENT ); + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Finally free the request handle + // + + if (( NdisRequest->RequestType == NdisRequestQueryInformation ) || + ( NdisRequest->RequestType == NdisRequestQueryStatistics )) + { + NdisFreeMemory( NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, 0,0 ); + } + else if ( NdisRequest->RequestType == NdisRequestSetInformation ) + { + if ( NdisRequest->DATA.SET_INFORMATION.InformationBufferLength > 0 ) + { + NdisFreeMemory( NdisRequest->DATA.SET_INFORMATION.InformationBuffer, 0,0 ); + } + } + else + { + TP_ASSERT( FALSE ); + } + + NdisFreeMemory( NdisRequest,0,0 ); + NdisFreeMemory( OpenP->RequestReqHndl,0,0 ); + OpenP->RequestReqHndl = NULL; + + } + else if (( OpenP->OpenReqHndl != NULL ) && + (( OpenP->OpenReqHndl->Open == OpenP ) && + ( OpenP->OpenReqHndl->Signature == OPEN_REQUEST_HANDLE_SIGNATURE ))) + { + KeSetEvent( &OpenP->OpenReqHndl->u.OPEN_REQ.OpenEvent,0,FALSE ); + } + else + { + // + // We are not expecting any requests to complete at this + // point, so stick this on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteRequest; + OpenP->EventQueue->Head = NextEvent; + + // we should also stick some interesting info like requesttype. + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } +} + + + +NDIS_STATUS +TpFuncSend( + IN POPEN_BLOCK OpenP + ) + +// ---------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// --------- + +{ + // + // Increment the reference count on the OpenBlock stating that + // an async test is running and must be ended prior to closing + // the adapter on this open. Sending of only one packet although + // handled differently still will increment the ref count. + // + + TpAddReference( OpenP ); + + NdisZeroMemory( (PVOID)OpenP->Send->Counters, + sizeof( INSTANCE_COUNTERS ) ); + + // + // Initialize the SEND control flags, and reset the packet sending + // control counters. + // + + OpenP->Send->Sending = TRUE; + OpenP->Send->StopSending = FALSE; + OpenP->Send->PacketsSent = 0; + OpenP->Send->PacketsPending = 0; + OpenP->Send->SendEndDpcCount = 0; + + if ( OpenP->Send->NumberOfPackets == 1 ) + { + // + // We are only sending one packet so just call the send + // routine, don't queue it as a DPC. + // + TpFuncSendDpc( NULL,OpenP,NULL,NULL ); + } + else + { + // + // We will be sending more than one packet, so queue TpFuncSendDpc + // and return Pending to the user, the DPC will send the packets, + // and after all the packets have been sent complete the request. + // + + if ( !KeInsertQueueDpc( &OpenP->Send->SendDpc, NULL, NULL )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncSend failed to queue the TpFuncSendDpc.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->Send->SendIrp != NULL ) + { + OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_FAILURE; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_FAILURE; + } + } + return NDIS_STATUS_PENDING; +} + + + +VOID +TpFuncInitializeSendArguments( + POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs + ) + +// ------------ +// +// Routine Description: +// +// This routine simply copies the arguments for Send into the Send +// struct on the Open Block. The send routines may then reference +// the arguments there after an asynchrnous call has returned. +// +// Arguments: +// +// OpenP - The open block represent this open instance, the location +// where the arguments will be stored. +// +// CmdArgs - The arguments passed in from the app for this test run. +// +// Return Value: +// +// None - the Send arguments are copied to the Open Block. +// +// ------------- + +{ + PUCHAR p, q, s, t; + ULONG i; + + OpenP->Send->NumberOfPackets = CmdArgs->ARGS.TPSEND.NumberOfPackets; + + if ( CmdArgs->ARGS.TPSEND.PacketSize > OpenP->Media->MaxPacketLen ) + { + OpenP->Send->PacketSize = OpenP->Media->MaxPacketLen; + IF_TPDBG ( TP_DEBUG_IOCTL_ARGS ) + { + TpPrint1("TpFuncInitializeSendArguments: Invalid PacketSize; using %d\n", + OpenP->Send->PacketSize); + } + } + else + { + OpenP->Send->PacketSize = CmdArgs->ARGS.TPSEND.PacketSize; + } + + p = OpenP->Send->DestAddress; + q = CmdArgs->ARGS.TPSEND.DestAddress; + s = OpenP->Send->ResendAddress; + t = CmdArgs->ARGS.TPSEND.ResendAddress; + + // + // STARTCHANGE + // + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = *q++; + *s++ = *t++; + } + + if (OpenP->Send->PacketSize < (sizeof(FUNC2_PACKET) + 4)) + { + OpenP->Send->ResendPackets = FALSE; + } + + else if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + // + // Since there is no concept of a NULL address we have no choice but + // to always use a resend address + // Addresses in arcnet range from 0x00 to 0xff where 0x00 is a broadcast + // address + // + OpenP->Send->ResendPackets = TRUE; + } + + else + { + if ( RtlCompareMemory( OpenP->Send->ResendAddress, + NULL_ADDRESS, + OpenP->Media->AddressLen ) != OpenP->Media->AddressLen ) + { + OpenP->Send->ResendPackets = TRUE; + } + else + { + OpenP->Send->ResendPackets = FALSE; + } + } + // + // STOPCHANGE + // +} + + + +VOID +TpFuncSendDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// ------------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// ----------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PTP_REQUEST_HANDLE RequestHandle; + NDIS_STATUS Status; + PNDIS_PACKET Packet; + LARGE_INTEGER DueTime; + PPROTOCOL_RESERVED ProtRes; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + Status = NdisAllocateMemory((PVOID *)&RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncSendDpc: unable to allocate Request Handle.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Send->SendIrp != NULL ) + { + OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + TpFuncSendEndDpc( NULL,OpenP,NULL,NULL ); + return; + } + else + { + NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE )); + } + + RequestHandle->Signature = SEND_REQUEST_HANDLE_SIGNATURE; + RequestHandle->Open = OpenP; + RequestHandle->RequestPended = TRUE; + RequestHandle->Irp = OpenP->Send->SendIrp; + + Packet = TpFuncAllocateSendPacket( OpenP ); + + if ( Packet == NULL ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncSendDpc: Unable to create a Send packet\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if ( OpenP->Send->SendIrp != NULL ) + { + OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + + TpFuncSendEndDpc( NULL,OpenP,NULL,NULL ); + return; + } + + RequestHandle->u.SEND_REQ.Packet = Packet; + RequestHandle->u.SEND_REQ.PacketSize = OpenP->Send->PacketSize; + RequestHandle->u.SEND_REQ.SendPacket = TRUE; + + ProtRes = PROT_RES( Packet ); + ProtRes->RequestHandle = RequestHandle; + + // + // Set the check sum in the PROTOCOL RESERVED Section of the + // packet header to ensure it is not touched while the packet + // is in the hands of the MAC. + // + + ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) ); + ++OpenP->Send->PacketsPending; + ++OpenP->Send->Counters->Sends; + + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + + if ( Status != NDIS_STATUS_PENDING ) + { + --OpenP->Send->PacketsPending; + + if ( Status != NDIS_STATUS_SUCCESS ) + { + // + // If we are running on TokenRing the following to "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + // SanjeevK : Even FDDI returns the same errors as 802.5 + // + // STARTCHANGE + // + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++OpenP->Send->Counters->SendFails; + } + } + else + { + ++OpenP->Send->Counters->SendFails; + TpPrint1("Send failed: status = %s", TpGetStatus(Status)); + } + + // + // STOPCHANGE + // + } + + RequestHandle->RequestPended = FALSE; + + TpFuncSendComplete( OpenP,Packet,Status ); + } + else + { + ++OpenP->Send->Counters->SendPends; + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ((( OpenP->Send->SendIrp != NULL ) && + ( OpenP->Send->SendIrp->Cancel == FALSE )) && + (( ++OpenP->Send->PacketsSent < OpenP->Send->NumberOfPackets ) && + ( OpenP->Send->StopSending == FALSE ))) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-4 * (ONE_HUNDREDTH_SECOND)); + + if ( KeSetTimer(&OpenP->Send->SendTimer, + DueTime, + &OpenP->Send->SendDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncSendDpc set SendTimer while timer existed.\n"); + } + } + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&OpenP->Send->SendTimer, + DueTime, + &OpenP->Send->SendEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncSendDpc set SendTimer while timer existed(2).\n"); + } + } + } +} + + + +VOID +TpFuncSendEndDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// ------------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// ------------ + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + LARGE_INTEGER DueTime; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + // + // See if we have any outstanding packets left to complete. If we do, + // then we will reset the time to queue this dpc routine again in one + // second, if after ten requeue the packet has still no completed we + // assume it will never complete and return the results and finish. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ((( OpenP->Send->SendIrp != NULL ) && + ( OpenP->Send->SendIrp->Cancel == FALSE )) && + (( OpenP->Send->PacketsPending != 0 ) && + ( OpenP->Send->SendEndDpcCount++ < 10 ))) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&OpenP->Send->SendTimer, + DueTime, + &OpenP->Send->SendEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncSendEndDpc set SendTimer while timer existed.\n"); + } + } + return; + } + + // + // Write the statistics to the send results outputbuffer. + // + + if (( OpenP->Send->SendIrp != NULL ) && + ( OpenP->Send->SendIrp->Cancel == FALSE )) + { + TpWriteSendReceiveResults( OpenP->Send->Counters, + OpenP->Send->SendIrp ); + } + + // + // and if the IoStatus.Status has not been set, then set it. + // + + if ( (OpenP->Send->SendIrp != NULL) && + (OpenP->Send->SendIrp->IoStatus.Status == NDIS_STATUS_PENDING )) + { + OpenP->Send->SendIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; + } + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Now set the sending flag to indicate that we are no longer + // SENDing packets. + // + + OpenP->Send->Sending = FALSE; + + // + // and decrement the reference count on the OpenBlock stating this + // instance of an async test is no longer running, and the adapter + // may be closed if requested. + // + + + if (OpenP->Send->SendIrp != NULL) + { + TpRemoveReference( OpenP ); + IoMarkIrpPending( OpenP->Send->SendIrp ); + + IoAcquireCancelSpinLock( &OpenP->Send->SendIrp->CancelIrql ); + IoSetCancelRoutine( OpenP->Send->SendIrp,NULL ); + IoReleaseCancelSpinLock( OpenP->Send->SendIrp->CancelIrql ); + + IoCompleteRequest( OpenP->Send->SendIrp,IO_NETWORK_INCREMENT ); + + OpenP->Send->SendIrp = NULL; + } +} + + + +VOID +TpFuncSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// -------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PPROTOCOL_RESERVED ProtRes; + PTP_REQUEST_HANDLE SendReqHndl; + PNDIS_BUFFER Buffer; + ULONG NextEvent; + + TP_ASSERT( Packet != NULL ); + + // + // Zero out the private section reserved for the MAC out of the NDIS packet + // + RtlZeroMemory( (PVOID)Packet->MacReserved, sizeof( Packet->MacReserved ) ); + + ProtRes = PROT_RES( Packet ); + SendReqHndl = ProtRes->RequestHandle; + + TP_ASSERT( Packet == SendReqHndl->u.SEND_REQ.Packet ); + + // + // Where did this packet originate from ? + // + + if (( SendReqHndl->Signature == SEND_REQUEST_HANDLE_SIGNATURE ) && + ( SendReqHndl->u.SEND_REQ.SendPacket == TRUE )) + { + // + // If the packet was sent by the SEND command, then decrement the + // counter tracking the number of outstanding functional packets, + // and if the send succeeded increment the completion counter. + // + + if ( SendReqHndl->RequestPended ) + { + --OpenP->Send->PacketsPending; + + ++OpenP->Send->Counters->SendComps; + + if ( Status != NDIS_STATUS_SUCCESS ) + { + // + // If we are running on TokenRing the following to "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + // SanjeevK : Even FDDI returns the same errors as 802.5 + // + // STARTCHANGE + // + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++OpenP->Send->Counters->SendFails; + } + } + else + { + ++OpenP->Send->Counters->SendFails; + TpPrint1("Send failed: status = %s", TpGetStatus(Status)); + } + } + } + + // + // also check that the PROTOCOL_RESERVED section of the packet + // header was not touched. + // + + if ( !TpCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ), + &ProtRes->CheckSum )) + { + ++OpenP->Send->Counters->SendFails; + TP_ASSERT( FALSE ); + } + + // + // then break the packet down and release its memory. + // + + TpFuncFreePacket( SendReqHndl->u.SEND_REQ.Packet,SendReqHndl->u.SEND_REQ.PacketSize ); + + NdisFreeMemory( SendReqHndl,0,0 ); + + } + else if (( SendReqHndl->Signature == SEND_REQUEST_HANDLE_SIGNATURE ) && + ( SendReqHndl->u.SEND_REQ.SendPacket == FALSE )) + { + // + // This packet was sent by an invocation of the RECEIVE command from + // TpFuncReceive when a RESEND packet was received. + // + + if ( SendReqHndl->RequestPended ) + { + --OpenP->Receive->PacketsPending; + + ++OpenP->Receive->Counters->SendComps; + + if ( Status != NDIS_STATUS_SUCCESS ) + { + // + // If we are running on TokenRing the following to "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + // SanjeevK : Even FDDI returns the same errors as 802.5 + // + // STARTCHANGE + // + + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++OpenP->Send->Counters->SendFails; + } + } + else + { + ++OpenP->Send->Counters->SendFails; + } + } + } + + // + // also check that the PROTOCOL_RESERVED section of the packet + // header was not touched. + // + + if ( !TpCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ), + &ProtRes->CheckSum )) + { + ++OpenP->Send->Counters->SendFails; + TP_ASSERT( FALSE ); + } + + // + // then break the packet down and release its memory. + // + + NdisUnchainBufferAtFront( Packet,&Buffer ); + NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 ); + TpFreeBuffer( Buffer ); + NdisFreePacket( Packet ); + NdisFreeMemory( SendReqHndl,0,0 ); + + } + else if ( SendReqHndl->Signature == GO_REQUEST_HANDLE_SIGNATURE ) + { + // + // check that the PROTOCOL_RESERVED section of the packet + // header was not touched. + // + + // This is just a go packet, check that the PROTOCOL_RESERVED + // section of the packet header was not touched, then break + // the packet down and release its memory. + // + + if ( !TpCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ), + &ProtRes->CheckSum )) + { + TP_ASSERT( FALSE ); + } + + NdisUnchainBufferAtFront( Packet,&Buffer ); + NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 ); + TpFreeBuffer( Buffer ); + NdisFreePacket( Packet ); + NdisFreeMemory( SendReqHndl,0,0 ); + + } + else + { + // + // An unexpected call to the send completion routine has been made. + // Since we are not expecting it, stick the information on the + // Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteSend; + OpenP->EventQueue->Head = NextEvent; + } + else + { + // + // The event queue is full, and this would overflow it. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } + +} + + + +NDIS_STATUS +TpFuncInitializeReceive( + IN POPEN_BLOCK OpenP + ) + +// --------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// ------- + +{ + LARGE_INTEGER DueTime; + + NdisZeroMemory( (PVOID)OpenP->Receive->Counters, + sizeof( INSTANCE_COUNTERS ) ); + + // + // Initialize the RECEIVE control flags, and reset the packet + // sending control counters. + // + + OpenP->Receive->Receiving = TRUE; + OpenP->Receive->StopReceiving = FALSE; + OpenP->Receive->PacketsPending = 0; + OpenP->Receive->ReceiveEndDpcCount = 0; + + // + // The zero out the receive counters. + // + + NdisZeroMemory( (PVOID)OpenP->Receive->Counters, + sizeof( INSTANCE_COUNTERS ) ); + + // + // Initialize the DPCs used to call ReceiveDpc and ReceiveEndDpc. + // + + KeInitializeDpc(&OpenP->Receive->ReceiveDpc, + TpFuncReceiveDpc, + (PVOID)OpenP ); + + KeInitializeDpc(&OpenP->Receive->ReceiveEndDpc, + TpFuncReceiveEndDpc, + (PVOID)OpenP ); + + // + // And finally set the timer for the ReceiveDpc to queue the + // routine later. + // + + DueTime.HighPart = 0xFFFFFFFF; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&OpenP->Receive->ReceiveTimer, + DueTime, + &OpenP->Receive->ReceiveDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncReceiveDpc set Receive timer while timer existed.\n"); + } + } + + // + // Increment the reference count on the OpenBlock stating that + // an async test is running and must be ended prior to closing + // the adapter on this open. + // + + TpAddReference( OpenP ); + + return NDIS_STATUS_PENDING; +} + + + +NDIS_STATUS +TpFuncReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ) + +// ------------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PPACKET_INFO PacketInfo; + PTP_REQUEST_HANDLE RequestHandle; + PGO_PACKET_INFO GoPacketInfo; + PUCHAR Memory; + PUCHAR SrcAddr; + PNDIS_PACKET Packet; + PNDIS_BUFFER Buffer; + PPROTOCOL_RESERVED ProtRes; + UINT BytesTransferred; + UINT HeaderVariance = sizeof(MEDIA_HEADER)-HeaderBufferSize; + ULONG DataSize; + ULONG NextEvent; + ULONG i; + + // + // The LookAhead Buffer has been adjusted to point to the beggining of the + // PACKET_INFO structure + // + PacketInfo = (PPACKET_INFO)LookaheadBuffer; + + // + // Are we expecting to receive a packet at this time, and is this + // packet large enough to be a functional send packet, and is the + // signature in the packet header correct? + // + + if ((( OpenP->Receive->Receiving == TRUE ) && + ( PacketSize >= sizeof( PACKET_INFO ))) && + (( PacketInfo->Signature == FUNC1_PACKET_SIGNATURE ) || + ( PacketInfo->Signature == FUNC2_PACKET_SIGNATURE ))) + { + if ( OpenP->Receive->StopReceiving == TRUE ) + { + // + // The receive test is shutting down, so just count the packet. + // + + ++OpenP->Receive->Counters->Receives; + + if ( !TpCheckSum( (PUCHAR)PacketInfo, + sizeof( PACKET_INFO ) - sizeof( ULONG ), + (PULONG)&PacketInfo->CheckSum )) + { + ++OpenP->Receive->Counters->CorruptRecs; + } + } + else + { + // + // We are in the normal receiving mode, and have a good + // packet, so we will handle it as requested. + // + + ++OpenP->Receive->Counters->Receives; + + if ( !TpCheckSum( (PUCHAR)PacketInfo, + sizeof( PACKET_INFO ) - sizeof( ULONG ), + (PULONG)&PacketInfo->CheckSum )) + { + ++OpenP->Receive->Counters->CorruptRecs; + return NDIS_STATUS_NOT_RECOGNIZED; + } + + // + // Is there any thing in the packet other than the header?? + // + + // + // STARTCHANGE + // Please note that this packet size is NOT the PacketSize which + // we receive in the TestProtocolReceive but is + // + // PacketSize we get with IndicateReceive + the size of the header + // = TRUE PACKET SIZE + // + DataSize = ((PPACKET_INFO)LookaheadBuffer)->PacketSize - + ( sizeof( PACKET_INFO ) + sizeof( MEDIA_HEADER ) ); + // + // STOPCHANGE + // + + if ( DataSize > 0 ) + { + SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset; + OpenP->Receive->ResendType = + ( RtlCompareMemory(SrcAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen) == OpenP->Media->AddressLen); + + // + // Allocate the request handle and set it up as if the request + // pended. If it does not pend we will reset the flags later before + // calling the completion routine. + // + + Status = NdisAllocateMemory((PVOID *)&RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncReceive: unable to allocated request handle.\n"); + } + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (OpenP->Receive->ReceiveIrp != NULL ) + { + OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE )); + } + + RequestHandle->Signature = FUNC_REQUEST_HANDLE_SIGNATURE; + RequestHandle->Open = OpenP; + RequestHandle->RequestPended = TRUE; + RequestHandle->u.TRANS_REQ.DataSize = DataSize; + + // + // Now allocate the memory to copy the packet data into. + // + + Status = NdisAllocateMemory((PVOID *)&Memory, + DataSize, + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncReceive: unable to allocate resend buffer memory.\n"); + } + NdisFreeMemory( RequestHandle,0,0 ); + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (OpenP->Receive->ReceiveIrp != NULL ) + { + OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( Memory,DataSize ); + } + + // + // Then allocate the buffer that will reference the memory, + // + + Buffer = IoAllocateMdl( Memory, + DataSize, + TRUE, + FALSE, + NULL ); + + if ( Buffer == NULL ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncReceive: unable to allocate resend mdl buffer\n"); + } + NdisFreeMemory( Memory,0,0 ); + NdisFreeMemory( RequestHandle,0,0 ); + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (OpenP->Receive->ReceiveIrp != NULL ) + { + OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_RESOURCES; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return NDIS_STATUS_RESOURCES; + } + + MmBuildMdlForNonPagedPool( (PMDL)Buffer ); + + // + // and finally the NDIS_PACKET to pass to the NdisTransferData call. + // + + NdisAllocatePacket( &Status, + &Packet, + OpenP->Receive->PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncReceive: unable to allocate resend packet\n"); + } + IoFreeMdl( Buffer ); + NdisFreeMemory( Memory,0,0 ); + NdisFreeMemory( RequestHandle,0,0 ); + + NdisAcquireSpinLock( &OpenP->SpinLock ); + if (OpenP->Receive->ReceiveIrp != NULL ) + { + OpenP->Receive->ReceiveIrp->IoStatus.Status = Status; + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + return Status; + } + else + { + // + // Setup the protocol reserved portion of the packet so the + // completion routines know what and where to deallocate. + // + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.PacketHandle = OpenP->Receive->PacketHandle; + ProtRes->InstanceCounters = OpenP->Receive->Counters; + ProtRes->RequestHandle = RequestHandle; + + ProtRes->CheckSum = + TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) ); + + // + // reference the packet in the request handle. + // + + RequestHandle->u.TRANS_REQ.Packet = Packet; + } + + // + // Now chain the buffer to the packet. + // + + NdisChainBufferAtFront( Packet,Buffer ); + + // + // And transfer the data into the newly created packet. + // + + ++OpenP->Receive->Counters->XferData; + + // + // STARTCHANGE + // + NdisTransferData( &Status, + OpenP->NdisBindingHandle, + MacReceiveContext, + (sizeof(PACKET_INFO)+HeaderVariance), + DataSize, + Packet, + &BytesTransferred ); + // + // STOPCHANGE + // + + if ( Status == NDIS_STATUS_PENDING ) + { + // + // The deallocation of resources and any resending will + // be handled by the completion routine, so just count + // the transfer pending and split. + // + ++OpenP->Receive->Counters->XferDataPends; + } + else + { + // + // If the request did not pend, we should reset the + // pend flag, and the status flag in the RequestHandle, + // and then call the completion handler ourselves. + // + + RequestHandle->RequestPended = FALSE; + + TpFuncTransferDataComplete( OpenP, + Packet, + Status, + BytesTransferred ); + } + } + else + { + TpPrint2("Full packetsize = %d, true packetsize = %d\n", + ((PPACKET_INFO)LookaheadBuffer)->PacketSize, DataSize); + TpBreakPoint(); + } + } + } + else if (( PacketSize >= sizeof( GO_PACKET_INFO )) && + ( PacketInfo->Signature == GO_PACKET_SIGNATURE )) + { + GoPacketInfo = (PGO_PACKET_INFO)LookaheadBuffer; + SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset; + + if ( !TpCheckSum( (PUCHAR)GoPacketInfo, + sizeof( GO_PACKET_INFO ) - sizeof( ULONG ), + (PULONG)&GoPacketInfo->CheckSum )) + { + Status = NDIS_STATUS_NOT_RECOGNIZED; + } + else + { + NdisAcquireSpinLock( &OpenP->Pause->SpinLock ); + + if ((( OpenP->Pause->GoReceived == TRUE ) || + + // + // We have not finished processing the last GO packet, + // and a new one has arrived. We can't accept it until + // the last GO has been handled. We will ignore this + // packet. + // + + ((( GoPacketInfo->PacketType == TP_GO ) && + ( GoPacketInfo->TestSignature == OpenP->Pause->TestSignature )) && + ( GoPacketInfo->UniqueSignature == OpenP->Pause->UniqueSignature ))) || + + // + // Or we have finished handling the last GO packet, and + // received another one for the same PAUSE before the + // GO sender received and handled the GO_ACK packet. + // We will ignore this packet also. + // + + ( RtlCompareMemory( SrcAddr, + OpenP->StationAddress, + OpenP->Media->AddressLen) == OpenP->Media->AddressLen )) + { + + // + // Or this packet was sent by us, not another protocol + // on another machine, must have the packet filter set + // to promiscuous mode, ignore this packet also. + // + + NdisReleaseSpinLock( &OpenP->Pause->SpinLock ); + } + else + { + OpenP->Pause->GoReceived = TRUE; + + switch ( OpenP->Media->MediumType ) + { + case NdisMediumArcnet878_2: + case NdisMediumFddi : + case NdisMediumDix : + case NdisMedium802_3 : + case NdisMedium802_5 : + for ( i=0 ; i < OpenP->Media->AddressLen; i++ ) + { + OpenP->Pause->RemoteAddress[i] = (CHAR)&SrcAddr[i]; + } + break; + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncReceive: Unsupported MAC Media Type\n"); + } + } + + OpenP->Pause->TestSignature = GoPacketInfo->TestSignature; + OpenP->Pause->UniqueSignature = GoPacketInfo->UniqueSignature; + OpenP->Pause->PacketType = GoPacketInfo->PacketType; + + NdisReleaseSpinLock( &OpenP->Pause->SpinLock ); + } + } + } + else + { +// TEMP -- Find out WHY we got here... + +// this one is valid--can get it during abort of performance test +// if ( OpenP->Receive->Receiving != TRUE ) +// { +// TpPrint0("Rcv--receiving == FALSE\n"); +// } + + if ( PacketSize >= sizeof( PACKET_INFO )) + { + TpPrint1("Rcv--Psize >= PACKET_INFO, signature = %x\n", PacketInfo->Signature); + } + else if ( PacketSize >= sizeof( GO_PACKET_INFO )) + { + TpPrint1("Rcv--Psize >= GO_PACKET_INFO, signature = %x\n", PacketInfo->Signature); + } + else + { + TpPrint0("Rcv--Psize < GO_PACKET_INFO\n"); + } +// TpBreakPoint(); + +// + // + // We are not expecting to receive packets, or this packet is not + // large enough to be a functional packet, or we are not expecting + // to receive this packet. so stick it on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateReceive; + OpenP->EventQueue->Head = NextEvent; + + // + // XXX: At this point we could stick the first X bytes (header) + // into the Events[head].EventInfo using xferdata. + // + + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + ++OpenP->EventQueue->ReceiveIndicationCount; + OpenP->EventQueue->ExpectReceiveComplete = TRUE; + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + + Status = NDIS_STATUS_NOT_RECOGNIZED; + + } + + return Status; +} + + + +VOID +TpFuncReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) + +// ------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ----- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + + if ( OpenP->Receive->Receiving == TRUE ) + { + ++OpenP->Receive->Counters->ReceiveComps; + } + else + { + // + // We are not expecting this completion, so stick the + // info on the event queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + //**************************************************************** + // + // NOTE: Due to the fact that a MAC will complete all receive + // indications to EVERY transport that has it opened this + // completion is not entirely unexpected, and therefore will + // not be added to the Event Queue. + // + //**************************************************************** + +#if 0 + // + // We have received an unexpected Status Indication, so + // we are expecting (???) to receive the completion. + // + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateReceiveComplete; + OpenP->EventQueue->Head = NextEvent; + + // XXX: Was it expected ??? + } + else + { + // + // The event queue is full, and this would overflow it. + // + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } +#endif + + // + // Reset the status indication counter to zero, and set the + // status completion expected flag to show that no completion + // routine is expected. + // + + OpenP->EventQueue->ReceiveIndicationCount = 0; + OpenP->EventQueue->ExpectReceiveComplete = FALSE; + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } +} + + + +VOID +TpFuncTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ) + +// ---------- +// +// Routine Description: +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +// --------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + PNDIS_BUFFER Buffer; + PPROTOCOL_RESERVED ProtRes; + PTP_REQUEST_HANDLE XferReqHndl; + PTP_REQUEST_HANDLE SendReqHndl; + PTP_PACKET TpPacket; + PUCHAR BufMem; +// NDIS_STATUS SendStatus; + ULONG NextEvent; + ULONG i; + LARGE_INTEGER DueTime; + + + TP_ASSERT( Packet != NULL ); + + ProtRes = PROT_RES( Packet ); + XferReqHndl = ProtRes->RequestHandle; + + TP_ASSERT( Status == NDIS_STATUS_SUCCESS ); + TP_ASSERT( Packet == XferReqHndl->u.TRANS_REQ.Packet ); + + // + // Are we expecting to complete a Transfer Data at this time? + // First determine if we are running a RECEIVE test. If so, + // determine whether this is a legitimate completion, or a + // bug. + // + + TP_ASSERT( OpenP != NULL ); + + if (( OpenP->Receive->StopReceiving == FALSE ) && + (( XferReqHndl->Signature == FUNC_REQUEST_HANDLE_SIGNATURE ) && + ( XferReqHndl->Open == (POPEN_BLOCK)ProtocolBindingContext ))) + { + // + // If so then verfiy the PROTOCOL RESERVED section of the + // packet was not touched. + // + + if ( !TpCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ), + &ProtRes->CheckSum )) + { + ++OpenP->Receive->Counters->XferDataFails; + return; + } + + // + // and then grab the pointer to the newly transferred packet, + // and the data stored in it. + // + + NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL ); + + TpPacket = (PTP_PACKET)MmGetMdlVirtualAddress( Buffer ); + + TP_ASSERT( BytesTransferred == XferReqHndl->u.TRANS_REQ.DataSize ); + + // + // We are expecting it, so if the request truly pended, then + // count the completion now. + // + + if ( XferReqHndl->RequestPended == TRUE ) + { + ++OpenP->Receive->Counters->XferDataComps; + } + + // + // We have a Func Packet, is it a resend packet or not? + // + + if (( TpPacket->u.F1.info.Signature == FUNC2_PACKET_SIGNATURE ) && + ( TpPacket->u.F1.info.PacketType == (UCHAR)FUNC2_PACKET_TYPE )) + { + if ( Status == NDIS_STATUS_SUCCESS ) + { + // + // It is a resend packet, we need to resend it. first check + // the header and the data in the pacekt. + // + + if ( !TpCheckSum( (PUCHAR)&TpPacket->u.F1.info, + sizeof( PACKET_INFO ) - sizeof( ULONG ), + (PULONG)&TpPacket->u.F1.info.CheckSum )) + { + ++OpenP->Receive->Counters->CorruptRecs; + } + + // XXX: function for this + BufMem = (PUCHAR)((PUCHAR)TpPacket + (UCHAR)sizeof( FUNC1_PACKET )); + + for ( i = 0 ; i < ( BytesTransferred - sizeof( FUNC1_PACKET )) ; i++ ) + { + if ( BufMem[i] != (UCHAR)( i % 256 )) + { + IF_TPDBG( TP_DEBUG_DATA ) + { + TpPrint1( + "TpFuncTransferDataComplete: Data Corruption in packet 0x%lX at\n", + Packet); + TpPrint3( + " offset %d into data. Expected 0x%X, found 0x%X.\n\n", + i,(i % 256),BufMem[i]); + } + ++OpenP->Receive->Counters->CorruptRecs; + + IF_TPDBG( TP_DEBUG_BREAKPOINT ) + { + TpBreakPoint(); + } + break; + } + } + + // + // Then copy the local adapter address into the source + // address in the packet header. + // + + // + // STARTCHANGE + // + if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) // Tokenring + { + for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ ) + { + TpPacket->u.F1.media.tr.SrcAddress[i] = OpenP->StationAddress[i]; + } + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) // Fddi + { + for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ ) + { + TpPacket->u.F1.media.fddi.SrcAddress[i] = OpenP->StationAddress[i]; + } + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_3 ) // Ethernet + { + for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ ) + { + TpPacket->u.F1.media.e.SrcAddress[i] = OpenP->StationAddress[i]; + } + } + else if ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2 ) // Arcnet + { + for ( i = 0 ; i < OpenP->Media->AddressLen ; i++ ) + { + TpPacket->u.F1.media.a.SrcAddress[i] = OpenP->StationAddress[i]; + } + } + // + // STOPCHANGE + // + + // + // if the NdisTransferData call completed successfully, + // then we can resend the packet now. Allocate the + // request handle and set it up as if the request + // pended. If it does not pend we will reset the + // flags later before calling the completion routine. + // + + Status = NdisAllocateMemory((PVOID *)&SendReqHndl, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0( + "TpFuncTransferDataComplete: unable to allocated request handle\n"); + } + return; + } + else + { + NdisZeroMemory( SendReqHndl,sizeof( TP_REQUEST_HANDLE )); + } + + SendReqHndl->Signature = SEND_REQUEST_HANDLE_SIGNATURE; + SendReqHndl->Open = OpenP; + SendReqHndl->RequestPended = TRUE; + SendReqHndl->u.SEND_REQ.Packet = Packet; + + // + // STARTCHANGE + // + SendReqHndl->u.SEND_REQ.PacketSize = BytesTransferred + sizeof( MEDIA_HEADER ); + // + // STOPCHANGE + // + + SendReqHndl->u.SEND_REQ.SendPacket = FALSE; + + // + // Now reset the packet to a FUNC1 packet type, and + // calculate the new checksum. + // + + TpPacket->u.F1.info.PacketType = FUNC1_PACKET_TYPE; + TpPacket->u.F1.info.Signature = FUNC1_PACKET_SIGNATURE; + + TpPacket->u.F1.info.CheckSum = + TpSetCheckSum( (PUCHAR)&TpPacket->u.F1.info, + sizeof( PACKET_INFO ) - sizeof( ULONG ) ); + + // + // Reference the new request handle off the reserved area. + // + + ProtRes->RequestHandle = SendReqHndl; + // + // Set the check sum in the PROTOCOL RESERVED Section of the + // packet header to ensure it is not touched while the packet + // is in the hands of the MAC. + // + + ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - + sizeof( ULONG ) ); + + if (OpenP->Receive->ResendReq == NULL) + { + OpenP->Receive->ResendReq = SendReqHndl; + + DueTime.HighPart = -1; // So it will be relative. + if (OpenP->Receive->ResendType) + { + DueTime.LowPart = (ULONG)(-2 * (ONE_HUNDREDTH_SECOND)); + } + else + { + DueTime.LowPart = (ULONG)(-(ONE_HUNDREDTH_SECOND)); + } + + if ( KeSetTimer(&OpenP->Receive->ResendTimer, + DueTime, + &OpenP->Receive->ResendDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncTransferDataComplete set SendTimer while timer existed.\n"); + } + } + } + else + { + TpFuncResend(OpenP, SendReqHndl); + } + } + else // ( Status == Some Type Failure ) + { + // + // The transfer data call failed, increment the counter, + // and deallocate the resources. + // + + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncTransferDataComplete: NdisTransferData failed: returned %s\n", + TpGetStatus(Status)); + } + ++OpenP->Receive->Counters->XferDataFails; + + // + // Now free up the transfer packet resources. + // + + NdisUnchainBufferAtFront( Packet,&Buffer ); + NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 ); + TpFreeBuffer( Buffer ); + NdisFreePacket( Packet ); + } + } + else + { + // + // This is just a packet we should receive, count, and drop. + // + + BufMem = (PUCHAR)TpPacket; + + for ( i = 0 ; i < BytesTransferred ; i++ ) + { + if ( BufMem[i] != (UCHAR)( i % 256 )) + { + IF_TPDBG( TP_DEBUG_DATA ) + { + TpPrint1("TpFuncTransferDataComplete: Data Corruption in packet 0x%lX at\n", + Packet); + TpPrint3( + " offset %d into data. Expected 0x%X found 0x%X.\n", + i,(i % 256),BufMem[i]); + } + ++OpenP->Receive->Counters->CorruptRecs; + + IF_TPDBG( TP_DEBUG_BREAKPOINT ) + { + TpBreakPoint(); + } + break; + } + } + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncReceive: NdisTransferData failed: returned %s\n", + TpGetStatus(Status)); + } + ++OpenP->Receive->Counters->XferDataFails; + } + + // + // Now free up the transfer packet resources. + // + + NdisUnchainBufferAtFront( Packet,&Buffer ); + NdisFreeMemory( MmGetMdlVirtualAddress( Buffer ),0,0 ); + TpFreeBuffer( Buffer ); + NdisFreePacket( Packet ); + } + + // + // And finally free up the Request Handle that was allocated + // in the Receive routine for the call to NdisTransferData. + // + + NdisFreeMemory( XferReqHndl,0,0 ); + } + else + { + // + // We are not expecting a transfer data to complete at this + // point, so stick this on the Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = CompleteTransferData; + OpenP->EventQueue->Head = NextEvent; + } + else + { + // + // The event queue is full, and this would have overflowed it, so + // mark the Head event overflow flag to show this. + // + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + // + // We have a resource, the packet, should we free it? to where? + // who really owns it? + // + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + } + return; +} + +VOID +TpFuncResend(POPEN_BLOCK OpenP, + PTP_REQUEST_HANDLE SendReqHndl) +{ + NDIS_STATUS Status; + PNDIS_PACKET Packet = SendReqHndl->u.SEND_REQ.Packet; + + // + // Increment the send pending packet counter, + // + + ++OpenP->Receive->PacketsPending; + + // + // and the number of packets sent, + // + + ++OpenP->Receive->Counters->Sends; + + // + // and send it... + // + + NdisSend( &Status, + OpenP->NdisBindingHandle, + Packet ); + + if ( Status != NDIS_STATUS_PENDING ) + { + --OpenP->Receive->PacketsPending; + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_NDIS_CALLS ) + { + TpPrint1("TpFuncResendDpc: NdisSend failed: returned %s\n", TpGetStatus(Status)); + } + // + // If we are running on TokenRing the following to "failures" + // are not considered failures NDIS_STATUS_NOT_RECOGNIZED - + // no one on the ring recognized the address as theirs, or + // NDIS_STATUS_NOT_COPIED - no one on the ring copied the + // packet, so we need to special case this and not count + // these as failures. + // + if ( ( NdisMediumArray[OpenP->MediumIndex] == NdisMedium802_5 ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumFddi ) || + ( NdisMediumArray[OpenP->MediumIndex] == NdisMediumArcnet878_2) ) + { + if (( Status != NDIS_STATUS_NOT_RECOGNIZED ) && + ( Status != NDIS_STATUS_NOT_COPIED )) + { + ++OpenP->Send->Counters->SendFails; + } + } + else + { + ++OpenP->Send->Counters->SendFails; + } + } + SendReqHndl->RequestPended = FALSE; + TpFuncSendComplete( OpenP,Packet,Status ); + } + else + { + ++OpenP->Receive->Counters->SendPends; + } + +} + + +VOID +TpFuncResendDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + PTP_REQUEST_HANDLE SendReqHndl = OpenP->Receive->ResendReq; + + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + TpFuncResend(OpenP, SendReqHndl); + + OpenP->Receive->ResendReq = NULL; +} + + + +VOID +TpFuncReceiveDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + LARGE_INTEGER DueTime; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + // + // If the Irp has been cancelled or the Stop Receive + // flag has been set then end the test. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ((( OpenP->Receive->ReceiveIrp == NULL ) || + ( OpenP->Receive->ReceiveIrp->Cancel == TRUE )) || + (( OpenP->Receive->Receiving == TRUE ) && + ( OpenP->Receive->StopReceiving == TRUE ))) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // The receive test should now stop, so queue the Receive + // End dpc routine. + // + + if ( KeSetTimer(&OpenP->Receive->ReceiveTimer, + DueTime, + &OpenP->Receive->ReceiveEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncReceiveDpc set StressEnd timer while timer existed.\n"); + } + } + } + else + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Otherwise the test should continue, so insert the next instance + // of the Receive Dpc in the timer queue and exit. This will queue + // the next instance of the TpFuncReceiveDpc routine when the + // timer goes off. + // + + if ( KeSetTimer(&OpenP->Receive->ReceiveTimer, + DueTime, + &OpenP->Receive->ReceiveDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncReceiveDpc set Receive timer while timer existed.\n"); + } + } + } +} + + + +VOID +TpFuncReceiveEndDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ) + +// ---------- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// +// -------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext); + LARGE_INTEGER DueTime; + + UNREFERENCED_PARAMETER( Dpc ); + UNREFERENCED_PARAMETER( SysArg1 ); + UNREFERENCED_PARAMETER( SysArg2 ); + + // + // See if we have any outstanding packets left to complete. If we do, + // then we will reset the time to queue this dpc routine again in one + // second, if after ten requeues the packet(s) has still no completed + // we assume it will never complete and return the results and finish. + // + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if (((( OpenP->Receive->ReceiveIrp != NULL ) && + ( OpenP->Receive->ReceiveIrp->Cancel == FALSE )) && + ( OpenP->Receive->PacketsPending != 0 )) && + ( OpenP->Receive->ReceiveEndDpcCount++ < 10 )) + { + NdisReleaseSpinLock( &OpenP->SpinLock ); + + DueTime.HighPart = -1; // So it will be relative. + DueTime.LowPart = (ULONG)(-(ONE_SECOND)); + + if ( KeSetTimer(&OpenP->Receive->ReceiveTimer, + DueTime, + &OpenP->Receive->ReceiveEndDpc )) + { + IF_TPDBG ( TP_DEBUG_DPC ) + { + TpPrint0("TpFuncReceiveEndDpc set ReceiveTimer while timer existed.\n"); + } + } + return; + } + + // + // If the status has not been reset, then set it to success now. + // + + if ( OpenP->Receive->ReceiveIrp->IoStatus.Status == NDIS_STATUS_PENDING ) + { + OpenP->Receive->ReceiveIrp->IoStatus.Status = NDIS_STATUS_SUCCESS; + } + + // + // Now write the RECEIVE results to the output buffer. + // + + TpWriteSendReceiveResults( OpenP->Receive->Counters, + OpenP->Receive->ReceiveIrp ); + + NdisReleaseSpinLock( &OpenP->SpinLock ); + + // + // Now set the receiving flag to indicate that we are no longer + // RECEIVEing packets. + // + + OpenP->Receive->Receiving = FALSE; + + // + // and decrement the reference count on the OpenBlock stating this + // instance of an async test is no longer running, and the adapter + // may be closed if requested. + // + + TpRemoveReference( OpenP ); + + IoMarkIrpPending( OpenP->Receive->ReceiveIrp ); + + IoAcquireCancelSpinLock( &OpenP->Receive->ReceiveIrp->CancelIrql ); + IoSetCancelRoutine( OpenP->Receive->ReceiveIrp,NULL ); + IoReleaseCancelSpinLock( OpenP->Receive->ReceiveIrp->CancelIrql ); + + IoCompleteRequest( OpenP->Receive->ReceiveIrp,IO_NETWORK_INCREMENT ); + + OpenP->Receive->ReceiveIrp = NULL; + + return; +} + + + +NDIS_STATUS +TpFuncGetEvent( + IN POPEN_BLOCK OpenP + ) + +// ---- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// Status - +// +// ----- + +{ + PEVENT_RESULTS OutputBuffer; + ULONG NextEvent; + + OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress ); + + OutputBuffer->Signature = EVENT_RESULTS_SIGNATURE; + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + if ( OpenP->EventQueue->Head == OpenP->EventQueue->Tail ) + { + // + // There is nothing in the Event Queue. + // + + OpenP->Irp->IoStatus.Status = TP_STATUS_NO_EVENTS; + } + else + { + if (( NextEvent = ++OpenP->EventQueue->Tail ) == MAX_EVENT ) + { + NextEvent = OpenP->EventQueue->Tail = 0; + } + + OutputBuffer->TpEventType = OpenP->EventQueue->Events[NextEvent].TpEventType; + OutputBuffer->QueueOverFlowed = OpenP->EventQueue->Events[NextEvent].Overflow; + + OpenP->EventQueue->Events[NextEvent].TpEventType = Unknown; + OpenP->EventQueue->Events[NextEvent].EventInfo = NULL; + OpenP->EventQueue->Events[NextEvent].Overflow = FALSE; + + OpenP->Irp->IoStatus.Status = STATUS_SUCCESS; + } + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); + + return OpenP->Irp->IoStatus.Status; +} + + + +VOID +TpFuncStatus( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ) +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + ULONG NextEvent; + + // + // We have receive a Status indication, stick it on the + // Event Queue. + // + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateStatus; + OpenP->EventQueue->Head = NextEvent; + + // + // At this point we could stick the General Status + // into the EventInfo buffer. + // + + } + else + { + // + // The event queue is full, and this would overflow it. + // + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + // + // Increment the Status Indication counter and set the status + // completion flag to true to show that a completion is expected. + // + + ++OpenP->EventQueue->StatusIndicationCount; + + OpenP->EventQueue->ExpectStatusComplete = TRUE; + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); +} + + + +VOID +TpFuncStatusComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) + +// ---------- +// +// Routine Description: +// +// Print out the help message to the debugger screen. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +// --------- + +{ + POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext); + ULONG NextEvent; + + NdisAcquireSpinLock( &OpenP->EventQueue->SpinLock ); + + // + // We have received an unexpected Status Completion, so + // we are expecting (???) to receive the completion. + // + + NextEvent = OpenP->EventQueue->Head + 1; + + if ( NextEvent == MAX_EVENT ) + { + NextEvent = 0; + } + + if ( NextEvent != OpenP->EventQueue->Tail ) + { + // + // There is room to add another event to the event queue. + // + + OpenP->EventQueue->Events[NextEvent].TpEventType = IndicateStatusComplete; + OpenP->EventQueue->Head = NextEvent; + } + else + { + // + // The event queue is full, and this would overflow it. + // + + OpenP->EventQueue->Events[OpenP->EventQueue->Head].Overflow = TRUE; + } + + // + // Reset the status indication counter to zero, and set the + // status completion expected flag to show that no completion + // routine is expected. + // + + OpenP->EventQueue->StatusIndicationCount = 0; + OpenP->EventQueue->ExpectStatusComplete = FALSE; + + NdisReleaseSpinLock( &OpenP->EventQueue->SpinLock ); +} + + + +NDIS_STATUS +TpFuncSendGo( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN UCHAR PacketType + ) + +// ----- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---- + +{ + NDIS_STATUS Status; + PTP_REQUEST_HANDLE RequestHandle; + PGO_PACKET GoPacket; + PUCHAR p, q; + USHORT DataSizeShort; + PNDIS_BUFFER Buffer; + PNDIS_PACKET Packet; + PPROTOCOL_RESERVED ProtRes; + PREQUEST_RESULTS OutputBuffer; + ULONG i; + + OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress ); + + // + // Allocate the request handle, and init the relevant fields + // + + Status = NdisAllocateMemory((PVOID *)&RequestHandle, + sizeof( TP_REQUEST_HANDLE ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncSendGo: unable to allocated request handle.\n"); + } + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( RequestHandle,sizeof( TP_REQUEST_HANDLE )); + } + + RequestHandle->Signature = GO_REQUEST_HANDLE_SIGNATURE; + RequestHandle->Open = OpenP; + + // + // Now allocate the GoPacket to copy the packet data into. + // + + Status = NdisAllocateMemory((PVOID *)&GoPacket, + sizeof( GO_PACKET ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncSendGo: unable to allocate buffer memory.\n"); + } + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( (PUCHAR)GoPacket,sizeof( GO_PACKET )); + } + + switch ( OpenP->Media->MediumType ) + { + case NdisMedium802_5: + GoPacket->go_media.tr.AC = 0x10; + GoPacket->go_media.tr.FC = 0x40; + + p = (PUCHAR)&GoPacket->go_media.tr.DestAddress[0]; + q = (PUCHAR)&GoPacket->go_media.tr.SrcAddress[0]; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i]; + *q++ = OpenP->StationAddress[i]; + } + break; + + case NdisMediumDix: + case NdisMedium802_3: + + p = (PUCHAR)&GoPacket->go_media.e.DestAddress[0]; + q = (PUCHAR)&GoPacket->go_media.e.SrcAddress[0]; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i]; + *q++ = OpenP->StationAddress[i]; + } + + DataSizeShort = (USHORT)( sizeof( GO_PACKET ) - OpenP->Media->HeaderSize ); + + GoPacket->go_media.e.PacketSize_Hi = (UCHAR)(DataSizeShort >> 8 ); + GoPacket->go_media.e.PacketSize_Lo = (UCHAR)DataSizeShort; + break; + + case NdisMediumFddi: + GoPacket->go_media.fddi.FC = 0x57; + + p = (PUCHAR)&GoPacket->go_media.fddi.DestAddress[0]; + q = (PUCHAR)&GoPacket->go_media.fddi.SrcAddress[0]; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i]; + *q++ = OpenP->StationAddress[i]; + } + break; + + // + // STARTCHANGE + // + case NdisMediumArcnet878_2: + GoPacket->go_media.a.ProtocolID = ARCNET_DEFAULT_PROTOCOLID; + + p = (PUCHAR)&GoPacket->go_media.a.DestAddress[0]; + q = (PUCHAR)&GoPacket->go_media.a.SrcAddress[0]; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = CmdArgs->ARGS.PAUSE_GO.RemoteAddress[i]; + *q++ = OpenP->StationAddress[i]; + } + break; + // + // STOPCHANGE + // + + default: + IF_TPDBG ( TP_DEBUG_RESOURCES ) + { + TpPrint0("TpFuncSendGo: Unsupported MAC Type\n"); + } + + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + return NDIS_STATUS_RESOURCES; + } + + GoPacket->info.Signature = GO_PACKET_SIGNATURE; + GoPacket->info.TestSignature = CmdArgs->ARGS.PAUSE_GO.TestSignature; + GoPacket->info.UniqueSignature = OpenP->Pause->UniqueSignature; + GoPacket->info.PacketType = PacketType; + + GoPacket->info.CheckSum = TpSetCheckSum((PUCHAR)&GoPacket->info, + sizeof( GO_PACKET_INFO ) - sizeof( ULONG ) ); + + // + // Then allocate the buffer that will reference the memory, + // + + Buffer = IoAllocateMdl( (PVOID)GoPacket,sizeof( GO_PACKET ),TRUE,FALSE,NULL ); + + if ( Buffer == NULL ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncSendGo: unable to allocate mdl buffer\n"); + } + NdisFreeMemory( (PVOID)GoPacket,0,0 ); + OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES; + return NDIS_STATUS_RESOURCES; + } + MmBuildMdlForNonPagedPool( (PMDL)Buffer ); + + // + // and finally the NDIS_PACKET to pass to the NdisTransferData call. + // + + NdisAllocatePacket( &Status, + &Packet, + OpenP->Pause->PacketHandle ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG(TP_DEBUG_RESOURCES) + { + TpPrint0("TpFuncReceive: unable to allocate resend packet\n"); + } + IoFreeMdl( Buffer ); + NdisFreeMemory( (PVOID)GoPacket,0,0 ); + OpenP->Irp->IoStatus.Status = Status; + return Status; + } + else + { + // + // Setup the protocol reserved portion of the packet so the + // completion routines know what and where to deallocate. + // + + ProtRes = PROT_RES( Packet ); + ProtRes->Pool.PacketHandle = OpenP->Pause->PacketHandle; + ProtRes->InstanceCounters = NULL; + ProtRes->RequestHandle = RequestHandle; + RequestHandle->u.SEND_REQ.Packet = Packet; + } + + // + // Now chain the buffer to the packet. + // + + NdisChainBufferAtFront( Packet,Buffer ); + + // + // Set the check sum in the PROTOCOL RESERVED Section of the + // packet header to ensure it is not touched while the packet + // is in the hands of the MAC. + // + + ProtRes->CheckSum = TpSetCheckSum( (PUCHAR)ProtRes, + sizeof( PROTOCOL_RESERVED ) - sizeof( ULONG ) ); + // + // And send it. + // + + NdisSend( &Status,OpenP->NdisBindingHandle,Packet ); + + if ( Status != NDIS_STATUS_PENDING ) + { + TpFuncSendComplete( OpenP,Packet,Status ); + } + else + { + // NOTE: should we somehow handle sends failing , or will be catch + // that on the next iteration??? - this could cause us problems + // on the go response packet. + Status = NDIS_STATUS_SUCCESS; + } + + OutputBuffer->RequestStatus = Status; + OpenP->Irp->IoStatus.Status = Status; + return Status; +} + + + +NDIS_STATUS +TpFuncPause( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN UCHAR PacketType + ) + +// ---- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// ---- + +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + LARGE_INTEGER TimeOut; + PREQUEST_RESULTS OutputBuffer; + + OpenP->Pause->TimeOut = 0; + + OutputBuffer = MmGetSystemAddressForMdl( OpenP->Irp->MdlAddress ); + OutputBuffer->RequestStatus = TP_STATUS_TIMEDOUT; + + TimeOut.HighPart = -1; // so it will be relative. + TimeOut.LowPart = (ULONG)(-(ONE_SECOND)); + + do + { + NdisAcquireSpinLock( &OpenP->Pause->SpinLock ); + + if ( OpenP->Pause->GoReceived == FALSE ) + { + NdisReleaseSpinLock( &OpenP->Pause->SpinLock ); + + // + // If the Go packet has not arrived stall for a moment + // waiting for it to arrive. + // + + Status = KeDelayExecutionThread( KernelMode,FALSE,&TimeOut ); + if ( Status != STATUS_SUCCESS ) + { + break; + } + else + { + ++OpenP->Pause->TimeOut; + } + } + else + { + // + // Otherwise we have received a go packet, see if it + // is the one we are waiting for. + // + + if (( CmdArgs->ARGS.PAUSE_GO.TestSignature == OpenP->Pause->TestSignature ) && + ( OpenP->Pause->PacketType == PacketType )) + { + // + // It is, get out of here. + // + OpenP->Pause->GoReceived = FALSE; + + NdisReleaseSpinLock( &OpenP->Pause->SpinLock ); + + OutputBuffer->RequestStatus = NDIS_STATUS_SUCCESS; + break; + } + else + { + // + // We received a GO packet with the wrong test signature. + // + + OpenP->Pause->GoReceived = FALSE; + NdisReleaseSpinLock( &OpenP->Pause->SpinLock ); + } + } + + } while (( OpenP->Pause->TimeOut < 10 ) && ( OpenP->IrpCancelled == FALSE )); + + OpenP->Irp->IoStatus.Status = Status; + return Status; +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/tpprocs.h b/private/ntos/ndis/testprot/tpdrvr/tpprocs.h new file mode 100644 index 000000000..72cdd6290 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tpprocs.h @@ -0,0 +1,841 @@ +// ------------------------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpprocs.h +// +// Abstract: +// +// Function prototypes for test and stress sections of the Test Protocol. +// +// Author: +// +// Tom Adams (tomad) 16-Jul-1990 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Tom Adams (tomad) 27-Nov-1990 +// Divided the procedures and defintions into two seperate include files. +// Added definitions for TpRunTest and support routines. +// +// Tom Adams (tomad) 30-Dec-1990 +// Added defintions for TpStress and support routines. +// +// Tim Wynsma (timothyw) 4-27-94 +// Added performance tests +// +// Tim Wynsma (timothyw) 6-08-94 +// Chgd performance tests to client/server model +// +// --------------------------------------- + +// +// driver initialization and open/close routines +// + +NTSTATUS +TpCreateDeviceContext( + IN PDRIVER_OBJECT DriverObject, + IN STRING DeviceName, + PDEVICE_CONTEXT *DeviceContext + ); + +NTSTATUS +TpCreateSymbolicLinkObject( + VOID + ); + +NTSTATUS +TpInitializeEventQueue( + IN PDEVICE_CONTEXT DeviceContext + ); + +NTSTATUS +TpRegisterProtocol( + IN PDEVICE_CONTEXT DeviceContext, + IN STRING *NameString + ); + +NTSTATUS +TpDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +TpOpenDriver( + IN PDEVICE_CONTEXT DeviceObject + ); + +NTSTATUS +TpCleanUpDriver( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp + ); + +VOID +TpCloseDriver( + IN PDEVICE_CONTEXT DeviceObject + ); + +VOID +TpUnloadDriver( + IN PDRIVER_OBJECT DriverObject + ); + +BOOLEAN +TpAddReference( + IN POPEN_BLOCK OpenP + ); + +VOID +TpRemoveReference( + IN POPEN_BLOCK OpenP + ); + +NTSTATUS +TpAllocateOpenArray( + POPEN_BLOCK OpenP + ); + +VOID +TpDeallocateOpenArray( + POPEN_BLOCK OpenP + ); + +VOID +TpCancelIrp( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp + ); + + +// +// +// + +PUCHAR +TpGetStatus( + IN NDIS_STATUS GeneralStatus + ); + +// +// functions exported to the MAC for phases 0 and 1 of the Test Protocol +// + +VOID +TestProtocolOpenComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ); + +VOID +TestProtocolCloseComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +VOID +TestProtocolSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ); + +VOID +TestProtocolTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ); + +VOID +TestProtocolResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +VOID +TestProtocolRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ); + +NDIS_STATUS +TestProtocolReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ); + +VOID +TestProtocolReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ); + +VOID +TestProtocolStatus( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ); + +VOID +TestProtocolStatusComplete( + IN NDIS_HANDLE ProtocolBindingContext + ); + +// +// Stress Function Prototypes +// + +NDIS_STATUS +TpStressStart( + IN POPEN_BLOCK OpenP, + IN PSTRESS_ARGUMENTS StressArguments + ); + +VOID +TpStressCleanUp( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressFreeResources( + IN POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpStressReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ); + +VOID +TpStressReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ); + +// +// Test Protocol Ndis Stress Routines +// + +NDIS_STATUS +TpStressReset( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +NDIS_STATUS +TpStressAddMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN BOOLEAN SetZeroTableSize + ); + +NDIS_STATUS +TpStressAddLongMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN BOOLEAN SetZeroTableSize + ); + +NDIS_STATUS +TpStressSetFunctionalAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR FunctionalAddress, + IN BOOLEAN SetZeroTableSize + ); + +NDIS_STATUS +TpStressSetPacketFilter( + IN POPEN_BLOCK OpenP, + IN UINT PacketFilter + ); + +VOID +TpStressRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ); + +NDIS_STATUS +TpStressClientSend( + IN POPEN_BLOCK OpenP, + IN OUT NDIS_HANDLE PacketHandle, + IN OUT PTP_TRANSMIT_POOL TpTransmitPool, + IN PUCHAR DestAddr, + IN UCHAR SrcInstance, + IN UCHAR DestInstance, + IN UCHAR PacketProtocol, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN INT PacketSize, + IN INT BufferSize + ); + +VOID +TpStressServerSend( + IN POPEN_BLOCK OpenP, + IN OUT PTP_TRANSMIT_POOL TpTransmitPool, + IN PUCHAR DestAddr, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN INT PacketSize, + IN ULONG DataBufferOffset + ); + +VOID +TpStressSend( + IN POPEN_BLOCK OpenP, + IN PNDIS_PACKET Packet, + IN PINSTANCE_COUNTERS Counters + ); + +VOID +TpStressSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ); + +VOID +TpStressCheckPacketData( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE MacReceiveContext, + IN ULONG DataOffset, + IN UINT PacketSize, + IN PINSTANCE_COUNTERS Counters + ); + +VOID +TpStressTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ); + +VOID +TpStressDoNothing( + VOID + ); + +// +// Function prototypes for packet.c +// + +PNDIS_PACKET +TpStressCreatePacket( + IN POPEN_BLOCK OpenP, + IN OUT NDIS_HANDLE PacketHandle, + IN OUT PACKET_MAKEUP PacketMakeUp, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType, + IN PUCHAR DestAddr, + IN INT PacketSize, + IN INT BufferSize, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN BOOLEAN DataChecking + ); + +PNDIS_PACKET +TpStressCreateTruncatedPacket( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE PacketHandle, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType + ); + +ULONG +TpGetPacketSignature( + IN PNDIS_PACKET Packet + ); + +VOID +TpStressFreePacket( + IN PNDIS_PACKET Packet + ); + +PTP_TRANSMIT_POOL +TpStressCreateTransmitPool( + IN POPEN_BLOCK OpenP, + IN NDIS_HANDLE PacketHandle, + IN PACKET_MAKEUP PacketMakeUp, + IN UCHAR PacketProtocol, + IN UCHAR ResponseType, + IN INT PacketSize, + IN INT NumPackets, + IN BOOLEAN ServerPool + ); + +VOID +TpStressFreeTransmitPool( + IN OUT PTP_TRANSMIT_POOL TpTransmitPool + ); + +PNDIS_PACKET +TpStressAllocatePoolPacket( + IN PTP_TRANSMIT_POOL TpTransmitPool, + IN PINSTANCE_COUNTERS Counters + ); + +VOID +TpStressSetPoolPacketInfo( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PUCHAR DestAddr, + IN UCHAR ClientInstance, + IN UCHAR ServerInstance, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference + ); + +VOID +TpStressSetTruncatedPacketInfo( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PUCHAR DestAddr, + IN INT PacketSize, + IN UCHAR DestInstance, + IN UCHAR SrcInstance, + IN ULONG SequenceNumber, + IN ULONG MaxSequenceNumber, + IN UCHAR ClientReference, + IN UCHAR ServerReference, + IN ULONG DataBufferOffset + ); + +VOID +TpStressFreePoolPacket( + IN OUT PNDIS_PACKET Packet + ); + +PTP_PACKET +TpFuncInitPacketHeader( + IN POPEN_BLOCK OpenP, + IN INT PacketSize + ); + +BOOLEAN +TpCheckSum( + IN PUCHAR Buffer, + IN ULONG BufLen, + IN PULONG CheckSum + ); + +ULONG +TpSetCheckSum( + IN PUCHAR Buffer, + IN ULONG BufLen + ); + +PNDIS_PACKET +TpFuncAllocateSendPacket( + POPEN_BLOCK OpenP + ); + +VOID +TpFuncFreePacket( + PNDIS_PACKET Packet, + ULONG PacketSize + ); + +// +// Functions prototypes to replace buffer management routines +// + +PNDIS_BUFFER +TpAllocateBuffer( + IN PUCHAR TmpBuf, + IN INT BufSize + ); + +VOID +TpFreeBuffer( + IN OUT PNDIS_BUFFER Buf + ); + +VOID +TpStressInitDataBuffer( + IN OUT POPEN_BLOCK OpenP, + IN INT BufferSize + ); + +// +// Sanjeevk : Renamed function +// + +VOID +TpStressFreeDataBuffers( + IN OUT POPEN_BLOCK OpenP + ); + +// +// Sanjeevk : Added new function +// +VOID +TpStressFreeDataBufferMdls( + IN OUT POPEN_BLOCK OpenP + ); + +// +// Utility Function Prototypes for utils.c +// + +NDIS_STATUS +TpInitStressArguments( + PSTRESS_ARGUMENTS *StressArguments, + PCMD_ARGS CmdArgs + ); + +NDIS_STATUS +TpInitServerArguments( + PSTRESS_ARGUMENTS *StressArguments + ); + +VOID +TpPrintClientStatistics( + IN POPEN_BLOCK OpenP + ); + +VOID +TpStressWriteResults( + IN POPEN_BLOCK OpenP + ); + +VOID +TpCopyClientStatistics( + IN POPEN_BLOCK OpenP + ); + +VOID +TpWriteServerStatistics( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PCLIENT_INFO Client + ); + +VOID +TpCopyServerStatistics( + IN POPEN_BLOCK OpenP, + IN PVOID Buffer, + IN INT ServerReference + ); + +VOID +TpPrintServerStatistics( + IN POPEN_BLOCK OpenP, + IN PCLIENT_INFO Client + ); + +VOID +TpWriteSendReceiveResults( + PINSTANCE_COUNTERS Counters, + PIRP Irp + ); + +VOID +TpInitializePending( + PPENDING Pend + ); + +VOID +TpInitializeStressResults( + PSTRESS_RESULTS Results + ); + +// +// Function prototypes for Test Protocol utility routines +// + +VOID +TpSetRandom( + VOID + ); + +UINT +TpGetRandom( + UINT Low, + UINT High + ); + + +NTSTATUS +TpIssueRequest( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ); + +NDIS_STATUS +TpFuncSend( + IN POPEN_BLOCK OpenP + ); + +VOID +TpFuncSendDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpFuncSendEndDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpFuncInitializeSendArguments( + POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs + ); + +NDIS_STATUS +TpPerfClient( + POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs + ); + +NDIS_STATUS +TpPerfServer( + POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpPerfAbort( + POPEN_BLOCK OpenP + ); + +VOID +TpPerfSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ); + +NDIS_STATUS +TpPerfReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ); + +NDIS_STATUS +TpFuncGetEvent( + IN POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpFuncRequestQueryInfo( + POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs, + PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ); + +NDIS_STATUS +TpFuncRequestSetInfo( + POPEN_BLOCK OpenP, + PCMD_ARGS CmdArgs, + PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ); + +NDIS_STATUS +TpFuncOpenAdapter( + IN POPEN_BLOCK OpenP, + IN UCHAR OpenInstance, + IN PCMD_ARGS CmdArgs + ); + +NDIS_STATUS +TpFuncCloseAdapter( + IN POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpFuncReset( + IN POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpFuncAddMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN PTP_REQUEST_HANDLE *RequestHandle + ); + +NDIS_STATUS +TpFuncDeleteMulticastAddress( + IN POPEN_BLOCK OpenP, + IN PUCHAR MulticastAddress, + IN PTP_REQUEST_HANDLE *RequestHandle + ); + +VOID +TpFuncOpenComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ); + +VOID +TpFuncCloseComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +VOID +TpFuncSendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status + ); + +VOID +TpFuncTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ); + +VOID +TpFuncResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +VOID +TpFuncRequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ); + +NDIS_STATUS +TpFuncInitializeReceive( + IN POPEN_BLOCK OpenP + ); + +NDIS_STATUS +TpFuncReceive( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ); + +VOID +TpFuncReceiveComplete( + IN NDIS_HANDLE ProtocolBindingContext + ); + +VOID +TpFuncReceiveDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpFuncReceiveEndDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpFuncResendDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SysArg1, + IN PVOID SysArg2 + ); + +VOID +TpFuncTransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ); + +VOID +TpFuncStatus( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ); + +VOID +TpFuncStatusComplete( + IN NDIS_HANDLE ProtocolBindingContext + ); + +NDIS_STATUS +TpFuncSendGo( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN UCHAR PacketType + ); + +NDIS_STATUS +TpFuncPause( + IN POPEN_BLOCK OpenP, + IN PCMD_ARGS CmdArgs, + IN UCHAR PacketType + ); + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/tpreq.c b/private/ntos/ndis/testprot/tpdrvr/tpreq.c new file mode 100644 index 000000000..25bbe79b0 --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tpreq.c @@ -0,0 +1,952 @@ +// -------------------- +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tpreq.c +// +// Abstract: +// +// This module contains code which defines the Test Protocol +// device object. +// +// Author: +// +// Tom Adams (tomad) 19-Apr-1991 +// +// Environment: +// +// Kernel mode, FSD +// +// Revision History: +// +// Tim Wynsma (timothyw) 4-27-94 +// Added performance tests +// Tim Wynsma (timothyw) 6-08-94 +// chgd perf tests to client/server model +// +// ------------------ + +#include <ndis.h> + +#include "tpdefs.h" +#include "tpprocs.h" +#include "media.h" + + +NTSTATUS +TpIssueRequest( + IN PDEVICE_CONTEXT DeviceContext, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) + +// --- +// +// Routine Description: +// +// +// Arguments: +// +// +// Return Value: +// +// ---- + +{ + NTSTATUS Status; + PVOID InputBuffer; + ULONG InputBufferLength; + PMDL OutputMdl; + ULONG OutputMdlLength; + UCHAR OpenInstance; + POPEN_BLOCK OpenP; + PCMD_ARGS CmdArgs; + PSTRESS_ARGUMENTS StressArguments; + ULONG i; + ULONG CmdCode; + + // + // Get the Input and Output buffers for the Incoming commands, + // and the buffer to return the results in. + // + + InputBuffer = Irp->AssociatedIrp.SystemBuffer; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + OutputMdl = Irp->MdlAddress; + + OutputMdlLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + // + // Then find out which Open Instance we will be using. + // + + OpenInstance = (UCHAR)(((PCMD_ARGS)InputBuffer)->OpenInstance - 1); + + OpenP = (POPEN_BLOCK)&(DeviceContext->Open[OpenInstance]); + + // + // Set the IoStatus.Information field to the value of the OpenInstance + // so that a Cancelled Irp may find the Open that it is required to + // cancel the irp for. + // + + Irp->IoStatus.Information = (ULONG)OpenP; + + // + // and reference the Irp, for the general case Irp Cancel. + // + + OpenP->Irp = Irp; + OpenP->IrpCancelled = FALSE; + + // + // Then set up the cancel routine for the Irp. + // + + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + + if ( Irp->Cancel ) + { + Irp->IoStatus.Status = STATUS_CANCELLED; + return STATUS_CANCELLED; + } + + IoSetCancelRoutine( Irp,(PDRIVER_CANCEL)TpCancelIrp ); + + IoReleaseCancelSpinLock( Irp->CancelIrql ); + + // + // Now switch to the specific command to call. + // + + CmdArgs = ((PCMD_ARGS)InputBuffer); + CmdCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; + + switch ( CmdCode ) + { + case IOCTL_TP_SETENV: + { + PUCHAR p, q; + + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETENV.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tWindowSize = %lu\n",CmdArgs->ARGS.ENV.WindowSize); + TpPrint1("\tRandomBufferNumber = %lu\n", CmdArgs->ARGS.ENV.RandomBufferNumber); + TpPrint1("\tStressDelayInterval = %lu\n", CmdArgs->ARGS.ENV.StressDelayInterval); + TpPrint1("\tUpForAirDelay = %lu\n", CmdArgs->ARGS.ENV.UpForAirDelay); + TpPrint1("\tStandardDelay = %lu\n", CmdArgs->ARGS.ENV.StandardDelay); + + // + // STARTCHANGE + // + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tStress Address = %02x\n", CmdArgs->ARGS.ENV.StressAddress[0]); + } + else + { + TpPrint6("\tStress Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.ENV.StressAddress[0], + CmdArgs->ARGS.ENV.StressAddress[1], + CmdArgs->ARGS.ENV.StressAddress[2], + CmdArgs->ARGS.ENV.StressAddress[3], + CmdArgs->ARGS.ENV.StressAddress[4], + CmdArgs->ARGS.ENV.StressAddress[5]); + } + // + // STOPCHANGE + // + } + + OpenP->Environment->WindowSize = CmdArgs->ARGS.ENV.WindowSize; + + if ( CmdArgs->ARGS.ENV.RandomBufferNumber > OpenP->Media->MaxPacketLen ) + { + OpenP->Environment->RandomBufferNumber = OpenP->Media->MaxPacketLen; + + TpPrint2("RandomBufferNumber \"%d\"to large, using %d instead\n", + CmdArgs->ARGS.ENV.RandomBufferNumber, + OpenP->Media->MaxPacketLen); + } + else + { + OpenP->Environment->RandomBufferNumber = CmdArgs->ARGS.ENV.RandomBufferNumber; + } + + OpenP->Environment->StressDelayInterval = CmdArgs->ARGS.ENV.StressDelayInterval; + OpenP->Environment->UpForAirDelay = CmdArgs->ARGS.ENV.UpForAirDelay; + OpenP->Environment->StandardDelay = CmdArgs->ARGS.ENV.StandardDelay; + + p = OpenP->Environment->StressAddress; + q = (PUCHAR)(CmdArgs->ARGS.ENV.StressAddress); + + // + // STARTCHANGE + // + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = *q++ ; + } + // + // STOPCHANGE + // + + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + + case IOCTL_TP_GO: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_GO.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + // + // STARTCHANGE + // + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tRemote Address = %02x\n", CmdArgs->ARGS.PAUSE_GO.RemoteAddress[0]); + } + else + { + TpPrint6("\tRemote Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[0], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[1], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[2], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[3], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[4], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[5]); + } + // + // STOPCHANGE + // + TpPrint1("\tTest Signature = %lu\n", CmdArgs->ARGS.PAUSE_GO.TestSignature); + TpPrint1("\tUnique Signature = %lu\n",CmdArgs->ARGS.PAUSE_GO.UniqueSignature); + } + OpenP->Pause->UniqueSignature = CmdArgs->ARGS.PAUSE_GO.UniqueSignature; + + Status = TpFuncSendGo( OpenP,CmdArgs,TP_GO ); + + if ( Status == NDIS_STATUS_SUCCESS ) + { + Status = TpFuncPause( OpenP,CmdArgs,TP_GO_ACK ); + } + break; + + case IOCTL_TP_PAUSE: + { + PREQUEST_RESULTS ResBuf; + + ResBuf = MmGetSystemAddressForMdl( Irp->MdlAddress ); + + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_PAUSE.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + // + // STARTCHANGE + // + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tRemote Address = %02x\n", CmdArgs->ARGS.PAUSE_GO.RemoteAddress[0]); + } + else + { + TpPrint6("\tRemote Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[0], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[1], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[2], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[3], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[4], + CmdArgs->ARGS.PAUSE_GO.RemoteAddress[5]); + } + TpPrint1("\tTest Signature = %lu\n", CmdArgs->ARGS.PAUSE_GO.TestSignature); + } + + Status = TpFuncPause( OpenP,CmdArgs,TP_GO ); + + if (( Status == NDIS_STATUS_SUCCESS ) && + ( ResBuf->RequestStatus == NDIS_STATUS_SUCCESS )) + { + Status = TpFuncSendGo( OpenP,CmdArgs,TP_GO_ACK ); + } + break; + } + + case IOCTL_TP_OPEN: // NdisOpenAdapter + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_OPEN.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tAdapter_Name = %s\n",CmdArgs->ARGS.OPEN_ADAPTER.AdapterName); + TpPrint1("\tNoArcNetFlag = %lu\n",CmdArgs->ARGS.OPEN_ADAPTER.NoArcNet); + } + Status = TpFuncOpenAdapter( OpenP,OpenInstance,CmdArgs ); + break; + + case IOCTL_TP_CLOSE: // NdisCloseAdapter + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_CLOSE.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + Status = TpFuncCloseAdapter( OpenP ); + break; + + case IOCTL_TP_SETPF: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETPF.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tPacketFilter = %lu\n", CmdArgs->ARGS.TPSET.U.PacketFilter); + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_SETLA: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETLA.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tLookaheadSize = %lu\n", CmdArgs->ARGS.TPSET.U.LookaheadSize); + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_ADDMA: + case IOCTL_TP_DELMA: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_ADDMA.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tNumber MulticastAddresses = %d\n", + CmdArgs->ARGS.TPSET.NumberMultAddrs); + + TpPrint0("\tMulticast Address List = \n"); + + for ( i=0;i<CmdArgs->ARGS.TPSET.NumberMultAddrs;i++ ) + { + TpPrint6("\t\t%02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][0], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][1], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][2], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][3], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][4], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][5]); + } + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_SETFA: // NdisSetInformation + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETFA.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint4("\tFunctional Address = %02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.FunctionalAddress[0], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[1], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[2], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[3]); + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_SETGA: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETFA.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint4("\tGlobal Address = %02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.FunctionalAddress[0], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[1], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[2], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[3]); + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_QUERYINFO: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_QUERYINFO.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tInformation OID = 0x%08lX\n", CmdArgs->ARGS.TPQUERY.OID); + } + Status = TpFuncRequestQueryInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_SETINFO: // NdisSetInformation + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SETINFO.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tInformation OID = 0x%08lX\n",CmdArgs->ARGS.TPSET.OID); + + switch ( CmdArgs->ARGS.TPSET.OID ) + { + case OID_GEN_CURRENT_PACKET_FILTER: + TpPrint1("\tPacketFilter = %lu\n", CmdArgs->ARGS.TPSET.U.PacketFilter); + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + TpPrint1("\tLookAheadSize = %lu\n", CmdArgs->ARGS.TPSET.U.LookaheadSize); + break; + + case OID_802_3_MULTICAST_LIST: + TpPrint0("\tMulticast Address List = \n"); + + for ( i=0;i<CmdArgs->ARGS.TPSET.NumberMultAddrs;i++ ) + { + TpPrint6("\t\t%02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][0], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][1], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][2], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][3], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][4], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][5]); + } + break; + + case OID_FDDI_LONG_MULTICAST_LIST: + TpPrint0("\tLong Multicast Address List = \n"); + + for ( i=0;i<CmdArgs->ARGS.TPSET.NumberMultAddrs;i++ ) + { + TpPrint6("\t\t%02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][0], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][1], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][2], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][3], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][4], + CmdArgs->ARGS.TPSET.U.MulticastAddress[i][5]); + } + break; + + case OID_802_5_CURRENT_FUNCTIONAL: + case OID_802_5_CURRENT_GROUP: + TpPrint4("\tAddress to Set = %02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSET.U.FunctionalAddress[0], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[1], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[2], + CmdArgs->ARGS.TPSET.U.FunctionalAddress[3]); + break; + + default: + TpPrint0("\tInvalid Oid\n"); + break; + } + } + Status = TpFuncRequestSetInfo( OpenP,CmdArgs,Irp,IrpSp ); + break; + + case IOCTL_TP_RESET: // NdisReset + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_RESET.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + Status = TpFuncReset( OpenP ); + break; + + case IOCTL_TP_SEND: // NdisSend + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_SEND.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tDestination Address = %02x\n", CmdArgs->ARGS.TPSEND.DestAddress[0]); + } + else + { + TpPrint6("\tDestination Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSEND.DestAddress[0], + CmdArgs->ARGS.TPSEND.DestAddress[1], + CmdArgs->ARGS.TPSEND.DestAddress[2], + CmdArgs->ARGS.TPSEND.DestAddress[3], + CmdArgs->ARGS.TPSEND.DestAddress[4], + CmdArgs->ARGS.TPSEND.DestAddress[5]); + } + TpPrint1("\tPacket Size = %lu\n",CmdArgs->ARGS.TPSEND.PacketSize); + TpPrint1("\tNumber of Packets = %lu\n", CmdArgs->ARGS.TPSEND.NumberOfPackets); + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tResend Address = %02x\n", CmdArgs->ARGS.TPSEND.ResendAddress[0]); + } + else + { + TpPrint6("\tResend Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPSEND.ResendAddress[0], + CmdArgs->ARGS.TPSEND.ResendAddress[1], + CmdArgs->ARGS.TPSEND.ResendAddress[2], + CmdArgs->ARGS.TPSEND.ResendAddress[3], + CmdArgs->ARGS.TPSEND.ResendAddress[4], + CmdArgs->ARGS.TPSEND.ResendAddress[5]); + } + } + + OpenP->Send->SendIrp = Irp; + OpenP->Irp = NULL; + + TpFuncInitializeSendArguments( OpenP,CmdArgs ); + + Status = TpFuncSend( OpenP ); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to start TpFuncNdisSend; returned %s\n", + TpGetStatus(Status)); + } + } + break; + + case IOCTL_TP_STOPSEND: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_STOPSEND.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + + // + // We want to stop the TpFuncSendDpc from executing, so we set the + // StopSending flag to true. This will cause the TpFuncSendDpc to + // call the TpFuncSendEndDpc to clean up and + // + + OpenP->Send->StopSending = TRUE; + + // + // And then wait for it to finish. + // + + while ( OpenP->Send->Sending == TRUE ) + { + /* NULL */ ; + } + + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("STOPSEND finished waiting for TpFuncSendDpc to end.\n"); + } + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IOCTL_TP_RECEIVE: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_RECEIVE.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + + OpenP->Receive->ReceiveIrp = Irp; + + OpenP->Irp = NULL; + + Status = TpFuncInitializeReceive( OpenP ); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1( + "TpIssueRequest: failed to initilaize Receive structures: returned %s\n", + TpGetStatus(Status)); + } + } + break; + + case IOCTL_TP_STOPREC: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_STOPREC.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + + // + // We want the functional receive routines to stop expecting + // packets, so we set the StopReceiving flag to TRUE. + // + + OpenP->Receive->StopReceiving = TRUE; + + // + // And then wait for it to finish. + // + + while ( OpenP->Receive->Receiving == TRUE ) + { + /* NULL */ ; + } + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IOCTL_TP_GETEVENTS: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_GETEVENTS.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + Status = TpFuncGetEvent( OpenP ); + break; + + case IOCTL_TP_STRESS: + IF_TPDBG (TP_DEBUG_DISPATCH ) + { + TpPrint0("IoControlCode is IOCTL_TP_STRESS.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + TpPrint1("\tMember Type = %lu\n", CmdArgs->ARGS.TPSTRESS.MemberType); + TpPrint1("\tPacket Type = %lu\n", CmdArgs->ARGS.TPSTRESS.PacketType); + TpPrint1("\tPacket Size = %lu\n", CmdArgs->ARGS.TPSTRESS.PacketSize); + TpPrint1("\tPacket MakeUp = %lu\n", CmdArgs->ARGS.TPSTRESS.PacketMakeUp); + TpPrint1("\tResponse Type = %lu\n", CmdArgs->ARGS.TPSTRESS.ResponseType); + TpPrint1("\tInterpacket Delay Type = %lu\n", CmdArgs->ARGS.TPSTRESS.DelayType); + TpPrint1("\tInterpacket Delay Length = %lu\n", CmdArgs->ARGS.TPSTRESS.DelayLength); + TpPrint1("\tTotal Iterations = %lu\n", CmdArgs->ARGS.TPSTRESS.TotalIterations); + TpPrint1("\tTotal Packets = %lu\n", CmdArgs->ARGS.TPSTRESS.TotalPackets); + TpPrint1("\tWindowing Enabled = %lu\n", CmdArgs->ARGS.TPSTRESS.WindowEnabled); + TpPrint1("\tData Checking = %lu\n", CmdArgs->ARGS.TPSTRESS.DataChecking); + TpPrint1("\tPackets From Pool = %lu\n", CmdArgs->ARGS.TPSTRESS.PacketsFromPool); + } + + Status = TpInitStressArguments( &StressArguments,CmdArgs ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to initialize stress arguments; return %s\n", + TpGetStatus(Status)); + } + + Irp->IoStatus.Status = Status; + + // + // BUGBUG: Bugfix #5492 NTRAID, NTBUG + // + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + IoSetCancelRoutine( Irp,NULL ); + IoReleaseCancelSpinLock( Irp->CancelIrql ); + IoCompleteRequest( Irp,IO_NETWORK_INCREMENT ); + } + else + { + OpenP->Stress->StressIrp = Irp; + OpenP->Irp = NULL; + + Status = TpStressStart( OpenP,StressArguments ); + + if (( Status != NDIS_STATUS_SUCCESS ) && + ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to start TpStress; returned %s\n", + TpGetStatus(Status)); + } + OpenP->Stress->StressStarted = FALSE; + TpStressCleanUp( OpenP ); + } + } + break; + + case IOCTL_TP_STRESSSERVER: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_STRESSSERVER.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + Status = TpInitServerArguments( &StressArguments ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to initialize stress arguments; return %s\n", + TpGetStatus(Status)); + } + Irp->IoStatus.Status = Status; + + // + // BUGBUG: Bugfix #5492 NTRAID, NTBUG + // + IoAcquireCancelSpinLock( &Irp->CancelIrql ); + IoSetCancelRoutine( Irp,NULL ); + IoReleaseCancelSpinLock( Irp->CancelIrql ); + IoCompleteRequest( Irp,IO_NETWORK_INCREMENT ); + } + else + { + OpenP->Stress->StressIrp = Irp; + OpenP->Irp = NULL; + + Status = TpStressStart( OpenP,StressArguments ); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to start TpStressServer; returned %s\n", + TpGetStatus(Status)); + } + OpenP->Stress->StressStarted = FALSE; + TpStressCleanUp( OpenP ); + } + } + break; + + case IOCTL_TP_ENDSTRESS: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_ENDSTRESS.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + + // + // We want to stop any active client and/or server on this open + // instance from running the stress routines, so set the + // StopStressing flag. + // + + OpenP->Stress->StopStressing = TRUE; + + // + // And wait for them to finish. + // + + while ( OpenP->Stress->Stressing == TRUE ) + { + /* NULL */ ; + } + + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("ENDSTRESS finished waiting for TpStress to end.\n"); + } + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IOCTL_TP_BREAKPOINT: + // + // This is a DbgBreakPoint and not a TpBreakPoint because we + // want it to remain in the nodebug builds. If this is called + // with out a debugger - tough! + // + DbgBreakPoint(); + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IOCTL_TP_PERF_SERVER: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_PERF_SERVER.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + + Status = TpPerfServer( OpenP ); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1("TpIssueRequest: failed to start TpPerfServer: returned %s\n", + TpGetStatus(Status)); + } + } + break; + + + case IOCTL_TP_PERF_CLIENT: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_PERF_CLIENT.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tServer Address = %02x\n", + CmdArgs->ARGS.TPPERF.PerfServerAddr[0]); + TpPrint1("\tSend Address = %02x\n", + CmdArgs->ARGS.TPPERF.PerfSendAddr[0]); + } + else + { + TpPrint6("\tServer Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPPERF.PerfServerAddr[0], + CmdArgs->ARGS.TPPERF.PerfServerAddr[1], + CmdArgs->ARGS.TPPERF.PerfServerAddr[2], + CmdArgs->ARGS.TPPERF.PerfServerAddr[3], + CmdArgs->ARGS.TPPERF.PerfServerAddr[4], + CmdArgs->ARGS.TPPERF.PerfServerAddr[5]); + TpPrint6("\tSend Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + CmdArgs->ARGS.TPPERF.PerfSendAddr[0], + CmdArgs->ARGS.TPPERF.PerfSendAddr[1], + CmdArgs->ARGS.TPPERF.PerfSendAddr[2], + CmdArgs->ARGS.TPPERF.PerfSendAddr[3], + CmdArgs->ARGS.TPPERF.PerfSendAddr[4], + CmdArgs->ARGS.TPPERF.PerfSendAddr[5]); + } + TpPrint1("\tPacket Size = %lu\n", CmdArgs->ARGS.TPPERF.PerfPacketSize); + TpPrint1("\tNumber of packets = %lu\n", CmdArgs->ARGS.TPPERF.PerfNumPackets); + TpPrint1("\tDelay = %lu\n", CmdArgs->ARGS.TPPERF.PerfDelay); + TpPrint1("\tMode = %lu\n", CmdArgs->ARGS.TPPERF.PerfMode); + } + + Status = TpPerfClient( OpenP, CmdArgs); + + if (( Status != NDIS_STATUS_SUCCESS ) && ( Status != NDIS_STATUS_PENDING )) + { + IF_TPDBG ( TP_DEBUG_DISPATCH ) + { + TpPrint1( + "TpIssueRequest: failed to start TpPerfClient: returned %s\n", + TpGetStatus(Status)); + } + } + break; + + case IOCTL_TP_PERF_ABORT: + IF_TPDBG (TP_DEBUG_DISPATCH) + { + TpPrint0("IoControlCode is IOCTL_TP_PERF_ABORT.\n"); + } + + IF_TPDBG(TP_DEBUG_IOCTL_ARGS) + { + TpPrint1("\tOpenInstance = %lu\n",OpenInstance); + } + Status = TpPerfAbort(OpenP); + break; + + default: + TpPrint0("Invalid Command Entered\n"); + Status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + break; + + } // switch(); + + if ( ( CmdCode != IOCTL_TP_STRESS ) && + ( CmdCode != IOCTL_TP_STRESSSERVER ) && + ( CmdCode != IOCTL_TP_SEND ) && + ( CmdCode != IOCTL_TP_RECEIVE ) && + ( CmdCode != IOCTL_TP_PERF_SERVER ) && + ( CmdCode != IOCTL_TP_PERF_CLIENT ) ) + { + NdisAcquireSpinLock( &OpenP->SpinLock ); + + if ( OpenP->IrpCancelled == TRUE ) + { + return STATUS_CANCELLED; + } + else + { + IoAcquireCancelSpinLock( &OpenP->Irp->CancelIrql ); + IoSetCancelRoutine( OpenP->Irp,NULL ); + IoReleaseCancelSpinLock( OpenP->Irp->CancelIrql ); + } + NdisReleaseSpinLock( &OpenP->SpinLock ); + } + return Status; +} + + + diff --git a/private/ntos/ndis/testprot/tpdrvr/tputils.c b/private/ntos/ndis/testprot/tpdrvr/tputils.c new file mode 100644 index 000000000..b16105ccf --- /dev/null +++ b/private/ntos/ndis/testprot/tpdrvr/tputils.c @@ -0,0 +1,1080 @@ +// ******************************* +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// tputils.c +// +// Abstract: +// +// This module implements the utility functions for the NDIS 3.0 +// Test Protocol Tester. +// +// Author: +// +// Tom Adams (tomad) 14-Jul-1990 +// +// Environment: +// +// Kernel mode +// +// Revision History: +// +// Tom Adams (tomad) 15-Dec-1990 +// seperate from testprot.c and add test control and statistics fcns. +// +// Tom Adams (tomad) 14-March-1991 +// add support for calling TpStress from command line with arguments. +// +// Tim Wynsma (timothyw) 5-18-94 +// Fixed warnings, some general cleanup +// +// **************************** + +#include <ndis.h> +#include <stdlib.h> +#include <string.h> + +#include "tpdefs.h" +#include "media.h" +#include "tpprocs.h" + + +PUCHAR +TpGetStatus( + 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 + }; + + 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 UCHAR BadStatus[] = "UNDEFINED"; + +#define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS)) + + INT i; + + for (i=0; i<StatusCount; i++) + { + if (GeneralStatus == Status[i]) + { + return String[i]; + } + } + return BadStatus; + +#undef StatusCount +} + + + +NDIS_STATUS +TpInitStressArguments( + PSTRESS_ARGUMENTS *StressArguments, + PCMD_ARGS CmdArgs + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// The arguments for the test to be run. +// +// Return Value: +// +// ------ + +{ + NDIS_STATUS Status; + + Status = NdisAllocateMemory((PVOID *)StressArguments, + sizeof( STRESS_ARGUMENTS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpInitStressArguments: unable to allocate Argument buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( *StressArguments,sizeof( STRESS_ARGUMENTS )); + } + + + (*StressArguments)->MemberType = CmdArgs->ARGS.TPSTRESS.MemberType; + (*StressArguments)->PacketType = CmdArgs->ARGS.TPSTRESS.PacketType; + (*StressArguments)->PacketSize = CmdArgs->ARGS.TPSTRESS.PacketSize; + (*StressArguments)->PacketMakeUp = CmdArgs->ARGS.TPSTRESS.PacketMakeUp; + (*StressArguments)->ResponseType = CmdArgs->ARGS.TPSTRESS.ResponseType; + (*StressArguments)->Iterations = 0; + (*StressArguments)->TotalIterations = CmdArgs->ARGS.TPSTRESS.TotalIterations; + (*StressArguments)->TotalPackets = CmdArgs->ARGS.TPSTRESS.TotalPackets; + (*StressArguments)->AllPacketsSent = FALSE; + (*StressArguments)->DelayType = CmdArgs->ARGS.TPSTRESS.DelayType; + (*StressArguments)->DelayLength = CmdArgs->ARGS.TPSTRESS.DelayLength; + (*StressArguments)->WindowEnabled = (UCHAR)CmdArgs->ARGS.TPSTRESS.WindowEnabled; + (*StressArguments)->DataChecking = (UCHAR)CmdArgs->ARGS.TPSTRESS.DataChecking; + (*StressArguments)->PacketsFromPool = (UCHAR)CmdArgs->ARGS.TPSTRESS.PacketsFromPool; + (*StressArguments)->BeginReceives = FALSE; + (*StressArguments)->ServerContinue = TRUE; + + return NDIS_STATUS_SUCCESS; +} + + + +NDIS_STATUS +TpInitServerArguments( + PSTRESS_ARGUMENTS *StressArguments + ) + +// ----------- +// +// Routine Description: +// +// Arguments: +// +// The arguments for the test to be run. +// +// Return Value: +// +// ---------------- + +{ + NDIS_STATUS Status; + + Status = NdisAllocateMemory((PVOID *)StressArguments, + sizeof( STRESS_ARGUMENTS ), + 0, + HighestAddress ); + + if ( Status != NDIS_STATUS_SUCCESS ) + { + IF_TPDBG (TP_DEBUG_RESOURCES) + { + TpPrint0("TpInitServerArguments: unable to allocate Argument buffer.\n"); + } + return NDIS_STATUS_RESOURCES; + } + else + { + NdisZeroMemory( *StressArguments,sizeof( STRESS_ARGUMENTS )); + } + + (*StressArguments)->MemberType = TP_SERVER; + (*StressArguments)->PacketType = 0; + (*StressArguments)->PacketSize = 100; + (*StressArguments)->PacketMakeUp = RAND; + (*StressArguments)->ResponseType = ACK_EVERY; + (*StressArguments)->Iterations = 0; + (*StressArguments)->TotalIterations = 0; + (*StressArguments)->TotalPackets = 0; + (*StressArguments)->AllPacketsSent = FALSE; + (*StressArguments)->DelayType = 0; + (*StressArguments)->DelayLength = FIXEDDELAY; + (*StressArguments)->WindowEnabled = TRUE; + (*StressArguments)->DataChecking = FALSE; + (*StressArguments)->PacketsFromPool = TRUE; + (*StressArguments)->BeginReceives = FALSE; + (*StressArguments)->ServerContinue = TRUE; + + return NDIS_STATUS_SUCCESS; +} + + + +VOID +TpStressWriteResults( + IN POPEN_BLOCK OpenP + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// None. +// +// --------- + +{ + PSTRESS_RESULTS OutputBuffer; + + NdisAcquireSpinLock( &OpenP->SpinLock ); + + OutputBuffer = MmGetSystemAddressForMdl( OpenP->Stress->StressIrp->MdlAddress ); + + RtlMoveMemory( OutputBuffer, + OpenP->Stress->Results, + sizeof( STRESS_RESULTS ) ); + + NdisReleaseSpinLock( &OpenP->SpinLock ); +} + + + +VOID +TpCopyClientStatistics( + IN POPEN_BLOCK OpenP + ) + +// -------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// None. +// +// --------- + +{ + PSTRESS_RESULTS res; + PGLOBAL_COUNTERS gc; + PINSTANCE_COUNTERS ic; + PINSTANCE_COUNTERS lc; + PUCHAR p, q; + USHORT i; + + p = OpenP->Stress->Results->Address; + q = OpenP->StationAddress; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = *q++; + } + + res = OpenP->Stress->Results; + gc = OpenP->GlobalCounters; + + res->OpenInstance = OpenP->OpenInstance; + res->NumServers = OpenP->Stress->Client->NumServers; + + res->Global.Sends = gc->Sends; + res->Global.SendComps = gc->SendComps; + res->Global.Receives = gc->Receives; + res->Global.ReceiveComps = gc->ReceiveComps; + res->Global.CorruptRecs = gc->CorruptRecs; + res->Global.InvalidPacketRecs = gc->InvalidPacketRecs; + + // + // Now calculate the Packets Per Second value. + // + + // first find the total number of test packets sent. + + gc->Sends = 0; + gc->Receives = 0; + + for ( i = 0 ; i < OpenP->Stress->Client->NumServers ; i++ ) + { + ic = OpenP->Stress->Client->Servers[i].Counters; + gc->Sends += ic->Sends; + gc->Receives += ic->Receives; + } + + // find the total test time in Nanoseconds + + OpenP->Stress->EndTime = RtlLargeIntegerSubtract( OpenP->Stress->EndTime, + OpenP->Stress->StartTime ); + // convert it to seconds. + + OpenP->Stress->EndTime = RtlExtendedLargeIntegerDivide( OpenP->Stress->EndTime, + 10000000, + NULL ); + + // then determine the packets per second value. + // NOTE: we are assuming that the high part of time is now 0. + + res->PacketsPerSecond = OpenP->Stress->PacketsPerSecond = + (( gc->Sends + gc->Receives ) / OpenP->Stress->EndTime.LowPart ); + + // + // Now copy the Server stats into the buffer. + // + + for( i=0;i<OpenP->Stress->Client->NumServers;i++ ) + { + ic = OpenP->Stress->Client->Servers[i].Counters; + lc = &res->Servers[i].Instance; + + lc->Sends = ic->Sends; + lc->SendPends = ic->SendPends; + lc->SendComps = ic->SendComps; + lc->SendFails = ic->SendFails; + lc->Receives = ic->Receives; + ic->ReceiveComps = ic->ReceiveComps; + lc->CorruptRecs = ic->CorruptRecs; + } +} + + + +VOID +TpCopyServerStatistics( + IN POPEN_BLOCK OpenP, + IN PVOID Buffer, + IN INT ServerReference + ) + +// ----------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// None. +// +// ------------- + +{ + PSERVER_RESULTS res; + PINSTANCE_COUNTERS ic; + PGLOBAL_COUNTERS gc; + PUCHAR p, q; + USHORT i; + + res = &OpenP->Stress->Results->Servers[ServerReference]; + + ic = (PINSTANCE_COUNTERS)((PUCHAR)Buffer + + (ULONG)sizeof( PACKET_INFO ) + + (ULONG)sizeof( STRESS_CONTROL )); + + gc = (PGLOBAL_COUNTERS)((PUCHAR)Buffer + + (ULONG)( sizeof( PACKET_INFO ) + + sizeof( STRESS_CONTROL ) + + sizeof( INSTANCE_COUNTERS ))); + + res->OpenInstance = OpenP->Stress->Client->Servers[ServerReference].ServerInstance; + + res->StatsRcvd = TRUE; + + // p = res->Address; + p = OpenP->Stress->Results->Servers[ServerReference].Address; + q = OpenP->Stress->Client->Servers[ServerReference].Address; + + for ( i=0;i<OpenP->Media->AddressLen;i++ ) + { + *p++ = *q++; + } + + // + // Now copy the servers instance counters into the results buffer array. + // + + res->S_Instance.Sends = ic->Sends; + res->S_Instance.SendPends = ic->SendPends; + res->S_Instance.SendComps = ic->SendComps; + res->S_Instance.SendFails = ic->SendFails; + + res->S_Instance.Receives = ic->Receives; + res->S_Instance.ReceiveComps = ic->ReceiveComps; + res->S_Instance.CorruptRecs = ic->CorruptRecs; + + res->S_Instance.XferData = ic->XferData; + res->S_Instance.XferDataPends = ic->XferDataPends; + res->S_Instance.XferDataComps = ic->XferDataComps; + res->S_Instance.XferDataFails = ic->XferDataFails; + + // + // and the servers global counters. + // + + res->S_Global.Sends = gc->Sends; + res->S_Global.SendComps = gc->SendComps; + res->S_Global.Receives = gc->Receives; + res->S_Global.ReceiveComps = gc->ReceiveComps; + + res->S_Global.CorruptRecs = gc->CorruptRecs; + res->S_Global.InvalidPacketRecs = gc->InvalidPacketRecs; +} + + + +VOID +TpWriteServerStatistics( + IN POPEN_BLOCK OpenP, + IN OUT PNDIS_PACKET Packet, + IN PCLIENT_INFO Client + ) + +// ----------------- +// +// Routine Description: +// +// +// NOTE: This routine requires a packet with one single contiguous +// buffer, it does not attempt to write to any other buffers. +// +// Arguments: +// +// OpenP - A pointer to the OPEN_BLOCK describing the Server. +// +// Return Value: +// +// None. +// +// ----------------- + +{ + PNDIS_BUFFER Buffer; + PUCHAR Memory; + UINT BufLen; + + + NdisQueryPacket(Packet,NULL,NULL,&Buffer,NULL); + + NdisQueryBuffer( Buffer,(PVOID *)&Memory,&BufLen ); + + RtlMoveMemory( Memory + sizeof( STRESS_PACKET ), + (PVOID)Client->Counters, + sizeof( INSTANCE_COUNTERS ) ); + + RtlMoveMemory( Memory + (ULONG) ( sizeof( STRESS_PACKET ) + + sizeof( INSTANCE_COUNTERS )), + (PVOID)OpenP->GlobalCounters, + sizeof( GLOBAL_COUNTERS ) ); +} + + + +VOID +TpPrintClientStatistics( + POPEN_BLOCK OpenP + ) + +// -------------- +// +// Routine Description: +// +// This routine dumps the interesting statistics held in the Client's +// Test Protocol data structures at the end of the test. +// +// Arguments: +// +// OpenP - A pointer to the OPEN_BLOCK describing the Client. +// +// Return Value: +// +// None. +// +// -------------- + +{ + PGLOBAL_COUNTERS GCounters; + PINSTANCE_COUNTERS ICounters; + PSERVER_INFO Server; + USHORT i; + + // + // Print out the Client Network Address and Test Counters. + // + + IF_TPDBG ( TP_DEBUG_STATISTICS ) + { + TpPrint0("\n\t****** CLIENT STATISTICS ******\n\n"); + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tLocal Address %x\t", OpenP->StationAddress[0]); + } + else + { + TpPrint6("\tLocal Address %x-%x-%x-%x-%x-%x\t", + OpenP->StationAddress[0],OpenP->StationAddress[1], + OpenP->StationAddress[2],OpenP->StationAddress[3], + OpenP->StationAddress[4],OpenP->StationAddress[5]); + } + TpPrint1("OpenInstance %d\n",OpenP->OpenInstance); + + TpPrint0("\n\t****** Global Statistics ******\n\n"); + + GCounters = OpenP->GlobalCounters; + + GCounters->Sends = 0; + GCounters->Receives = 0; + + for (i=0;i<OpenP->Stress->Client->NumServers;i++) + { + ICounters = OpenP->Stress->Client->Servers[i].Counters; + GCounters->Sends += ICounters->Sends; + GCounters->Receives += ICounters->Receives; + } + + TpPrint1("\tTotal Packets Sent:\t\t%8lu\n",GCounters->Sends); + TpPrint1("\tTotal Packets Received:\t\t%8lu\n",GCounters->Receives); + TpPrint1("\tTotal Packets Lost:\t\t%8lu\n\n", GCounters->Sends-GCounters->Receives); + + TpPrint1("\tTotal Packet Sends Completed:\t%8lu\n", GCounters->SendComps); + TpPrint1("\tTotal Packet Receives Completed:%8lu\n\n", GCounters->ReceiveComps); + + TpPrint1("\tCorrupted Packet Receives:\t%8lu\n", GCounters->CorruptRecs); + TpPrint1("\tInvalid Packet Receives:\t%8lu\n", GCounters->InvalidPacketRecs); + + // + // And then print out the information about each of the Servers + // involved in the test. + // + + TpPrint0("\n\t***** Remote Server Statistics ******\n\n"); + + TpPrint1("\tClient at this address has %d Server(s) as follows:\n", + OpenP->Stress->Client->NumServers); + + for (i=0;i<OpenP->Stress->Client->NumServers;i++) + { + Server = &OpenP->Stress->Client->Servers[i]; + + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\n\tRemote Server Address %x, ", Server->Address[0]); + } + else + { + TpPrint6("\n\tRemote Server Address %x-%x-%x-%x-%x-%x, ", + Server->Address[0],Server->Address[1],Server->Address[2], + Server->Address[3],Server->Address[4],Server->Address[5]); + } + + TpPrint1("OpenInstance %d\n\n",Server->ServerInstance); + + ICounters = Server->Counters; + + TpPrint1("\tTotal Packets Sent To:\t\t%8lu\n", ICounters->Sends); + TpPrint1("\tTotal Packets Received From:\t%8lu\n", ICounters->Receives); + TpPrint1("\tTotal Packets Lost:\t\t%8lu\n\n", ICounters->Sends-ICounters->Receives); + + TpPrint1("\tPacket Sends Failed:\t\t%8lu\n", ICounters->SendFails); + TpPrint1("\tPacket Sends Pended:\t\t%8lu\n", ICounters->SendPends); + TpPrint1("\tPacket Sends Completed:\t\t%8lu\n\n", ICounters->SendComps); + } + } +} + + + +VOID +TpPrintServerStatistics( + POPEN_BLOCK OpenP, + PCLIENT_INFO Client + ) + +// -------------- +// +// Routine Description: +// +// This routine dumps the interesting statistics held in the Server's +// Test Protocol data structures at the end of the test, and information +// about the Client that the Server was cooperating with. +// +// Arguments: +// +// OpenP - A pointer to the OPEN_BLOCK describing the Server. +// +// Client - A pointer to the CLIENT_INFO structure describing the +// Client this Server was responding to. +// +// Return Value: +// +// None. +// +// ---------------- + +{ + PINSTANCE_COUNTERS ICounters; + + // + // Print out the Server's Network Address and Test Counters. + // + IF_TPDBG ( TP_DEBUG_STATISTICS ) + { + TpPrint0("\t****** SERVER STATISTICS ******\n\n"); + + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\tLocal Address %x\t", OpenP->StationAddress[0]); + } + else + { + TpPrint6("\tLocal Address %x-%x-%x-%x-%x-%x\t", + OpenP->StationAddress[0],OpenP->StationAddress[1], + OpenP->StationAddress[2],OpenP->StationAddress[3], + OpenP->StationAddress[4],OpenP->StationAddress[5]); + } + + TpPrint1("OpenInstance %d\n",OpenP->OpenInstance); + + TpPrint0("\n\t****** Client Instance Statistics ******\n"); + + if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 ) + { + TpPrint1("\n\tRemote Client Address %x, ", Client->Address[0]); + } + else + { + TpPrint6("\n\tRemote Client Address %x-%x-%x-%x-%x-%x, ", + Client->Address[0],Client->Address[1],Client->Address[2], + Client->Address[3],Client->Address[4],Client->Address[5]); + } + TpPrint1("OpenInstance %d\n\n",Client->ClientInstance); + + // + // And then print out the information about the Client involved + // in the test. + // + + ICounters = Client->Counters; + + TpPrint1("\tPackets Received:\t\t%8lu\n",ICounters->Receives); + TpPrint1("\tPackets Sent:\t\t\t%8lu\n",ICounters->Sends); + TpPrint1("\tPackets Not Responded To:\t%8lu\n\n", ICounters->Receives-ICounters->Sends); + + TpPrint1("\tPacket Sends Failed:\t\t%8lu\n",ICounters->SendFails); + TpPrint1("\tPacket Sends Pended:\t\t%8lu\n",ICounters->SendPends); + TpPrint1("\tPacket Sends Completed:\t\t%8lu\n", ICounters->SendComps); + TpPrint1("\tPacket Receives Completed:\t%8lu\n\n", ICounters->ReceiveComps); + } +} + + + +VOID +TpWriteSendReceiveResults( + PINSTANCE_COUNTERS Counters, + PIRP Irp + ) + +// ------------ +// +// Routine Description: +// +// Write the SEND test statistics into the Output buffer passed +// in by the IOCTL call. The buffer is in the Irp->MdlAddress. +// NOTE: The OpenP->SpinLock must be held when making this call. +// +// Arguments: +// +// OpenP - The location of the Irp to find the Output buffer on. +// +// Counters - The counters to write into the Output buffer into. +// +// Return Value: +// +// None. +// +// ------------- + +{ + PSEND_RECEIVE_RESULTS OutputBuffer; + + // + // Get the output buffer out of the MDL stored in the IRP, and map + // it so we may write the statistics to it. + // + + OutputBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress ); + + // + // Write the statistics to the outbuffer + // + + OutputBuffer->Signature = SENDREC_RESULTS_SIGNATURE; + OutputBuffer->ResultsExist = TRUE; + + OutputBuffer->Counters.Sends = Counters->Sends; + OutputBuffer->Counters.SendPends = Counters->SendPends; + OutputBuffer->Counters.SendComps = Counters->SendComps; + OutputBuffer->Counters.SendFails = Counters->SendFails; + + OutputBuffer->Counters.Receives = Counters->Receives; + OutputBuffer->Counters.ReceiveComps = Counters->ReceiveComps; + OutputBuffer->Counters.CorruptRecs = Counters->CorruptRecs; + + OutputBuffer->Counters.XferData = Counters->XferData; + OutputBuffer->Counters.XferDataPends = Counters->XferDataPends; + OutputBuffer->Counters.XferDataComps = Counters->XferDataComps; + OutputBuffer->Counters.XferDataFails = Counters->XferDataFails; +} + + + +VOID +TpInitializePending( + PPENDING Pend + ) + +// ---------- +// +// Routine Description: +// +// This routine zeroes the counters in a PENDING_WATCH structure, and +// sets up the storage area for pending packets. +// +// Arguments: +// +// Pend - A pointer to the Pend Structure to be zeroed. +// +// Return Value: +// +// None. +// +// ---------- + +{ + INT i; + + // + // set up the pending packet storage and counters. + // + + Pend->PendingPackets = 0; + Pend->PendingRequests = 0; + Pend->PacketPendNumber = 0; + Pend->PacketCompleteNumber = 0; + + for ( i=0 ; i<NUM_PACKET_PENDS ; i++ ) + { + Pend->Packets[i] = NULL; + } +} + + + +VOID +TpInitializeStressResults( + PSTRESS_RESULTS Results + ) + +// --------- +// +// Routine Description: +// +// Arguments: +// +// Return Value: +// +// None. +// +// --------- + +{ + INT i; + + NdisZeroMemory((PVOID)Results,sizeof( STRESS_RESULTS )); + + Results->Signature = STRESS_RESULTS_SIGNATURE; + + for ( i=0;i<MAX_SERVERS;i++ ) + { + Results->Servers[i].Signature = STRESS_RESULTS_SIGNATURE; + } +} + + +#if 0 + +// do it on a per open basis. + + +VOID +TpDumpInfo( + VOID + ) + +// -------------- +// +// Routine Description: +// +// TpDumpInfo is a debugging routine that may be called from the kernel +// debugger by resetting EIP to the entry of TpDumpInfo to dump the state +// for the Test Protocol at any given time. +// +// NOTE: This routine does not reset the stack so care must be used if +// one wishes to continue running the Test Protocol after this +// procedure has executed. This routine was designed to dump +// the state of the Protocol after a system crash. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +// -------------- + +{ + static POPEN_BLOCK OpenP; + static PSTRESS_ARGUMENTS Args; + static PCLIENT_STORAGE Client; + static PSERVER_STORAGE Server; + static PGLOBAL_COUNTERS GCounters + static PINSTANCE_COUNTERS ICounters; + static INT i; + + OpenP = OpenList; + + TpPrint0("****** Open Block Structure ******\n\n"); + + TpPrint1("Ndis Handle\t\t%10lX\n",OpenP->NdisBindingHandle); + TpPrint1("Next Open Block\t\t%10lX\n",OpenP->Next); + TpPrint1("Open Instance\t\t%10ld\n",OpenP->OpenInstance); + + if ( OpenP->Media->NdisMedium == NdisMediumArcnet878_2 ) + { + TpPrint1("Machine Address \t%x\n\n", OpenP->StationAddress[0] ); + } + else + { + TpPrint6("Machine Address \t%x-%x-%x-%x-%x-%x\n\n", + OpenP->StationAddress[0],OpenP->StationAddress[1], + OpenP->StationAddress[2],OpenP->StationAddress[3], + OpenP->StationAddress[4],OpenP->StationAddress[5]); + } + + TpPrint0("****** Test Arguments Structure ******\n\n"); + + Args = OpenP->Arguments; + + TpPrint1("MemberType\t\t%10d\n",Args->MemberType); + TpPrint1"PACKET_TYPE\t\t%10d\n",Args->PacketType); + TpPrint1("Packet Size Value\t%10d\n",Args->PacketSize); + TpPrint1("PACKET_MAKEUP\t\t%10d\n",Args->PacketMakeUp); + TpPrint1("RESPONSE_TYPE\t\t%10d\n",Args->ResponseType); + TpPrint1("Iterations So Far\t%10lu\n",Args->Iterations); + TpPrint1("Total Iterations\t%10lu\n",Args->TotalIterations); + TpPrint1("Total Packets\t\t%10lu\n",Args->TotalPackets); + TpPrint1("Interpacket Delay\t%10lu\n",Args->DelayLength); + TpPrint1("All Packets Sent?\t\t%s\n",(Args->AllPacketsSent) ? "TRUE" : "FALSE"); + TpPrint1("Window Enabled?\t\t\t%s\n",(Args->WindowEnabled) ? "TRUE" : "FALSE"); + TpPrint1("Data Checking?\t\t\t%s\n",(Args->DataChecking) ? "TRUE" : "FALSE"); + TpPrint1("Packets From Pool?\t\t%s\n",(Args->PacketsFromPool) ? "TRUE" : "FALSE"); + TpPrint1("Begin Receives?\t\t\t%s\n",(Args->BeginReceives) ? "TRUE" : "FALSE"); + TpPrint1("Server Continue?\t\t\t%s\n\n",(Args->ServerContinue) ? "TRUE" : "FALSE"); + + TpPrint0("****** Global Counters Structure ******\n\n"); + + GCounters = OpenP->GlobalCounters; + + TpPrint1("Packet Sends\t\t\t%10lu\n",GCounters->Sends); + TpPrint1("Packet Receives\t\t%10lu\n",GCounters->Receives); + TpPrint1("Corrupted Packet Receives\t%10lu\n",GCounters->CorruptRecs); + TpPrint1("Invalid Protocol Receives\t%10lu\n",GCounters->InvalidPacketRecs); + + if (OpenP->Stress->Client != NULL) + { + TpPrint0("****** Client Storage Structure ******\n\n"); + + Client = OpenP->Stress->Client; + + TpPrint1("Number of Servers\t\t%10ld\n",Client->NumServers); + TpPrint1("Packet Pool\t\t\t%10lX\n",Client->PacketPool); + TpPrint1("Transmit Pool\t\t\t%10lX\n",Client->TransmitPool); + + TpPrint0("\n****** Servers with this Client ******\n\n"); + + for (i=0;i<Client->NumServers;i++) + { + TpPrint1("****** Server Number %d ******\n\n",i+1); + TpPrint1("Server Instance\t\t\t%10ld\n",Client->Servers[i].ServerInstance); + TpPrint1("Client Reference\t\t%10ld\n",Client->Servers[i].ClientReference); + TpPrint1("Server Reference\t\t\t%10ld\n",Client->Servers[i].ServerReference); + + if ( OpenP->Media->NdisMedium == NdisMediumArcnet878_2 ) + { + TpPrint1("Server[%d] Address\t%x\n",i, Client->Servers[i].Address[0]); + } + else + { + TpPrint6("Server[%d] Address\t%x-%x-%x-%x-%x-%x\n",i, + Client->Servers[i].Address[0],Client->Servers[i].Address[1], + Client->Servers[i].Address[2],Client->Servers[i].Address[3], + Client->Servers[i].Address[4],Client->Servers[i].Address[5]); + } + + TpPrint1("Sequence Number\t\t\t%10lu\n",Client->Servers[i].SequenceNumber); + TpPrint1("Max Sequence Number\t\t%10lu\n",Client->Servers[i].MaxSequenceNumber); + TpPrint1("Packet Delay\t\t\t%10lu\n\n", Client->Servers[i].PacketDelay); + + ICounters = Client->Servers[i].Counters; + + TpPrint1("****** Server Number %d's Counters ******\n\n",i+1); + TpPrint1("Packet Sends\t\t\t%10lu\n",ICounters->Sends); + TpPrint1("Packet Send Pends\t\t%10lu\n",ICounters->SendPends); + TpPrint1("Packet Send Completes\t\t%10lu\n",ICounters->SendComps); + TpPrint1("Packet Send Fails\t\t%10lu\n",ICounters->SendFails); + TpPrint1("Packet Receives\t\t\t%10lu\n",ICounters->Receives); + TpPrint1("Corrupted Packet Receives\t%10lu\n",ICounters->CorruptRecs); + } + } + + if (OpenP->Stress->Server != NULL) + { + TpPrint0("****** Server Storage Structure ******\n\n"); + + Server = OpenP->Stress->Server; + + TpPrint1("Number of Clients\t%10ld\n",Server->NumClients); + TpPrint1("Number of Active Clients%10ld\n",Server->ActiveClients); + TpPrint1("Packet Pool\t\t%10lX\n",Server->PacketPool); + TpPrint1("Transmit Pool\t\t%10lX\n\n",Server->TransmitPool); + + TpPrint0("******Clients with this Server******\n\n"); + + for (i=0;i<Server->NumClients;i++) + { + TpPrint1("****** Client Number %d ******\n\n",i+1); + TpPrint1("Client Instance\t\t%10ld\n",Server->Clients[i].ClientInstance); + TpPrint1("Client Reference\t%10ld\n",Server->Clients[i].ClientReference); + TpPrint1("Data Checking\t\t\t%s\n", + (Server->Clients[i].DataChecking) ? "TRUE" : "FALSE"); + + if ( OpenP->Media->NdisMedium == NdisMediumArcnet878_2 ) + { + TpPrint1("Client[%d] Address\t%x\n\n",i, Server->Clients[i].Address[0]); + } + else + { + TpPrint6("Client[%d] Address\t%x-%x-%x-%x-%x-%x\n\n",i, + Server->Clients[i].Address[0],Server->Clients[i].Address[1], + Server->Clients[i].Address[2],Server->Clients[i].Address[3], + Server->Clients[i].Address[4],Server->Clients[i].Address[5]); + } + + ICounters = Server->Clients[i].Counters; + + TpPrint1("****** Client Number %d's ICountersers ******\n\n",i); + TpPrint1("Packet Sends\t\t\t%10lu\n",ICounters->Sends); + TpPrint1("Packet Send Pends\t\t%10lu\n",ICounters->SendPends); + TpPrint1("Packet Send Completes\t\t%10lu\n",ICounters->SendComps); + TpPrint1("Packet Send Fails\t\t%10lu\n",ICounters->SendFails); + TpPrint1("Packet Receives\t\t\t%10lu\n",ICounters->Receives); + TpPrint1("Corrupted Packet Receives\t%10lu\n",ICounters->CorruptRecs); + } + } + + TpPrint0("\n\n\n"); + + ASSERT( FALSE ); +} + +#endif + diff --git a/private/ntos/ndis/testprot/tpkd/makefile b/private/ntos/ndis/testprot/tpkd/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/testprot/tpkd/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/testprot/tpkd/sources b/private/ntos/ndis/testprot/tpkd/sources new file mode 100644 index 000000000..92652ad3e --- /dev/null +++ b/private/ntos/ndis/testprot/tpkd/sources @@ -0,0 +1,55 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=testprot + +TARGETNAME=tpkd +TARGETPATH=obj +TARGETTYPE=DYNLINK +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\libc.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib + +DLLBASE=0x1010000 + +INCLUDES=..\inc;..\..\inc;..\..\..\inc;..\..\..\..\inc + +SOURCES=tpkd.c + +i386_SOURCES= +MIPS_SOURCES= + +386_STDCALL=1 +MIPS_FLAGS=-D_stdcall + +UMTYPE=console +OPTIONAL_NTTEST= + +!IFNDEF 386_WARNING_LEVEL +386_WARNING_LEVEL=/W3 +!ENDIF + +!IFNDEF MIPS_WARNINGS +MIPS_WARNINGS=-std +!ENDIF diff --git a/private/ntos/ndis/testprot/tpkd/tpkd.c b/private/ntos/ndis/testprot/tpkd/tpkd.c new file mode 100644 index 000000000..fb208dbc4 --- /dev/null +++ b/private/ntos/ndis/testprot/tpkd/tpkd.c @@ -0,0 +1,450 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + kdndis.c + +Abstract: + + Ndis Testprot Kernel Debugger extension + + This module contains a set of useful kernel debugger extensions for the + NT MAC Tester + +Author: + + Sanjeev Katariya May-6-1993 + +Revision History: + + Created + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <windows.h> +#include <ntkdexts.h> +#include <stdlib.h> +#include <malloc.h> + +#include "tpkd.h" + + +VOID +DumpNdisPacket( + PNTKD_OUTPUT_ROUTINE OutputRoutine, + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine, + PNDIS_PACKET NdisPacket, + DWORD AddressNdisPacket + ) +{ + + NDIS_BUFFER NdisBuffer; + DWORD BufferAddress; + BOOL ReadMemory = FALSE; + INT i; + + (OutputRoutine)( "\nNDIS_PACKET at Memory location: 0x%lx\n", AddressNdisPacket ); + + (OutputRoutine)( "\tNDIS_PACKET_PRIVATE\n" ); + (OutputRoutine)( "\t\tPhysical Count : %ld\n" , NdisPacket->Private.PhysicalCount ); + (OutputRoutine)( "\t\tTotal Length : %ld\n" , NdisPacket->Private.TotalLength ); + (OutputRoutine)( "\t\tNdis Buffer Head Ptr : 0x%lx\n", NdisPacket->Private.Head ); + (OutputRoutine)( "\t\tNdis Buffer Tail Ptr : 0x%lx\n", NdisPacket->Private.Tail ); + (OutputRoutine)( "\t\tNdis Packet Pool Ptr : 0x%lx\n", NdisPacket->Private.Pool ); + (OutputRoutine)( "\t\tCount : %ld\n" , NdisPacket->Private.Count ); + (OutputRoutine)( "\t\tFlags : 0x%lx\n", NdisPacket->Private.Flags ); + (OutputRoutine)( "\t\tValid Counts : %d\n" , NdisPacket->Private.ValidCounts ); + (OutputRoutine)( "\t\tMacReserved : " ); + + for( i = 0; i < 16; i++ ) { + (OutputRoutine)( "0x%2.2x", NdisPacket->MacReserved[i] ); + } + (OutputRoutine)( "\n\t\tProtocolReserved : 0x%2.2x\n", NdisPacket->ProtocolReserved[0] ); + + + // + // And now the NDIS_BUFFER chain + // + BufferAddress = NdisPacket->Private.Head; + + try { + + ReadMemory = (ReadMemoryRoutine)( (LPVOID)BufferAddress, + &NdisBuffer, + sizeof( NDIS_BUFFER ), + NULL + ); + + } except ( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access NDIS_BUFFER number of bytes.\n" ); + (OutputRoutine)( "Possible bad NDIS_BUFFER address 0x%lx\n", BufferAddress ); + return; + + } + + while ( ReadMemory ) { + + DumpNdisBuffer( OutputRoutine, ReadMemoryRoutine, &NdisBuffer, BufferAddress ); + + BufferAddress = NdisBuffer.Next; + (OutputRoutine)( "\n\tNext NDIS_BUFFER at address 0x%lx\n", BufferAddress ); + + try { + + ReadMemory = (ReadMemoryRoutine)( (LPVOID)BufferAddress, + &NdisBuffer, + sizeof( NDIS_BUFFER ), + NULL + ); + + } except ( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access NDIS_BUFFER number of bytes.\n" ); + (OutputRoutine)( "Possible bad NDIS_BUFFER address 0x%lx\n", BufferAddress ); + return; + + } + } + +} + + +VOID +DumpNdisBuffer( + PNTKD_OUTPUT_ROUTINE OutputRoutine, + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine, + PNDIS_BUFFER NdisBuffer, + DWORD AddressNdisBuffer + ) +{ + ULONG i; + BOOL ReadMemory = FALSE; + PUCHAR Buffer = calloc( NdisBuffer->ByteCount, sizeof( UCHAR ) ); + + (OutputRoutine)( "\n\tNDIS_BUFFER at Memory location: 0x%lx\n", AddressNdisBuffer ); + + (OutputRoutine)( "\t\tNext Buffer : 0x%lx\n", NdisBuffer->Next ); + (OutputRoutine)( "\t\tSize : %d\n" , NdisBuffer->Size ); + (OutputRoutine)( "\t\tMDL Flags : 0x%x\n" , NdisBuffer->MdlFlags ); + (OutputRoutine)( "\t\tEPROCESS Ptr : 0x%lx\n", NdisBuffer->Process ); + (OutputRoutine)( "\t\tMapped System VA : 0x%lx\n", NdisBuffer->MappedSystemVa ); + (OutputRoutine)( "\t\tStart VA : 0x%lx\n", NdisBuffer->StartVa ); + (OutputRoutine)( "\t\tByte Count : 0x%lx\n", NdisBuffer->ByteCount); + (OutputRoutine)( "\t\tByte Offset : 0x%lx\n", NdisBuffer->ByteOffset ); + (OutputRoutine)( "\t\tVA Contents\n" ); + + + if ( Buffer != NULL ) { + + try { + + ReadMemory = (ReadMemoryRoutine)( (LPVOID)NdisBuffer->StartVa, + Buffer, + NdisBuffer->ByteCount, + NULL + ); + + } except ( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access Byte Count number of bytes.\n" ); + (OutputRoutine)( "Possible bad StartVa address 0x%lx\n", NdisBuffer->StartVa ); + ReadMemory = FALSE; + + } + + if ( ReadMemory ) { + + for( i = 0; i < NdisBuffer->ByteCount ; i++ ) { + + if ( (i%16) == 0 ) { + + (OutputRoutine)( "\n\t\t%2x", Buffer[i] ); + + } else { + + (OutputRoutine)( "-%2x", Buffer[i] ); + + } + } + (OutputRoutine)( "\n" ); + free( Buffer ); + return; + + } + + free( Buffer ); + + } + + (OutputRoutine)( "Unable to access contents of StartVa: 0x%lx\n", NdisBuffer->StartVa ); + + +} + + +VOID +DumpOpenBuffer( + PNTKD_OUTPUT_ROUTINE OutputRoutine, + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine, + POPEN_BLOCK OpenBuffer, + DWORD AddressOpenBuffer + ) +{ + ULONG i; + BOOL ReadMemory = FALSE; + + (OutputRoutine)( "\n\tOPEN_BLOCK at Memory location: 0x%lx\n\n", AddressOpenBuffer ); + + (OutputRoutine)( "\t\tNdisBindingHandle : 0x%lx\n", OpenBuffer->NdisBindingHandle ); + (OutputRoutine)( "\t\tNdisProtocolHandle : 0x%lx\n", OpenBuffer->NdisProtocolHandle ); + (OutputRoutine)( "\t\tOpenInstance : %d\n" , OpenBuffer->OpenInstance ); + (OutputRoutine)( "\t\tClosing Status : %d\n" , OpenBuffer->Closing ); + (OutputRoutine)( "\t\tStation Address : " ); + for( i = 0 ; i < ADDRESS_LENGTH; i++ ) { + (OutputRoutine)( "%2.2x", OpenBuffer->StationAddress[i] ); + } + (OutputRoutine)( "\n" ); + (OutputRoutine)( "\t\tPtr to Adapter Name : 0x%lx\n", OpenBuffer->AdapterName ); + (OutputRoutine)( "\t\tSpin Lock Resource : 0x%lx\n", OpenBuffer->SpinLock ); + (OutputRoutine)( "\t\tReference Count : %d\n" , OpenBuffer->ReferenceCount ); + (OutputRoutine)( "\t\tMedium Index : %d\n" , OpenBuffer->MediumIndex ); + (OutputRoutine)( "\t\tPtr to Media Info : 0x%lx\n", OpenBuffer->Media ); + (OutputRoutine)( "\t\tPtr to Global Counters : 0x%lx\n", OpenBuffer->GlobalCounters ); + (OutputRoutine)( "\t\tPtr to Environment : 0x%lx\n", OpenBuffer->Environment ); + (OutputRoutine)( "\t\tPtr to Stress Block : 0x%lx\n", OpenBuffer->Stress ); + (OutputRoutine)( "\t\tPtr to Send Block : 0x%lx\n", OpenBuffer->Send ); + (OutputRoutine)( "\t\tPtr to Receive Block : 0x%lx\n", OpenBuffer->Receive ); + (OutputRoutine)( "\t\tPtr to Event Queue : 0x%lx\n", OpenBuffer->EventQueue ); + (OutputRoutine)( "\t\tPtr to Pause Block : 0x%lx\n", OpenBuffer->Pause ); + (OutputRoutine)( "\t\tPtr to Open Request Handle : 0x%lx\n", OpenBuffer->OpenReqHndl ); + (OutputRoutine)( "\t\tPtr to Close Request Handle : 0x%lx\n", OpenBuffer->CloseReqHndl ); + (OutputRoutine)( "\t\tPtr to Reset Request Handle : 0x%lx\n", OpenBuffer->ResetReqHndl ); + (OutputRoutine)( "\t\tPtr to Request Request Handle: 0x%lx\n", OpenBuffer->RequestReqHndl ); + (OutputRoutine)( "\t\tPtr to Stress Request Handle : 0x%lx\n", OpenBuffer->StressReqHndl ); + + (OutputRoutine)( "\t\tStatus IRP cancelled : %d\n" , OpenBuffer->IrpCancelled ); + (OutputRoutine)( "\t\tPtr to IRP : 0x%lx\n", OpenBuffer->Irp ); + (OutputRoutine)( "\t\tSignature : 0x%lx\n", OpenBuffer->Signature ); + +} + + + +/* + ************************* Exported Routines ********************************** + * * + * Method for invoking at debugger * + * * + * kd > !tpkd.ndispacket Address where Address is of type pointer * + * kd > !tpkd.ndisbuffer Address where Address is of type pointer * + * kd > !tpkd.openblock Address where Address is of type pointer * + * kd > !tpkd.help * + * * + ******************************************************************************* +*/ + + +VOID +ndispacket( + DWORD CurrentPc, + PNTKD_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +{ + + PNTKD_OUTPUT_ROUTINE OutputRoutine ; + PNTKD_GET_EXPRESSION GetExpressionRoutine; + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine ; + PNTKD_GET_SYMBOL GetSymbolRoutine ; + NDIS_PACKET Packet ; + DWORD AddressNdisPacket ; + BOOL ReadMemory = FALSE ; + + OutputRoutine = ExtensionApis->lpOutputRoutine; + GetExpressionRoutine = ExtensionApis->lpGetExpressionRoutine; + GetSymbolRoutine = ExtensionApis->lpGetSymbolRoutine; + ReadMemoryRoutine = ExtensionApis->lpReadVirtualMemRoutine; + + // + // Get the address of the NDIS_PACKET + AddressNdisPacket = (GetExpressionRoutine)(ArgumentString); + // + if ( !AddressNdisPacket ) { + return; + } + + try { + + // + // Now read the memory contents into our buffer area + // + ReadMemory = (ReadMemoryRoutine)( (LPVOID)AddressNdisPacket, + &Packet, + sizeof(NDIS_PACKET), + NULL + ); + } except( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access NDIS_PACKET size bytes.\n" ); + (OutputRoutine)( "Possible bad NDIS_PACKET address 0x%lx\n", AddressNdisPacket ); + ReadMemory = FALSE; + + } + + if ( !ReadMemory ) { + return; + } + + + DumpNdisPacket( OutputRoutine, + ReadMemoryRoutine, + &Packet, + AddressNdisPacket ); + +} + + +VOID +ndisbuffer( + DWORD CurrentPc, + PNTKD_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +{ + + PNTKD_OUTPUT_ROUTINE OutputRoutine ; + PNTKD_GET_EXPRESSION GetExpressionRoutine; + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine ; + PNTKD_GET_SYMBOL GetSymbolRoutine ; + NDIS_BUFFER NdisBuffer ; + DWORD AddressNdisBuffer ; + BOOL ReadMemory = FALSE ; + + OutputRoutine = ExtensionApis->lpOutputRoutine; + GetExpressionRoutine = ExtensionApis->lpGetExpressionRoutine; + GetSymbolRoutine = ExtensionApis->lpGetSymbolRoutine; + ReadMemoryRoutine = ExtensionApis->lpReadVirtualMemRoutine; + + // + // Get the address of the NDIS_PACKET + // + + AddressNdisBuffer = (GetExpressionRoutine)(ArgumentString); + if ( !AddressNdisBuffer ) { + return; + } + + try { + + // + // Now read the memory contents into our buffer area + // + ReadMemory = (ReadMemoryRoutine)( (LPVOID)AddressNdisBuffer, + &NdisBuffer, + sizeof(NDIS_BUFFER), + NULL + ); + } except( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access NDIS_BUFFER size bytes.\n" ); + (OutputRoutine)( "Possible bad NDIS_BUFFER address 0x%lx\n", AddressNdisBuffer ); + ReadMemory = FALSE; + + } + + if ( !ReadMemory ) { + return; + } + + + DumpNdisBuffer( OutputRoutine, + ReadMemoryRoutine, + &NdisBuffer, + AddressNdisBuffer ); + +} + + +VOID +openblock( + DWORD CurrentPc, + PNTKD_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +{ + + PNTKD_OUTPUT_ROUTINE OutputRoutine ; + PNTKD_GET_EXPRESSION GetExpressionRoutine; + PNTKD_READ_VIRTUAL_MEMORY ReadMemoryRoutine ; + PNTKD_GET_SYMBOL GetSymbolRoutine ; + OPEN_BLOCK OpenBuffer ; + DWORD AddressOpenBuffer ; + BOOL ReadMemory = FALSE ; + + OutputRoutine = ExtensionApis->lpOutputRoutine; + GetExpressionRoutine = ExtensionApis->lpGetExpressionRoutine; + GetSymbolRoutine = ExtensionApis->lpGetSymbolRoutine; + ReadMemoryRoutine = ExtensionApis->lpReadVirtualMemRoutine; + + // + // Get the address of the OPEN_BLOCK + // + + AddressOpenBuffer = (GetExpressionRoutine)(ArgumentString); + if ( !AddressOpenBuffer ) { + return; + } + + try { + + // + // Now read the memory contents into our buffer area + // + ReadMemory = (ReadMemoryRoutine)( (LPVOID)AddressOpenBuffer, + &OpenBuffer, + sizeof(OPEN_BLOCK), + NULL + ); + } except( EXCEPTION_ACCESS_VIOLATION ) { + + (OutputRoutine)( "The routine was unable to access OPEN_BLOCK size bytes.\n" ); + (OutputRoutine)( "Possible bad OPEN_BLOCK address 0x%lx\n", AddressOpenBuffer ); + ReadMemory = FALSE; + + } + + if ( !ReadMemory ) { + return; + } + + + DumpOpenBuffer( OutputRoutine, + ReadMemoryRoutine, + &OpenBuffer, + AddressOpenBuffer ); + +} + +VOID +help( + DWORD CurrentPc, + PNTKD_EXTENSION_APIS ExtensionApis, + LPSTR ArgumentString + ) +{ + + PNTKD_OUTPUT_ROUTINE OutputRoutine; + + OutputRoutine = ExtensionApis->lpOutputRoutine; + + (OutputRoutine)( "The following commands are available\n" ); + (OutputRoutine)( "\tndispacket <address>\n\tndisbuffer <address>\n\topenblock\n\thelp\n" ); + + +} diff --git a/private/ntos/ndis/testprot/tpkd/tpkd.def b/private/ntos/ndis/testprot/tpkd/tpkd.def new file mode 100644 index 000000000..9ee251527 --- /dev/null +++ b/private/ntos/ndis/testprot/tpkd/tpkd.def @@ -0,0 +1,8 @@ +LIBRARY TPKD +DESCRIPTION 'NDIS KD extensions' + +EXPORTS + ndispacket + ndisbuffer + openblock + help diff --git a/private/ntos/ndis/testprot/tpkd/tpkd.h b/private/ntos/ndis/testprot/tpkd/tpkd.h new file mode 100644 index 000000000..23942288d --- /dev/null +++ b/private/ntos/ndis/testprot/tpkd/tpkd.h @@ -0,0 +1,781 @@ +// +// I/O system definitions. +// +// Define a Memory Descriptor List (MDL) +// +// An MDL describes pages in a virtual buffer in terms of physical pages. The +// pages associated with the buffer are described in an array that is allocated +// just after the MDL header structure itself. In a future compiler this will +// be placed at: +// +// ULONG Pages[]; +// +// Until this declaration is permitted, however, one simply calculates the +// base of the array by adding one to the base MDL pointer: +// +// Pages = (PULONG) (Mdl + 1); +// +// Notice that while in the context of the subject thread, the base virtual +// address of a buffer mapped by an MDL may be referenced using the following: +// +// Mdl->StartVa | Mdl->ByteOffset +// + +typedef struct _MDL { + + struct _MDL *Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS *Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; + +} MDL, *PMDL; + +typedef struct _IRP { ULONG Value; } IRP ; +typedef struct _KEVENT { ULONG Value; } KEVENT; +typedef struct _KDPC { ULONG Value; } KDPC ; +typedef struct _KTIMER { ULONG Value; } KTIMER; + +typedef IRP *PIRP; +typedef KEVENT *PKEVENT; +typedef KDPC *PKDPC; +typedef KTIMER *PKTIMER; + + +// +// NDIS DEFINITIONS +// + +typedef MDL NDIS_BUFFER, * PNDIS_BUFFER; +typedef ULONG NDIS_OID, *PNDIS_OID ; +typedef PVOID NDIS_HANDLE, *PNDIS_HANDLE ; +typedef NTSTATUS NDIS_STATUS ; + + +typedef struct _NDIS_SPIN_LOCK { + + KSPIN_LOCK SpinLock; + KIRQL OldIrql; + +} NDIS_SPIN_LOCK, * PNDIS_SPIN_LOCK; + +typedef struct _NDIS_PACKET_POOL { + + NDIS_SPIN_LOCK SpinLock; + struct _NDIS_PACKET *FreeList; // linked list of free slots in pool + UINT PacketLength; // amount needed in each packet + UCHAR Buffer[1]; // actual pool memory + +} NDIS_PACKET_POOL, * PNDIS_PACKET_POOL; + +typedef struct _NDIS_PACKET_PRIVATE { + + UINT PhysicalCount; // number of physical pages in packet. + UINT TotalLength; // Total amount of data in the packet. + PNDIS_BUFFER Head; // first buffer in the chain + PNDIS_BUFFER Tail; // last buffer in the chain + PNDIS_PACKET_POOL Pool; // so we know where to free it back to + UINT Count; + ULONG Flags; + BOOLEAN ValidCounts; + +} NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE; + +typedef struct _NDIS_PACKET { + + NDIS_PACKET_PRIVATE Private; + UCHAR MacReserved[16]; + UCHAR ProtocolReserved[1]; + +} NDIS_PACKET, * PNDIS_PACKET; + +typedef enum _NDIS_REQUEST_TYPE { + + NdisRequestQueryInformation, + NdisRequestSetInformation, + NdisRequestQueryStatistics, + NdisRequestOpen, + NdisRequestClose, + NdisRequestSend, + NdisRequestTransferData, + NdisRequestReset, + NdisRequestGeneric1, + NdisRequestGeneric2, + NdisRequestGeneric3, + NdisRequestGeneric4 + +} NDIS_REQUEST_TYPE, *PNDIS_REQUEST_TYPE; + +typedef struct _NDIS_REQUEST { + + UCHAR MacReserved[16]; + NDIS_REQUEST_TYPE RequestType; + union _DATA { + + struct _QUERY_INFORMATION { + NDIS_OID Oid; + PVOID InformationBuffer; + UINT InformationBufferLength; + UINT BytesWritten; + UINT BytesNeeded; + } QUERY_INFORMATION; + + struct _SET_INFORMATION { + NDIS_OID Oid; + PVOID InformationBuffer; + UINT InformationBufferLength; + UINT BytesRead; + UINT BytesNeeded; + } SET_INFORMATION; + + } DATA; + +} NDIS_REQUEST, *PNDIS_REQUEST; + +// +// END OF NDIS DEFINITIONS +// + + +// +// TPDEF DEFINITIONS +// + +#define ADDRESS_LENGTH 6 +#define ADDRESS_LENGTH_1_OCTET 1 +#define MAX_SERVERS 10 +#define MAX_CLIENTS 10 +#define NUM_PACKET_PENDS 1000 +#define MAX_NUMBER_BUFFERS 2 +#define NUMBER_OF_POOL_PACKETS 10 +#define MAX_EVENT 20 + +#include <packon.h> + +// +// THE MEDIA HEADER +// +typedef struct _E_802_3 { + + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; + UCHAR PacketSize_Hi; + UCHAR PacketSize_Lo; + +} E_802_3; + +typedef struct _TR_802_5 { + + UCHAR AC; + UCHAR FC; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; + +} TR_802_5; + +typedef struct _FDDI { + + UCHAR FC; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR SrcAddress[ADDRESS_LENGTH]; + +} FDDI; + +typedef struct _ARCNET { + + UCHAR SrcAddress[ADDRESS_LENGTH_1_OCTET] ; + UCHAR DestAddress[ADDRESS_LENGTH_1_OCTET]; + UCHAR ProtocolID ; + +} ARCNET; + +typedef union _MEDIA_HEADER { + + E_802_3 e; + TR_802_5 tr; + FDDI fddi; + ARCNET a; + +} MEDIA_HEADER ; + +// +// THE TEST PROTOCOL HEADER +// +typedef struct _PACKET_INFO { + + ULONG Signature; + ULONG PacketSize; // the total size of the packet + UCHAR DestInstance; // instance of the packet's dest ndis binding + UCHAR SrcInstance; // instance of the packet's src ndis binding + UCHAR PacketType; // type of packet; STRESS or FUNC + union { + UCHAR PacketProtocol; // for STRESS packets the actual protocol type. + UCHAR PacketNumber; // ranges from 0x00 to 0xff, for tracking FUNCs. + } u; + ULONG CheckSum; // functional packet header check sum + +} PACKET_INFO; + +// +// THE FUNC1 PACKET HEADER +// +typedef struct _FUNC1_PACKET { + + MEDIA_HEADER media; + PACKET_INFO info; + +} FUNC1_PACKET; + +// +// THE FUNC2 PACKET HEADER +// +typedef struct _FUNC2_PACKET { + + FUNC1_PACKET hdr1; + FUNC1_PACKET hdr2; + +} FUNC2_PACKET; + +// +// THE STRESS PACKET CONTROL INFORMATION +// +typedef struct _STRESS_CONTROL { + + ULONG DataBufOffset; // offset into databuf used to generate packet data + ULONG SequenceNumber; // packet's sequence in order of sending + ULONG MaxSequenceNumber; // server window sequence number + UCHAR ResponseType; // how the server should respond. + UCHAR ClientReference; // the number of the Client sending the packet + UCHAR ServerReference; // the number of the Server sending the packet + BOOLEAN DataChecking; // + ULONG CheckSum; // stress packet header check sum + +} STRESS_CONTROL; + +// +// THE STRESS_PACKET +// +typedef struct _STRESS_PACKET { + + FUNC1_PACKET hdr; + STRESS_CONTROL sc; + +} STRESS_PACKET; + + +// +// THE GO PAUSE HEADER INFORMATION +// + +typedef struct _GO_PACKET_INFO { + + ULONG Signature; // GO_PACKET_SIGNATURE + ULONG TestSignature; // Test Signature + ULONG UniqueSignature; // Unique Signature for this GO PAUSE instance + UCHAR PacketType; // type of packet; STRESS or FUNC + ULONG CheckSum; // functional packet header check sum + +} GO_PACKET_INFO; + +// +// THE GO-PAUSE PACKET +// +typedef struct _GO_PACKET { + + MEDIA_HEADER go_media; + GO_PACKET_INFO info; + +} GO_PACKET; + + +// +// IN TOTAL: 4 TYPES OF PACKETS EXIST +// +// 1. FUNC1 +// 2. FUNC2 +// 3. STRESS +// 4. GO-PAUSE +// +#include <packoff.h> + + +typedef struct _ENVIRONMENT_VARIABLES { + + ULONG WindowSize; + ULONG RandomBufferNumber; + UCHAR StressAddress[ADDRESS_LENGTH]; + UCHAR ResendAddress[ADDRESS_LENGTH]; + ULONG StressDelayInterval; + ULONG UpForAirDelay; + ULONG StandardDelay; + ULONG MulticastListSize; + +} ENVIRONMENT_VARIABLES, * PENVIRONMENT_VARIABLES; + +typedef struct _GLOBAL_COUNTERS { + + ULONG Sends; + ULONG SendComps; + ULONG Receives; + ULONG ReceiveComps; + ULONG CorruptRecs; + ULONG InvalidPacketRecs; + +} GLOBAL_COUNTERS, *PGLOBAL_COUNTERS; + +typedef struct _INSTANCE_COUNTERS { + + ULONG Sends; + ULONG SendPends; + ULONG SendComps; + ULONG SendFails; + ULONG Receives; + ULONG ReceiveComps; + ULONG CorruptRecs; + ULONG XferData; + ULONG XferDataPends; + ULONG XferDataComps; + ULONG XferDataFails; + +} INSTANCE_COUNTERS, *PINSTANCE_COUNTERS; + +typedef enum _RESPONSE_TYPE { + + FULL_RESPONSE, + ACK_EVERY, + ACK_10_TIMES, + NO_RESPONSE + +} RESPONSE_TYPE; + +typedef enum _INTERPACKET_DELAY { + + FIXEDDELAY, + RANDOMDELAY + +} INTERPACKET_DELAY; + +typedef enum _PACKET_MAKEUP { + + RAND, + SMALL, + ZEROS, + ONES, + KNOWN + +} PACKET_MAKEUP; + +typedef enum _MEMBER_TYPE { + + TP_CLIENT, + TP_SERVER, + BOTH + +} MEMBER_TYPE; + +typedef enum _PACKET_TYPE { + + FIXEDSIZE, + RANDOMSIZE, + CYCLICAL + +} PACKET_TYPE; + +typedef enum _TP_EVENT_TYPE { + + CompleteOpen, + CompleteClose, + CompleteSend, + CompleteTransferData, + CompleteReset, + CompleteRequest, + IndicateReceive, + IndicateReceiveComplete, + IndicateStatus, + IndicateStatusComplete, + Unknown + +} TP_EVENT_TYPE; + + +typedef struct _SERVER_RESULTS { + + ULONG Signature; + UCHAR Address[ADDRESS_LENGTH]; + ULONG OpenInstance; + BOOLEAN StatsRcvd; + INSTANCE_COUNTERS Instance; + INSTANCE_COUNTERS S_Instance; + GLOBAL_COUNTERS S_Global; + +} SERVER_RESULTS, *PSERVER_RESULTS; + + + +typedef struct _STRESS_RESULTS { + + ULONG Signature; + UCHAR Address[ADDRESS_LENGTH]; + ULONG OpenInstance; + ULONG NumServers; + ULONG PacketsPerSecond; + GLOBAL_COUNTERS Global; + SERVER_RESULTS Servers[MAX_SERVERS]; + +} STRESS_RESULTS, *PSTRESS_RESULTS; + +typedef struct _TP_TRANSMIT_POOL { + + NDIS_SPIN_LOCK SpinLock; + BOOLEAN SpinLockAllocated; + ULONG Allocated; + ULONG Deallocated; + PNDIS_PACKET Head; + PNDIS_PACKET Tail; + +} TP_TRANSMIT_POOL, *PTP_TRANSMIT_POOL; + +struct _OPEN_BLOCK; + +typedef struct _TP_REQUEST_HANDLE { + + ULONG Signature; + struct _OPEN_BLOCK *Open; + BOOLEAN RequestPended; + PIRP Irp; + + union { + + struct _OPEN_REQ { + + NTSTATUS RequestStatus; + KEVENT OpenEvent; + + } OPEN_REQ; + + struct _RESET_REQ { + + NTSTATUS RequestStatus; + BOOLEAN PostResetStressCleanup; + + } RESET_REQ; + + struct _INFO_REQ { + + ULONG IoControlCode; + NDIS_REQUEST_TYPE NdisRequestType; + NDIS_OID OID; + PVOID InformationBuffer; + UINT InformationBufferLength; + + } INFO_REQ; + + struct _SEND_REQ { + + PNDIS_PACKET Packet; + ULONG PacketSize; + BOOLEAN SendPacket; + + } SEND_REQ; + + struct _TRANS_REQ { + + PNDIS_PACKET Packet; + ULONG DataOffset; + UINT DataSize; + PINSTANCE_COUNTERS InstanceCounters; + + } TRANS_REQ; + + struct _STRESS_REQ { + + struct _TP_REQUEST_HANDLE *NextReqHndl; + PNDIS_REQUEST Request; + + } STRESS_REQ; + + } u; + +} TP_REQUEST_HANDLE, *PTP_REQUEST_HANDLE; + + +typedef struct _PROTOCOL_RESERVED { + + union { + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + PNDIS_PACKET NextPacket; + } Pool; + PTP_REQUEST_HANDLE RequestHandle; + PINSTANCE_COUNTERS InstanceCounters; + ULONG CheckSum; + +} PROTOCOL_RESERVED, * PPROTOCOL_RESERVED; + + +typedef struct _SERVER_INFO { + + UCHAR ServerInstance; + UCHAR ClientReference; + UCHAR ServerReference; + UCHAR Address[ADDRESS_LENGTH]; // will be the same for a given ServerReference + BOOLEAN ServerActive; + UCHAR WindowReset; + ULONG SequenceNumber; + ULONG MaxSequenceNumber; + ULONG LastSequenceNumber; + ULONG PacketDelay; + ULONG DelayLength; + PINSTANCE_COUNTERS Counters; + +} SERVER_INFO, * PSERVER_INFO; + +typedef struct _CLIENT_STORAGE { + + UCHAR NumServers; + UCHAR NextServer; + UCHAR ActiveServers; + BOOLEAN PoolInitialized; + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + ULONG PacketSize; + ULONG BufferSize; + ULONG SizeIncrease; + SERVER_INFO Servers[MAX_SERVERS]; + +} CLIENT_STORAGE, * PCLIENT_STORAGE; + +typedef struct _CLIENT_INFO { + + UCHAR ClientInstance; + UCHAR ClientReference; + UCHAR Address[ADDRESS_LENGTH]; + BOOLEAN DataChecking; + BOOLEAN TestEnding; + RESPONSE_TYPE ServerResponseType; + ULONG LastSequenceNumber; + PINSTANCE_COUNTERS Counters; + +} CLIENT_INFO, * PCLIENT_INFO; + + + +typedef struct _SERVER_STORAGE { + + UCHAR NumClients; + UCHAR ActiveClients; + BOOLEAN PoolInitialized; + UCHAR PadByte; + NDIS_HANDLE PacketHandle; + PTP_TRANSMIT_POOL TransmitPool; + ULONG PadLong; + CLIENT_INFO Clients[MAX_CLIENTS]; + +} SERVER_STORAGE, * PSERVER_STORAGE; + +// +// +// + +typedef struct _STRESS_ARGUMENTS { + + MEMBER_TYPE MemberType; + PACKET_TYPE PacketType; + INT PacketSize; + PACKET_MAKEUP PacketMakeUp; + UCHAR ResponseType; + INTERPACKET_DELAY DelayType; + ULONG DelayLength; + ULONG Iterations; + ULONG TotalIterations; + ULONG TotalPackets; + BOOLEAN AllPacketsSent; + BOOLEAN WindowEnabled; + BOOLEAN DataChecking; + BOOLEAN PacketsFromPool; + BOOLEAN BeginReceives; + BOOLEAN ServerContinue; + +} STRESS_ARGUMENTS, * PSTRESS_ARGUMENTS; + + + + +typedef struct _PENDING { + + ULONG PendingPackets; + ULONG PendingRequests; + ULONG PacketPendNumber; + ULONG PacketCompleteNumber; + BOOLEAN PendingSpinLockAllocated; + NDIS_SPIN_LOCK SpinLock; + PNDIS_PACKET Packets[NUM_PACKET_PENDS]; + +} PENDING, * PPENDING; + + + + +typedef struct _STRESS_BLOCK { + + volatile BOOLEAN Stressing; + BOOLEAN StressStarted; + BOOLEAN StopStressing; + BOOLEAN StressFinal; + BOOLEAN StressEnded; + BOOLEAN Resetting; + BOOLEAN FirstIteration; + PCLIENT_STORAGE Client; + PSERVER_STORAGE Server; + LARGE_INTEGER StartTime; + LARGE_INTEGER EndTime; + ULONG PacketsPerSecond; + PSTRESS_ARGUMENTS Arguments; + PPENDING Pend; + PUCHAR DataBuffer[MAX_NUMBER_BUFFERS]; + PMDL DataBufferMdl[MAX_NUMBER_BUFFERS]; + BOOLEAN PoolInitialized; + NDIS_HANDLE PacketHandle; + PSTRESS_RESULTS Results; + PIRP StressIrp; + ULONG Counter; + ULONG Reg2Counter; + KTIMER TpStressTimer; + KTIMER TpStressReg2Timer; + KDPC TpStressDpc; + KDPC TpStressReg2Dpc; + KDPC TpStressStatsDpc; + KDPC TpStressEndReqDpc; + KDPC TpStressFinalDpc; + +} STRESS_BLOCK, * PSTRESS_BLOCK; + + +typedef struct _SEND_BLOCK { + + volatile BOOLEAN Sending; + BOOLEAN StopSending; + BOOLEAN ResendPackets; + UCHAR PadByte; + UCHAR DestAddress[ADDRESS_LENGTH]; + UCHAR ResendAddress[ADDRESS_LENGTH]; + ULONG PacketSize; + ULONG NumberOfPackets; + ULONG PacketsSent; + ULONG PacketsPending; + ULONG SendEndDpcCount; + NDIS_HANDLE PacketHandle; + PINSTANCE_COUNTERS Counters; + PIRP SendIrp; + KTIMER SendTimer; + KDPC SendDpc; + KDPC SendEndDpc; + +} SEND_BLOCK, * PSEND_BLOCK; + + + +typedef struct _RECEIVE_BLOCK { + + volatile BOOLEAN Receiving; + BOOLEAN StopReceiving; + ULONG PacketsPending; + ULONG ReceiveEndDpcCount; + NDIS_HANDLE PacketHandle; + PINSTANCE_COUNTERS Counters; + PIRP ReceiveIrp; + KTIMER ReceiveTimer; + KDPC ReceiveDpc; + KDPC ReceiveEndDpc; + +} RECEIVE_BLOCK, * PRECEIVE_BLOCK; + +typedef struct _PAUSE_BLOCK { + + volatile BOOLEAN GoReceived; + BOOLEAN PoolAllocated; + NDIS_HANDLE PacketHandle; + UCHAR RemoteAddress[ADDRESS_LENGTH]; + ULONG TestSignature; + ULONG UniqueSignature; + UCHAR PacketType; + ULONG TimeOut; + NDIS_SPIN_LOCK SpinLock; + +} PAUSE_BLOCK, * PPAUSE_BLOCK; + + +typedef struct _EVENTS { + + TP_EVENT_TYPE TpEventType; + NDIS_STATUS Status; + BOOLEAN Overflow; + PVOID EventInfo; + +} EVENTS, * PEVENTS; + + + + +typedef struct _EVENT_QUEUE { + + NDIS_SPIN_LOCK SpinLock; + ULONG ReceiveIndicationCount; + ULONG StatusIndicationCount; + BOOLEAN ExpectReceiveComplete; + BOOLEAN ExpectStatusComplete; + ULONG Head; + ULONG Tail; + ULONG PadUlong; + EVENTS Events[MAX_EVENT]; + +} EVENT_QUEUE, * PEVENT_QUEUE; + + +typedef struct _OPEN_BLOCK { + + NDIS_HANDLE NdisBindingHandle; + NDIS_HANDLE NdisProtocolHandle; + UCHAR OpenInstance; + BOOLEAN Closing; + UCHAR StationAddress[ADDRESS_LENGTH]; + PSZ AdapterName; + NDIS_SPIN_LOCK SpinLock; + volatile UCHAR ReferenceCount; + UINT MediumIndex; + struct _TP_MEDIA_INFO *Media; + PGLOBAL_COUNTERS GlobalCounters; + PENVIRONMENT_VARIABLES Environment; + PSTRESS_BLOCK Stress; + PSEND_BLOCK Send; + PRECEIVE_BLOCK Receive; + PEVENT_QUEUE EventQueue; + PPAUSE_BLOCK Pause; + PTP_REQUEST_HANDLE OpenReqHndl; + PTP_REQUEST_HANDLE CloseReqHndl; + PTP_REQUEST_HANDLE ResetReqHndl; + PTP_REQUEST_HANDLE RequestReqHndl; + PTP_REQUEST_HANDLE StressReqHndl; + BOOLEAN IrpCancelled; + PIRP Irp; + ULONG Signature; + +} OPEN_BLOCK, * POPEN_BLOCK; + + + + + +// +// Functions +// +VOID DumpNdisPacket( PNTKD_OUTPUT_ROUTINE, PNTKD_READ_VIRTUAL_MEMORY, PNDIS_PACKET, DWORD ); +VOID DumpNdisBuffer( PNTKD_OUTPUT_ROUTINE, PNTKD_READ_VIRTUAL_MEMORY, PNDIS_BUFFER, DWORD ); +VOID DumpOpenBuffer( PNTKD_OUTPUT_ROUTINE, PNTKD_READ_VIRTUAL_MEMORY, PNDIS_BUFFER, DWORD ); +VOID ndispacket ( DWORD, PNTKD_EXTENSION_APIS, LPSTR ); +VOID ndisbuffer ( DWORD, PNTKD_EXTENSION_APIS, LPSTR ); +VOID openblock ( DWORD, PNTKD_EXTENSION_APIS, LPSTR ); +VOID help ( DWORD, PNTKD_EXTENSION_APIS, LPSTR ); diff --git a/private/ntos/ndis/testprot/tplib/makefile b/private/ntos/ndis/testprot/tplib/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/ndis/testprot/tplib/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/testprot/tplib/oids.c b/private/ntos/ndis/testprot/tplib/oids.c new file mode 100644 index 000000000..f69958aef --- /dev/null +++ b/private/ntos/ndis/testprot/tplib/oids.c @@ -0,0 +1,206 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + oid.c + +Abstract: + + +Author: + + Tom Adams (tomad) 29-Nov-1991 + +Environment: + + Kernel mode, FSD + +Revision History: + + Sanjeev Katariya (sanjeevk) + + 4-6-1993 Added native ARCNET Support + 4-14-1993 Added additional OIDS + +--*/ + +//#include <ntos.h> + +#include <ndis.h> + +#include "tpdefs.h" + + +extern OID_INFO OidArray[] = { + + { OID_GEN_SUPPORTED_LIST, 1024, TRUE, FALSE, TRUE }, + { OID_GEN_HARDWARE_STATUS, 4, TRUE, FALSE, TRUE }, + { OID_GEN_MEDIA_SUPPORTED, 4*8, TRUE, FALSE, TRUE }, + { OID_GEN_MEDIA_IN_USE, 4*8, TRUE, FALSE, TRUE }, + { OID_GEN_MAXIMUM_LOOKAHEAD, 4, TRUE, FALSE, TRUE }, + { OID_GEN_MAXIMUM_FRAME_SIZE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_LINK_SPEED, 4, TRUE, FALSE, TRUE }, + { OID_GEN_TRANSMIT_BUFFER_SPACE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_RECEIVE_BUFFER_SPACE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_TRANSMIT_BLOCK_SIZE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_RECEIVE_BLOCK_SIZE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_VENDOR_ID, 4, TRUE, FALSE, TRUE }, + { OID_GEN_VENDOR_DESCRIPTION, 64, TRUE, FALSE, TRUE }, + { OID_GEN_CURRENT_PACKET_FILTER, 4, TRUE, TRUE, TRUE }, + { OID_GEN_CURRENT_LOOKAHEAD, 4, TRUE, TRUE, TRUE }, + { OID_GEN_DRIVER_VERSION, 2, TRUE, FALSE, TRUE }, + { OID_GEN_MAXIMUM_TOTAL_SIZE, 4, TRUE, FALSE, TRUE }, + { OID_GEN_PROTOCOL_OPTIONS, 4, TRUE, TRUE, TRUE }, + { OID_GEN_MAC_OPTIONS, 4, TRUE, TRUE, TRUE }, + + + { OID_GEN_XMIT_OK, 4, FALSE, FALSE, TRUE }, + { OID_GEN_RCV_OK, 4, FALSE, FALSE, TRUE }, + { OID_GEN_XMIT_ERROR, 4, FALSE, FALSE, TRUE }, + { OID_GEN_RCV_ERROR, 4, FALSE, FALSE, TRUE }, + { OID_GEN_RCV_NO_BUFFER, 4, FALSE, FALSE, TRUE }, + + { OID_GEN_DIRECTED_BYTES_XMIT, 8, FALSE, FALSE, TRUE }, + { OID_GEN_DIRECTED_FRAMES_XMIT, 4, FALSE, FALSE, TRUE }, + { OID_GEN_MULTICAST_BYTES_XMIT, 8, FALSE, FALSE, TRUE }, + { OID_GEN_MULTICAST_FRAMES_XMIT, 4, FALSE, FALSE, TRUE }, + { OID_GEN_BROADCAST_BYTES_XMIT, 8, FALSE, FALSE, TRUE }, + { OID_GEN_BROADCAST_FRAMES_XMIT, 4, FALSE, FALSE, TRUE }, + { OID_GEN_DIRECTED_BYTES_RCV, 8, FALSE, FALSE, TRUE }, + { OID_GEN_DIRECTED_FRAMES_RCV, 4, FALSE, FALSE, TRUE }, + { OID_GEN_MULTICAST_BYTES_RCV, 8, FALSE, FALSE, TRUE }, + { OID_GEN_MULTICAST_FRAMES_RCV, 4, FALSE, FALSE, TRUE }, + { OID_GEN_BROADCAST_BYTES_RCV, 8, FALSE, FALSE, TRUE }, + { OID_GEN_BROADCAST_FRAMES_RCV, 4, FALSE, FALSE, TRUE }, + { OID_GEN_RCV_CRC_ERROR, 4, FALSE, FALSE, TRUE }, + { OID_GEN_TRANSMIT_QUEUE_LENGTH, 4, FALSE, FALSE, TRUE }, + + { OID_802_3_PERMANENT_ADDRESS, 6, TRUE, FALSE, TRUE }, + { OID_802_3_CURRENT_ADDRESS, 6, TRUE, FALSE, TRUE }, + { OID_802_3_MULTICAST_LIST, 6, TRUE, TRUE, TRUE }, + { OID_802_3_MAXIMUM_LIST_SIZE, 4, TRUE, FALSE, TRUE }, + + { OID_802_3_RCV_ERROR_ALIGNMENT, 4, FALSE, FALSE, TRUE }, + { OID_802_3_XMIT_ONE_COLLISION, 4, FALSE, FALSE, TRUE }, + { OID_802_3_XMIT_MORE_COLLISIONS, 4, FALSE, FALSE, TRUE }, + + { OID_802_3_XMIT_DEFERRED, 4, FALSE, FALSE, TRUE }, + { OID_802_3_XMIT_MAX_COLLISIONS, 4, FALSE, FALSE, TRUE }, + { OID_802_3_RCV_OVERRUN, 4, FALSE, FALSE, TRUE }, + { OID_802_3_XMIT_UNDERRUN, 4, TRUE, FALSE, TRUE }, + { OID_802_3_XMIT_HEARTBEAT_FAILURE, 4, TRUE, FALSE, TRUE }, + { OID_802_3_XMIT_TIMES_CRS_LOST, 4, TRUE, FALSE, TRUE }, + { OID_802_3_XMIT_LATE_COLLISIONS, 4, TRUE, FALSE, TRUE }, + + { OID_802_5_PERMANENT_ADDRESS, 6, TRUE, FALSE, TRUE }, + { OID_802_5_CURRENT_ADDRESS, 6, TRUE, FALSE, TRUE }, + { OID_802_5_CURRENT_FUNCTIONAL, 4, TRUE, TRUE, TRUE }, + { OID_802_5_CURRENT_GROUP, 4, TRUE, TRUE, TRUE }, + { OID_802_5_LAST_OPEN_STATUS, 4, TRUE, TRUE, TRUE }, + { OID_802_5_CURRENT_RING_STATUS, 4, TRUE, TRUE, TRUE }, + { OID_802_5_CURRENT_RING_STATE, 4, TRUE, TRUE, TRUE }, + + { OID_802_5_LINE_ERRORS, 4, FALSE, FALSE, TRUE }, + { OID_802_5_LOST_FRAMES, 4, TRUE, FALSE, TRUE }, + + { OID_802_5_BURST_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_AC_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_ABORT_DELIMETERS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_FRAME_COPIED_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_FREQUENCY_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_TOKEN_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_802_5_INTERNAL_ERRORS, 4, TRUE, FALSE, TRUE }, + + { OID_FDDI_LONG_PERMANENT_ADDR, 6, TRUE, FALSE, TRUE }, + { OID_FDDI_LONG_CURRENT_ADDR, 6, TRUE, FALSE, TRUE }, + { OID_FDDI_LONG_MULTICAST_LIST, 6, TRUE, TRUE, TRUE }, + { OID_FDDI_LONG_MAX_LIST_SIZE, 4, TRUE, TRUE, TRUE }, + { OID_FDDI_SHORT_PERMANENT_ADDR, 2, TRUE, FALSE, TRUE }, + { OID_FDDI_SHORT_CURRENT_ADDR, 2, TRUE, FALSE, TRUE }, + { OID_FDDI_SHORT_MULTICAST_LIST, 6, TRUE, TRUE, TRUE }, + { OID_FDDI_SHORT_MAX_LIST_SIZE, 4, TRUE, TRUE, TRUE }, + + { OID_FDDI_ATTACHMENT_TYPE, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_UPSTREAM_NODE_LONG, 6, TRUE, FALSE, TRUE }, + { OID_FDDI_DOWNSTREAM_NODE_LONG, 6, TRUE, FALSE, TRUE }, + { OID_FDDI_FRAME_ERRORS, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_FRAMES_LOST, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_RING_MGT_STATE, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_LCT_FAILURES, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_LEM_REJECTS, 4, TRUE, FALSE, TRUE }, + { OID_FDDI_LCONNECTION_STATE, 4, TRUE, FALSE, TRUE }, + + // + // STARTCHANGE + // + { OID_ARCNET_PERMANENT_ADDRESS, 1, TRUE, FALSE, TRUE }, + { OID_ARCNET_CURRENT_ADDRESS, 1, TRUE, FALSE, TRUE }, + { OID_ARCNET_RECONFIGURATIONS, 4, FALSE, FALSE, TRUE }, + // + // STOPCHANGE + // + + // + // Async Objects + // + +/* Not currently supported. + + // + // XXX: the following must be verified for size and the set/query + // booleans. also are the correct OIDs defined? + // + + { OID_ASYNC_PERMANENT_ADDRESS 4, TRUE, FALSE, TRUE }, + { OID_ASYNC_CURRENT_ADDRESS 4, TRUE, FALSE, TRUE }, + { OID_ASYNC_QUALITY_OF_SERVICE 4, TRUE, FALSE, TRUE }, + { OID_ASYNC_PROTOCOL_TYPE 4, TRUE, FALSE, TRUE } + + { OID_LTALK_CURRENT_NODE_ID 4, TRUE, FALSE, TRUE }, + + { OID_LTALK_IN_BROADCASTS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_IN_LENGTH_ERRORS 4, TRUE, FALSE, TRUE }, + + { OID_LTALK_OUT_NO_HANDLERS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_COLLISIONS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_DEFERS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_NO_DATA_ERRORS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_RANDOM_CTS_ERRORS 4, TRUE, FALSE, TRUE }, + { OID_LTALK_FCS_ERRORS 4, TRUE, FALSE, TRUE } +*/ + +}; + + + +ULONG +TpLookUpOidInfo( + IN NDIS_OID RequestOid + ) + +/*++ + +Routine Description: + +Arguments: + + The arguments for the test to be run. + +Return Value: + + +--*/ + +{ + ULONG i; + + for (i=0;i<NUM_OIDS;i++) { + if ( OidArray[i].Oid == RequestOid) { + return i; + } + } + + return 0xFFFFFFFF; +} diff --git a/private/ntos/ndis/testprot/tplib/sources b/private/ntos/ndis/testprot/tplib/sources new file mode 100644 index 000000000..8c30bbdd2 --- /dev/null +++ b/private/ntos/ndis/testprot/tplib/sources @@ -0,0 +1,47 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=tplib +TARGETPATH=obj +TARGETTYPE=LIBRARY + +# Dependent on the setting of the build path. It is assumed that the TESTPROT directory has been +# set up under the dirs private\ntos\ndis +# The following directories will be accessed: +# private\ntos\ndis\testprot\inc private\ntos\inc \private\ntos\ndis\testprot\tpdrvr +# private\inc +INCLUDES=..\inc;..\..\..\inc;..\tpdrvr;..\..\..\..\inc + +SOURCES=oids.c + +i386_SOURCES= + +MIPS_SOURCES= + +RELATIVE_DEPTH=..\..\.. +NTTEST= +OPTIONAL_NTTEST= |