Rawether .NET C# Enumeration Test Application

Version 5.51.18.01, August 12, 2004

 

using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Net;
using PcaUsa.Rawether;
using PcaUsa.Rawether.IO;
using PcaUsa.Rawether.ProtocolInterface;
using PcaUsa.Ndis;
using PcaUsa.Ethernet;
// Copyright And Configuration Management ----------------------------------
//
//      Rawether.NET Adapter Enumeration Sample Application - EnumTest.cs
//
//                          Rawether.NET for Windows
//
//  Copyright (c) 2003-2004, Printing Communications Associates, Inc. (PCAUSA)
//
//                              Thomas F. Divine
//                            4201 Brunswick Court
//                         Smyrna, Georgia 30080 USA
//                               (770) 432-4580
//                             tdivine@pcausa.com
//
// End ---------------------------------------------------------------------
namespace PcaUsa.EnumTest
{
    /// <summary>
    /// Rawether.NET C# adapter enumeration sample application.
    /// </summary>
    class EnumTest
    {
        /////////////////////////////////////////////////////////////////////////////
        #region DisplayGeneralStatistics Test
        /// <summary>
        /// Make NDIS queries and display AdapterObject general statistics.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be queried.</param>
        /// <remarks>These are various queries from the OID_GEN_XYZ family. Here we use the
        /// QueryInformation function, which provides a simple interface for fetching
        /// non-critical numeric values. The function is called in the "quiet mode"  by specifying
        /// a default value. This overloaded version of QueryInformation makes the query and
        /// catches I/O and NDIS exceptions. If an exception is encountered default value is silently
        /// returned.</remarks>
        static void DisplayGeneralStatistics( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Adapter General Statistics" );
            // For this simple console sample application make a list of statistics OIDs to
            // query and then query each OID OID in the list in a loop. All statistic OID return
            // values are fetched as Uint32 - although Uint64 could be used if desired.
            //
            // The loop displays the OID using ToString, so it is not "pretty" but easy to implement.
            // Build list of statistics OIDs To query.
            Ndis.Oid[] queryList =
                new Ndis.Oid[]{
                        //
                        // Mandatory General Statistics Queries
                        //
                        Ndis.Oid.OID_GEN_XMIT_OK,
                        Ndis.Oid.OID_GEN_RCV_OK,
                        Ndis.Oid.OID_GEN_XMIT_ERROR,
                        Ndis.Oid.OID_GEN_RCV_ERROR,
                        Ndis.Oid.OID_GEN_RCV_NO_BUFFER,
                        //
                        // Optional General Statistics Queries
                        //
                        Ndis.Oid.OID_GEN_DIRECTED_BYTES_XMIT,
                        Ndis.Oid.OID_GEN_DIRECTED_FRAMES_XMIT,
                        Ndis.Oid.OID_GEN_MULTICAST_BYTES_XMIT,
                        Ndis.Oid.OID_GEN_MULTICAST_FRAMES_XMIT,
                        Ndis.Oid.OID_GEN_BROADCAST_BYTES_XMIT,
                        Ndis.Oid.OID_GEN_BROADCAST_FRAMES_XMIT,
                        Ndis.Oid.OID_GEN_DIRECTED_BYTES_RCV,
                        Ndis.Oid.OID_GEN_DIRECTED_FRAMES_RCV,
                        Oid.OID_GEN_MULTICAST_BYTES_RCV,
                        Ndis.Oid.OID_GEN_MULTICAST_FRAMES_RCV,
                        Ndis.Oid.OID_GEN_BROADCAST_BYTES_RCV,
                        Ndis.Oid.OID_GEN_BROADCAST_FRAMES_RCV,
                        Ndis.Oid.OID_GEN_RCV_CRC_ERROR,
                        Ndis.Oid.OID_GEN_TRANSMIT_QUEUE_LENGTH
                    };
            // Query each OID in the list.
            for( int i = 0; i < queryList.GetLength(0); ++i )
            {
                uint statistic = 0;     // Could use ulong (Uint64) if desired...
                uint returnValue = adapter.QueryInformation( queryList[i], ref statistic, 0 );
                if( returnValue == 0 )
                    Console.WriteLine( "  {0}: {1}", queryList[i].ToString(), statistic );
                else
                    Console.WriteLine( "  {0}: Query Failed; Status: {1}", queryList[i].ToString(), (Ndis.Status )returnValue );
            }
            Console.WriteLine();
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region DisplayEthernetStatistics Test
        /// <summary>
        /// Make NDIS queries and display AdapterObject Ethernet statistics characteristics.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be queried.</param>
        /// <remarks>These are various queries from the OID_802_11_XYZ family. Here we use helper
        /// functions designed to simplify fetching operational characteristics.</remarks>
        static void DisplayEthernetStatistics( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Adapter Ethernet Statistics" );
            // For this simple console sample application make a list of statistics OIDs to
            // query and then query each OID OID in the list in a loop. All statistic OID return
            // values are fetched as Uint32 - although Uint64 could be used if desired.
            //
            // The loop displays the OID using ToString, so it is not "pretty" but easy to implement.
            // Build list of statistics OIDs To query.
            Ndis.Oid[] queryList =
                new Ndis.Oid[]{
                        //
                        // Mandatory Ethernet Statistics Queries
                        //
                        Ndis.Oid.OID_802_3_RCV_ERROR_ALIGNMENT,
                        Ndis.Oid.OID_802_3_XMIT_ONE_COLLISION,
                        Ndis.Oid.OID_802_3_XMIT_MORE_COLLISIONS,
                        //
                        // Optional Ethernet Statistics Queries
                        //
                        Ndis.Oid.OID_802_3_XMIT_DEFERRED,
                        Ndis.Oid.OID_802_3_XMIT_MAX_COLLISIONS,
                        Ndis.Oid.OID_802_3_RCV_OVERRUN,
                        Ndis.Oid.OID_802_3_XMIT_UNDERRUN,
                        Ndis.Oid.OID_802_3_XMIT_HEARTBEAT_FAILURE,
                        Ndis.Oid.OID_802_3_XMIT_TIMES_CRS_LOST,
                        Ndis.Oid.OID_802_3_XMIT_LATE_COLLISIONS
                    };
            // Query each OID in the list.
            for( int i = 0; i < queryList.GetLength(0); ++i )
            {
                uint statistic = 0;     // Could use ulong (Uint64) if desired...
                uint returnValue = adapter.QueryInformation( queryList[i], ref statistic, 0 );
                if( returnValue == 0 )
                    Console.WriteLine( "  {0}: {1}", queryList[i].ToString(), statistic );
                else
                    Console.WriteLine( "  {0}: Query Failed; Status: {1}", queryList[i].ToString(), (Ndis.Status )returnValue );
            }
            Console.WriteLine();
        }
        
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region DisplayEthernetOperationalCharacteristics Test
        /// <summary>
        /// Make NDIS queries and display AdapterObject Ethernet operational characteristics.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be queried.</param>
        /// <remarks>These are various queries from the OID_802_3_XYZ family. Here we use helper
        /// functions designed to simplify fetching operational characteristics.</remarks>
        static void DisplayEthernetOperationalCharacteristics( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Adapter Ethernet Operational Characteristics" );
            uint returnValue = 0;
            Ndis.NDIS_802_3_ADDRESS macAddress = new NDIS_802_3_ADDRESS();
            // Query for Current MAC Address
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_802_3_CURRENT_ADDRESS, macAddress );
            Console.WriteLine( "  Current Address: {0}", macAddress );
            // Query for Permanent MAC Address
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_802_3_PERMANENT_ADDRESS, macAddress );
            Console.WriteLine( "  Permanent Address: {0}", macAddress );
            Console.WriteLine();
            // Query for Multicast List
            Ndis.NDIS_802_3_ADDRESS[] multicastList;
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_802_3_MULTICAST_LIST, out multicastList );
            if( returnValue == 0 )
            {
                Console.WriteLine( "  Multicast List:"  );
                if( multicastList.GetLength( 0 ) == 0 )
                {
                    Console.WriteLine( "    Empty List" );
                }
                else
                {
                    for( int i = 0; i < multicastList.GetLength( 0 ); ++i )
                    {
                        Console.WriteLine( "    Address {0}: {1}", i, multicastList[i] );
                    }
                }
            }
            else
                Console.WriteLine( "  Multicast List Query: Failed; Status: {0}", (Ndis.Status )returnValue );
            Console.WriteLine();
            DisplayWLANInformation( adapter, false );
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region DisplayWLANInformation Test
        /// <summary>
        /// Make NDIS queries and display AdapterObject wireless LAN (802.11) information.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be queried.</param>
        /// <param name="testSetInformation">If this parameter is true then the test will exercise
        /// illustrative calls to set 802.11 information.</param>
        /// <remarks>These are various queries from the OID_802_11_XYZ family. Here we use helper
        /// functions designed to simplify fetching operational characteristics.</remarks>
        /// <remarks>Some SetInformation code fragments are conditionally excluded from being
        /// executed by the testSetInformation parameter. The code that is excluded correctly
        /// illustrates the syntax of the SetInformation call. However, the code fragments should
        /// not actually be executed in the context of this simple demonstration application. If the
        /// SetInformation code fragments were actually executed the behavior would not be
        /// sensible.</remarks>
        static void DisplayWLANInformation( AdapterObject adapter, bool testSetInformation )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Adapter 802.11 Information" );
            // Get 802.11 Adapter Supported Rates
            Ndis.NDIS_802_11_SUPPORTED_RATES supportedRates = new Ndis.NDIS_802_11_SUPPORTED_RATES();
            uint returnValue;
            
            returnValue = adapter.QueryInformation( supportedRates );
            if( returnValue == 0 )
                Console.WriteLine( "  Supported Rates: {0} Mbps", supportedRates.ToString() );
            else
            {
                Console.WriteLine( "  Supported Rates: Query Failed; Status: {0}", (Ndis.Status )returnValue );
                return;
            }
            // Query for SSID
            Ndis.NDIS_802_11_SSID ssid = new Ndis.NDIS_802_11_SSID();
            returnValue = adapter.QueryInformation( ssid );
            if( returnValue == 0 )
                Console.WriteLine( "  SSID: \x22{0}\x22", ssid );
            else
                Console.WriteLine( "  SSID: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Possibly Illustrate Setting SSID
            if( testSetInformation && adapter.CanSetInformation )
            {
                //Set the SSID
                //                ssid.Ssid = "pcausa-gee";
                ssid.SetBytes( new byte[] { 0x70, 0x63, 0x61, 0x75, 0x73, 0x61, 0x2D, 0x67, 0x65, 0x65 } );
 
                returnValue = adapter.SetInformation( ssid );
                if( returnValue == 0 )
                    Console.WriteLine( "  Set SSID: Successful" );
                else
                    Console.WriteLine( "  Set SSID: Failed" );
                // Query SSID after setting
                returnValue = adapter.QueryInformation( ssid );
                if( returnValue == 0 )
                    Console.WriteLine( "  SSID After Setting: \x22{0}\x22", ssid );
                else
                    Console.WriteLine( "  SSID After Setting: Query Failed" );
            }
            // Query for BSSID
            Ndis.NDIS_802_3_ADDRESS macAddress = new NDIS_802_3_ADDRESS();
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_802_11_BSSID, macAddress );
            if( returnValue == 0 )
                Console.WriteLine( "  MacAddress: {0}", macAddress );
            else
                Console.WriteLine( "  MacAddress: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            if( adapter.CanSetInformation )
            {
                // Set BSSID
                macAddress.SetAddress( new byte[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } );
                returnValue = adapter.SetInformation( Ndis.Oid.OID_802_11_BSSID, macAddress );
                if( returnValue == 0 )
                    Console.WriteLine( "  Set BSSID: Operation Successful" );
                else
                    Console.WriteLine( "  Set BSSID: Operation Failed" );
            }
            // Query for RSSI
            Ndis.NDIS_802_11_RSSI rssi = new NDIS_802_11_RSSI();
            returnValue = adapter.QueryInformation( rssi );
            if( returnValue == 0 )
            {
                Console.WriteLine( "  RSSI: {0} dBm ({1})", rssi, rssi.SignalStrength );
            }
            else
                Console.WriteLine( "  RSSI: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Query for Infrastructure Mode
            Ndis.NDIS_802_11_NETWORK_INFRASTRUCTURE infrastructureMode = new NDIS_802_11_NETWORK_INFRASTRUCTURE();
            returnValue = adapter.QueryInformation( ref infrastructureMode );
            if( returnValue == 0 )
                Console.WriteLine( "  Infrastructure Mode: {0}", infrastructureMode );
            else
                Console.WriteLine( "  Infrastructure Mode: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Possibly Illustrate Setting Infrastructure Mode
            if( ( testSetInformation == true ) && ( adapter.CanSetInformation == true ) )
            {
                // Set infrastructure mode
                infrastructureMode = Ndis.NDIS_802_11_NETWORK_INFRASTRUCTURE.IBSS;    // An example...
                returnValue = adapter.SetInformation( infrastructureMode );
                if( returnValue == 0 )
                    Console.WriteLine( "  Set Infrastructure Mode: Operation Successful" );
                else
                    Console.WriteLine( "  Set Infrastructure Mode: Operation Failed" );
            }
            // Query for Authentication Mode
            Ndis.NDIS_802_11_AUTHENTICATION_MODE authenticationMode = new NDIS_802_11_AUTHENTICATION_MODE();
            returnValue = adapter.QueryInformation( ref authenticationMode );
            if( returnValue == 0 )
                Console.WriteLine( "  Authentication Mode: {0}", authenticationMode );
            else
                Console.WriteLine( "  Authentication Mode: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Query for Encryption Status
            Ndis.NDIS_802_11_ENCRYPTION_STATUS encryptionStatus = new NDIS_802_11_ENCRYPTION_STATUS();
            returnValue = adapter.QueryInformation( ref encryptionStatus );
            if( returnValue == 0 )
                Console.WriteLine( "  Encryption Status: {0}", encryptionStatus );
            else
                Console.WriteLine( "  Encryption Status: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Possibly Illustrate Setting Authentication Mode
            if( testSetInformation && adapter.CanSetInformation )
            {
                // Set Authentication Mode
                authenticationMode = Ndis.NDIS_802_11_AUTHENTICATION_MODE.Open;   // An example
                returnValue = adapter.SetInformation( authenticationMode );
                if( returnValue == 0 )
                    Console.WriteLine( "  Set Authentication Mode: Operation Successful" );
                else
                    Console.WriteLine( "  Set Authentication Mode: Operation Failed" );
            }
            // Query for network type in use
            Ndis.NDIS_802_11_NETWORK_TYPE networkType = new NDIS_802_11_NETWORK_TYPE();
            returnValue = adapter.QueryInformation( ref networkType );
            if( returnValue == 0 )
                Console.WriteLine( "  Network Type In Use: {0}", networkType );
            else
                Console.WriteLine( "  Network Type In Use: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Possibly Illustrate Setting Network Type
            if( testSetInformation && adapter.CanSetInformation )
            {
                // Set network type in use
                networkType = Ndis.NDIS_802_11_NETWORK_TYPE.DirectSequencing;   // An example...
                returnValue = adapter.SetInformation( networkType );
                if( returnValue == 0 )
                    Console.WriteLine( "  Set Network Type In Use: Operation Successful" );
                else
                    Console.WriteLine( "  Set Network Type In Use: Operation Failed" );
            }
            // Query for 802.11 configuration
            NDIS_802_11_CONFIGURATION configutation = new NDIS_802_11_CONFIGURATION();
            returnValue = adapter.QueryInformation( ref configutation );
            if( returnValue == 0 )
            {
                Console.WriteLine( "  Configuration: Query Successful" );
                Console.WriteLine( "    Beacon Period: {0} Kusec", configutation.BeaconPeriod );
                Console.WriteLine( "    ATIM Window: {0} Kusec", configutation.ATIMWindow );
                // Calculate and Display Frequency and Channel
                uint channel = 0;
                if( configutation.DSConfig >= 2412000 )
                {
                    channel = ( (configutation.DSConfig - 2412000)/5000 ) + 1;
                }
                Console.WriteLine( "    DSConfig: {0} MHz (CH {1})", configutation.DSConfig/1000, channel );
                if( adapter.CanSetInformation )
                {
                    // Set 802.11 configuration
                    // ------------------------
                    // For illustrative purposes, just set the same data queried above. Understand that
                    // although this is a mandatory OID, some adapters do not seem to accept it.
                    returnValue = adapter.SetInformation( ref configutation );
                    if( returnValue == 0 )
                        Console.WriteLine( "  Set Configuration: Successful" );
                    else
                        Console.WriteLine( "  Set Configuration: Failed; Status: {0}", (Ndis.Status )returnValue );
                }
            }
            else
                Console.WriteLine( "  802.11 Configuration: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            if( adapter.CanSetInformation )
            {
                // Make a call to start BSSID list scan
                returnValue = adapter.SetInformation( Ndis.Oid.OID_802_11_BSSID_LIST_SCAN );   // No parameter required
            }
            // Make a call to get a BSSID list
            BssidList bssidList = new BssidList();
            returnValue = adapter.QueryInformation( bssidList );
            if( returnValue == 0 )
            {
                int i = 0;
                Console.WriteLine();
                Console.WriteLine( "  BSSID List: Query Successful" );
                Console.WriteLine( "    Number of Items: {0}", bssidList.NumberOfItems );
                foreach( BssidListItem bssidItem in bssidList )
                {
                    Console.WriteLine();
                    Console.WriteLine( "  BSSID_LIST Entry {0}", i++ );
                    // Display The MacAddress Field
                    Console.WriteLine( "    MacAddress: {0}", bssidItem.MacAddress.ToString() );
                    // Display The Ssid
                    Console.WriteLine( "    SSID: \x22{0}\x22", bssidItem.Ssid );
                    // Display Rssi
                    Console.WriteLine( "    RSSI: {0} dBm ({1})", bssidItem.Rssi, bssidItem.Rssi.SignalStrength );
                    // Display Network Type In Use
                    Console.WriteLine( "    Network Type In Use: {0}", bssidItem.NetworkTypeInUse );
                    // Display Infrastructure Mode
                    Console.WriteLine( "    InfrastructureMode: {0}", bssidItem.InfrastructureMode );
                    // Display Supported Rates
                    Console.WriteLine( "    Supported Rates: {0} Mbps", bssidItem.SupportedRates.ToString() );
                    // Display Configuration Information
                    NDIS_802_11_CONFIGURATION itemConfiguration = bssidItem.Configuration;
                    Console.WriteLine( "    Configuration:" );
                    Console.WriteLine( "      Beacon Period: {0} Kusec", itemConfiguration.BeaconPeriod );
                    Console.WriteLine( "      ATIM Window: {0} Kusec", itemConfiguration.ATIMWindow );
                    // Calculate and Display Frequency and Channel
                    uint channel = 0;
                    if( itemConfiguration.DSConfig >= 2412000 )
                    {
                        channel = ( (itemConfiguration.DSConfig - 2412000)/5000 ) + 1;
                    }
                    Console.WriteLine( "      DSConfig: {0} MHz (CH {1})", itemConfiguration.DSConfig/1000, channel );
                    // Display information elements from beacon or probe response messages
                    int IELength = bssidItem.IELength;
                    if( IELength > 0 )
                    {
                    }
                }
            }
            else
                Console.WriteLine( "  BSSID List: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Possibly illustrate Reloading Defaults, etc.
            if( testSetInformation && adapter.CanSetInformation )
            {
                // Make a call to reload defaults
                returnValue = adapter.SetInformation( Ndis.Oid.OID_802_11_RELOAD_DEFAULTS );   // No parameter required
                // Make a call to remove a WEP key
                uint keyIndex = 0;  // NDIS_802_11_KEY_INDEX is a ULONG...
                returnValue = adapter.SetInformation( Ndis.Oid.OID_802_11_REMOVE_WEP, keyIndex );
                // Make a call to disassociate
                returnValue = adapter.SetInformation( Ndis.Oid.OID_802_11_DISASSOCIATE );  // No parameter required
            }
            Console.WriteLine();
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region DisplayGeneralOperationCharacteristics Test
        /// <summary>
        /// Make NDIS queries and display AdapterObject general operational characteristics.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be queried.</param>
        /// <remarks>These are various queries from the OID_GEN_XYZ family. Here we use helper
        /// functions designed to simplify fetching operational characteristics.</remarks>
        static void DisplayGeneralOperationCharacteristics( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Adapter General Operational Characteristics" );
            uint returnValue = 0;
            // Get Adapter's Vendor Description String
            string vendorDescription;
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_GEN_VENDOR_DESCRIPTION, out vendorDescription );
            if( returnValue == 0 )
                Console.WriteLine( "  Vendor Description: {0}", vendorDescription );
            else
                Console.WriteLine( "  Vendor Description: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // For this simple console sample application make a list of statistics OIDs to
            // query and then query each OID OID in the list in a loop. All statistic OID return
            // values are fetched as Uint32.
            //
            // The loop displays the OID using ToString, so it is not "pretty" but easy to implement.
            // Build list of statistics OIDs To query.
            Ndis.Oid[] queryList =
                new Ndis.Oid[]{
                        //
                        // Mandatory General Statistics Queries
                        //
                        Ndis.Oid.OID_GEN_MAXIMUM_FRAME_SIZE,
                        Ndis.Oid.OID_GEN_MAXIMUM_TOTAL_SIZE,
                        Ndis.Oid.OID_GEN_CURRENT_LOOKAHEAD,
                        Ndis.Oid.OID_GEN_MAXIMUM_LOOKAHEAD,
                        Ndis.Oid.OID_GEN_LINK_SPEED
                    };
            // Query each OID in the list.
            for( int i = 0; i < queryList.GetLength(0); ++i )
            {
                uint statistic = 0;
                returnValue = adapter.QueryInformation( queryList[i], ref statistic, 0 );
                if( returnValue == 0 )
                    Console.WriteLine( "  {0}: {1}", queryList[i].ToString(), statistic );
                else
                    Console.WriteLine( "  {0}: Query Failed; Status: {1}", queryList[i].ToString(), (Ndis.Status )returnValue );
            }
            // Get Current NDIS packet filter value
            PacketTypes packetFilter = PacketTypes.None;
            returnValue = adapter.QueryInformation( ref packetFilter );
            Console.WriteLine( "  Current Packet Filter: {0}", packetFilter.ToString() );
            // Get Physical Medium
            // -------------------
            // Note that support for OID_GEN_PhysicalMedium is optional. It is usually
            // supported on 802.11 adapters but not otherwise.
            Ndis.PhysicalMedium physicalMedium = Ndis.PhysicalMedium.Max;
            returnValue = adapter.QueryInformation( ref physicalMedium );
            if( returnValue == 0 )
                Console.WriteLine( "  Physical Medium: {0}", physicalMedium.ToString() );
            else
                Console.WriteLine( "  Physical Medium: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            // Get Media Connect State
            MediaState connectState = Ndis.MediaState.Unknown;
            returnValue = adapter.QueryInformation( ref connectState );
            Console.WriteLine( "  Media Connect Status: {0}", connectState.ToString() );
            // Get Medium In Use
            Ndis.Medium ndisMedium = Ndis.Medium.Max;
            returnValue = adapter.QueryInformation( ref ndisMedium );
            Console.WriteLine( "  Media In Use: {0}", ndisMedium.ToString() );
            Console.WriteLine();
            // Display Supported OID List
            // --------------------------
            // This is really just ot illustrate making a query on an array of uint's using the
            // out method parameter keyword.
            uint[] oidList = null;
            returnValue = adapter.QueryInformation( Ndis.Oid.OID_GEN_SUPPORTED_LIST, out oidList );
            Console.WriteLine( "  Supported OID List:" );
            if( returnValue == 0 )
            {
                if( oidList == null )
                {
                    Console.WriteLine( "    Empty List" );
                }
                else
                {
                    int length = oidList.GetLength(0);
                    Console.WriteLine( "    {0} Supported OIDs", length );
                    for( int i = 0; i < length; ++i )
                    {
                        if( oidList[i] >= (uint )0xFF000000 )
                        {
                            // Display Proprietary OIDs in HEX format
                            Console.WriteLine( "      {0} - 0x{1:X8}", i, oidList[i] );
                        }
                        else
                        {
                            // Display OID Enumeration Name for Known OIDs
                            Console.WriteLine( "      {0} - {1} (0x{2:X8})", i, (Ndis.Oid )oidList[i], oidList[i] );
                        }
                    }
                }
            }
            else
                Console.WriteLine( "  Supported OID List: Query Failed; Status: {0}", (Ndis.Status )returnValue );
            Console.WriteLine();
            Console.WriteLine();
            // Display Media-Specific Operational Characteristics
            switch( ndisMedium )
            {
                case Ndis.Medium.Dix:
                case Ndis.Medium.Ieee802_3:
                    DisplayEthernetStatistics( adapter );
                    DisplayEthernetOperationalCharacteristics( adapter );
                    break;
                case Ndis.Medium.Ieee1394:
                    break;
                default:
                    break;
            }
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region SetInformationTest Test
        /// <summary>
        /// Make NDIS queries and display the NDIS packet filter setting.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be tested.</param>
        /// <remarks>These are various queries from the OID_GEN_XYZ family. Here we use helper
        /// functions designed to simplify fetching operational characteristics.</remarks>
        static void SetInformationTest( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Set Information Test" );
            if( !adapter.CanSetInformation )
            {
                Console.WriteLine( "  Cannot set information using this AdapterObject" );
                return;
            }
            // Get Initial NDIS packet filter value
            PacketTypes originalFilter = PacketTypes.None;
            uint returnValue = adapter.QueryInformation( ref originalFilter );
            Console.WriteLine( "  Initial Packet Filter: {0}", originalFilter.ToString() );
            // Set NDIS packet filter to PROMISCUOUS
            returnValue = adapter.SetInformation( PacketTypes.Promiscuous );
            if( returnValue == 0 )
            {
                // Get NDIS packet filter value after setting
                PacketTypes updatedFilter = PacketTypes.None;
                returnValue = adapter.QueryInformation( ref updatedFilter );
                Console.WriteLine( "  SetPacketFilter: Successful; New Filter: {0}", updatedFilter.ToString() );
                // Restore Original NDIS Packet Filter
                returnValue = adapter.SetInformation( originalFilter );
                // Get NDIS packet filter value after resetting
                returnValue = adapter.QueryInformation( ref updatedFilter );
                Console.WriteLine( "  Packet Filter After Resetting: {0}", updatedFilter.ToString() );
            }
            else
                Console.WriteLine( "  SetPacketFilter: Failed; Status: {0}", (Ndis.Status )returnValue );
            Console.WriteLine();
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////
        #region Trivial Send Packet Test
        /// <summary>
        /// Trivial send packet example.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be tested.</param>
        /// <remarks>This trivial sample illustrates how to use the Rawether .NET
        /// SendSinglePacket function.</remarks>
        static void SendPacketTest( AdapterObject adapter, int numPackets )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Send Packet Test" );
            if( !adapter.CanSendPackets )
            {
                Console.WriteLine( "  Cannot send packets using using this AdapterObject" );
                return;
            }
            // This test only operates on 802.3 adapters
            if( adapter.MediaInUse != Ndis.Medium.Ieee802_3 )
            {
                Console.WriteLine( "  SendPacketTest cannot send on medium {0}", adapter.MediaInUse );
                return;
            }
            EthernetPacket packet = new EthernetPacket();
            // Create a PacketWriter for Packet Data
            // -------------------------------------
            // For sure a simple byte array can be used instead of a memory stream. More later
            // on this topic.
            PacketWriter packetWriter = new PacketWriter( packet );
            // Initialize the Packet MAC Header
            // --------------------------------
            //    Destination MAC Address -> Broadcast Address (0xFFFFFFFF)
            //    Source MAC Address      -> Fetched from the Adapter
            //    Ethernet Type           -> DEC Experimental (0x6000)
            //
            // The packet to be sent will look like this when it is sent on the network (from
            // an actual capture):
            //
            //    Packet No.: 0000000001            Time: 0342003053 msec       Length: 64/64
            //    Ethernet Dest: FF.FF.FF.FF.FF.FF   Src:  00.40.F4.00.07.B5    Type: 0x6000
            //    000000:  FF FF FF FF FF FF 00 40 : F4 00 07 B5 60 00 23 50    .......@....`.#P
            //    000010:  43 41 55 53 41 20 52 61 : 77 65 74 68 65 72 20 2E    CAUSA Rawether .
            //    000020:  4E 45 54 20 2D 20 43 23 : 20 56 65 72 73 69 6F 6E    NET - C# Version
            //    000030:  2E 20 00 00 00 00 00 00 : 00 00 00 00 00 00 00 00    . ..............
            //
            packetWriter.Write( Ndis.NDIS_802_3_ADDRESS.Broadcast );
            packetWriter.Write( adapter.EthernetCurrentAddress );   // AdapterObject has automatic query for this...
            packetWriter.Write( PacketWriter.HostToNetOrder( (ushort )Ethernet.EtherType.ETHERTYPE_DECEXPER ) );
            // Initialize Packet Payload
            string aString = "PCAUSA Rawether .NET - C# Version. ";
            packetWriter.Write( aString );
            uint packetTotalSize = (uint )packet.Position;
            for( int i = 0; i < numPackets; ++i )
            {
                uint returnValue;
               
                Console.WriteLine( "Sending Packet {0} of {1}", i + 1, numPackets );
                Console.WriteLine( "{0}", packet.ToString() );
                // Send The Packet
                // --------------
                // The SendSinglePacket function will block the current thread and send the network
                // frame synchronously.
                //
                try
                {
//                    returnValue = adapter.SendSinglePacket( packet.GetBuffer(), packetTotalSize );
                    returnValue = adapter.SendSinglePacket( packet );
                }
                catch( Rawether.Exceptions.AdapterIOException e )
                {
                    Console.WriteLine( "SendSinglePacket: AdapterIOException: {0}", e.LastError );
                    break;
                }
                if( returnValue == 0 )
                {
                    Console.WriteLine( "  SendPacket: Successful" );
                    Thread.Sleep( 10 );
                }
                else
                {
                    Console.WriteLine( "  SendPacket: Failed; Status: {0}", (Ndis.Status )returnValue );
                    break;
                }
            }
            Console.WriteLine();
        }
        #endregion
        #region Receive Packets Test
        /// <summary>
        /// Event that is used to shutdown the receiver thread.
        /// </summary>
        static event EventHandler ReceiverShutdownEvent;
        /// <summary>
        /// Invoke to shutdown the receiver thread.
        /// </summary>
        /// <param name="e"></param>
        static void SignalShutdown(AdapterObject adapter, EventArgs e) 
        {
            if( ReceiverShutdownEvent == null )
            {
                Console.WriteLine( "SignalShutdown: ReceiverShutdownEvent is null " );
                return;
            }
            foreach( EventHandler handler in ReceiverShutdownEvent.GetInvocationList() )
            {
                if( e == null )
                {
                    handler( adapter, null );
                }
                else
                {
                    handler( adapter, e );
                }
            }
        }
        /// <summary>
        /// Class defining receive thread, state information and asynchronous packet read callback.
        /// </summary>
        public class ReceiveHandler
        {
            public AdapterObject adapter;
            public int count;
            public int callsHandled = 0;
            public bool receiverShutdown = false;
            private AsyncCallback readCallback = null;
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="adapter">The AdapterObject that packets are being received on.</param>
            /// <param name="count">Simply illustrates initializing a parameter in the ReceiveHandler
            /// class when it is constructed.</param>
            public ReceiveHandler( AdapterObject adapter, int count )
            {
                this.adapter = adapter;
                this.count = count;
                readCallback = new AsyncCallback( PacketReadCallback );
            }
            /// <summary>
            /// Shutdown event handler.
            /// </summary>
            /// <param name="sender">Object passed to SignalShutdown.</param>
            /// <param name="e">EventArgs passed to SignalShutdown.</param>
            public void Shutdown(object sender, EventArgs e) 
            {
                Console.WriteLine("Shutdown Event Called.");
                receiverShutdown = true;
            }
            /// <summary>
            /// Display representative packet data.
            /// </summary>
            /// <param name="packet">The packet data to be displayed.</param>
            public void DisplayPacket( EthernetPacket packet )
            {
                PacketReader packetReader = new PacketReader( packet );
                Console.WriteLine( "BinaryReader: Offset: {0}; Data: {1}", packet.Position, packetReader.ReadEthernetAddress() );
                Console.WriteLine( "BinaryReader: Offset: {0}; Data: {1}", packet.Position, packetReader.ReadEthernetAddress() );
                Console.WriteLine( "BinaryReader: Offset: {0}; Data: {1}", packet.Position, (Ethernet.EtherType )PacketReader.NetToHostOrder( packetReader.ReadUInt16() ) );
                /*
Packet Number: 22          Timestamp: 185822000 msec   Length: 554
Dest: 00-06-25-8C-EE-6D   Src: 00-40-F4-00-07-B5      Type: ETHERTYPE_IP
*** Is LOOPBACK ***
                */
                // The packet ToString method provides basic information about the packet
                Console.WriteLine( "{0}", packet.ToString() );
                if( packet.DestinationAddress.IsBroadcast == true )
                {
                    Console.WriteLine( "  *** Dest is BROADCAST ***" );
                }
                if( packet.DestinationAddress.IsMulticast == true )
                {
                    Console.WriteLine( "  *** Dest is MULTICAST ***" );
                }
                if( adapter.IsEthernet == true )
                {
                    if( packet.DestinationAddress == adapter.EthernetCurrentAddress )
                    {
                        Console.WriteLine( "  *** Is DIRECTED ***" );
                    }
                    if( packet.SourceAddress == adapter.EthernetCurrentAddress )
                    {
                        Console.WriteLine( "  *** Is LOOPBACK ***" );
                    }
                }
                Console.WriteLine();
            }
            /// <summary>
            /// Callback method to be called when the asynchronous packet read operation is completed.
            /// </summary>
            /// <param name="ar">The IAsyncResult associated with the BeginGetPacket or GetPacket call
            /// that started this operation.</param>
            /// <remarks>Under some condifions this callback can be re-entered as soon as the BeginGetPacket
            /// call is made (below).</remarks>
            public void PacketReadCallback( IAsyncResult ar ) 
            {
                ++callsHandled;
                if( this.receiverShutdown == true )
                {
                    return;
                }
                
                AdapterObject adapter = (AdapterObject )ar.AsyncState;
                EthernetPacket packet;
                try
                {
                    // Since the media is 802.3 packet data is returned as EthernetPacket
                    packet = (EthernetPacket )adapter.EndGetPacket( ar );
                }
                catch( Rawether.Exceptions.AdapterIOException e )
                {
                    Console.WriteLine( "PacketReadCallback: AdapterIOException: {0}", e.LastError );
                    SignalShutdown( adapter, null );
                    return;
                }
                DisplayPacket( packet );
                if( this.receiverShutdown != true )
                {
                    try
                    {
                        ar = adapter.BeginGetPacket( readCallback, adapter );
                    }
                    catch( Rawether.Exceptions.AdapterIOException e )
                    {
                        Console.WriteLine( "PacketReadCallback: AdapterIOException: {0}", e.LastError );
                        SignalShutdown( adapter, null );
                        return;
                    }
                }
            }
            /// <summary>
            /// The ReceiveHandler thread start procedure.
            /// </summary>
            public void ThreadProc()
            {
                uint returnValue;
                // Get Media Connect State
                MediaState connectState = Ndis.MediaState.Unknown;
                adapter.QueryInformation( ref connectState );
                if( connectState == MediaState.Disconnected )
                {
                    Console.WriteLine( "  This AdapterObject is in Disconnected state" );
                    receiverShutdown = true;
                    return;
                }
                else if( connectState == MediaState.Unknown )
                {
                    Console.WriteLine( "  This AdapterObject is in UNKNOWN connect state" );
                    Console.WriteLine( "  Packets might not be received on this adapter" );
                }
                // Set NDIS packet filter to PROMISCUOUS
                // -------------------------------------
                // This effectively "turns on" the packet reception capability of the driver.
                returnValue = adapter.SetInformation( PacketTypes.Promiscuous );
                if( returnValue != 0 )
                {
                    Console.WriteLine( "  Unable to set NDIS packet filter to Promiscuous mode" );
                    returnValue = adapter.SetInformation( PacketTypes.AllLocal );
                }
                if( returnValue != 0 )
                {
                    Console.WriteLine( "  Unable to set NDIS packet filter" );
                    receiverShutdown = true;
                    return;
                }
                ReceiverShutdownEvent += new EventHandler(Shutdown);
//                // Optional Calls to Configure the Packet Read (Receive) Queue
//                // -----------------------------------------------------------
//                // These three optional calls can be made to adjust the configuration of the
//                // packet read queue. The parameters passed in the example calls are actually
//                // the default values that are used if the calls were not made at all.
//
//                // Configure read (receive) queue sizes. (Optional)
//                adapter.ConfigureReadQueue( 65535, 3 ); // Three 64KB buffers
//
//                // Specify the read idle timeout. (Optional)
//                adapter.SetReadIdleTimeout( 300 );  // 300 milliseconds
                // Create a BPF program that accepts only IP packets
                ulong[] bpfProgram = new ulong[]
                {
                    // Load accumulator with "half-word" (UInt16) extracted from packet at offset 12.
                    // This is the offset to the Ethernet Type/Length field.
                    Bpf.Statement( Bpf.LD + Bpf.H + Bpf.ABS, 12),
                    // Compare in accumulator the accumulator to ETHERTYPE_IP.
                    // Branch to instruction that returns accept value (pc+0) if equal.
                    // Branch to instruction that returns reject value (pc+1) if not equal.
                    Bpf.Jump( Bpf.JMP + Bpf.JEQ + Bpf.K, Ethernet.EtherType.ETHERTYPE_IP, 0, 1),
                    // Instruction that returns accept value.
                    Bpf.Statement( Bpf.RET + Bpf.K, UInt32.MaxValue),
                    // Instruction that returns reject value (i.e., accept zero bytes).
                    Bpf.Statement( Bpf.RET + Bpf.K, 0)
                };
                // Pass the BPF program to the adapter.
//                adapter.SetBpfProgram( bpfProgram );
                // Disable reception of send packets that are looped back into the receive path.
//                adapter.EnableLoopback( false );
#if !ZNEVER
                // Read test using asynchronous callback
                adapter.BeginGetPacket( readCallback, adapter );
                while( this.receiverShutdown != true )
                {
                    Console.WriteLine( "ThreadProc: Handled {0} calls", this.callsHandled );
                    Thread.Sleep( 1000 );
                }
#else
                // Read test using Begin/End methods
                while( this.receiverShutdown != true )
                {
                    IAsyncResult ar = adapter.BeginGetPacket( null, null );
                    // Since the media is 802.3 packet data is returned as EthernetPacket
                    EthernetPacket packet = (EthernetPacket )adapter.EndGetPacket( ar );
                    DisplayPacket( packet );
                }
#endif
                // Remove the BPF program. Driver will accept all packets.
                // Note: Not really necessary. Just exercising the API.
                adapter.SetBpfProgram( null );
                ReceiverShutdownEvent -= new EventHandler(Shutdown);
                // Set NDIS packet filter to NONE
                // ------------------------------
                // This effectively "turns off" the packet reception capability of the driver.
                //
                // We check IsOpen because there could have been a surprise removal of the adapter.
                // Making the SetInformation call on an adapter that has laready been closed will
                // generate another exception...
                if( adapter.IsOpen == true )
                {
                    returnValue = adapter.SetInformation( PacketTypes.None );
                    if( returnValue != 0 )
                    {
                        Console.WriteLine( "  Unable to set NDIS packet filter to None mode" );
                    }
                }
                Console.WriteLine( "ThreadProc: Exiting" );
                receiverShutdown = true;
            }
        }
        /// <summary>
        /// Trivial receive packets example.
        /// </summary>
        /// <param name="adapter">Specifies the adapter to be tested.</param>
        /// <remarks>This trivial sample illustrates how to use the Rawether .NET
        /// XXXX function.</remarks>
        static void ReceivePacketsTest( AdapterObject adapter )
        {
            Console.WriteLine( "*****************************************" );
            Console.WriteLine( "Receive Packets Test" );
            if( !adapter.CanReceivePackets )
            {
                Console.WriteLine( "  Cannot receive packets using using this AdapterObject" );
                return;
            }
            // This test only operates on 802.3 adapters
            if( adapter.MediaInUse != Ndis.Medium.Ieee802_3 )
            {
                Console.WriteLine( "  ReceivePacketsTest cannot receive on medium {0}", adapter.MediaInUse );
                return;
            }
            ReceiveHandler recvHandler = new ReceiveHandler( adapter, 500 );
            Thread t = new Thread( new ThreadStart( recvHandler.ThreadProc ) );
            
            t.Name = "ReceiveHandler";
            t.Start();
            for (int i = 0; i < 60; i++) 
            {
                if( ( t.IsAlive != true ) || ( recvHandler.receiverShutdown == true ) )
                {
                    break;
                }
            
                Console.WriteLine( "Main Thread: Loop: {0}; Handled {1} receive events calls", i, recvHandler.callsHandled );
                Thread.Sleep(1000);
                SendPacketTest( adapter, 20 );
            }
            if( t.IsAlive == true )
            {
                SignalShutdown( adapter, null );
            }
            Console.WriteLine("Main thread: Call Join(), to wait until ReceiveProc ends.");
            t.Join();
            Console.WriteLine("Main thread: ThreadProc.Join has returned.");
            Console.WriteLine();
        }
        
        #endregion
        /// <summary>
        /// The main entry point for the EnumTest application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine( "Rawether.NET Adapter Enumeration Test Application (Visual C#)" );
            Console.WriteLine( "Copyright (c) 2000-2004 Printing Communications Associates, Inc" );
            Console.WriteLine();
            Console.WriteLine( "Friendly Name: {0}", AppDomain.CurrentDomain.FriendlyName );
            Console.WriteLine( "OS  : {0}", Environment.OSVersion );
            Console.WriteLine( "Date: {0}", DateTime.Now.ToLocalTime() );
            Console.WriteLine();
            // Create an Instance of the Desired Rawether Driver Object
            // --------------------------------------------------------
            // This may throw exceptions if the specified driver is not present or has faults.
            DriverObject ndisDriver = null;
            try
            {
//                ndisDriver = new PcaFltDriver();
                ndisDriver = new PcaMprProtDriver();
//                ndisDriver = new PcaMuxDriver();
//                ndisDriver = new PcaLwfDriver();
            }
            catch( Rawether.Exceptions.DriverNotPresent )
            {
                Console.WriteLine( "Rawether NDIS driver is not present" );
                return;
            }
            // Verify that NDIS driver has a protocol interface
            if( ndisDriver.HasProtocolInterface != true )
            {
                Console.WriteLine( "{0} does not have a protocol interface", ndisDriver.Description );
                return;
            }
            Console.WriteLine( "Using {0} Version {1}", ndisDriver.Description, ndisDriver.Version );
            Console.WriteLine();
            // Create The Adapter Collection
            AdapterCollection adapterList = ndisDriver.GetAdapterCollection();
            // Perform The Adapter Enumeration
            foreach( BindingName adapterName in adapterList )
            {
                Console.WriteLine( "*****************************************" );
                // Display AdapterName Information
                Console.WriteLine( "Friendly Name  : {0}", adapterName.InstanceName );
                Console.WriteLine( "DeviceName Name: {0}", adapterName.DeviceName );
                AdapterObject adapter;
                // Open an AdapterObject on the found AdapterName
                try
                {
                    adapter = ndisDriver.OpenAdapter( adapterName );
                }
                catch( Rawether.Exceptions.OpenAdapterFailedException )
                {
                    Console.WriteLine( "OpenAdapter: FAILED." );
                    continue;
                }
                Console.WriteLine( "OpenAdapter: SUCCESSFUL" );
                Console.WriteLine();
                DisplayGeneralStatistics( adapter );
                DisplayGeneralOperationCharacteristics( adapter );
                SetInformationTest( adapter );
                SendPacketTest( adapter, 20 );
                // Get Media Connect State
                MediaState connectState = Ndis.MediaState.Unknown;
                adapter.QueryInformation( ref connectState );
                // NOTE: Rawether .NET reports "Disconnected" only if the adapter actually supports
                // the OID_GEN_MEDIA_CONNECT_STATE query. If the OID is not supported the state
                // will be "Unknown".
                if( connectState == MediaState.Disconnected )
                {
                    Console.WriteLine( "  This AdapterObject is in Disconnected state" );
                    Console.WriteLine( "  It is probable that no packets will be received" );
                    Console.WriteLine( "   **********************************************" );
                    Console.WriteLine( "   * Skipping test receive test on this adapter *" );
                    Console.WriteLine( "   *********************************************" );
                    adapter.CloseAdapter();
                    continue;
                }
                else if( connectState == MediaState.Unknown )
                {
                    Console.WriteLine( "  This AdapterObject is in UNKNOWN connect state" );
                    Console.WriteLine( "  It is possible that no packets will be received" );
                    Console.WriteLine( "  Continuing receive test on this adapter, but it may hang..." );
                }
                ReceivePacketsTest( adapter );
                adapter.CloseAdapter();
            }
            Console.WriteLine( "Done" );
        }
    }
}

 

Mailing Lists  · PCAUSA Newsletter · PCAUSA Discussion List
·
Privacy Statement · 
WinDis 32 is a trademark of Printing Communications Assoc., Inc. (PCAUSA).
Rawether for Windows and Rawether .NET are trademarks of Printing Communications Assoc., Inc. (PCAUSA).
Microsoft, MS, Windows, Windows 95, Windows 98, Windows Millennium, Windows 2000, Windows XP, and Win32 are registered trademarks and Visual C++ and Windows NT are trademarks of the Microsoft Corporation.
Send mail to rawether-webmaster@pcausa.com with questions or comments about this web site.
Copyright © 1996-2008 Printing Communications Assoc., Inc. (PCAUSA).
All rights reserved.
Last modified: December 31, 2007