1 /*
2  * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3  * Copyright (c) 2005 CACE Technologies, Davis (California)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16  * nor the names of its contributors may be used to endorse or promote
17  * products derived from this software without specific prior written
18  * permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #include <GlobalConst.h>
35 
36 #include "ntddk.h"
37 #include "ntiologc.h"
38 #include "ndis.h"
39 
40 #include "debug.h"
41 #include "packet.h"
42 
43 static NDIS_MEDIUM MediumArray[] = {
44 	NdisMedium802_3,
45 //	NdisMediumWan,
46 	NdisMediumFddi,
47 	NdisMediumArcnet878_2,
48 	NdisMediumAtm,
49 	NdisMedium802_5
50 };
51 
52 #define NUM_NDIS_MEDIA  (sizeof MediumArray / sizeof MediumArray[0])
53 
54 ULONG NamedEventsCounter=0;
55 
56 //Itoa. Replaces the buggy RtlIntegerToUnicodeString
PacketItoa(UINT n,PUCHAR buf)57 void PacketItoa(UINT n,PUCHAR buf){
58 int i;
59 
60 	for(i=0;i<20;i+=2){
61 		buf[18-i]=(n%10)+48;
62 		buf[19-i]=0;
63 		n/=10;
64 	}
65 
66 }
67 
68 /// Global start time. Used as an absolute reference for timestamp conversion.
69 struct time_conv G_Start_Time = {
70 	0,
71 	{0, 0},
72 };
73 
74 UINT n_Opened_Instances = 0;
75 
76 NDIS_SPIN_LOCK Opened_Instances_Lock;
77 
78 //-------------------------------------------------------------------
79 
NPF_Open(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)80 NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
81 {
82 
83     PDEVICE_EXTENSION DeviceExtension;
84 
85     POPEN_INSTANCE    Open;
86 
87     PIO_STACK_LOCATION  IrpSp;
88 
89     NDIS_STATUS     Status;
90     NDIS_STATUS     ErrorStatus;
91     UINT            i;
92 	PCHAR			EvName;
93 
94     IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
95 
96 	DeviceExtension = DeviceObject->DeviceExtension;
97 
98     IrpSp = IoGetCurrentIrpStackLocation(Irp);
99 
100     //  allocate some memory for the open structure
101     Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
102 
103     if (Open==NULL) {
104         // no memory
105         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
106         IoCompleteRequest(Irp, IO_NO_INCREMENT);
107         return STATUS_INSUFFICIENT_RESOURCES;
108     }
109 
110     RtlZeroMemory(
111         Open,
112         sizeof(OPEN_INSTANCE)
113         );
114 
115 
116 	EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\SEE0000000000"), '1OWA');
117 
118     if (EvName==NULL) {
119         // no memory
120         ExFreePool(Open);
121 	    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
122         IoCompleteRequest(Irp, IO_NO_INCREMENT);
123         return STATUS_INSUFFICIENT_RESOURCES;
124     }
125 
126     //  Save or open here
127     IrpSp->FileObject->FsContext=Open;
128 
129     Open->DeviceExtension=DeviceExtension;
130 
131 
132     //  Save the Irp here for the completion routine to retrieve
133     Open->OpenCloseIrp=Irp;
134 
135     //  Allocate a packet pool for our xmit and receive packets
136     NdisAllocatePacketPool(
137         &Status,
138         &Open->PacketPool,
139         TRANSMIT_PACKETS,
140         sizeof(PACKET_RESERVED));
141 
142 
143     if (Status != NDIS_STATUS_SUCCESS) {
144 
145         IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
146 
147 		ExFreePool(Open);
148 		ExFreePool(EvName);
149         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
150         IoCompleteRequest(Irp, IO_NO_INCREMENT);
151         return STATUS_INSUFFICIENT_RESOURCES;
152     }
153 
154 
155 	RtlCopyBytes(EvName,L"\\BaseNamedObjects\\SEE0000000000",sizeof(L"\\BaseNamedObjects\\SEE0000000000"));
156 
157 	//Create the string containing the name of the read event
158 	RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
159 
160 	PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
161 
162 	InterlockedIncrement(&NamedEventsCounter);
163 
164 	IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
165 
166 	//allocate the event objects
167 	Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
168 	if(Open->ReadEvent==NULL){
169 		ExFreePool(Open);
170 		ExFreePool(EvName);
171         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
172         IoCompleteRequest(Irp, IO_NO_INCREMENT);
173         return STATUS_INSUFFICIENT_RESOURCES;
174 	}
175 
176 	KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
177 	KeClearEvent(Open->ReadEvent);
178 	NdisInitializeEvent(&Open->WriteEvent);
179 	NdisInitializeEvent(&Open->IOEvent);
180  	NdisInitializeEvent(&Open->DumpEvent);
181 	NdisAllocateSpinLock(&Open->MachineLock);
182 	NdisAllocateSpinLock(&Open->WriteLock);
183 	Open->WriteInProgress = FALSE;
184 
185     //  list to hold irp's want to reset the adapter
186     InitializeListHead(&Open->ResetIrpList);
187 
188 
189     //  Initialize the request list
190     KeInitializeSpinLock(&Open->RequestSpinLock);
191     InitializeListHead(&Open->RequestList);
192 
193 	// Initializes the extended memory of the NPF machine
194 	Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
195 	if((Open->mem_ex.buffer) == NULL)
196 	{
197         // no memory
198         ExFreePool(Open);
199 		ExFreePool(EvName);
200 	    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
201         IoCompleteRequest(Irp, IO_NO_INCREMENT);
202         return STATUS_INSUFFICIENT_RESOURCES;
203     }
204 
205 	Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
206 	RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
207 
208 	//
209 	// Initialize the open instance
210 	//
211 //	Open->BufSize = 0;
212 //	Open->Buffer = NULL;
213 //	Open->Bhead = 0;
214 //	Open->Btail = 0;
215 //	(INT)Open->BLastByte = -1;
216 //	Open->Dropped = 0;		//reset the dropped packets counter
217 //	Open->Received = 0;		//reset the received packets counter
218 //	Open->Accepted = 0;		//reset the accepted packets counter
219 	Open->bpfprogram = NULL;	//reset the filter
220 	Open->mode = MODE_CAPT;
221 	Open->Nbytes.QuadPart = 0;
222 	Open->Npackets.QuadPart = 0;
223 	Open->Nwrites = 1;
224 	Open->Multiple_Write_Counter = 0;
225 	Open->MinToCopy = 0;
226 	Open->TimeOut.QuadPart = (LONGLONG)1;
227 	Open->Bound = TRUE;
228 	Open->DumpFileName.Buffer = NULL;
229 	Open->DumpFileHandle = NULL;
230 	Open->tme.active = TME_NONE_ACTIVE;
231 	Open->DumpLimitReached = FALSE;
232 	Open->MaxFrameSize = 0;
233 	Open->WriterSN=0;
234 	Open->ReaderSN=0;
235 	Open->Size=0;
236 
237 
238 
239 	//allocate the spinlock for the statistic counters
240     NdisAllocateSpinLock(&Open->CountersLock);
241 
242 	//allocate the spinlock for the buffer pointers
243 	//    NdisAllocateSpinLock(&Open->BufLock);
244 
245     //
246     //  link up the request stored in our open block
247     //
248     for (i=0;i<MAX_REQUESTS;i++) {
249         ExInterlockedInsertTailList(
250             &Open->RequestList,
251             &Open->Requests[i].ListElement,
252             &Open->RequestSpinLock);
253 
254     }
255 
256 
257     IoMarkIrpPending(Irp);
258 
259     //
260     //  Try to open the MAC
261     //
262     IF_LOUD(DbgPrint("NPF: Opening the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
263 
264 	NdisOpenAdapter(
265         &Status,
266         &ErrorStatus,
267         &Open->AdapterHandle,
268         &Open->Medium,
269         MediumArray,
270         NUM_NDIS_MEDIA,
271         DeviceExtension->NdisProtocolHandle,
272         Open,
273         &DeviceExtension->AdapterName,
274         0,
275         NULL);
276 
277     IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
278 
279 	if (Status != NDIS_STATUS_PENDING)
280     {
281 		NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
282     }
283 
284     return(STATUS_PENDING);
285 }
286 
287 //-------------------------------------------------------------------
288 
NPF_OpenAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status,IN NDIS_STATUS OpenErrorStatus)289 VOID NPF_OpenAdapterComplete(
290 	IN NDIS_HANDLE  ProtocolBindingContext,
291     IN NDIS_STATUS  Status,
292     IN NDIS_STATUS  OpenErrorStatus)
293 {
294 
295     PIRP				Irp;
296     POPEN_INSTANCE		Open;
297     PLIST_ENTRY			RequestListEntry;
298 	PINTERNAL_REQUEST	MaxSizeReq;
299 	NDIS_STATUS			ReqStatus;
300 
301 
302     IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
303 
304     Open= (POPEN_INSTANCE)ProtocolBindingContext;
305 
306     //
307     //  get the open irp
308     //
309     Irp=Open->OpenCloseIrp;
310 
311     if (Status != NDIS_STATUS_SUCCESS) {
312 
313         IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
314 
315         NdisFreePacketPool(Open->PacketPool);
316 
317 		//free mem_ex
318 		Open->mem_ex.size = 0;
319 		if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
320 
321 		ExFreePool(Open->ReadEventName.Buffer);
322 
323 		ZwClose(Open->ReadEventHandle);
324 
325 
326         ExFreePool(Open);
327     }
328 	else {
329 		NdisAcquireSpinLock(&Opened_Instances_Lock);
330 		n_Opened_Instances++;
331 		NdisReleaseSpinLock(&Opened_Instances_Lock);
332 
333 		IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
334 
335 		// Get the absolute value of the system boot time.
336 		// This is used for timestamp conversion.
337 		TIME_SYNCHRONIZE(&G_Start_Time);
338 
339 		// Extract a request from the list of free ones
340 		RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
341 
342 		if (RequestListEntry == NULL)
343 		{
344 
345 		    Open->MaxFrameSize = 1600;	// Assume Ethernet
346 
347 			Irp->IoStatus.Status = Status;
348 		    Irp->IoStatus.Information = 0;
349 		    IoCompleteRequest(Irp, IO_NO_INCREMENT);
350 
351 		    return;
352 		}
353 
354 		MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
355 		MaxSizeReq->Irp = Irp;
356 		MaxSizeReq->Internal = TRUE;
357 
358 
359 		MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
360 		MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
361 
362 
363 		MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
364 		MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
365 
366 		//  submit the request
367 		NdisRequest(
368 			&ReqStatus,
369 			Open->AdapterHandle,
370 			&MaxSizeReq->Request);
371 
372 
373 		if (ReqStatus != NDIS_STATUS_PENDING) {
374 			NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
375 		}
376 
377 		return;
378 
379 	}
380 
381 	Irp->IoStatus.Status = Status;
382 	Irp->IoStatus.Information = 0;
383 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
384 
385     return;
386 
387 }
388 
389 //-------------------------------------------------------------------
390 
391 NTSTATUS
NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)392 NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
393 {
394 
395     POPEN_INSTANCE    Open;
396     NDIS_STATUS     Status;
397     PIO_STACK_LOCATION  IrpSp;
398 	LARGE_INTEGER ThreadDelay;
399 
400     IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
401 
402 	IrpSp = IoGetCurrentIrpStackLocation(Irp);
403 
404     Open=IrpSp->FileObject->FsContext;
405 
406  	// Reset the buffer size. This tells the dump thread to stop.
407 // 	Open->BufSize = 0;
408 
409 	if( Open->Bound == FALSE){
410 
411 		NdisWaitEvent(&Open->IOEvent,10000);
412 
413 		// Free the filter if it's present
414 		if(Open->bpfprogram != NULL)
415 			ExFreePool(Open->bpfprogram);
416 
417 //
418 // Jitted filters are supported on x86 (32bit) only
419 //
420 #ifdef __NPF_x86__
421 		// Free the jitted filter if it's present
422 		if(Open->Filter != NULL)
423 			BPF_Destroy_JIT_Filter(Open->Filter);
424 #endif
425 
426 		//free the buffer
427 //		Open->BufSize=0;
428 //		if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
429 
430 		if (Open->Size > 0)
431 			ExFreePool(Open->CpuData[0].Buffer);
432 
433 		//free mem_ex
434 		Open->mem_ex.size = 0;
435 		if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
436 
437 		NdisFreePacketPool(Open->PacketPool);
438 
439 		// Free the string with the name of the dump file
440 		if(Open->DumpFileName.Buffer!=NULL)
441 			ExFreePool(Open->DumpFileName.Buffer);
442 
443 		ExFreePool(Open->ReadEventName.Buffer);
444 		ExFreePool(Open);
445 
446 		Irp->IoStatus.Information = 0;
447 		Irp->IoStatus.Status = STATUS_SUCCESS;
448 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
449 
450 		return(STATUS_SUCCESS);
451 	}
452 
453  	// Unfreeze the consumer
454  	if(Open->mode & MODE_DUMP)
455  		NdisSetEvent(&Open->DumpEvent);
456  	else
457  		KeSetEvent(Open->ReadEvent,0,FALSE);
458 
459     // Save the IRP
460     Open->OpenCloseIrp = Irp;
461 
462     IoMarkIrpPending(Irp);
463 
464 	// If this instance is in dump mode, complete the dump and close the file
465 	if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
466 
467 		NTSTATUS wres;
468 
469 		ThreadDelay.QuadPart = -50000000;
470 		// Wait the completion of the thread
471 		wres = KeWaitForSingleObject(Open->DumpThreadObject,
472 				UserRequest,
473 				KernelMode,
474 				TRUE,
475 				&ThreadDelay);
476 
477 		ObDereferenceObject(Open->DumpThreadObject);
478 
479 
480 		// Flush and close the dump file
481 		NPF_CloseDumpFile(Open);
482 	}
483 
484 	// Destroy the read Event
485 	ZwClose(Open->ReadEventHandle);
486 
487 	// Close the adapter
488 	NdisCloseAdapter(
489 		&Status,
490 		Open->AdapterHandle
491 		);
492 
493 	if (Status != NDIS_STATUS_PENDING) {
494 
495 		NPF_CloseAdapterComplete(
496 			Open,
497 			Status
498 			);
499 		return STATUS_SUCCESS;
500 
501 	}
502 
503 	return(STATUS_PENDING);
504 }
505 
506 //-------------------------------------------------------------------
507 
508 VOID
NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)509 NPF_CloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
510 {
511     POPEN_INSTANCE    Open;
512     PIRP              Irp;
513 
514     IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
515 
516     Open= (POPEN_INSTANCE)ProtocolBindingContext;
517 
518 	// free the allocated structures only if the instance is still bound to the adapter
519 	if(Open->Bound == TRUE){
520 
521 		// Free the filter if it's present
522 		if(Open->bpfprogram != NULL)
523 			ExFreePool(Open->bpfprogram);
524 
525 //
526 // Jitted filters are supported on x86 (32bit) only
527 //
528 #ifdef __NPF_x86__
529 		// Free the jitted filter if it's present
530 		if(Open->Filter != NULL)
531 			BPF_Destroy_JIT_Filter(Open->Filter);
532 #endif // __NPF_x86__
533 
534 		//free the buffer
535 //		Open->BufSize = 0;
536 //		if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
537 
538 		if (Open->Size > 0)
539 			ExFreePool(Open->CpuData[0].Buffer);
540 
541 		//free mem_ex
542 		Open->mem_ex.size = 0;
543 		if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
544 
545 		NdisFreePacketPool(Open->PacketPool);
546 
547 		Irp=Open->OpenCloseIrp;
548 
549 		// Free the string with the name of the dump file
550 		if(Open->DumpFileName.Buffer!=NULL)
551 			ExFreePool(Open->DumpFileName.Buffer);
552 
553 		ExFreePool(Open->ReadEventName.Buffer);
554 		ExFreePool(Open);
555 
556 		// Complete the request only if the instance is still bound to the adapter
557 		Irp->IoStatus.Status = STATUS_SUCCESS;
558 		Irp->IoStatus.Information = 0;
559 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
560 	}
561 	else
562 		NdisSetEvent(&Open->IOEvent);
563 
564 	// Decrease the counter of open instances
565 	NdisAcquireSpinLock(&Opened_Instances_Lock);
566 	n_Opened_Instances--;
567 	NdisReleaseSpinLock(&Opened_Instances_Lock);
568 
569 	IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
570 
571 	if(n_Opened_Instances == 0){
572 		// Force a synchronization at the next NPF_Open().
573 		// This hopefully avoids the synchronization issues caused by hibernation or standby.
574 		TIME_DESYNCHRONIZE(&G_Start_Time);
575 	}
576 
577 	return;
578 
579 }
580 //-------------------------------------------------------------------
581 
582 #ifdef NDIS50
583 NDIS_STATUS
NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext,IN PNET_PNP_EVENT pNetPnPEvent)584 NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
585 {
586     IF_LOUD(DbgPrint("NPF: PowerChange\n");)
587 
588 	TIME_DESYNCHRONIZE(&G_Start_Time);
589 
590 	TIME_SYNCHRONIZE(&G_Start_Time);
591 
592 	return STATUS_SUCCESS;
593 }
594 #endif
595 
596 //-------------------------------------------------------------------
597 
598 VOID
NPF_BindAdapter(OUT PNDIS_STATUS Status,IN NDIS_HANDLE BindContext,IN PNDIS_STRING DeviceName,IN PVOID SystemSpecific1,IN PVOID SystemSpecific2)599 NPF_BindAdapter(
600     OUT PNDIS_STATUS            Status,
601     IN  NDIS_HANDLE             BindContext,
602     IN  PNDIS_STRING            DeviceName,
603     IN  PVOID                   SystemSpecific1,
604     IN  PVOID                   SystemSpecific2
605     )
606 {
607 	IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
608 }
609 
610 //-------------------------------------------------------------------
611 
612 VOID
NPF_UnbindAdapter(OUT PNDIS_STATUS Status,IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE UnbindContext)613 NPF_UnbindAdapter(
614     OUT PNDIS_STATUS        Status,
615     IN  NDIS_HANDLE         ProtocolBindingContext,
616     IN  NDIS_HANDLE         UnbindContext
617     )
618 {
619     POPEN_INSTANCE   Open =(POPEN_INSTANCE)ProtocolBindingContext;
620 	NDIS_STATUS		 lStatus;
621 
622 	IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
623 
624 	// Reset the buffer size. This tells the dump thread to stop.
625 // 	Open->BufSize=0;
626 
627 	NdisResetEvent(&Open->IOEvent);
628 
629 	// This open instance is no more bound to the adapter, set Bound to False
630     InterlockedExchange( (PLONG) &Open->Bound, FALSE );
631 
632 	// Awake a possible pending read on this instance
633  	if(Open->mode & MODE_DUMP)
634  		NdisSetEvent(&Open->DumpEvent);
635  	else
636  		KeSetEvent(Open->ReadEvent,0,FALSE);
637 
638 	// If this instance is in dump mode, complete the dump and close the file
639  	if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
640  		NPF_CloseDumpFile(Open);
641 
642 	// Destroy the read Event
643 	ZwClose(Open->ReadEventHandle);
644 
645     //  close the adapter
646     NdisCloseAdapter(
647         &lStatus,
648         Open->AdapterHandle
649 	    );
650 
651     if (lStatus != NDIS_STATUS_PENDING) {
652 
653         NPF_CloseAdapterComplete(
654             Open,
655             lStatus
656             );
657 
658 		*Status = NDIS_STATUS_SUCCESS;
659         return;
660 
661     }
662 
663 	*Status = NDIS_STATUS_SUCCESS;
664     return;
665 }
666 
667 //-------------------------------------------------------------------
668 
669 VOID
NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)670 NPF_ResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
671 
672 {
673     POPEN_INSTANCE      Open;
674     PIRP                Irp;
675 
676     PLIST_ENTRY         ResetListEntry;
677 
678     IF_LOUD(DbgPrint("NPF: PacketResetComplete\n");)
679 
680     Open= (POPEN_INSTANCE)ProtocolBindingContext;
681 
682 
683     //
684     //  remove the reset IRP from the list
685     //
686     ResetListEntry=ExInterlockedRemoveHeadList(
687                        &Open->ResetIrpList,
688                        &Open->RequestSpinLock
689                        );
690 
691 #if DBG
692     if (ResetListEntry == NULL) {
693         DbgBreakPoint();
694         return;
695     }
696 #endif
697 
698     Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
699 
700     Irp->IoStatus.Status = STATUS_SUCCESS;
701     IoCompleteRequest(Irp, IO_NO_INCREMENT);
702 
703     IF_LOUD(DbgPrint("NPF: PacketResetComplete exit\n");)
704 
705     return;
706 
707 }
708