summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/testprot
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/testprot
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/testprot')
-rw-r--r--private/ntos/ndis/testprot/dirs28
-rw-r--r--private/ntos/ndis/testprot/docs/arcnet.docbin0 -> 41019 bytes
-rw-r--r--private/ntos/ndis/testprot/docs/rfc1051227
-rw-r--r--private/ntos/ndis/testprot/docs/rfc1201388
-rw-r--r--private/ntos/ndis/testprot/inc/common.h835
-rw-r--r--private/ntos/ndis/testprot/inc/defaults.h193
-rw-r--r--private/ntos/ndis/testprot/tpctl/cmd.c4160
-rw-r--r--private/ntos/ndis/testprot/tpctl/cpuperf.c307
-rw-r--r--private/ntos/ndis/testprot/tpctl/globals.c390
-rw-r--r--private/ntos/ndis/testprot/tpctl/info.c1497
-rw-r--r--private/ntos/ndis/testprot/tpctl/init.c1098
-rw-r--r--private/ntos/ndis/testprot/tpctl/makefile6
-rw-r--r--private/ntos/ndis/testprot/tpctl/parse.c2526
-rw-r--r--private/ntos/ndis/testprot/tpctl/parse.h312
-rw-r--r--private/ntos/ndis/testprot/tpctl/results.c1312
-rw-r--r--private/ntos/ndis/testprot/tpctl/sources49
-rw-r--r--private/ntos/ndis/testprot/tpctl/tp_ndis.h180
-rw-r--r--private/ntos/ndis/testprot/tpctl/tpctl.c3852
-rw-r--r--private/ntos/ndis/testprot/tpctl/tpctl.h751
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/makefile11
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/sources63
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/tpdiff.c2527
-rw-r--r--private/ntos/ndis/testprot/tpdiff.new/tpdiff.h213
-rw-r--r--private/ntos/ndis/testprot/tpdiff/makefile6
-rw-r--r--private/ntos/ndis/testprot/tpdiff/sources48
-rw-r--r--private/ntos/ndis/testprot/tpdiff/tpdiff.c1749
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/buffer.c313
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/makefile6
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/media.c385
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/media.h350
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/packet.c2164
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/perf.c2162
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/protocol.c442
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/sources57
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/stress.c2503
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/strfunc.c1858
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/strrcv.c1280
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpdefs.h769
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpdrvr.c1656
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpfunc.c4639
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpprocs.h841
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpreq.c952
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tputils.c1080
-rw-r--r--private/ntos/ndis/testprot/tpkd/makefile6
-rw-r--r--private/ntos/ndis/testprot/tpkd/sources55
-rw-r--r--private/ntos/ndis/testprot/tpkd/tpkd.c450
-rw-r--r--private/ntos/ndis/testprot/tpkd/tpkd.def8
-rw-r--r--private/ntos/ndis/testprot/tpkd/tpkd.h781
-rw-r--r--private/ntos/ndis/testprot/tplib/makefile6
-rw-r--r--private/ntos/ndis/testprot/tplib/oids.c206
-rw-r--r--private/ntos/ndis/testprot/tplib/sources47
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
new file mode 100644
index 000000000..db7a2302e
--- /dev/null
+++ b/private/ntos/ndis/testprot/docs/arcnet.doc
Binary files differ
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, &ltemp);
+
+ 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=