⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethsock.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/*
 * ethsock.cxx
 *
 * Direct Ethernet socket implementation.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Revision: 19558 $
 * $Author: rjongbloed $
 * $Date: 2008-02-20 07:57:11 +0000 (Wed, 20 Feb 2008) $
 */

#include <ptlib.h>
#include <ptlib/sockets.h>

#include <iphlpapi.h>
#ifdef _MSC_VER
  #pragma comment(lib, "iphlpapi.lib")
#endif


///////////////////////////////////////////////////////////////////////////////
// Stuff from ndis.h

#define OID_802_3_PERMANENT_ADDRESS         0x01010101
#define OID_802_3_CURRENT_ADDRESS           0x01010102

#define OID_GEN_DRIVER_VERSION              0x00010110
#define OID_GEN_CURRENT_PACKET_FILTER       0x0001010E
#define OID_GEN_MEDIA_SUPPORTED             0x00010103

#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_PROMISCUOUS        0x0020

typedef enum _NDIS_MEDIUM {
    NdisMedium802_3,
    NdisMedium802_5,
    NdisMediumFddi,
    NdisMediumWan,
    NdisMediumLocalTalk,
    NdisMediumDix,              // defined for convenience, not a real medium
    NdisMediumArcnetRaw,
    NdisMediumArcnet878_2
} NDIS_MEDIUM, *PNDIS_MEDIUM;                    

///////////////////////////////////////////////////////////////////////////////


#define USE_VPACKET
#include <ptlib/msos/ptlib/epacket.h>

#ifdef USE_VPACKET
#define PACKET_SERVICE_NAME "Packet"
#define PACKET_VXD_NAME     "VPacket"
#else
#define PACKET_SERVICE_NAME "EPacket"
#define PACKET_VXD_NAME     "EPacket"
#endif

#define SERVICES_REGISTRY_KEY "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"


/////////////////////////////////////////////////////////////////////////////

class PWin32OidBuffer
{
  public:
    PWin32OidBuffer(UINT oid, UINT len, const BYTE * data = NULL);
    ~PWin32OidBuffer() { delete buffer; }

    operator void *()         { return buffer; }
    operator DWORD ()         { return size; }
    DWORD operator [](int i)  { return buffer[i]; }

    void Move(BYTE * data, DWORD received);

  private:
    DWORD * buffer;
    UINT size;
};


///////////////////////////////////////////////////////////////////////////////

class PWin32PacketDriver
{
  public:
    static PWin32PacketDriver * Create();

    virtual ~PWin32PacketDriver();

    bool IsOpen() const;
    void Close();
    DWORD GetLastError() const;

    virtual bool EnumInterfaces(PINDEX idx, PString & name) = 0;
    virtual bool BindInterface(const PString & interfaceName) = 0;

    virtual bool EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask) = 0;

    virtual bool BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap) = 0;
    virtual bool BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap) = 0;
    bool CompleteIO(DWORD & received, PWin32Overlapped & overlap);

    bool IoControl(UINT func,
                   const void * input, DWORD inSize,
                   void * output, DWORD outSize,
                   DWORD & received);

    PBoolean QueryOid(UINT oid, DWORD & data);
    PBoolean QueryOid(UINT oid, UINT len, BYTE * data);
    PBoolean SetOid(UINT oid, DWORD data);
    PBoolean SetOid(UINT oid, UINT len, const BYTE * data);
    virtual UINT GetQueryOidCommand(DWORD /*oid*/) const { return IOCTL_EPACKET_QUERY_OID; }

  protected:
    PWin32PacketDriver();

    DWORD dwError;
    HANDLE hDriver;
};

///////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32_WCE

class PWin32PacketCe : public PWin32PacketDriver
{
  public:
    PWin32PacketCe();

    virtual bool EnumInterfaces(PINDEX idx, PString & name);
    virtual bool BindInterface(const PString & interfaceName);

    virtual bool EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);

    virtual bool BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
    virtual bool BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);

  protected:
    PStringArray ipAddresses;
    PStringArray netMasks;
    PStringArray interfaces;
};

#else // _WIN32_WCE

/////////////////////////////////////////////////////////////////////////////

class PWin32PacketVxD : public PWin32PacketDriver
{
  public:
    virtual bool EnumInterfaces(PINDEX idx, PString & name);
    virtual bool BindInterface(const PString & interfaceName);

    virtual bool EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);

    virtual bool BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
    virtual bool BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);

#ifdef USE_VPACKET
    virtual UINT GetQueryOidCommand(DWORD oid) const
      { return oid >= OID_802_3_PERMANENT_ADDRESS ? IOCTL_EPACKET_QUERY_OID : IOCTL_EPACKET_STATISTICS; }
#endif

  protected:
    PStringArray transportBinding;
};


///////////////////////////////////////////////////////////////////////////////

class PWin32PacketSYS : public PWin32PacketDriver
{
  public:
    PWin32PacketSYS();

    virtual bool EnumInterfaces(PINDEX idx, PString & name);
    virtual bool BindInterface(const PString & interfaceName);

    virtual bool EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);

    virtual bool BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
    virtual bool BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);

  protected:
    PString registryKey;
};


#endif // _WIN32_WCE


///////////////////////////////////////////////////////////////////////////////

class PWin32PacketBuffer : public PBYTEArray
{
  PCLASSINFO(PWin32PacketBuffer, PBYTEArray)
  public:
    enum Statuses {
      Uninitialised,
      Progressing,
      Completed
    };

    PWin32PacketBuffer(PINDEX sz);

    PINDEX GetData(void * buf, PINDEX size);
    PINDEX PutData(const void * buf, PINDEX length);
    HANDLE GetEvent() const { return overlap.hEvent; }

    bool ReadAsync(PWin32PacketDriver & pkt);
    bool ReadComplete(PWin32PacketDriver & pkt);
    bool WriteAsync(PWin32PacketDriver & pkt);
    bool WriteComplete(PWin32PacketDriver & pkt);

    bool InProgress() const { return status == Progressing; }
    bool IsCompleted() const { return status == Completed; }
    bool IsType(WORD type) const;

  protected:
    Statuses         status;
    PWin32Overlapped overlap;
    DWORD            count;
};


#define new PNEW


/////////////////////////////////////////////////////////////////////////////

PWin32OidBuffer::PWin32OidBuffer(UINT oid, UINT len, const BYTE * data)
{
  size = sizeof(DWORD)*2 + len;
  buffer = new DWORD[(size+sizeof(DWORD)-1)/sizeof(DWORD)];

  buffer[0] = oid;
  buffer[1] = len;
  if (data != NULL)
    memcpy(&buffer[2], data, len);
}


void PWin32OidBuffer::Move(BYTE * data, DWORD received)
{
  memcpy(data, &buffer[2], received-sizeof(DWORD)*2);
}


///////////////////////////////////////////////////////////////////////////////

PWin32PacketDriver * PWin32PacketDriver::Create()
{
  OSVERSIONINFO info;
  info.dwOSVersionInfoSize = sizeof(info);
  GetVersionEx(&info);
#ifdef _WIN32_WCE
  return new PWin32PacketCe;
#else // _WIN32_WCE
  if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
    return new PWin32PacketSYS;
  else
    return new PWin32PacketVxD;
#endif // _WIN32_WCE
}


PWin32PacketDriver::PWin32PacketDriver()
{
  hDriver = INVALID_HANDLE_VALUE;
  dwError = ERROR_OPEN_FAILED;
}


PWin32PacketDriver::~PWin32PacketDriver()
{
  Close();
}


void PWin32PacketDriver::Close()
{
  if (hDriver != INVALID_HANDLE_VALUE) {
    CloseHandle(hDriver);
    hDriver = INVALID_HANDLE_VALUE;
  }
}


bool PWin32PacketDriver::IsOpen() const
{
  return hDriver != INVALID_HANDLE_VALUE;
}


DWORD PWin32PacketDriver::GetLastError() const
{
  return dwError;
}


bool PWin32PacketDriver::IoControl(UINT func,
                              const void * input, DWORD inSize,
                              void * output, DWORD outSize, DWORD & received)
{
  PWin32Overlapped overlap;

  if (DeviceIoControl(hDriver, func,
                      (LPVOID)input, inSize, output, outSize,
                      &received, &overlap)) {
    dwError = ERROR_SUCCESS;
    return true;
  }

  dwError = ::GetLastError();
  if (dwError != ERROR_IO_PENDING)
    return false;

  return CompleteIO(received, overlap);
}

#ifdef _WIN32_WCE
bool PWin32PacketDriver::CompleteIO(DWORD &, PWin32Overlapped &)
{
  return true;
}
#else
bool PWin32PacketDriver::CompleteIO(DWORD & received, PWin32Overlapped & overlap)
{
  received = 0;
  if (GetOverlappedResult(hDriver, &overlap, &received, true)) {
    dwError = ERROR_SUCCESS;
    return true;
  }

  dwError = ::GetLastError();
  return false;
}
#endif


PBoolean PWin32PacketDriver::QueryOid(UINT oid, UINT len, BYTE * data)
{
  PWin32OidBuffer buf(oid, len);
  DWORD rxsize = 0;
  if (!IoControl(GetQueryOidCommand(oid), buf, buf, buf, buf, rxsize))
    return PFalse;

  if (rxsize == 0)
    return PFalse;

  buf.Move(data, rxsize);
  return PTrue;
}


PBoolean PWin32PacketDriver::QueryOid(UINT oid, DWORD & data)
{
  DWORD oidData[3];
  oidData[0] = oid;
  oidData[1] = sizeof(data);
  oidData[2] = 0x12345678;

  DWORD rxsize = 0;
  if (!IoControl(GetQueryOidCommand(oid),
                 oidData, sizeof(oidData),
                 oidData, sizeof(oidData),
                 rxsize))
    return PFalse;

  if (rxsize == 0)
    return PFalse;

  data = oidData[2];
  return PTrue;
}


PBoolean PWin32PacketDriver::SetOid(UINT oid, UINT len, const BYTE * data)
{
  DWORD rxsize = 0;
  PWin32OidBuffer buf(oid, len, data);
  return IoControl(IOCTL_EPACKET_SET_OID, buf, buf, buf, buf, rxsize);
}


PBoolean PWin32PacketDriver::SetOid(UINT oid, DWORD data)
{
  DWORD oidData[3];
  oidData[0] = oid;
  oidData[1] = sizeof(data);
  oidData[2] = data;
  DWORD rxsize;
  return IoControl(IOCTL_EPACKET_SET_OID,
                   oidData, sizeof(oidData), oidData, sizeof(oidData), rxsize);
}


///////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32_WCE

PWin32PacketCe::PWin32PacketCe()
{
  PString str, driver, nameStr, keyStr, driverStr, miniportStr, linkageStr, routeStr, tcpipStr;

  static const PString ActiveDrivers = "HKEY_LOCAL_MACHINE\\Drivers\\Active";
  static const PString CommBase = "HKEY_LOCAL_MACHINE\\Comm";

  // Collecting active drivers
  RegistryKey registry(ActiveDrivers, RegistryKey::ReadOnly);
  for (PINDEX idx = 0; registry.EnumKey(idx, str); idx++) 
  {
    driver = ActiveDrivers + "\\" + str;
    RegistryKey driverKey( driver, RegistryKey::ReadOnly );

    // Filter out non - NDS drivers
    if (!driverKey.QueryValue( "Name", nameStr ) || nameStr.Find("NDS") == P_MAX_INDEX )
      continue;

    // Active network driver found
    // 
    // e.g. built-in driver has "Key" = Drivers\BuiltIn\NDIS
    if( driverKey.QueryValue( "Key", keyStr ) )
    {
      if( P_MAX_INDEX != keyStr.Find("BuiltIn") )
      {
        // Built-in driver case
        continue;
      }
      else
      {
        driverStr = "HKEY_LOCAL_MACHINE\\"+ keyStr;
        RegistryKey ActiveDriverKey( driverStr, RegistryKey::ReadOnly );

        // Get miniport value
        if( ActiveDriverKey.QueryValue( "Miniport", miniportStr ) )
        {
          // Get miniport linkage
          //
          // e.g. [HKEY_LOCAL_MACHINE\Comm\SOCKETLPE\Linkage]
          linkageStr = CommBase + "\\" + miniportStr + "\\Linkage";

          RegistryKey LinkageKey( linkageStr, RegistryKey::ReadOnly );

          // Get route to real driver
          if( LinkageKey.QueryValue( "Route", routeStr ) )
          {
            tcpipStr = CommBase + "\\" + routeStr + "\\Parms\\TcpIp";

            RegistryKey TcpIpKey( tcpipStr, RegistryKey::ReadOnly );

            DWORD dwDHCPEnabled = false;
            TcpIpKey.QueryValue( "EnableDHCP", dwDHCPEnabled, true );

            /// Collect IP addresses and net masks
            PString ipAddress, netMask;
            if ( !dwDHCPEnabled )
            {
              if  (TcpIpKey.QueryValue( "IpAddress", ipAddress ) 
                  && (ipAddress != "0.0.0.0") )
              {
                interfaces[interfaces.GetSize()] = tcpipStr; // Registry key for the driver
                ipAddresses[ipAddresses.GetSize()] = ipAddress; // It's IP
                if( driverKey.QueryValue( "Subnetmask", netMask ) )
                  netMasks[netMasks.GetSize()] = netMask; // It's mask
                else
                  netMasks[netMasks.GetSize()] = "255.255.255.0";
              }
            }
            else // DHCP enabled
            if( TcpIpKey.QueryValue( "DhcpIpAddress", ipAddress ) 
              && (ipAddress != "0.0.0.0") )
            {
              interfaces[interfaces.GetSize()] = str;
              ipAddresses[ipAddresses.GetSize()] = ipAddress;
              if( driverKey.QueryValue( "DhcpSubnetMask", netMask ) )
                netMasks[netMasks.GetSize()] = netMask;
              else
                netMasks[netMasks.GetSize()] = "255.255.255.0";
            }
          }
        }
      }      
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -