📄 ethsock.cxx
字号:
BOOL PWin32PacketVxD::BindInterface(const PString & interfaceName)
{
#ifndef _WIN32_WCE
BYTE buf[20];
DWORD rxsize;
if (hDriver == INVALID_HANDLE_VALUE) {
hDriver = CreateFile("\\\\.\\" PACKET_VXD_NAME ".VXD",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED |
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
dwError = ::GetLastError();
return FALSE;
}
#ifndef USE_VPACKET
rxsize = 0;
if (!IoControl(IOCTL_EPACKET_VERSION, NULL, 0, buf, sizeof(buf), rxsize)) {
dwError = ::GetLastError();
return FALSE;
}
if (rxsize != 2 || buf[0] < 1 || buf[1] < 1) { // Require driver version 1.1
Close();
dwError = ERROR_BAD_DRIVER;
return FALSE;
}
#endif
}
PString devName;
PINDEX colon = interfaceName.Find(':');
if (colon != P_MAX_INDEX)
devName = interfaceName.Left(colon);
else
devName = interfaceName;
rxsize = 0;
if (!IoControl(IOCTL_EPACKET_BIND,
(const char *)devName, devName.GetLength()+1,
buf, sizeof(buf), rxsize) || rxsize == 0) {
dwError = ::GetLastError();
if (dwError == 0)
dwError = ERROR_BAD_DRIVER;
return FALSE;
}
// Get a random OID to verify that the driver did actually open
if (!QueryOid(OID_GEN_DRIVER_VERSION, 2, buf))
return FALSE;
dwError = ERROR_SUCCESS; // Successful, even if may not be bound.
PString devKey = SearchRegistryKeys("HKEY_LOCAL_MACHINE\\Enum\\", "Driver", "Net\\" + devName);
if (devKey.IsEmpty())
return TRUE;
RegistryKey bindRegistry(devKey + "Bindings", RegistryKey::ReadOnly);
PString binding;
PINDEX idx = 0;
while (bindRegistry.EnumValue(idx++, binding)) {
if (binding.Left(6) *= "MSTCP\\") {
RegistryKey mstcpRegistry("HKEY_LOCAL_MACHINE\\Enum\\Network\\" + binding, RegistryKey::ReadOnly);
PString str;
if (mstcpRegistry.QueryValue("Driver", str))
transportBinding.AppendString(SERVICES_REGISTRY_KEY "Class\\" + str);
}
}
#endif // !_WIN32_WCE
return TRUE;
}
BOOL PWin32PacketVxD::EnumIpAddress(PINDEX idx,
PIPSocket::Address & addr,
PIPSocket::Address & net_mask)
{
if (idx >= transportBinding.GetSize())
return FALSE;
RegistryKey transportRegistry(transportBinding[idx], RegistryKey::ReadOnly);
PString str;
if (transportRegistry.QueryValue("IPAddress", str))
addr = str;
else
addr = 0;
if (addr != 0) {
if (addr.GetVersion() == 6) {
net_mask = 0;
// Seb: Something to do ?
} else {
if (transportRegistry.QueryValue("IPMask", str))
net_mask = str;
else {
if (IN_CLASSA(addr))
net_mask = "255.0.0.0";
else if (IN_CLASSB(addr))
net_mask = "255.255.0.0";
else if (IN_CLASSC(addr))
net_mask = "255.255.255.0";
else
net_mask = 0;
}
}
return TRUE;
}
PEthSocket::Address macAddress;
if (!QueryOid(OID_802_3_CURRENT_ADDRESS, sizeof(macAddress), macAddress.b))
return FALSE;
PINDEX dhcpCount;
for (dhcpCount = 0; dhcpCount < 8; dhcpCount++) {
RegistryKey dhcpRegistry(psprintf(SERVICES_REGISTRY_KEY "VxD\\DHCP\\DhcpInfo%02u", dhcpCount),
RegistryKey::ReadOnly);
if (dhcpRegistry.QueryValue("DhcpInfo", str)) {
struct DhcpInfo {
DWORD index;
PIPSocket::Address ipAddress;
PIPSocket::Address mask;
PIPSocket::Address server;
PIPSocket::Address anotherAddress;
DWORD unknown1;
DWORD unknown2;
DWORD unknown3;
DWORD unknown4;
DWORD unknown5;
DWORD unknown6;
BYTE unknown7;
PEthSocket::Address macAddress;
} * dhcpInfo = (DhcpInfo *)(const char *)str;
if (dhcpInfo->macAddress == macAddress) {
addr = dhcpInfo->ipAddress;
net_mask = dhcpInfo->mask;
return TRUE;
}
}
else if (dhcpRegistry.QueryValue("HardwareAddress", str) &&
str.GetSize() >= sizeof(PEthSocket::Address)) {
PEthSocket::Address hardwareAddress;
memcpy(&hardwareAddress, (const char *)str, sizeof(hardwareAddress));
if (hardwareAddress == macAddress) {
if (dhcpRegistry.QueryValue("DhcpIPAddress", str) &&
str.GetSize() >= sizeof(addr)) {
memcpy(&addr, (const char *)str, sizeof(addr));
if (dhcpRegistry.QueryValue("DhcpSubnetMask", str) &&
str.GetSize() >= sizeof(net_mask)) {
memcpy(&net_mask, (const char *)str, sizeof(net_mask));
return TRUE;
}
}
}
}
}
return FALSE;
}
BOOL PWin32PacketVxD::BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap)
{
received = 0;
if (DeviceIoControl(hDriver, IOCTL_EPACKET_READ,
buf, size, buf, size, &received, &overlap)) {
dwError = ERROR_SUCCESS;
return TRUE;
}
dwError = ::GetLastError();
return dwError == ERROR_IO_PENDING;
}
BOOL PWin32PacketVxD::BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap)
{
DWORD rxsize = 0;
BYTE dummy[2];
if (DeviceIoControl(hDriver, IOCTL_EPACKET_WRITE,
(void *)buf, len, dummy, sizeof(dummy), &rxsize, &overlap)) {
dwError = ERROR_SUCCESS;
return TRUE;
}
dwError = ::GetLastError();
return dwError == ERROR_IO_PENDING;
}
///////////////////////////////////////////////////////////////////////////////
PWin32PacketSYS::PWin32PacketSYS()
{
#ifndef _WIN32_WCE
// Start the packet driver service
SC_HANDLE hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hManager != NULL) {
SC_HANDLE hService = OpenService(hManager, PACKET_SERVICE_NAME, SERVICE_START);
if (hService != NULL) {
StartService(hService, 0, NULL);
dwError = ::GetLastError();
CloseServiceHandle(hService);
}
CloseServiceHandle(hManager);
}
#endif // !_WIN32_WCE
}
static const char PacketDeviceStr[] = "\\Device\\" PACKET_SERVICE_NAME "_";
BOOL PWin32PacketSYS::EnumInterfaces(PINDEX idx, PString & name)
{
#ifndef _WIN32_WCE
RegistryKey registry(SERVICES_REGISTRY_KEY PACKET_SERVICE_NAME "\\Linkage",
RegistryKey::ReadOnly);
if (!RegistryQueryMultiSz(registry, "Export", idx, name)) {
dwError = ERROR_NO_MORE_ITEMS;
return FALSE;
}
if (strncasecmp(name, PacketDeviceStr, sizeof(PacketDeviceStr)-1) == 0)
name.Delete(0, sizeof(PacketDeviceStr)-1);
#endif // !_WIN32_WCE
return TRUE;
}
BOOL PWin32PacketSYS::BindInterface(const PString & interfaceName)
{
#ifndef _WIN32_WCE
Close();
if (!DefineDosDevice(DDD_RAW_TARGET_PATH,
PACKET_SERVICE_NAME "_" + interfaceName,
PacketDeviceStr + interfaceName)) {
dwError = ::GetLastError();
return FALSE;
}
::SetLastError(0);
hDriver = CreateFile("\\\\.\\" PACKET_SERVICE_NAME "_" + interfaceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
dwError = ::GetLastError();
return FALSE;
}
registryKey = SERVICES_REGISTRY_KEY + interfaceName + "\\Parameters\\Tcpip";
dwError = ERROR_SUCCESS;
#endif // !_WIN32_WCE
return TRUE;
}
BOOL PWin32PacketSYS::EnumIpAddress(PINDEX idx,
PIPSocket::Address & addr,
PIPSocket::Address & net_mask)
{
PString str;
RegistryKey registry(registryKey, RegistryKey::ReadOnly);
if (!RegistryQueryMultiSz(registry, "IPAddress", idx, str)) {
dwError = ERROR_NO_MORE_ITEMS;
return FALSE;
}
addr = str;
if (!RegistryQueryMultiSz(registry, "SubnetMask", idx, str)) {
dwError = ERROR_NO_MORE_ITEMS;
return FALSE;
}
net_mask = str;
return TRUE;
}
BOOL PWin32PacketSYS::BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap)
{
overlap.Reset();
received = 0;
if (ReadFile(hDriver, buf, size, &received, &overlap)) {
dwError = ERROR_SUCCESS;
return TRUE;
}
return (dwError = ::GetLastError()) == ERROR_IO_PENDING;
}
BOOL PWin32PacketSYS::BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap)
{
overlap.Reset();
DWORD sent = 0;
if (WriteFile(hDriver, buf, len, &sent, &overlap)) {
dwError = ERROR_SUCCESS;
return TRUE;
}
dwError = ::GetLastError();
return dwError == ERROR_IO_PENDING;
}
///////////////////////////////////////////////////////////////////////////////
#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";
}
}
}
}
}
}
}
BOOL PWin32PacketCe::EnumInterfaces(PINDEX idx, PString & name)
{
if( idx >= interfaces.GetSize() )
return FALSE;
name = interfaces[idx];
return TRUE;
}
BOOL PWin32PacketCe::BindInterface(const PString &)
{
return TRUE;
}
BOOL PWin32PacketCe::EnumIpAddress(PINDEX idx,
PIPSocket::Address & addr,
PIPSocket::Address & net_mask)
{
if( idx >= interfaces.GetSize() )
return FALSE;
addr = ipAddresses[idx];
net_mask = netMasks[idx];
return TRUE;
}
BOOL PWin32PacketCe::BeginRead(void *, DWORD, DWORD & , PWin32Overlapped &)
{
return TRUE;
}
BOOL PWin32PacketCe::BeginWrite(const void *, DWORD, PWin32Overlapped &)
{
return TRUE;
}
#endif // _WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
PEthSocket::PEthSocket(PINDEX nReadBuffers, PINDEX nWriteBuffers, PINDEX size)
: readBuffers(min(nReadBuffers, MAXIMUM_WAIT_OBJECTS)),
writeBuffers(min(nWriteBuffers, MAXIMUM_WAIT_OBJECTS))
{
driver = PWin32PacketDriver::Create();
PINDEX i;
for (i = 0; i < nReadBuffers; i++)
readBuffers.SetAt(i, new PWin32PacketBuffer(size));
for (i = 0; i < nWriteBuffers; i++)
writeBuffers.SetAt(i, new PWin32PacketBuffer(size));
filterType = TypeAll;
}
PEthSocket::~PEthSocket()
{
Close();
delete driver;
}
BOOL PEthSocket::OpenSocket()
{
PAssertAlways(PUnimplementedFunction);
return FALSE;
}
BOOL PEthSocket::Close()
{
driver->Close();
os_handle = -1;
return TRUE;
}
PString PEthSocket::GetName() const
{
return interfaceName;
}
BOOL PEthSocket::Connect(const PString & newName)
{
Close();
if (!driver->BindInterface(newName))
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
interfaceName = newName;
os_handle = 1;
return TRUE;
}
BOOL PEthSocket::EnumInterfaces(PINDEX idx, PString & name)
{
return driver->EnumInterfaces(idx, name);
}
BOOL PEthSocket::GetAddress(Address & addr)
{
if (driver->QueryOid(OID_802_3_CURRENT_ADDRESS, sizeof(addr), addr.b))
return TRUE;
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
}
BOOL PEthSocket::EnumIpAddress(PINDEX idx,
PIPSocket::Address & addr,
PIPSocket::Address & net_mask)
{
if (IsOpen()) {
if (driver->EnumIpAddress(idx, addr, net_mask))
return TRUE;
return SetErrorValues(NotFound, ENOENT);
}
return SetErrorValues(NotOpen, EBADF);
}
static const struct {
unsigned pwlib;
DWORD ndis;
} FilterMasks[] = {
{ PEthSocket::FilterDirected, NDIS_PACKET_TYPE_DIRECTED },
{ PEthSocket::FilterMulticast, NDIS_PACKET_TYPE_MULTICAST },
{ PEthSocket::FilterAllMulticast, NDIS_PACKET_TYPE_ALL_MULTICAST },
{ PEthSocket::FilterBroadcast, NDIS_PACKET_TYPE_BROADCAST },
{ PEthSocket::FilterPromiscuous, NDIS_PACKET_TYPE_PROMISCUOUS }
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -