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
Log Message:
Import nt5 version of the ethernet driver from 2001 sources.

File Contents

# User Rev Content
1 asvitkine 1.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     }