📄 ethsock.cxx
字号:
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;
}
#else // _WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
bool PWin32PacketVxD::EnumInterfaces(PINDEX idx, PString & name)
{
static const PString RegBase = SERVICES_REGISTRY_KEY "Class\\Net";
PString keyName;
RegistryKey registry(RegBase, RegistryKey::ReadOnly);
if (!registry.EnumKey(idx, keyName))
return false;
PString description;
RegistryKey subkey(RegBase + "\\" + keyName, RegistryKey::ReadOnly);
if (subkey.QueryValue("DriverDesc", description))
name = keyName + ": " + description;
else
name = keyName;
return true;
}
static PString SearchRegistryKeys(const PString & key,
const PString & variable,
const PString & value)
{
RegistryKey registry(key, RegistryKey::ReadOnly);
PString str;
if (registry.QueryValue(variable, str) && (str *= value))
return key;
for (PINDEX idx = 0; registry.EnumKey(idx, str); idx++) {
PString result = SearchRegistryKeys(key + str + '\\', variable, value);
if (!result)
return result;
}
return PString::Empty();
}
bool PWin32PacketVxD::BindInterface(const PString & interfaceName)
{
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);
}
}
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;
}
///////////////////////////////////////////////////////////////////////////////
static bool RegistryQueryMultiSz(RegistryKey & registry,
const PString & variable,
PINDEX idx,
PString & value)
{
PString allValues;
if (!registry.QueryValue(variable, allValues))
return PFalse;
const char * ptr = allValues;
while (*ptr != '\0' && idx-- > 0)
ptr += strlen(ptr)+1;
if (*ptr == '\0')
return PFalse;
value = ptr;
return PTrue;
}
///////////////////////////////////////////////////////////////////////////////
PWin32PacketSYS::PWin32PacketSYS()
{
// 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);
}
}
static const char PacketDeviceStr[] = "\\Device\\" PACKET_SERVICE_NAME "_";
bool PWin32PacketSYS::EnumInterfaces(PINDEX idx, PString & name)
{
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);
return true;
}
bool PWin32PacketSYS::BindInterface(const PString & interfaceName)
{
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;
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;
}
#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;
}
PBoolean PEthSocket::OpenSocket()
{
PAssertAlways(PUnimplementedFunction);
return false;
}
PBoolean PEthSocket::Close()
{
driver->Close();
os_handle = -1;
return true;
}
PString PEthSocket::GetName() const
{
return interfaceName;
}
PBoolean PEthSocket::Connect(const PString & newName)
{
Close();
if (!driver->BindInterface(newName))
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
interfaceName = newName;
os_handle = 1;
return true;
}
PBoolean PEthSocket::EnumInterfaces(PINDEX idx, PString & name)
{
return driver->EnumInterfaces(idx, name);
}
PBoolean PEthSocket::GetAddress(Address & addr)
{
if (driver->QueryOid(OID_802_3_CURRENT_ADDRESS, sizeof(addr), addr.b))
return true;
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
}
PBoolean 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 },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -