ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/b2ether/nt5/b2ether.c
Revision: 1.1
Committed: 2012-04-22T03:13:32Z (12 years, 7 months ago) by asvitkine
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Error occurred while calculating annotation data.
Log Message:
Import nt5 version of the ethernet driver from 2001 sources.

File Contents

# Content
1 /*
2 * b2ether driver -- derived from DDK packet driver sample
3 *
4 * Basilisk II (C) 1997-1999 Christian Bauer
5 *
6 * Windows platform specific code copyright (C) Lauri Pesonen
7 *
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.
12 *
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.
17 *
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
21 */
22
23
24 #include "ntddk.h"
25 #include "ndis.h"
26 #include "ntddpack.h"
27 #include "b2ether.h"
28 #include "stdio.h"
29
30
31
32 NTSTATUS
33 DriverEntry(
34 IN PDRIVER_OBJECT DriverObject,
35 IN PUNICODE_STRING RegistryPath
36 )
37 {
38 NDIS_PROTOCOL_CHARACTERISTICS protocolChar;
39 NTSTATUS status = STATUS_SUCCESS;
40 NDIS_STRING protoName = NDIS_STRING_CONST("B2ether");
41 UNICODE_STRING ntDeviceName;
42 UNICODE_STRING win32DeviceName;
43 BOOLEAN fSymbolicLink = FALSE;
44 PDEVICE_OBJECT deviceObject;
45
46 // DebugPrint(("\n\nDriverEntry\n"));
47
48 Globals.DriverObject = DriverObject;
49 Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
50 Globals.RegistryPath.Length = RegistryPath->Length;
51 Globals.RegistryPath.Buffer = ExAllocatePool( PagedPool, Globals.RegistryPath.MaximumLength );
52 if (!Globals.RegistryPath.Buffer) {
53 // DebugPrint (("Couldn't allocate pool for registry path."));
54 return STATUS_INSUFFICIENT_RESOURCES;
55 }
56
57 RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);
58 RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
59
60 status = IoCreateDevice (DriverObject,
61 0,
62 &ntDeviceName,
63 FILE_DEVICE_UNKNOWN,
64 0,
65 FALSE,
66 &deviceObject);
67
68
69 if (!NT_SUCCESS (status)) {
70 // Either not enough memory to create a deviceobject or another
71 // deviceobject with the same name exits. This could happen
72 // if you install another instance of this device.
73 goto ERROR;
74 }
75
76 RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
77
78 status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
79 if (!NT_SUCCESS(status)) goto ERROR;
80
81 fSymbolicLink = TRUE;
82
83 deviceObject->Flags |= DO_BUFFERED_IO;
84 Globals.ControlDeviceObject = deviceObject;
85
86 InitializeListHead(&Globals.AdapterList);
87 KeInitializeSpinLock(&Globals.GlobalLock);
88
89 NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
90
91 protocolChar.MajorNdisVersion = 5;
92 protocolChar.MinorNdisVersion = 0;
93 protocolChar.Name = protoName;
94 protocolChar.OpenAdapterCompleteHandler = PacketOpenAdapterComplete;
95 protocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete;
96 protocolChar.SendCompleteHandler = PacketSendComplete;
97 protocolChar.TransferDataCompleteHandler = PacketTransferDataComplete;
98 protocolChar.ResetCompleteHandler = PacketResetComplete;
99 protocolChar.RequestCompleteHandler = PacketRequestComplete;
100 protocolChar.ReceiveHandler = PacketReceiveIndicate;
101 protocolChar.ReceiveCompleteHandler = PacketReceiveComplete;
102 protocolChar.StatusHandler = PacketStatus;
103 protocolChar.StatusCompleteHandler = PacketStatusComplete;
104 protocolChar.BindAdapterHandler = PacketBindAdapter;
105 protocolChar.UnbindAdapterHandler = PacketUnbindAdapter;
106 protocolChar.UnloadHandler = NULL;
107 protocolChar.ReceivePacketHandler = PacketReceivePacket;
108 protocolChar.PnPEventHandler = PacketPNPHandler;
109
110 NdisRegisterProtocol(
111 &status,
112 &Globals.NdisProtocolHandle,
113 &protocolChar,
114 sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
115
116 if (status != NDIS_STATUS_SUCCESS) {
117 // DebugPrint(("Failed to register protocol with NDIS\n"));
118 status = STATUS_UNSUCCESSFUL;
119 goto ERROR;
120 }
121
122 DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen;
123 DriverObject->MajorFunction[IRP_MJ_CLOSE] = PacketClose;
124 DriverObject->MajorFunction[IRP_MJ_READ] = PacketRead;
125 DriverObject->MajorFunction[IRP_MJ_WRITE] = PacketWrite;
126 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PacketCleanup;
127 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PacketIoControl;
128 DriverObject->DriverUnload = PacketUnload;
129
130 return(STATUS_SUCCESS);
131
132 ERROR:
133 if(deviceObject)
134 IoDeleteDevice(deviceObject);
135 if(fSymbolicLink)
136 IoDeleteSymbolicLink(&win32DeviceName);
137 if(Globals.RegistryPath.Buffer)
138 ExFreePool(Globals.RegistryPath.Buffer);
139 return status;
140 }
141
142
143 VOID PacketUnload( IN PDRIVER_OBJECT DriverObject )
144 {
145 NDIS_STATUS status;
146 UNICODE_STRING win32DeviceName;
147
148 // DebugPrint(("Unload Enter\n"));
149
150 RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
151 IoDeleteSymbolicLink(&win32DeviceName);
152
153 if(Globals.ControlDeviceObject)
154 IoDeleteDevice(Globals.ControlDeviceObject);
155
156 // Unbind from all the adapters. The system removes the driver code
157 // pages from the memory as soon as the unload returns. So you
158 // must wait for all the CloseAdapterCompleteHandler to finish
159 // before returning from the unload routine. You don't any callbacks
160 // to trigger after the driver is unloaded.
161
162 while(DriverObject->DeviceObject) {
163 PacketUnbindAdapter(&status, DriverObject->DeviceObject->DeviceExtension,NULL);
164 }
165
166 if(Globals.RegistryPath.Buffer)
167 ExFreePool(Globals.RegistryPath.Buffer);
168
169 // DebugPrint(("Deregister\n"));
170
171 NdisDeregisterProtocol( &status, Globals.NdisProtocolHandle );
172 // DebugPrint(("Unload Exit\n"));
173 }
174
175
176
177 NTSTATUS PacketIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
178 {
179 POPEN_INSTANCE open;
180 PIO_STACK_LOCATION irpSp;
181 PINTERNAL_REQUEST pRequest;
182 ULONG functionCode;
183 NDIS_STATUS status;
184 ULONG dataLength =0;
185
186 // DebugPrint(("IoControl\n"));
187
188 irpSp = IoGetCurrentIrpStackLocation(Irp);
189
190 functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
191
192 if (functionCode == IOCTL_ENUM_ADAPTERS) {
193 // If the request is not made to the controlobject, fail the request.
194
195 if(DeviceObject != Globals.ControlDeviceObject) {
196 status = STATUS_INVALID_DEVICE_REQUEST;
197 } else {
198 status = PacketGetAdapterList(
199 Irp->AssociatedIrp.SystemBuffer,
200 irpSp->Parameters.DeviceIoControl.OutputBufferLength,
201 &dataLength
202 );
203 }
204 Irp->IoStatus.Status = status;
205 Irp->IoStatus.Information = dataLength;
206 IoCompleteRequest(Irp, IO_NO_INCREMENT);
207 return status;
208 }
209
210 open = DeviceObject->DeviceExtension;
211 IoIncrement(open);
212
213 if(!open->Bound) {
214 Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
215 IoCompleteRequest(Irp, IO_NO_INCREMENT);
216 IoDecrement(open);
217 return status;
218 }
219
220 // DebugPrint(("Function code is %08lx buff size=%08lx %08lx\n",
221 // functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength,
222 // irpSp->Parameters.DeviceIoControl.OutputBufferLength));
223
224 // Important: Since we have marked the IRP pending, we must return
225 // STATUS_PENDING even we happen to complete the IRP synchronously.
226
227 IoMarkIrpPending(Irp);
228
229 if (functionCode == IOCTL_PROTOCOL_RESET) {
230 // DebugPrint(("IoControl - Reset request\n"));
231
232 //
233 // Since NDIS doesn't have an interface to cancel a request
234 // pending at miniport, we cannot set a cancel routine.
235 // As a result if the application that made the request
236 // terminates, we wait in the Cleanup routine for all pending
237 // NDIS requests to complete.
238
239 ExInterlockedInsertTailList(
240 &open->ResetIrpList,
241 &Irp->Tail.Overlay.ListEntry,
242 &open->ResetQueueLock);
243
244 NdisReset( &status, open->AdapterHandle );
245
246 if (status != NDIS_STATUS_PENDING) {
247 // DebugPrint(("IoControl - ResetComplete being called\n"));
248 PacketResetComplete( open, status );
249 }
250 } else {
251 // See if it is an Ndis request
252 PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer;
253
254 pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST));
255
256 if(!pRequest) {
257 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
258 IoCompleteRequest (Irp, IO_NO_INCREMENT);
259 IoDecrement(open);
260 return STATUS_PENDING;
261 }
262 pRequest->Irp=Irp;
263
264 if (((functionCode == IOCTL_PROTOCOL_SET_OID) || (functionCode == IOCTL_PROTOCOL_QUERY_OID))
265 &&
266 (irpSp->Parameters.DeviceIoControl.InputBufferLength == irpSp->Parameters.DeviceIoControl.OutputBufferLength)
267 &&
268 (irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
269 &&
270 (irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length))
271 {
272 // DebugPrint(("IoControl: Request: Oid=%08lx, Length=%08lx\n", OidData->Oid,OidData->Length));
273
274 if (functionCode == IOCTL_PROTOCOL_SET_OID) {
275 pRequest->Request.RequestType = NdisRequestSetInformation;
276 pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid;
277 pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data;
278 pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length;
279 } else {
280 pRequest->Request.RequestType=NdisRequestQueryInformation;
281 pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid;
282 pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data;
283 pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length;
284 }
285 NdisRequest( &status, open->AdapterHandle, &pRequest->Request );
286 } else {
287 status=NDIS_STATUS_FAILURE;
288 pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
289 pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
290 }
291
292 if (status != NDIS_STATUS_PENDING) {
293 // DebugPrint(("Calling RequestCompleteHandler\n"));
294 PacketRequestComplete( open, &pRequest->Request, status );
295 }
296 }
297 return STATUS_PENDING;
298 }
299
300
301 VOID
302 PacketRequestComplete(
303 IN NDIS_HANDLE ProtocolBindingContext,
304 IN PNDIS_REQUEST NdisRequest,
305 IN NDIS_STATUS Status
306 )
307 {
308 POPEN_INSTANCE open;
309 PIO_STACK_LOCATION irpSp;
310 PIRP irp;
311 PINTERNAL_REQUEST pRequest;
312 UINT functionCode;
313
314 PPACKET_OID_DATA OidData;
315
316 // DebugPrint(("RequestComplete\n"));
317
318 open = (POPEN_INSTANCE)ProtocolBindingContext;
319
320 pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
321 irp = pRequest->Irp;
322
323 if(Status == NDIS_STATUS_SUCCESS) {
324 irpSp = IoGetCurrentIrpStackLocation(irp);
325 functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
326 OidData = irp->AssociatedIrp.SystemBuffer;
327 if (functionCode == IOCTL_PROTOCOL_SET_OID) {
328 OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
329 } else {
330 if (functionCode == IOCTL_PROTOCOL_QUERY_OID) {
331 OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
332 }
333 }
334 irp->IoStatus.Status = STATUS_SUCCESS;
335 irp->IoStatus.Information=irpSp->Parameters.DeviceIoControl.InputBufferLength;
336 } else {
337 irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
338 irp->IoStatus.Information = 0;
339 }
340
341 ExFreePool(pRequest);
342 IoCompleteRequest(irp, IO_NO_INCREMENT);
343 IoDecrement(open);
344 }
345
346
347 VOID
348 PacketStatus(
349 IN NDIS_HANDLE ProtocolBindingContext,
350 IN NDIS_STATUS Status,
351 IN PVOID StatusBuffer,
352 IN UINT StatusBufferSize
353 )
354 {
355 // DebugPrint(("Indication Status: %0x, StatusBufferSize: %d\n", Status, StatusBufferSize));
356 }
357
358
359 VOID PacketStatusComplete( IN NDIS_HANDLE ProtocolBindingContext )
360 {
361 // DebugPrint(("StatusIndicationComplete\n"));
362 }
363
364
365 NTSTATUS
366 PacketGetAdapterList(
367 IN PVOID Buffer,
368 IN ULONG Length,
369 IN OUT PULONG DataLength
370 )
371 {
372 ULONG requiredLength = 0, numOfAdapters = 0;
373 KIRQL oldIrql;
374 PLIST_ENTRY thisEntry, listHead;
375 POPEN_INSTANCE open;
376
377 // DebugPrint(("Enter PacketGetAdapterList\n"));
378
379 KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql);
380
381 // Walks the list to find out total space required for AdapterName and Symbolic Link.
382
383 listHead = &Globals.AdapterList;
384
385 for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink) {
386 open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry);
387 requiredLength += open->AdapterName.Length + sizeof(UNICODE_NULL);
388 requiredLength += open->SymbolicLink.Length + sizeof(UNICODE_NULL);
389 numOfAdapters++;
390 }
391
392 //
393 // We will return the data in the following format:
394 // numOfAdapters + One_Or_More("AdapterName\0" + "SymbolicLink\0") + UNICODE_NULL
395 // So let's include the numOfAdapters and UNICODE_NULL size
396 // to the total length.
397 //
398
399 requiredLength += sizeof(ULONG) + sizeof(UNICODE_NULL);
400 *DataLength = requiredLength;
401
402 if(requiredLength > Length) {
403 KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
404 return STATUS_BUFFER_TOO_SMALL;
405 }
406
407 *(PULONG)Buffer = numOfAdapters;
408 (PCHAR)Buffer += sizeof(ULONG);
409
410 for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) {
411 open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry);
412 RtlCopyMemory( Buffer, open->AdapterName.Buffer, open->AdapterName.Length+sizeof(WCHAR) );
413 (PCHAR)Buffer += open->AdapterName.Length+sizeof(WCHAR);
414 RtlCopyMemory( Buffer, open->SymbolicLink.Buffer, open->SymbolicLink.Length+sizeof(WCHAR) );
415 (PCHAR)Buffer += open->SymbolicLink.Length+sizeof(WCHAR);
416 }
417
418 *(PWCHAR)Buffer = UNICODE_NULL;
419 KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
420 return STATUS_SUCCESS;
421 }
422
423 VOID
424 PacketBindAdapter(
425 OUT PNDIS_STATUS Status,
426 IN NDIS_HANDLE BindContext,
427 IN PNDIS_STRING DeviceName,
428 IN PVOID SystemSpecific1,
429 IN PVOID SystemSpecific2
430 )
431 {
432 NDIS_STATUS status;
433 UINT mediumIndex;
434 USHORT length;
435 POPEN_INSTANCE open = NULL;
436 UNICODE_STRING unicodeDeviceName;
437 PDEVICE_OBJECT deviceObject = NULL;
438 PWSTR symbolicLink = NULL, deviceNameStr = NULL;
439 NDIS_MEDIUM mediumArray = NdisMedium802_3; // Ethernet medium
440
441 // DebugPrint(("Binding DeviceName %ws\n", DeviceName->Buffer));
442
443 do {
444 // Create a deviceobject for every adapter we bind to.
445 // To make a name for the deviceObject, we will append Packet_
446 // to the name portion of the input DeviceName.
447
448 unicodeDeviceName.Buffer = NULL;
449 length = DeviceName->Length + 7 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
450
451 deviceNameStr = ExAllocatePool(NonPagedPool, length);
452 if (!deviceNameStr) {
453 // DebugPrint(("Memory allocation for create symbolic failed\n"));
454 *Status = NDIS_STATUS_FAILURE;
455 break;
456 }
457 swprintf(deviceNameStr, L"\\Device\\B2ether_%ws", &DeviceName->Buffer[8]);
458 RtlInitUnicodeString(&unicodeDeviceName, deviceNameStr);
459
460 // DebugPrint(("Exported DeviceName %ws\n", unicodeDeviceName.Buffer));
461
462 status = IoCreateDevice(
463 Globals.DriverObject,
464 sizeof(OPEN_INSTANCE),
465 &unicodeDeviceName,
466 FILE_DEVICE_PROTOCOL,
467 0,
468 TRUE, // only one handle to the device at a time.
469 &deviceObject
470 );
471
472 if (status != STATUS_SUCCESS) {
473 // DebugPrint(("CreateDevice Failed: %x\n", status));
474 *Status = NDIS_STATUS_FAILURE;
475 break;
476 }
477
478 deviceObject->Flags |= DO_DIRECT_IO;
479 open = (POPEN_INSTANCE) deviceObject->DeviceExtension;
480 open->DeviceObject = deviceObject;
481
482 // Create a symbolic link.
483 // We need to replace Device from \Device\Packet_{GUID} with DosDevices
484 // to create a symbolic link of the form \DosDevices\Packet_{GUID}
485 // There is a four character difference between these two
486 // strings.
487
488 length = unicodeDeviceName.Length + sizeof(UNICODE_NULL) + (4 * sizeof(WCHAR));
489
490 symbolicLink = ExAllocatePool(NonPagedPool, length);
491 if (!symbolicLink) {
492 // DebugPrint(("Memory allocation for create symbolic failed\n"));
493 *Status = NDIS_STATUS_FAILURE;
494 break;
495 }
496
497 swprintf( symbolicLink, L"\\DosDevices\\%ws", &unicodeDeviceName.Buffer[8]);
498
499 RtlInitUnicodeString(&open->SymbolicLink,symbolicLink);
500
501 // DebugPrint(("Symbolic Link: %ws\n", open->SymbolicLink.Buffer));
502
503 status = IoCreateSymbolicLink(
504 (PUNICODE_STRING) &open->SymbolicLink,
505 (PUNICODE_STRING) &unicodeDeviceName
506 );
507 if (status != STATUS_SUCCESS) {
508 // DebugPrint(("Create symbolic failed\n"));
509 *Status = NDIS_STATUS_FAILURE;
510 break;
511 }
512
513 ExFreePool(unicodeDeviceName.Buffer);
514 unicodeDeviceName.Buffer = NULL;
515
516 NdisAllocatePacketPool(
517 &status,
518 &open->PacketPool,
519 TRANSMIT_PACKETS,
520 sizeof(PACKET_RESERVED));
521
522 if (status != NDIS_STATUS_SUCCESS) {
523 // DebugPrint(("B2ether: Failed to allocate packet pool\n"));
524 break;
525 }
526
527 NdisInitializeEvent(&open->Event);
528 InitializeListHead(&open->ResetIrpList);
529 KeInitializeSpinLock(&open->ResetQueueLock);
530 KeInitializeSpinLock(&open->RcvQSpinLock);
531 InitializeListHead(&open->RcvList);
532
533 NdisOpenAdapter(Status,
534 &status,
535 &open->AdapterHandle,
536 &mediumIndex,
537 &mediumArray,
538 sizeof(mediumArray)/sizeof(NDIS_MEDIUM),
539 Globals.NdisProtocolHandle,
540 open,
541 DeviceName,
542 0,
543 NULL);
544
545 if(*Status == NDIS_STATUS_PENDING) {
546 NdisWaitEvent(&open->Event, 0);
547 *Status = open->Status;
548 }
549 if(*Status != NDIS_STATUS_SUCCESS) {
550 // DebugPrint(("Failed to openAdapter\n"));
551 break;
552 }
553
554 open->IrpCount = 0;
555 InterlockedExchange( (PLONG)&open->Bound, TRUE );
556 NdisInitializeEvent(&open->CleanupEvent);
557
558 NdisSetEvent(&open->CleanupEvent);
559
560 NdisQueryAdapterInstanceName( &open->AdapterName, open->AdapterHandle );
561 // DebugPrint(("Bound AdapterName %ws\n", open->AdapterName.Buffer));
562
563 open->Medium = mediumArray;
564
565 InitializeListHead(&open->AdapterListEntry);
566
567 ExInterlockedInsertTailList(&Globals.AdapterList,
568 &open->AdapterListEntry,
569 &Globals.GlobalLock);
570
571 // Clear the DO_DEVICE_INITIALIZING flag. This is required
572 // if you create deviceobjects outside of DriverEntry.
573 // Untill you do this, application cannot send I/O request.
574
575 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
576 } while (FALSE);
577
578 if (*Status != NDIS_STATUS_SUCCESS) {
579 if (open && open->PacketPool) NdisFreePacketPool(open->PacketPool);
580 if (deviceObject) IoDeleteDevice(deviceObject);
581 if(unicodeDeviceName.Buffer) ExFreePool(unicodeDeviceName.Buffer);
582 if(symbolicLink) {
583 IoDeleteSymbolicLink(&open->SymbolicLink);
584 ExFreePool(open->SymbolicLink.Buffer);
585 }
586 }
587 // DebugPrint(("Return BindAdapter :0x%x\n", *Status));
588 }
589
590
591 VOID
592 PacketUnbindAdapter(
593 OUT PNDIS_STATUS Status,
594 IN NDIS_HANDLE ProtocolBindingContext,
595 IN NDIS_HANDLE UnbindContext
596 )
597 {
598 POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext;
599 KIRQL oldIrql;
600
601 // DebugPrint(("PacketUnbindAdapter :%ws\n", open->AdapterName.Buffer));
602
603 if(open->AdapterHandle) {
604 NdisResetEvent(&open->Event);
605 InterlockedExchange( (PLONG) &open->Bound, FALSE );
606 PacketCancelReadIrps(open->DeviceObject);
607
608 // DebugPrint(("Waiting on CleanupEvent\n"));
609 NdisWaitEvent(&open->CleanupEvent, 0);
610
611 NdisCloseAdapter(Status, open->AdapterHandle);
612
613 // Wait for it to complete
614 if(*Status == NDIS_STATUS_PENDING) {
615 NdisWaitEvent(&open->Event, 0);
616 *Status = open->Status;
617 } else {
618 *Status = NDIS_STATUS_FAILURE;
619 // ASSERT(0);
620 }
621
622 KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql);
623 RemoveEntryList(&open->AdapterListEntry);
624 KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
625
626 NdisFreePacketPool(open->PacketPool);
627
628 NdisFreeMemory(open->AdapterName.Buffer, open->AdapterName.Length, 0);
629
630 IoDeleteSymbolicLink(&open->SymbolicLink);
631 ExFreePool(open->SymbolicLink.Buffer);
632
633 IoDeleteDevice(open->DeviceObject);
634 }
635
636 // DebugPrint(("Exit PacketUnbindAdapter\n"));
637 }
638
639 VOID
640 PacketOpenAdapterComplete(
641 IN NDIS_HANDLE ProtocolBindingContext,
642 IN NDIS_STATUS Status,
643 IN NDIS_STATUS OpenErrorStatus
644 )
645 {
646 POPEN_INSTANCE open = ProtocolBindingContext;
647
648 // DebugPrint(("B2ether: OpenAdapterComplete\n"));
649
650 open->Status = Status;
651 NdisSetEvent(&open->Event);
652 }
653
654 VOID
655 PacketCloseAdapterComplete(
656 IN NDIS_HANDLE ProtocolBindingContext,
657 IN NDIS_STATUS Status
658 )
659 {
660 POPEN_INSTANCE open = ProtocolBindingContext;
661
662 // DebugPrint(("CloseAdapterComplete\n"));
663
664 open->Status = Status;
665 NdisSetEvent(&open->Event);
666 }
667
668
669 NDIS_STATUS
670 PacketPNPHandler(
671 IN NDIS_HANDLE ProtocolBindingContext,
672 IN PNET_PNP_EVENT NetPnPEvent
673 )
674 {
675 POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext;
676 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
677 PNET_DEVICE_POWER_STATE powerState;
678
679 // DebugPrint(("PacketPNPHandler\n"));
680
681 powerState = (PNET_DEVICE_POWER_STATE)NetPnPEvent->Buffer;
682
683 // This will happen when all entities in the system need to be notified
684 //
685 //if(open == NULL)
686 //{
687 // return Status;
688 //}
689
690 switch(NetPnPEvent->NetEvent) {
691 case NetEventSetPower :
692 // DebugPrint(("NetEventSetPower\n"));
693 switch (*powerState) {
694 case NetDeviceStateD0:
695 Status = NDIS_STATUS_SUCCESS;
696 break;
697 default:
698 // We can't suspend, so we ask NDIS to Unbind us by
699 // returning this status:
700 Status = NDIS_STATUS_NOT_SUPPORTED;
701 break;
702 }
703 break;
704 case NetEventQueryPower :
705 // DebugPrint(("NetEventQueryPower\n"));
706 break;
707 case NetEventQueryRemoveDevice :
708 // DebugPrint(("NetEventQueryRemoveDevice \n"));
709 break;
710 case NetEventCancelRemoveDevice :
711 // DebugPrint(("NetEventCancelRemoveDevice \n"));
712 break;
713 case NetEventReconfigure :
714 // The protocol should always succeed this event by returning NDIS_STATUS_SUCCESS
715 // DebugPrint(("NetEventReconfigure\n"));
716 break;
717 case NetEventBindsComplete :
718 // DebugPrint(("NetEventBindsComplete \n"));
719 break;
720 case NetEventPnPCapabilities :
721 // DebugPrint(("NetEventPnPCapabilities \n"));
722 case NetEventBindList:
723 // DebugPrint(("NetEventBindList \n"));
724 default:
725 Status = NDIS_STATUS_NOT_SUPPORTED;
726 break;
727 }
728 return Status;
729 }
730
731
732 VOID IoIncrement( IN OUT POPEN_INSTANCE Open )
733 {
734 LONG result = InterlockedIncrement(&Open->IrpCount);
735
736 //DebugPrint(("IoIncrement %d\n", result));
737
738 // Need to clear event (when IrpCount bumps from 0 to 1)
739 if (result == 1) {
740 NdisResetEvent(&Open->CleanupEvent);
741 }
742 }
743
744
745 VOID IoDecrement ( IN OUT POPEN_INSTANCE Open )
746 {
747 LONG result = InterlockedDecrement(&Open->IrpCount);
748
749 //DebugPrint(("IoDecrement %d\n", result));
750
751 if (result == 0) {
752 // Set the event when the count transition from 1 to 0.
753 NdisSetEvent (&Open->CleanupEvent);
754 }
755 }