4
* Basilisk II (C) 1997-1999 Christian Bauer
6
* Windows platform specific code copyright (C) Lauri Pesonen
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#include "cpu_emulation.h"
28
typedef unsigned long ULONG_PTR, *PULONG_PTR;
30
// VC6 does not have this, Platform SDK has.
31
// In case of errors, try to comment out, the needed
32
// definitions are below (#ifndef _NTDDNDIS_)
34
// Most people don't have the Platform SDK, so I take this one out.
35
// #include <ntddndis.h>
37
#include "inc/ntddpack.h"
40
#include "ether_defs.h"
41
#include "b2ether/multiopt.h"
42
#include "b2ether/inc/b2ether_hl.h"
47
#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
48
#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
49
#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
50
#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
51
#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
52
#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
54
#define OID_802_3_PERMANENT_ADDRESS 0x01010101
55
#define OID_802_3_CURRENT_ADDRESS 0x01010102
56
#define OID_802_3_MULTICAST_LIST 0x01010103
58
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
61
#define DEBUG_PACKETS 0
70
#pragma optimize("",off)
73
#define MAX_MULTICAST 100
74
#define MAX_MULTICAST_SZ (20*ETH_802_3_ADDRESS_LENGTH)
76
static int os = VER_PLATFORM_WIN32_WINDOWS;
78
static ULONG packet_filter = 0;
81
LPADAPTER PacketOpenAdapter( LPCSTR AdapterName, int16 mode )
84
BOOLEAN Result = TRUE;
87
D(bug("Packet32: PacketOpenAdapter\n"));
89
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
90
if(GetVersionEx( &osv )) os = osv.dwPlatformId;
92
if(os == VER_PLATFORM_WIN32_NT) {
93
// May fail if user is not an Administrator.
94
StartPacketDriver( "B2ether" );
97
lpAdapter = (LPADAPTER)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(ADAPTER) );
98
if (lpAdapter==NULL) {
99
D(bug("Packet32: PacketOpenAdapter GlobalAlloc Failed\n"));
103
if(os == VER_PLATFORM_WIN32_NT) {
104
char device_name[256];
105
wsprintf( lpAdapter->SymbolicLink, "\\\\.\\B2ether_%s", AdapterName );
106
wsprintf( device_name, "\\Device\\B2ether_%s", AdapterName );
108
// Work around one subtle NT4 bug.
110
DDD_REMOVE_DEFINITION,
111
&lpAdapter->SymbolicLink[4],
116
&lpAdapter->SymbolicLink[4],
120
wsprintf( lpAdapter->SymbolicLink, "\\\\.\\B2ether" );
123
packet_filter = NDIS_PACKET_TYPE_DIRECTED |
124
NDIS_PACKET_TYPE_MULTICAST |
125
NDIS_PACKET_TYPE_BROADCAST;
127
if(mode == ETHER_MULTICAST_ALL) packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
128
if(mode == ETHER_MULTICAST_PROMISCUOUS) packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
131
lpAdapter->hFile = CreateFile(lpAdapter->SymbolicLink,
132
GENERIC_WRITE | GENERIC_READ,
135
// (os == VER_PLATFORM_WIN32_NT) ? CREATE_ALWAYS : OPEN_EXISTING,
137
FILE_FLAG_OVERLAPPED,
140
if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
141
if(*AdapterName && strcmp(AdapterName,"<None>") != 0) {
142
if(os == VER_PLATFORM_WIN32_WINDOWS) {
143
PacketSelectAdapterByName( lpAdapter, AdapterName );
145
PacketSetFilter( lpAdapter, packet_filter );
150
D(bug("Packet32: PacketOpenAdapter Could not open adapter\n"));
151
GlobalFreePtr( lpAdapter );
155
VOID PacketCloseAdapter( LPADAPTER lpAdapter )
157
D(bug("Packet32: PacketCloseAdapter\n"));
160
if(lpAdapter->hFile) {
161
CloseHandle(lpAdapter->hFile);
163
GlobalFreePtr(lpAdapter);
167
LPPACKET PacketAllocatePacket( LPADAPTER AdapterObject, UINT Length )
171
lpPacket = (LPPACKET)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(PACKET) );
173
D(bug("Packet32: PacketAllocatePacket: GlobalAlloc Failed\n"));
177
lpPacket->OverLapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
178
if(!lpPacket->OverLapped.hEvent) {
179
D(bug("Packet32: PacketAllocatePacket: CreateEvent Failed\n"));
180
GlobalFreePtr(lpPacket);
184
lpPacket->Buffer = GlobalAllocPtr(GMEM_MOVEABLE,2048); // 1514
185
if(!lpPacket->Buffer) {
186
D(bug("Packet32: PacketAllocatePacket: GlobalAllocPtr Failed\n"));
187
if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent);
188
GlobalFreePtr(lpPacket);
192
lpPacket->OverLapped.Offset = 0;
193
lpPacket->OverLapped.OffsetHigh = 0;
194
lpPacket->Length = Length;
195
lpPacket->BytesReceived = 0;
196
lpPacket->bIoComplete = FALSE;
197
lpPacket->free = TRUE;
202
VOID PacketFreePacket( LPPACKET lpPacket )
205
if(lpPacket->Buffer) GlobalFreePtr(lpPacket->Buffer);
206
if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent);
207
GlobalFreePtr(lpPacket);
211
BOOLEAN PacketDeviceIoControl(
212
LPADAPTER lpAdapterObject,
220
lpPacket->OverLapped.Offset = 0;
221
lpPacket->OverLapped.OffsetHigh = 0;
222
lpPacket->BytesReceived = 0;
224
if ( !ResetEvent( lpPacket->OverLapped.hEvent ) ) {
225
lpPacket->bIoComplete = FALSE;
226
D(bug( "Packet32: PacketDeviceIoControl failed to reset event\r\n", GetLastError() ));
230
Result = DeviceIoControl(
231
lpAdapterObject->hFile,
237
&(lpPacket->BytesReceived),
238
&(lpPacket->OverLapped) );
240
if( !Result && bSync ) {
241
if (GetLastError() == ERROR_IO_PENDING) {
242
Result = GetOverlappedResult( lpAdapterObject->hFile,
243
&(lpPacket->OverLapped),
244
&(lpPacket->BytesReceived),
247
D(bug( "Packet32: unsupported API call returned error 0x%x\r\n", GetLastError() ));
250
lpPacket->bIoComplete = Result;
254
VOID CALLBACK PacketSendCompletionRoutine(
256
DWORD dwNumberOfBytesTransfered,
257
LPOVERLAPPED lpOverlapped
260
LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped);
263
D(bug("PacketSendCompletionRoutine %d\n",dwNumberOfBytesTransfered));
266
lpPacket->bIoComplete = TRUE;
267
// lpPacket->free = TRUE;
268
// PacketFreePacket(lpPacket);
269
recycle_write_packet(lpPacket);
272
BOOLEAN PacketSendPacket(
273
LPADAPTER AdapterObject,
276
BOOLEAN RecyclingAllowed
282
D(bug("Packet32: PacketSendPacket bytes=%d, sync=%d\n",lpPacket->Length,Sync));
285
if(os == VER_PLATFORM_WIN32_NT) {
286
lpPacket->OverLapped.Offset = 0;
287
lpPacket->OverLapped.OffsetHigh = 0;
288
lpPacket->bIoComplete = FALSE;
292
AdapterObject->hFile,
295
&lpPacket->BytesReceived,
296
&lpPacket->OverLapped
299
Result = GetOverlappedResult(
300
AdapterObject->hFile,
301
&lpPacket->OverLapped,
302
&lpPacket->BytesReceived,
306
D(bug("Packet32: PacketSendPacket WriteFile failed, err=%d\n",(int)GetLastError()));
308
lpPacket->bIoComplete = TRUE;
309
if(RecyclingAllowed) PacketFreePacket(lpPacket);
311
D(bug("Packet32: PacketSendPacket result=%d, bytes=%d\n",(int)Result,(int)lpPacket->BytesReceived));
314
// don't care about the result
315
Result = WriteFileEx(
316
AdapterObject->hFile,
319
&lpPacket->OverLapped,
320
PacketSendCompletionRoutine
323
D(bug("Packet32: PacketSendPacket result=%d\n",(int)Result));
325
if(!Result && RecyclingAllowed) {
326
recycle_write_packet(lpPacket);
330
// Now: make writes always synchronous under Win9x
332
Result = PacketDeviceIoControl( AdapterObject,
334
IOCTL_PROTOCOL_WRITE,
336
if(RecyclingAllowed) recycle_write_packet(lpPacket);
342
BOOLEAN PacketReceivePacket(
343
LPADAPTER AdapterObject,
350
if(os == VER_PLATFORM_WIN32_NT) {
351
lpPacket->OverLapped.Offset=0;
352
lpPacket->OverLapped.OffsetHigh=0;
353
lpPacket->bIoComplete = FALSE;
356
D(bug("Packet32: PacketReceivePacket\n"));
361
AdapterObject->hFile,
364
&lpPacket->BytesReceived,
365
&lpPacket->OverLapped
368
Result = GetOverlappedResult(
369
AdapterObject->hFile,
370
&lpPacket->OverLapped,
371
&lpPacket->BytesReceived,
375
lpPacket->bIoComplete = TRUE;
377
lpPacket->free = TRUE;
381
AdapterObject->hFile,
384
&lpPacket->OverLapped,
385
packet_read_completion
389
if(!Result) lpPacket->BytesReceived = 0;
391
Result = PacketDeviceIoControl( AdapterObject,
395
if( !Result && !Sync ) {
396
if (GetLastError() == ERROR_IO_PENDING) {
403
D(bug("Packet32: PacketReceivePacket got %d bytes, result=%d\n",lpPacket->BytesReceived,(int)Result));
409
BOOLEAN PacketRequest(
410
LPADAPTER lpAdapterObject,
415
BOOLEAN Result = FALSE;
417
Result = PacketDeviceIoControl(
420
(ULONG) ((bSet) ? IOCTL_PROTOCOL_SET_OID : IOCTL_PROTOCOL_QUERY_OID),
423
if ( lpPacket->BytesReceived == 0 ) {
424
D(bug( "Packet32: Ndis returned error to OID\r\n"));
430
LPPACKET PacketQueryOid(
439
#define pOidData ((PPACKET_OID_DATA)(lpPacket->Buffer))
441
lpPacket = PacketAllocatePacket( lpAdapter, sizeof(PACKET_OID_DATA)-1+ulLength );
444
ioctl = IOCTL_PROTOCOL_QUERY_OID;
445
pOidData->Oid = ulOid;
446
pOidData->Length = ulLength;
448
if (PacketRequest( lpAdapter, lpPacket, FALSE )) {
451
PacketFreePacket( lpPacket );
459
BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent )
464
lpPacket = PacketQueryOid(
466
permanent ? OID_802_3_PERMANENT_ADDRESS : OID_802_3_CURRENT_ADDRESS,
467
ETH_802_3_ADDRESS_LENGTH
471
((BYTE *)(lpPacket->Buffer)) + sizeof(PACKET_OID_DATA) - 1,
472
ETH_802_3_ADDRESS_LENGTH );
473
PacketFreePacket( lpPacket );
482
// There are other ways to do this.
484
BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address )
486
BOOLEAN Status = FALSE;
491
D(bug("PacketAddMulticast\n"));
494
if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) {
495
D(bug("PacketAddMulticast: already listening for all multicast\n"));
500
lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ );
501
#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer))
504
count = OidData->Length / ETH_802_3_ADDRESS_LENGTH;
506
D(bug("PacketAddMulticast: %d old addresses\n",count));
508
p = (LPBYTE)OidData->Data;
510
for( i=0; i<count; i++ ) {
511
if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) {
512
// This multicast is already defined -- error or not?
514
D(bug("PacketAddMulticast: address already defined\n"));
517
p += ETH_802_3_ADDRESS_LENGTH;
520
if(i >= MAX_MULTICAST) {
521
D(bug("PacketAddMulticast: too many addresses\n"));
524
D(bug("PacketAddMulticast: adding a new address\n"));
526
// ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*1-1);
527
ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count+1)-1);
529
LPPACKET lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength );
530
#define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer))
532
OidData2->Oid = OID_802_3_MULTICAST_LIST;
534
// OidData2->Length = ETH_802_3_ADDRESS_LENGTH*1;
535
// memcpy( OidData2->Data, address, ETH_802_3_ADDRESS_LENGTH );
537
memcpy( OidData2->Data, OidData->Data, ETH_802_3_ADDRESS_LENGTH*count );
538
memcpy( OidData2->Data+ETH_802_3_ADDRESS_LENGTH*count, address, ETH_802_3_ADDRESS_LENGTH );
539
OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count+1);
541
Status = PacketRequest( AdapterObject, lpPacket2, TRUE );
542
PacketFreePacket( lpPacket2 );
547
PacketFreePacket( lpPacket );
556
// It seems that the last multicast address is never deleted. Why?
557
// Don't know the reason, but luckily this is not fatal.
558
// Hard to examine return codes. See NE2000 sources, always returns ok.
560
BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address )
562
BOOLEAN Status = FALSE;
565
LPPACKET lpPacket, lpPacket2;
567
D(bug("PacketDelMulticast\n"));
569
if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) {
570
D(bug("PacketDelMulticast: already listening for all multicast\n"));
574
lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ );
575
#define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer))
578
count = OidData->Length / ETH_802_3_ADDRESS_LENGTH;
580
D(bug("PacketDelMulticast: %d old addresses\n",count));
584
p = (LPBYTE)OidData->Data;
586
for( i=0; i<count; i++ ) {
588
if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) {
589
D(bug("PacketDelMulticast: address found, deleting\n"));
590
ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count-1)-1);
591
lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength );
592
#define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer))
594
OidData2->Oid = OID_802_3_MULTICAST_LIST;
595
OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count-1);
596
tail_len = ETH_802_3_ADDRESS_LENGTH * (count-i-1);
597
if(tail_len) memmove( p, p+ETH_802_3_ADDRESS_LENGTH, tail_len );
598
if(OidData2->Length) memcpy( OidData2->Data, OidData->Data, OidData2->Length );
599
if(count == 1) memset( OidData2->Data, 0, ETH_802_3_ADDRESS_LENGTH ); // eh...
600
Status = PacketRequest( AdapterObject, lpPacket2, TRUE );
601
PacketFreePacket( lpPacket2 );
602
D(bug("PacketDelMulticast: PacketRequest returned status 0x%X, last error = 0x%X\n",Status,GetLastError()));
607
p += ETH_802_3_ADDRESS_LENGTH;
610
D(bug("PacketDelMulticast: cannot delete, was not defined\n"));
612
PacketFreePacket( lpPacket );
620
BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter )
623
ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
626
lpPacket = PacketAllocatePacket( AdapterObject, IoCtlBufferLength );
627
#define lpOidData ((PPACKET_OID_DATA)(lpPacket->Buffer))
630
lpOidData->Oid = OID_GEN_CURRENT_PACKET_FILTER;
631
lpOidData->Length = sizeof(ULONG);
632
*((PULONG)lpOidData->Data) = Filter;
633
Status = PacketRequest( AdapterObject, lpPacket, TRUE );
634
PacketFreePacket( lpPacket );
644
BOOLEAN StartPacketDriver( LPTSTR ServiceName )
646
BOOLEAN Status = FALSE;
648
SC_HANDLE SCManagerHandle;
649
SC_HANDLE SCServiceHandle;
651
SCManagerHandle = OpenSCManager(
654
SC_MANAGER_ALL_ACCESS);
656
if(SCManagerHandle == NULL) {
657
D(bug("Could not open Service Control Manager\r\n"));
659
SCServiceHandle = OpenService(SCManagerHandle,ServiceName,SERVICE_START);
660
if (SCServiceHandle == NULL) {
661
D(bug("Could not open service %s\r\n",ServiceName));
663
Status = StartService( SCServiceHandle, 0, NULL );
665
if (GetLastError()==ERROR_SERVICE_ALREADY_RUNNING) {
670
// loop until the service is fully started.
672
SERVICE_STATUS ServiceStatus;
673
if (QueryServiceStatus(SCServiceHandle, &ServiceStatus)) {
674
switch(ServiceStatus.dwCurrentState) {
675
case SERVICE_RUNNING:
679
case SERVICE_START_PENDING:
690
CloseServiceHandle(SCServiceHandle);
692
CloseServiceHandle(SCManagerHandle);
697
ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, PTSTR pStr, PULONG BufferSize )
701
if(os == VER_PLATFORM_WIN32_NT) {
707
"SYSTEM\\CurrentControlSet\\Services\\B2Ether\\Linkage",
710
if( Status == ERROR_SUCCESS ) {
711
Status = RegQueryValueEx(
722
if (lpAdapter && lpAdapter->hFile != INVALID_HANDLE_VALUE) {
723
LPPACKET Packet = PacketAllocatePacket( lpAdapter, *BufferSize );
725
memset( pStr, 0, *BufferSize );
726
Packet->Buffer = (PVOID)pStr;
727
Packet->Length = *BufferSize;
728
Status = PacketDeviceIoControl(
731
(ULONG)IOCTL_PROTOCOL_MACNAME,
736
if(*pStr == '|' || *pStr == ' ') *pStr = 0;
740
Status = ERROR_SUCCESS;
742
Status = ERROR_ACCESS_DENIED;
744
*BufferSize = Packet->BytesReceived;
745
PacketFreePacket(Packet);
754
ULONG PacketSelectAdapterByName( LPADAPTER lpAdapter, LPCSTR name )
758
if(os == VER_PLATFORM_WIN32_WINDOWS) {
759
int len = strlen(name) + 1;
760
LPPACKET Packet = PacketAllocatePacket( lpAdapter, len );
762
Packet->Buffer = (PVOID)name;
763
Packet->Length = len;
764
Status = PacketDeviceIoControl(
767
(ULONG)IOCTL_PROTOCOL_SELECT_BY_NAME,
771
Status = ERROR_SUCCESS;
773
Status = ERROR_ACCESS_DENIED;
775
PacketFreePacket(Packet);
787
#pragma optimize("",on)