mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-14 05:30:41 +03:00
ac865f04fc
* spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
708 lines
18 KiB
C
708 lines
18 KiB
C
/*
|
|
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
|
|
* Copyright (c) 2005 CACE Technologies, Davis (California)
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
|
|
* nor the names of its contributors may be used to endorse or promote
|
|
* products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include <GlobalConst.h>
|
|
|
|
#include "ntddk.h"
|
|
#include "ntiologc.h"
|
|
#include "ndis.h"
|
|
|
|
#include "debug.h"
|
|
#include "packet.h"
|
|
|
|
static NDIS_MEDIUM MediumArray[] = {
|
|
NdisMedium802_3,
|
|
// NdisMediumWan,
|
|
NdisMediumFddi,
|
|
NdisMediumArcnet878_2,
|
|
NdisMediumAtm,
|
|
NdisMedium802_5
|
|
};
|
|
|
|
#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
|
|
|
|
ULONG NamedEventsCounter=0;
|
|
|
|
//Itoa. Replaces the buggy RtlIntegerToUnicodeString
|
|
void PacketItoa(UINT n,PUCHAR buf){
|
|
int i;
|
|
|
|
for(i=0;i<20;i+=2){
|
|
buf[18-i]=(n%10)+48;
|
|
buf[19-i]=0;
|
|
n/=10;
|
|
}
|
|
|
|
}
|
|
|
|
/// Global start time. Used as an absolute reference for timestamp conversion.
|
|
struct time_conv G_Start_Time = {
|
|
0,
|
|
{0, 0},
|
|
};
|
|
|
|
UINT n_Opened_Instances = 0;
|
|
|
|
NDIS_SPIN_LOCK Opened_Instances_Lock;
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|
{
|
|
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
|
|
POPEN_INSTANCE Open;
|
|
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
NDIS_STATUS Status;
|
|
NDIS_STATUS ErrorStatus;
|
|
UINT i;
|
|
PCHAR EvName;
|
|
|
|
IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
// allocate some memory for the open structure
|
|
Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
|
|
|
|
if (Open==NULL) {
|
|
// no memory
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(
|
|
Open,
|
|
sizeof(OPEN_INSTANCE)
|
|
);
|
|
|
|
|
|
EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\SEE0000000000"), '1OWA');
|
|
|
|
if (EvName==NULL) {
|
|
// no memory
|
|
ExFreePool(Open);
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// Save or open here
|
|
IrpSp->FileObject->FsContext=Open;
|
|
|
|
Open->DeviceExtension=DeviceExtension;
|
|
|
|
|
|
// Save the Irp here for the completion routine to retrieve
|
|
Open->OpenCloseIrp=Irp;
|
|
|
|
// Allocate a packet pool for our xmit and receive packets
|
|
NdisAllocatePacketPool(
|
|
&Status,
|
|
&Open->PacketPool,
|
|
TRANSMIT_PACKETS,
|
|
sizeof(PACKET_RESERVED));
|
|
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
|
|
|
|
ExFreePool(Open);
|
|
ExFreePool(EvName);
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
RtlCopyBytes(EvName,L"\\BaseNamedObjects\\SEE0000000000",sizeof(L"\\BaseNamedObjects\\SEE0000000000"));
|
|
|
|
//Create the string containing the name of the read event
|
|
RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
|
|
|
|
PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
|
|
|
|
InterlockedIncrement(&NamedEventsCounter);
|
|
|
|
IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
|
|
|
|
//allocate the event objects
|
|
Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
|
|
if(Open->ReadEvent==NULL){
|
|
ExFreePool(Open);
|
|
ExFreePool(EvName);
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
|
|
KeClearEvent(Open->ReadEvent);
|
|
NdisInitializeEvent(&Open->WriteEvent);
|
|
NdisInitializeEvent(&Open->IOEvent);
|
|
NdisInitializeEvent(&Open->DumpEvent);
|
|
NdisAllocateSpinLock(&Open->MachineLock);
|
|
NdisAllocateSpinLock(&Open->WriteLock);
|
|
Open->WriteInProgress = FALSE;
|
|
|
|
// list to hold irp's want to reset the adapter
|
|
InitializeListHead(&Open->ResetIrpList);
|
|
|
|
|
|
// Initialize the request list
|
|
KeInitializeSpinLock(&Open->RequestSpinLock);
|
|
InitializeListHead(&Open->RequestList);
|
|
|
|
// Initializes the extended memory of the NPF machine
|
|
Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
|
|
if((Open->mem_ex.buffer) == NULL)
|
|
{
|
|
// no memory
|
|
ExFreePool(Open);
|
|
ExFreePool(EvName);
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
|
|
RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
|
|
|
|
//
|
|
// Initialize the open instance
|
|
//
|
|
// Open->BufSize = 0;
|
|
// Open->Buffer = NULL;
|
|
// Open->Bhead = 0;
|
|
// Open->Btail = 0;
|
|
// (INT)Open->BLastByte = -1;
|
|
// Open->Dropped = 0; //reset the dropped packets counter
|
|
// Open->Received = 0; //reset the received packets counter
|
|
// Open->Accepted = 0; //reset the accepted packets counter
|
|
Open->bpfprogram = NULL; //reset the filter
|
|
Open->mode = MODE_CAPT;
|
|
Open->Nbytes.QuadPart = 0;
|
|
Open->Npackets.QuadPart = 0;
|
|
Open->Nwrites = 1;
|
|
Open->Multiple_Write_Counter = 0;
|
|
Open->MinToCopy = 0;
|
|
Open->TimeOut.QuadPart = (LONGLONG)1;
|
|
Open->Bound = TRUE;
|
|
Open->DumpFileName.Buffer = NULL;
|
|
Open->DumpFileHandle = NULL;
|
|
Open->tme.active = TME_NONE_ACTIVE;
|
|
Open->DumpLimitReached = FALSE;
|
|
Open->MaxFrameSize = 0;
|
|
Open->WriterSN=0;
|
|
Open->ReaderSN=0;
|
|
Open->Size=0;
|
|
|
|
|
|
|
|
//allocate the spinlock for the statistic counters
|
|
NdisAllocateSpinLock(&Open->CountersLock);
|
|
|
|
//allocate the spinlock for the buffer pointers
|
|
// NdisAllocateSpinLock(&Open->BufLock);
|
|
|
|
//
|
|
// link up the request stored in our open block
|
|
//
|
|
for (i=0;i<MAX_REQUESTS;i++) {
|
|
ExInterlockedInsertTailList(
|
|
&Open->RequestList,
|
|
&Open->Requests[i].ListElement,
|
|
&Open->RequestSpinLock);
|
|
|
|
}
|
|
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
//
|
|
// Try to open the MAC
|
|
//
|
|
IF_LOUD(DbgPrint("NPF: Opening the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
|
|
|
|
NdisOpenAdapter(
|
|
&Status,
|
|
&ErrorStatus,
|
|
&Open->AdapterHandle,
|
|
&Open->Medium,
|
|
MediumArray,
|
|
NUM_NDIS_MEDIA,
|
|
DeviceExtension->NdisProtocolHandle,
|
|
Open,
|
|
&DeviceExtension->AdapterName,
|
|
0,
|
|
NULL);
|
|
|
|
IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
|
|
|
|
if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
return(STATUS_PENDING);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID NPF_OpenAdapterComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_STATUS OpenErrorStatus)
|
|
{
|
|
|
|
PIRP Irp;
|
|
POPEN_INSTANCE Open;
|
|
PLIST_ENTRY RequestListEntry;
|
|
PINTERNAL_REQUEST MaxSizeReq;
|
|
NDIS_STATUS ReqStatus;
|
|
|
|
|
|
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
|
|
|
|
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
|
|
|
//
|
|
// get the open irp
|
|
//
|
|
Irp=Open->OpenCloseIrp;
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
|
|
|
|
NdisFreePacketPool(Open->PacketPool);
|
|
|
|
//free mem_ex
|
|
Open->mem_ex.size = 0;
|
|
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
|
|
|
ExFreePool(Open->ReadEventName.Buffer);
|
|
|
|
ZwClose(Open->ReadEventHandle);
|
|
|
|
|
|
ExFreePool(Open);
|
|
}
|
|
else {
|
|
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
|
n_Opened_Instances++;
|
|
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
|
|
|
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
|
|
|
// Get the absolute value of the system boot time.
|
|
// This is used for timestamp conversion.
|
|
TIME_SYNCHRONIZE(&G_Start_Time);
|
|
|
|
// Extract a request from the list of free ones
|
|
RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
|
|
|
|
if (RequestListEntry == NULL)
|
|
{
|
|
|
|
Open->MaxFrameSize = 1600; // Assume Ethernet
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return;
|
|
}
|
|
|
|
MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
|
|
MaxSizeReq->Irp = Irp;
|
|
MaxSizeReq->Internal = TRUE;
|
|
|
|
|
|
MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
|
|
MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
|
|
|
|
|
|
MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
|
|
MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
// submit the request
|
|
NdisRequest(
|
|
&ReqStatus,
|
|
Open->AdapterHandle,
|
|
&MaxSizeReq->Request);
|
|
|
|
|
|
if (ReqStatus != NDIS_STATUS_PENDING) {
|
|
NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|
{
|
|
|
|
POPEN_INSTANCE Open;
|
|
NDIS_STATUS Status;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
LARGE_INTEGER ThreadDelay;
|
|
|
|
IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Open=IrpSp->FileObject->FsContext;
|
|
|
|
// Reset the buffer size. This tells the dump thread to stop.
|
|
// Open->BufSize = 0;
|
|
|
|
if( Open->Bound == FALSE){
|
|
|
|
NdisWaitEvent(&Open->IOEvent,10000);
|
|
|
|
// Free the filter if it's present
|
|
if(Open->bpfprogram != NULL)
|
|
ExFreePool(Open->bpfprogram);
|
|
|
|
//
|
|
// Jitted filters are supported on x86 (32bit) only
|
|
//
|
|
#ifdef __NPF_x86__
|
|
// Free the jitted filter if it's present
|
|
if(Open->Filter != NULL)
|
|
BPF_Destroy_JIT_Filter(Open->Filter);
|
|
#endif
|
|
|
|
//free the buffer
|
|
// Open->BufSize=0;
|
|
// if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
|
|
|
|
if (Open->Size > 0)
|
|
ExFreePool(Open->CpuData[0].Buffer);
|
|
|
|
//free mem_ex
|
|
Open->mem_ex.size = 0;
|
|
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
|
|
|
NdisFreePacketPool(Open->PacketPool);
|
|
|
|
// Free the string with the name of the dump file
|
|
if(Open->DumpFileName.Buffer!=NULL)
|
|
ExFreePool(Open->DumpFileName.Buffer);
|
|
|
|
ExFreePool(Open->ReadEventName.Buffer);
|
|
ExFreePool(Open);
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
// Unfreeze the consumer
|
|
if(Open->mode & MODE_DUMP)
|
|
NdisSetEvent(&Open->DumpEvent);
|
|
else
|
|
KeSetEvent(Open->ReadEvent,0,FALSE);
|
|
|
|
// Save the IRP
|
|
Open->OpenCloseIrp = Irp;
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
// If this instance is in dump mode, complete the dump and close the file
|
|
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
|
|
|
|
NTSTATUS wres;
|
|
|
|
ThreadDelay.QuadPart = -50000000;
|
|
// Wait the completion of the thread
|
|
wres = KeWaitForSingleObject(Open->DumpThreadObject,
|
|
UserRequest,
|
|
KernelMode,
|
|
TRUE,
|
|
&ThreadDelay);
|
|
|
|
ObDereferenceObject(Open->DumpThreadObject);
|
|
|
|
|
|
// Flush and close the dump file
|
|
NPF_CloseDumpFile(Open);
|
|
}
|
|
|
|
// Destroy the read Event
|
|
ZwClose(Open->ReadEventHandle);
|
|
|
|
// Close the adapter
|
|
NdisCloseAdapter(
|
|
&Status,
|
|
Open->AdapterHandle
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
|
|
NPF_CloseAdapterComplete(
|
|
Open,
|
|
Status
|
|
);
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
return(STATUS_PENDING);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID
|
|
NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
|
{
|
|
POPEN_INSTANCE Open;
|
|
PIRP Irp;
|
|
|
|
IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
|
|
|
|
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
|
|
|
// free the allocated structures only if the instance is still bound to the adapter
|
|
if(Open->Bound == TRUE){
|
|
|
|
// Free the filter if it's present
|
|
if(Open->bpfprogram != NULL)
|
|
ExFreePool(Open->bpfprogram);
|
|
|
|
//
|
|
// Jitted filters are supported on x86 (32bit) only
|
|
//
|
|
#ifdef __NPF_x86__
|
|
// Free the jitted filter if it's present
|
|
if(Open->Filter != NULL)
|
|
BPF_Destroy_JIT_Filter(Open->Filter);
|
|
#endif // __NPF_x86__
|
|
|
|
//free the buffer
|
|
// Open->BufSize = 0;
|
|
// if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
|
|
|
|
if (Open->Size > 0)
|
|
ExFreePool(Open->CpuData[0].Buffer);
|
|
|
|
//free mem_ex
|
|
Open->mem_ex.size = 0;
|
|
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
|
|
|
NdisFreePacketPool(Open->PacketPool);
|
|
|
|
Irp=Open->OpenCloseIrp;
|
|
|
|
// Free the string with the name of the dump file
|
|
if(Open->DumpFileName.Buffer!=NULL)
|
|
ExFreePool(Open->DumpFileName.Buffer);
|
|
|
|
ExFreePool(Open->ReadEventName.Buffer);
|
|
ExFreePool(Open);
|
|
|
|
// Complete the request only if the instance is still bound to the adapter
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
NdisSetEvent(&Open->IOEvent);
|
|
|
|
// Decrease the counter of open instances
|
|
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
|
n_Opened_Instances--;
|
|
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
|
|
|
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
|
|
|
if(n_Opened_Instances == 0){
|
|
// Force a synchronization at the next NPF_Open().
|
|
// This hopefully avoids the synchronization issues caused by hibernation or standby.
|
|
TIME_DESYNCHRONIZE(&G_Start_Time);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
//-------------------------------------------------------------------
|
|
|
|
#ifdef NDIS50
|
|
NDIS_STATUS
|
|
NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
|
|
{
|
|
IF_LOUD(DbgPrint("NPF: PowerChange\n");)
|
|
|
|
TIME_DESYNCHRONIZE(&G_Start_Time);
|
|
|
|
TIME_SYNCHRONIZE(&G_Start_Time);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID
|
|
NPF_BindAdapter(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE BindContext,
|
|
IN PNDIS_STRING DeviceName,
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID SystemSpecific2
|
|
)
|
|
{
|
|
IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID
|
|
NPF_UnbindAdapter(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_HANDLE UnbindContext
|
|
)
|
|
{
|
|
POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
|
|
NDIS_STATUS lStatus;
|
|
|
|
IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
|
|
|
|
// Reset the buffer size. This tells the dump thread to stop.
|
|
// Open->BufSize=0;
|
|
|
|
NdisResetEvent(&Open->IOEvent);
|
|
|
|
// This open instance is no more bound to the adapter, set Bound to False
|
|
InterlockedExchange( (PLONG) &Open->Bound, FALSE );
|
|
|
|
// Awake a possible pending read on this instance
|
|
if(Open->mode & MODE_DUMP)
|
|
NdisSetEvent(&Open->DumpEvent);
|
|
else
|
|
KeSetEvent(Open->ReadEvent,0,FALSE);
|
|
|
|
// If this instance is in dump mode, complete the dump and close the file
|
|
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
|
|
NPF_CloseDumpFile(Open);
|
|
|
|
// Destroy the read Event
|
|
ZwClose(Open->ReadEventHandle);
|
|
|
|
// close the adapter
|
|
NdisCloseAdapter(
|
|
&lStatus,
|
|
Open->AdapterHandle
|
|
);
|
|
|
|
if (lStatus != NDIS_STATUS_PENDING) {
|
|
|
|
NPF_CloseAdapterComplete(
|
|
Open,
|
|
lStatus
|
|
);
|
|
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
return;
|
|
|
|
}
|
|
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
return;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID
|
|
NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
|
|
|
{
|
|
POPEN_INSTANCE Open;
|
|
PIRP Irp;
|
|
|
|
PLIST_ENTRY ResetListEntry;
|
|
|
|
IF_LOUD(DbgPrint("NPF: PacketResetComplete\n");)
|
|
|
|
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
|
|
|
|
|
//
|
|
// remove the reset IRP from the list
|
|
//
|
|
ResetListEntry=ExInterlockedRemoveHeadList(
|
|
&Open->ResetIrpList,
|
|
&Open->RequestSpinLock
|
|
);
|
|
|
|
#if DBG
|
|
if (ResetListEntry == NULL) {
|
|
DbgBreakPoint();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
IF_LOUD(DbgPrint("NPF: PacketResetComplete exit\n");)
|
|
|
|
return;
|
|
|
|
}
|