diff --git a/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h b/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h new file mode 100755 index 00000000..7caebb01 --- /dev/null +++ b/BasiliskII/src/Windows/b2ether/inc/b2ether_hl.h @@ -0,0 +1,116 @@ +/* + * b2ether_hl.h - Win32 ethernet driver high-level interface + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _B2_ETHER_HL_ +#define _B2_ETHER_HL_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ETH_802_3_ADDRESS_LENGTH 6 +#define MAX_LINK_NAME_LENGTH 124 + +typedef struct _ADAPTER { + HANDLE hFile; + TCHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; +} ADAPTER, *LPADAPTER; + +typedef struct _PACKET { + OVERLAPPED OverLapped; + PVOID Buffer; + UINT Length; + ULONG BytesReceived; + BOOL bIoComplete; + BOOL free; + struct _PACKET *next; +} PACKET, *LPPACKET; + + + +BOOLEAN StartPacketDriver( + LPTSTR ServiceName +); + +LPADAPTER PacketOpenAdapter( + LPCSTR AdapterName, + int16 mode +); + +VOID PacketCloseAdapter( + LPADAPTER lpAdapter +); + +LPPACKET PacketAllocatePacket( + LPADAPTER AdapterObject, + UINT Length +); + +VOID PacketFreePacket( + LPPACKET lpPacket +); + +BOOLEAN PacketSendPacket( + LPADAPTER AdapterObject, + LPPACKET lpPacket, + BOOLEAN Sync, + BOOLEAN RecyclingAllowed +); + +BOOLEAN PacketGetAddress( + LPADAPTER AdapterObject, + PUCHAR AddressBuffer, + PUINT Length +); + +BOOLEAN PacketReceivePacket( + LPADAPTER AdapterObject, + LPPACKET lpPacket, + BOOLEAN Sync +); + +BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter ); +BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent ); +BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address ); +BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address ); + +ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, PTSTR pStr, PULONG BufferSize ); +ULONG PacketSelectAdapterByName( LPADAPTER AdapterObject, LPCSTR name ); + +// callbacks +void recycle_write_packet( LPPACKET Packet ); + +VOID CALLBACK packet_read_completion( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped +); + + +#ifdef __cplusplus +} +#endif + + +#endif // _B2_ETHER_HL_ diff --git a/BasiliskII/src/Windows/b2ether/inc/ntddpack.h b/BasiliskII/src/Windows/b2ether/inc/ntddpack.h new file mode 100755 index 00000000..62af4f3f --- /dev/null +++ b/BasiliskII/src/Windows/b2ether/inc/ntddpack.h @@ -0,0 +1,32 @@ +// #include + +#ifndef __NTDDPACKET +#define __NTDDPACKET 1 + +// #include + +#define MAX_LINK_NAME_LENGTH 124 + +#pragma pack(1) +typedef struct _PACKET_OID_DATA { + ULONG Oid; + ULONG Length; + UCHAR Data[1]; +} ATTRIBUTE_PACKED PACKET_OID_DATA, *PPACKET_OID_DATA; +#pragma pack() + + +#define FILE_DEVICE_PROTOCOL 0x8000 + + + +#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_SELECT_BY_NAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_ENUM_ADAPTERS CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif diff --git a/BasiliskII/src/Windows/b2ether/multiopt.h b/BasiliskII/src/Windows/b2ether/multiopt.h new file mode 100755 index 00000000..8bfc55bf --- /dev/null +++ b/BasiliskII/src/Windows/b2ether/multiopt.h @@ -0,0 +1,27 @@ +/* + * multiopt.h + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +enum { + ETHER_MULTICAST_MAC, + ETHER_MULTICAST_ALL, + ETHER_MULTICAST_PROMISCUOUS +}; diff --git a/BasiliskII/src/Windows/b2ether/packet32.cpp b/BasiliskII/src/Windows/b2ether/packet32.cpp new file mode 100755 index 00000000..edeac178 --- /dev/null +++ b/BasiliskII/src/Windows/b2ether/packet32.cpp @@ -0,0 +1,788 @@ +/* + * packet32.cpp + * + * Basilisk II (C) 1997-1999 Christian Bauer + * + * Windows platform specific code copyright (C) Lauri Pesonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "sysdeps.h" +#include +#include +#include +#include "cpu_emulation.h" +typedef unsigned long ULONG_PTR, *PULONG_PTR; + +// VC6 does not have this, Platform SDK has. +// In case of errors, try to comment out, the needed +// definitions are below (#ifndef _NTDDNDIS_) + +// Most people don't have the Platform SDK, so I take this one out. +// #include + +#include "inc\ntddpack.h" + +#include "ether.h" +#include "ether_defs.h" +#include "b2ether\multiopt.h" +#include "b2ether\inc\b2ether_hl.h" + + + +#ifndef _NTDDNDIS_ +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 + +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#endif + +#define DEBUG_PACKETS 0 +#define DEBUG 0 +#include "debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if DEBUG +#pragma optimize("",off) +#endif + +#define MAX_MULTICAST 100 +#define MAX_MULTICAST_SZ (20*ETH_802_3_ADDRESS_LENGTH) + +static int os = VER_PLATFORM_WIN32_WINDOWS; + +static ULONG packet_filter = 0; + + +LPADAPTER PacketOpenAdapter( LPCSTR AdapterName, int16 mode ) +{ + LPADAPTER lpAdapter; + BOOLEAN Result = TRUE; + OSVERSIONINFO osv; + + D(bug("Packet32: PacketOpenAdapter\n")); + + osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(GetVersionEx( &osv )) os = osv.dwPlatformId; + + if(os == VER_PLATFORM_WIN32_NT) { + // May fail if user is not an Administrator. + StartPacketDriver( "B2ether" ); + } + + lpAdapter = (LPADAPTER)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(ADAPTER) ); + if (lpAdapter==NULL) { + D(bug("Packet32: PacketOpenAdapter GlobalAlloc Failed\n")); + return NULL; + } + + if(os == VER_PLATFORM_WIN32_NT) { + char device_name[256]; + wsprintf( lpAdapter->SymbolicLink, "\\\\.\\B2ether_%s", AdapterName ); + wsprintf( device_name, "\\Device\\B2ether_%s", AdapterName ); + + // Work around one subtle NT4 bug. + DefineDosDevice( + DDD_REMOVE_DEFINITION, + &lpAdapter->SymbolicLink[4], + NULL + ); + DefineDosDevice( + DDD_RAW_TARGET_PATH, + &lpAdapter->SymbolicLink[4], + device_name + ); + } else { + wsprintf( lpAdapter->SymbolicLink, "\\\\.\\B2ether" ); + } + + packet_filter = NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_MULTICAST | + NDIS_PACKET_TYPE_BROADCAST; + + if(mode == ETHER_MULTICAST_ALL) packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + if(mode == ETHER_MULTICAST_PROMISCUOUS) packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; + + if (Result) { + lpAdapter->hFile = CreateFile(lpAdapter->SymbolicLink, + GENERIC_WRITE | GENERIC_READ, + 0, + NULL, + // (os == VER_PLATFORM_WIN32_NT) ? CREATE_ALWAYS : OPEN_EXISTING, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + 0 + ); + if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { + if(*AdapterName && strcmp(AdapterName,"") != 0) { + if(os == VER_PLATFORM_WIN32_WINDOWS) { + PacketSelectAdapterByName( lpAdapter, AdapterName ); + } + PacketSetFilter( lpAdapter, packet_filter ); + } + return lpAdapter; + } + } + D(bug("Packet32: PacketOpenAdapter Could not open adapter\n")); + GlobalFreePtr( lpAdapter ); + return NULL; +} + +VOID PacketCloseAdapter( LPADAPTER lpAdapter ) +{ + D(bug("Packet32: PacketCloseAdapter\n")); + + if(lpAdapter) { + if(lpAdapter->hFile) { + CloseHandle(lpAdapter->hFile); + } + GlobalFreePtr(lpAdapter); + } +} + +LPPACKET PacketAllocatePacket( LPADAPTER AdapterObject, UINT Length ) +{ + LPPACKET lpPacket; + + lpPacket = (LPPACKET)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(PACKET) ); + if(lpPacket==NULL) { + D(bug("Packet32: PacketAllocatePacket: GlobalAlloc Failed\n")); + return NULL; + } + + lpPacket->OverLapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); + if(!lpPacket->OverLapped.hEvent) { + D(bug("Packet32: PacketAllocatePacket: CreateEvent Failed\n")); + GlobalFreePtr(lpPacket); + return NULL; + } + + lpPacket->Buffer = GlobalAllocPtr(GMEM_MOVEABLE,2048); // 1514 + if(!lpPacket->Buffer) { + D(bug("Packet32: PacketAllocatePacket: GlobalAllocPtr Failed\n")); + if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); + GlobalFreePtr(lpPacket); + return NULL; + } + + lpPacket->OverLapped.Offset = 0; + lpPacket->OverLapped.OffsetHigh = 0; + lpPacket->Length = Length; + lpPacket->BytesReceived = 0; + lpPacket->bIoComplete = FALSE; + lpPacket->free = TRUE; + + return lpPacket; +} + +VOID PacketFreePacket( LPPACKET lpPacket ) +{ + if(lpPacket) { + if(lpPacket->Buffer) GlobalFreePtr(lpPacket->Buffer); + if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); + GlobalFreePtr(lpPacket); + } +} + +BOOLEAN PacketDeviceIoControl( + LPADAPTER lpAdapterObject, + LPPACKET lpPacket, + ULONG ulIoctl, + BOOLEAN bSync +) +{ + BOOLEAN Result; + + lpPacket->OverLapped.Offset = 0; + lpPacket->OverLapped.OffsetHigh = 0; + lpPacket->BytesReceived = 0; + + if ( !ResetEvent( lpPacket->OverLapped.hEvent ) ) { + lpPacket->bIoComplete = FALSE; + D(bug( "Packet32: PacketDeviceIoControl failed to reset event\r\n", GetLastError() )); + return FALSE; + } + + Result = DeviceIoControl( + lpAdapterObject->hFile, + ulIoctl, + lpPacket->Buffer, + lpPacket->Length, + lpPacket->Buffer, + lpPacket->Length, + &(lpPacket->BytesReceived), + &(lpPacket->OverLapped) ); + + if( !Result && bSync ) { + if (GetLastError() == ERROR_IO_PENDING) { + Result = GetOverlappedResult( lpAdapterObject->hFile, + &(lpPacket->OverLapped), + &(lpPacket->BytesReceived), + TRUE ); + } else { + D(bug( "Packet32: unsupported API call returned error 0x%x\r\n", GetLastError() )); + } + } + lpPacket->bIoComplete = Result; + return Result; +} + +VOID CALLBACK PacketSendCompletionRoutine( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped +) +{ + LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped); + +#if DEBUG_PACKETS + D(bug("PacketSendCompletionRoutine %d\n",dwNumberOfBytesTransfered)); +#endif + + lpPacket->bIoComplete = TRUE; + // lpPacket->free = TRUE; + // PacketFreePacket(lpPacket); + recycle_write_packet(lpPacket); +} + +BOOLEAN PacketSendPacket( + LPADAPTER AdapterObject, + LPPACKET lpPacket, + BOOLEAN Sync, + BOOLEAN RecyclingAllowed +) +{ + BOOLEAN Result; + +#if DEBUG_PACKETS + D(bug("Packet32: PacketSendPacket bytes=%d, sync=%d\n",lpPacket->Length,Sync)); +#endif + + if(os == VER_PLATFORM_WIN32_NT) { + lpPacket->OverLapped.Offset = 0; + lpPacket->OverLapped.OffsetHigh = 0; + lpPacket->bIoComplete = FALSE; + + if(Sync) { + Result = WriteFile( + AdapterObject->hFile, + lpPacket->Buffer, + lpPacket->Length, + &lpPacket->BytesReceived, + &lpPacket->OverLapped + ); + if(Result) { + Result = GetOverlappedResult( + AdapterObject->hFile, + &lpPacket->OverLapped, + &lpPacket->BytesReceived, + TRUE + ); + } else { + D(bug("Packet32: PacketSendPacket WriteFile failed, err=%d\n",(int)GetLastError())); + } + lpPacket->bIoComplete = TRUE; + if(RecyclingAllowed) PacketFreePacket(lpPacket); +#if DEBUG_PACKETS + D(bug("Packet32: PacketSendPacket result=%d, bytes=%d\n",(int)Result,(int)lpPacket->BytesReceived)); +#endif + } else { + // don't care about the result + Result = WriteFileEx( + AdapterObject->hFile, + lpPacket->Buffer, + lpPacket->Length, + &lpPacket->OverLapped, + PacketSendCompletionRoutine + ); +#if DEBUG_PACKETS + D(bug("Packet32: PacketSendPacket result=%d\n",(int)Result)); +#endif + if(!Result && RecyclingAllowed) { + recycle_write_packet(lpPacket); + } + } + } else { + // Now: make writes always synchronous under Win9x + Sync = TRUE; + Result = PacketDeviceIoControl( AdapterObject, + lpPacket, + IOCTL_PROTOCOL_WRITE, + Sync ); + if(RecyclingAllowed) recycle_write_packet(lpPacket); + } + + return Result; +} + +BOOLEAN PacketReceivePacket( + LPADAPTER AdapterObject, + LPPACKET lpPacket, + BOOLEAN Sync +) +{ + BOOLEAN Result; + + if(os == VER_PLATFORM_WIN32_NT) { + lpPacket->OverLapped.Offset=0; + lpPacket->OverLapped.OffsetHigh=0; + lpPacket->bIoComplete = FALSE; + +#if DEBUG_PACKETS + D(bug("Packet32: PacketReceivePacket\n")); +#endif + + if (Sync) { + Result = ReadFile( + AdapterObject->hFile, + lpPacket->Buffer, + lpPacket->Length, + &lpPacket->BytesReceived, + &lpPacket->OverLapped + ); + if(Result) { + Result = GetOverlappedResult( + AdapterObject->hFile, + &lpPacket->OverLapped, + &lpPacket->BytesReceived, + TRUE + ); + if(Result) + lpPacket->bIoComplete = TRUE; + else + lpPacket->free = TRUE; + } + } else { + Result = ReadFileEx( + AdapterObject->hFile, + lpPacket->Buffer, + lpPacket->Length, + &lpPacket->OverLapped, + packet_read_completion + ); + } + + if(!Result) lpPacket->BytesReceived = 0; + } else { + Result = PacketDeviceIoControl( AdapterObject, + lpPacket, + IOCTL_PROTOCOL_READ, + Sync ); + if( !Result && !Sync ) { + if (GetLastError() == ERROR_IO_PENDING) { + Result = TRUE; + } + } + } + +#if DEBUG_PACKETS + D(bug("Packet32: PacketReceivePacket got %d bytes, result=%d\n",lpPacket->BytesReceived,(int)Result)); +#endif + + return Result; +} + +BOOLEAN PacketRequest( + LPADAPTER lpAdapterObject, + LPPACKET lpPacket, + BOOLEAN bSet +) +{ + BOOLEAN Result = FALSE; + + Result = PacketDeviceIoControl( + lpAdapterObject, + lpPacket, + (ULONG) ((bSet) ? IOCTL_PROTOCOL_SET_OID : IOCTL_PROTOCOL_QUERY_OID), + TRUE ); + + if ( lpPacket->BytesReceived == 0 ) { + D(bug( "Packet32: Ndis returned error to OID\r\n")); + Result = FALSE; + } + return Result; +} + +LPPACKET PacketQueryOid( + LPADAPTER lpAdapter, + ULONG ulOid, + ULONG ulLength +) +{ + ULONG ioctl; + LPPACKET lpPacket; + +#define pOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) + + lpPacket = PacketAllocatePacket( lpAdapter, sizeof(PACKET_OID_DATA)-1+ulLength ); + + if( lpPacket ) { + ioctl = IOCTL_PROTOCOL_QUERY_OID; + pOidData->Oid = ulOid; + pOidData->Length = ulLength; + + if (PacketRequest( lpAdapter, lpPacket, FALSE )) { + return lpPacket; + } + PacketFreePacket( lpPacket ); + } + +#undef pOidData + + return 0; +} + +BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent ) +{ + BOOLEAN Status; + LPPACKET lpPacket; + + lpPacket = PacketQueryOid( + AdapterObject, + permanent ? OID_802_3_PERMANENT_ADDRESS : OID_802_3_CURRENT_ADDRESS, + ETH_802_3_ADDRESS_LENGTH + ); + if(lpPacket) { + memcpy( address, + ((BYTE *)(lpPacket->Buffer)) + sizeof(PACKET_OID_DATA) - 1, + ETH_802_3_ADDRESS_LENGTH ); + PacketFreePacket( lpPacket ); + Status = TRUE; + } else { + Status = FALSE; + } + + return Status; +} + +// There are other ways to do this. + +BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address ) +{ + BOOLEAN Status = FALSE; + LPBYTE p; + int i, count; + LPPACKET lpPacket; + + D(bug("PacketAddMulticast\n")); + + /* + if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { + D(bug("PacketAddMulticast: already listening for all multicast\n")); + return TRUE; + } + */ + + lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); +#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) + + if(lpPacket) { + count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; + + D(bug("PacketAddMulticast: %d old addresses\n",count)); + + p = (LPBYTE)OidData->Data; + + for( i=0; i= MAX_MULTICAST) { + D(bug("PacketAddMulticast: too many addresses\n")); + Status = FALSE; + } else { + D(bug("PacketAddMulticast: adding a new address\n")); + + // ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*1-1); + ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count+1)-1); + + LPPACKET lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); +#define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer)) + if ( lpPacket2 ) { + OidData2->Oid = OID_802_3_MULTICAST_LIST; + + // OidData2->Length = ETH_802_3_ADDRESS_LENGTH*1; + // memcpy( OidData2->Data, address, ETH_802_3_ADDRESS_LENGTH ); + + memcpy( OidData2->Data, OidData->Data, ETH_802_3_ADDRESS_LENGTH*count ); + memcpy( OidData2->Data+ETH_802_3_ADDRESS_LENGTH*count, address, ETH_802_3_ADDRESS_LENGTH ); + OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count+1); + + Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); + PacketFreePacket( lpPacket2 ); + } +#undef OidData2 + } + } + PacketFreePacket( lpPacket ); + } + + #undef OidData + + // return Status; + return TRUE; +} + +// It seems that the last multicast address is never deleted. Why? +// Don't know the reason, but luckily this is not fatal. +// Hard to examine return codes. See NE2000 sources, always returns ok. + +BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address ) +{ + BOOLEAN Status = FALSE; + LPBYTE p; + int i, count; + LPPACKET lpPacket, lpPacket2; + + D(bug("PacketDelMulticast\n")); + + if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { + D(bug("PacketDelMulticast: already listening for all multicast\n")); + return TRUE; + } + + lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); +#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) + + if(lpPacket) { + count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; + + D(bug("PacketDelMulticast: %d old addresses\n",count)); + + Status = FALSE; + + p = (LPBYTE)OidData->Data; + + for( i=0; iBuffer)) + if ( lpPacket2 ) { + OidData2->Oid = OID_802_3_MULTICAST_LIST; + OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count-1); + tail_len = ETH_802_3_ADDRESS_LENGTH * (count-i-1); + if(tail_len) memmove( p, p+ETH_802_3_ADDRESS_LENGTH, tail_len ); + if(OidData2->Length) memcpy( OidData2->Data, OidData->Data, OidData2->Length ); + if(count == 1) memset( OidData2->Data, 0, ETH_802_3_ADDRESS_LENGTH ); // eh... + Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); + PacketFreePacket( lpPacket2 ); + D(bug("PacketDelMulticast: PacketRequest returned status 0x%X, last error = 0x%X\n",Status,GetLastError())); + } + break; +#undef OidData2 + } + p += ETH_802_3_ADDRESS_LENGTH; + } + if( i == count ) { + D(bug("PacketDelMulticast: cannot delete, was not defined\n")); + } + PacketFreePacket( lpPacket ); +#undef OidData + } + + // return Status; + return TRUE; +} + +BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter ) +{ + BOOLEAN Status; + ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); + LPPACKET lpPacket; + + lpPacket = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); +#define lpOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) + + if ( lpPacket ) { + lpOidData->Oid = OID_GEN_CURRENT_PACKET_FILTER; + lpOidData->Length = sizeof(ULONG); + *((PULONG)lpOidData->Data) = Filter; + Status = PacketRequest( AdapterObject, lpPacket, TRUE ); + PacketFreePacket( lpPacket ); + } else { + Status = FALSE; + } + +#undef lpOidData + + return Status; +} + +BOOLEAN StartPacketDriver( LPTSTR ServiceName ) +{ + BOOLEAN Status = FALSE; + + SC_HANDLE SCManagerHandle; + SC_HANDLE SCServiceHandle; + + SCManagerHandle = OpenSCManager( + NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + + if(SCManagerHandle == NULL) { + D(bug("Could not open Service Control Manager\r\n")); + } else { + SCServiceHandle = OpenService(SCManagerHandle,ServiceName,SERVICE_START); + if (SCServiceHandle == NULL) { + D(bug("Could not open service %s\r\n",ServiceName)); + } else { + Status = StartService( SCServiceHandle, 0, NULL ); + if(!Status) { + if (GetLastError()==ERROR_SERVICE_ALREADY_RUNNING) { + Status = TRUE; + } + } + BOOL waiting = TRUE; + // loop until the service is fully started. + while (waiting) { + SERVICE_STATUS ServiceStatus; + if (QueryServiceStatus(SCServiceHandle, &ServiceStatus)) { + switch(ServiceStatus.dwCurrentState) { + case SERVICE_RUNNING: + waiting = FALSE; + Status = TRUE; + break; + case SERVICE_START_PENDING: + Sleep(500); + break; + default: + waiting = FALSE; + break; + } + } else { + waiting = FALSE; + } + } + CloseServiceHandle(SCServiceHandle); + } + CloseServiceHandle(SCManagerHandle); + } + return Status; +} + +ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, PTSTR pStr, PULONG BufferSize ) +{ + LONG Status; + + if(os == VER_PLATFORM_WIN32_NT) { + HKEY hKey; + DWORD RegType; + + Status = RegOpenKey( + HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\B2Ether\\Linkage", + &hKey + ); + if( Status == ERROR_SUCCESS ) { + Status = RegQueryValueEx( + hKey, + "Export", + NULL, + &RegType, + (LPBYTE)pStr, + BufferSize + ); + RegCloseKey(hKey); + } + } else { + if (lpAdapter && lpAdapter->hFile != INVALID_HANDLE_VALUE) { + LPPACKET Packet = PacketAllocatePacket( lpAdapter, *BufferSize ); + if(Packet) { + memset( pStr, 0, *BufferSize ); + Packet->Buffer = (PVOID)pStr; + Packet->Length = *BufferSize; + Status = PacketDeviceIoControl( + lpAdapter, + Packet, + (ULONG)IOCTL_PROTOCOL_MACNAME, + TRUE + ); + if(Status) { + while(*pStr) { + if(*pStr == '|' || *pStr == ' ') *pStr = 0; + pStr++; + } + *(++pStr) = 0; + Status = ERROR_SUCCESS; + } else { + Status = ERROR_ACCESS_DENIED; + } + *BufferSize = Packet->BytesReceived; + PacketFreePacket(Packet); + } + } + } + + return Status; +} + + +ULONG PacketSelectAdapterByName( LPADAPTER lpAdapter, LPCSTR name ) +{ + ULONG Status = 0; + + if(os == VER_PLATFORM_WIN32_WINDOWS) { + int len = strlen(name) + 1; + LPPACKET Packet = PacketAllocatePacket( lpAdapter, len ); + if(Packet) { + Packet->Buffer = (PVOID)name; + Packet->Length = len; + Status = PacketDeviceIoControl( + lpAdapter, + Packet, + (ULONG)IOCTL_PROTOCOL_SELECT_BY_NAME, + TRUE + ); + if(Status) { + Status = ERROR_SUCCESS; + } else { + Status = ERROR_ACCESS_DENIED; + } + PacketFreePacket(Packet); + } + } + return Status; +} + + +#ifdef __cplusplus +} +#endif + +#if DEBUG +#pragma optimize("",on) +#endif