import original b2ether code from B2/Win32

This commit is contained in:
gbeauche 2004-12-05 16:51:29 +00:00
parent 2de1c1760f
commit 553127f8f3
4 changed files with 963 additions and 0 deletions

View File

@ -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_

View File

@ -0,0 +1,32 @@
// #include <ntddndis.h>
#ifndef __NTDDPACKET
#define __NTDDPACKET 1
// #include <devioctl.h>
#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

View File

@ -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
};

View File

@ -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 <windows.h>
#include <windowsx.h>
#include <winioctl.h>
#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 <ntddndis.h>
#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,"<None>") != 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<count; i++ ) {
if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) {
// This multicast is already defined -- error or not?
Status = TRUE;
D(bug("PacketAddMulticast: address already defined\n"));
break;
}
p += ETH_802_3_ADDRESS_LENGTH;
}
if(i == count) {
if(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; i<count; i++ ) {
int tail_len;
if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) {
D(bug("PacketDelMulticast: address found, deleting\n"));
ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count-1)-1);
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*(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