📄 ethsock.cxx
字号:
/*
* 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 + -