www.pudn.com > ntsniff.zip > PACKET.C


/* 
 *  NtSniff by Davide Libenzi ( To rebuild NtSniff You need Microsoft SDK & DDK ) 
 *  Copyright (C) 1999  Davide Libenzi 
 * 
 *  This program is free software; you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation; either version 2 of the License, or 
 *  (at your option) any later version. 
 * 
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details. 
 * 
 *  You should have received a copy of the GNU General Public License 
 *  along with this program; if not, write to the Free Software 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 * 
 *  Davide Libenzi  
 * 
 */ 
 
 
#include "stdarg.h" 
#include "ntddk.h" 
#include "ntiologc.h" 
#include "ndis.h" 
 
#include "ntddpack.h" 
 
#include "debug.h" 
#include "packet.h" 
 
 
NTSTATUS 
DriverEntry( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ); 
 
 
NTSTATUS 
PacketReadRegistry( 
    IN  PWSTR              *MacDriverName, 
    IN  PWSTR              *PacketDriverName, 
    IN  PUNICODE_STRING     RegistryPath 
    ); 
 
 
NTSTATUS 
PacketCreateSymbolicLink( 
    IN  PUNICODE_STRING  DeviceName, 
    IN  BOOLEAN          Create 
    ); 
 
NTSTATUS 
PacketQueryRegistryRoutine( 
    IN PWSTR     ValueName, 
    IN ULONG     ValueType, 
    IN PVOID     ValueData, 
    IN ULONG     ValueLength, 
    IN PVOID     Context, 
    IN PVOID     EntryContext 
    ); 
 
 
#if DBG 
// 
// Declare the global debug flag for this driver. 
// 
 
ULONG PacketDebugFlag = PACKET_DEBUG_LOUD; 
 
#endif 
 
PWSTR          BindStringSave = NULL; 
PWSTR          ExportStringSave = NULL; 
 
 
NTSTATUS 
DriverEntry( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ) 
 
/*++ 
 
Routine Description: 
 
    This routine initializes the Packet driver. 
 
Arguments: 
 
    DriverObject - Pointer to driver object created by system. 
 
    RegistryPath - Pointer to the Unicode name of the registry path 
        for this driver. 
 
Return Value: 
 
    The function value is the final status from the initialization operation. 
 
--*/ 
 
{ 
 
    NDIS_PROTOCOL_CHARACTERISTICS  ProtocolChar; 
 
    UNICODE_STRING MacDriverName; 
    UNICODE_STRING UnicodeDeviceName; 
 
    PDEVICE_OBJECT DeviceObject = NULL; 
    PDEVICE_EXTENSION DeviceExtension = NULL; 
 
    NTSTATUS Status = STATUS_SUCCESS; 
    NTSTATUS ErrorCode = STATUS_SUCCESS; 
    NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver"); 
 
    ULONG          DevicesCreated=0; 
 
    PWSTR          BindString; 
    PWSTR          ExportString; 
 
    NDIS_HANDLE    NdisProtocolHandle; 
 
    IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");) 
 
    RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); 
 
    ProtocolChar.MajorNdisVersion            = 3; 
    ProtocolChar.MinorNdisVersion            = 0; 
    ProtocolChar.Reserved                    = 0; 
    ProtocolChar.OpenAdapterCompleteHandler  = PacketOpenAdapterComplete; 
    ProtocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete; 
    ProtocolChar.SendCompleteHandler         = PacketSendComplete; 
    ProtocolChar.TransferDataCompleteHandler = PacketTransferDataComplete; 
    ProtocolChar.ResetCompleteHandler        = PacketResetComplete; 
    ProtocolChar.RequestCompleteHandler      = PacketRequestComplete; 
    ProtocolChar.ReceiveHandler              = PacketReceiveIndicate; 
    ProtocolChar.ReceiveCompleteHandler      = PacketReceiveComplete; 
    ProtocolChar.StatusHandler               = PacketStatus; 
    ProtocolChar.StatusCompleteHandler       = PacketStatusComplete; 
    ProtocolChar.Name                        = ProtoName; 
 
    NdisRegisterProtocol( 
        &Status, 
        &NdisProtocolHandle, 
        &ProtocolChar, 
        sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); 
 
    if (Status != NDIS_STATUS_SUCCESS) { 
        IF_LOUD(DbgPrint("Packet: Failed to register protocol with NDIS\n");) 
 
        return Status; 
 
    } 
 
    // 
    // Set up the device driver entry points. 
    // 
 
    DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen; 
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = PacketClose; 
    DriverObject->MajorFunction[IRP_MJ_READ]   = PacketRead; 
    DriverObject->MajorFunction[IRP_MJ_WRITE]  = PacketWrite; 
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]  = PacketCleanup; 
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = PacketIoControl; 
 
    DriverObject->DriverUnload = PacketUnload; 
 
 
    // 
    //  Get the name of the Packet driver and the name of the MAC driver 
    //  to bind to from the registry 
    // 
 
    Status=PacketReadRegistry( 
               &BindString, 
               &ExportString, 
               RegistryPath 
               ); 
 
    if (Status != STATUS_SUCCESS) { 
 
        IF_LOUD(DbgPrint("Packet: Failed to read registry\n");) 
 
        goto Error; 
    } 
 
    BindStringSave   = BindString; 
    ExportStringSave = ExportString; 
 
 
    // 
    //  create a device object for each entry 
    // 
    while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) { 
 
        // 
        //  Create a counted unicode string for both null terminated strings 
        // 
        RtlInitUnicodeString( 
            &MacDriverName, 
            BindString 
            ); 
 
        RtlInitUnicodeString( 
            &UnicodeDeviceName, 
            ExportString 
            ); 
 
        // 
        //  Advance to the next string of the MULTI_SZ string 
        // 
        BindString   += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); 
 
        ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); 
 
        IF_LOUD(DbgPrint("Packet: DeviceName=%ws  MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);) 
 
        // 
        //  Create the device object 
        // 
 
        Status = IoCreateDevice( 
                    DriverObject, 
                    sizeof(DEVICE_EXTENSION), 
                    &UnicodeDeviceName, 
                    FILE_DEVICE_PROTOCOL, 
                    0, 
                    TRUE,  // only one handle to the device at a time 
                    &DeviceObject 
                    ); 
 
        if (Status != STATUS_SUCCESS) { 
 
            IF_LOUD(DbgPrint("Packet: IoCreateDevice() failed:\n");) 
            break; 
        } 
        if (Status != STATUS_SUCCESS) { 
 
            IF_LOUD(DbgPrint("Packet: IoCreateSymbolicLink() failed:\n");) 
            break; 
        } 
 
        Status = PacketCreateSymbolicLink(&UnicodeDeviceName, TRUE); 
        DevicesCreated++; 
 
 
        DeviceObject->Flags |= DO_DIRECT_IO; 
        DeviceExtension  =  (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
        DeviceExtension->DeviceObject = DeviceObject; 
 
        // 
        //  Save the name of the MAC driver to open in the Device Extension 
        // 
 
        DeviceExtension->AdapterName = MacDriverName; 
 
        DeviceExtension->DeviceName = UnicodeDeviceName; 
 
        DeviceExtension->NdisProtocolHandle=NdisProtocolHandle; 
 
    } 
 
    if (DevicesCreated > 0) { 
        // 
        //  Managed to create at least one device. 
        // 
        return STATUS_SUCCESS; 
    } 
 
Error: 
 
    PacketUnload(DriverObject); 
 
    return(Status); 
 
} 
 
 
VOID 
PacketUnload( 
    IN PDRIVER_OBJECT DriverObject 
    ) 
 
{ 
 
    PDEVICE_OBJECT     DeviceObject; 
    PDEVICE_EXTENSION  DeviceExtension; 
 
    NDIS_HANDLE        NdisProtocolHandle; 
    NDIS_STATUS        Status; 
 
 
    IF_LOUD(DbgPrint("Packet: Unload\n");) 
 
 
    while (DriverObject->DeviceObject) { 
 
        DeviceObject    = DriverObject->DeviceObject; 
        DeviceExtension = DeviceObject->DeviceExtension; 
 
        NdisProtocolHandle=DeviceExtension->NdisProtocolHandle; 
        PacketCreateSymbolicLink(&DeviceExtension->DeviceName, FALSE); 
        IoDeleteDevice(DeviceObject); 
    } 
 
    if(BindStringSave) 
        ExFreePool(BindStringSave); 
 
    if(ExportStringSave) 
        ExFreePool(ExportStringSave); 
 
    NdisDeregisterProtocol( 
        &Status, 
        NdisProtocolHandle 
        ); 
 
} 
 
 
NTSTATUS 
PacketIoControl( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
 
/*++ 
 
Routine Description: 
 
    This is the dispatch routine for create/open and close requests. 
    These requests complete successfully. 
 
Arguments: 
 
    DeviceObject - Pointer to the device object. 
 
    Irp - Pointer to the request packet. 
 
Return Value: 
 
    Status is returned. 
 
--*/ 
 
{ 
 
    POPEN_INSTANCE      Open; 
    PIO_STACK_LOCATION  IrpSp; 
    PLIST_ENTRY         RequestListEntry; 
    PINTERNAL_REQUEST   pRequest; 
    ULONG               FunctionCode; 
    NDIS_STATUS         Status; 
 
    IF_LOUD(DbgPrint("Packet: IoControl\n");) 
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp); 
 
    FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; 
 
    Open=IrpSp->FileObject->FsContext; 
 
    IoIncrement(Open); 
  
    RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, 
                                                &Open->RequestSpinLock); 
 
    if (RequestListEntry == NULL) { 
        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
        IoCompleteRequest(Irp, IO_NO_INCREMENT); 
        IoDecrement(Open); 
        return STATUS_UNSUCCESSFUL; 
    } 
 
 
    pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement); 
    pRequest->Irp=Irp; 
 
    // 
    // Important: Since we have marked the IRP pending, we must return  
    // STATUS_PENDING even we happen to complete the IRP synchronously. 
    //  
     
    IoMarkIrpPending(Irp); 
 
 
    IF_LOUD(DbgPrint("Packet: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);) 
 
    if (FunctionCode == IOCTL_PROTOCOL_RESET) { 
 
 
        IF_LOUD(DbgPrint("Packet: IoControl - Reset request\n");) 
 
        // 
        // Since NDIS doesn't have an interface to cancel a request 
        // pending at miniport, we cannot set a cancel routine. 
        // As a result if the application that made the request 
        // terminates, we wait in the Cleanup routine for all pending 
        // NDIS requests to complete. 
        // 
 
        ExInterlockedInsertTailList( 
                &Open->ResetIrpList, 
                &Irp->Tail.Overlay.ListEntry, 
                &Open->RequestSpinLock); 
 
 
        NdisReset( 
            &Status, 
            Open->AdapterHandle 
            ); 
 
 
        if (Status != NDIS_STATUS_PENDING) { 
 
            IF_LOUD(DbgPrint("Packet: IoControl - ResetComplte being called\n");) 
 
            PacketResetComplete( 
                Open, 
                Status 
                ); 
            return STATUS_PENDING; 
 
        } 
 
    } else { 
        // 
        //  See if it is an Ndis request 
        // 
        PPACKET_OID_DATA    OidData=Irp->AssociatedIrp.SystemBuffer; 
 
        if (((FunctionCode == IOCTL_PROTOCOL_SET_OID) || (FunctionCode == IOCTL_PROTOCOL_QUERY_OID)) 
            && 
            (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength) 
            && 
            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) 
            && 
            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) { 
 
            IF_LOUD(DbgPrint("Packet: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);) 
 
            // 
            //  The buffer is valid 
            // 
            if (FunctionCode == IOCTL_PROTOCOL_SET_OID) { 
 
                pRequest->Request.RequestType=NdisRequestSetInformation; 
                pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid; 
 
                pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data; 
                pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length; 
 
 
            } else { 
 
 
                pRequest->Request.RequestType=NdisRequestQueryInformation; 
                pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid; 
 
                pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data; 
                pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length; 
 
            } 
 
            // 
            //  submit the request 
            // 
            NdisRequest( 
                &Status, 
                Open->AdapterHandle, 
                &pRequest->Request 
                ); 
 
        } else { 
            // 
            //  buffer too small 
            // 
            Status=NDIS_STATUS_FAILURE; 
            pRequest->Request.DATA.SET_INFORMATION.BytesRead=0; 
            pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0; 
 
        } 
 
        if (Status != NDIS_STATUS_PENDING) { 
 
            IF_LOUD(DbgPrint("Packet: Calling RequestCompleteHandler\n");) 
 
            PacketRequestComplete( 
                Open, 
                &pRequest->Request, 
                Status 
                ); 
        } 
 
    } 
 
    return(STATUS_PENDING); 
 
} 
 
 
 
VOID 
PacketRequestComplete( 
    IN NDIS_HANDLE   ProtocolBindingContext, 
    IN PNDIS_REQUEST NdisRequest, 
    IN NDIS_STATUS   Status 
    ) 
 
{ 
    POPEN_INSTANCE      Open; 
    PIO_STACK_LOCATION  IrpSp; 
    PIRP                Irp; 
    PINTERNAL_REQUEST   pRequest; 
    UINT                FunctionCode; 
 
    PPACKET_OID_DATA    OidData; 
 
    IF_LOUD(DbgPrint("Packet: RequestComplete\n");) 
 
    Open= (POPEN_INSTANCE)ProtocolBindingContext; 
 
    pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); 
 
    Irp=pRequest->Irp; 
 
    if(Status == NDIS_STATUS_SUCCESS) 
    { 
 
        IrpSp = IoGetCurrentIrpStackLocation(Irp); 
 
        FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; 
 
        OidData=Irp->AssociatedIrp.SystemBuffer; 
 
        if (FunctionCode == IOCTL_PROTOCOL_SET_OID) { 
 
            OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead; 
 
        } else { 
 
            if (FunctionCode == IOCTL_PROTOCOL_QUERY_OID) { 
 
                OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten; 
 
            } 
 
        } 
 
        Irp->IoStatus.Status = STATUS_SUCCESS; 
        Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength; 
 
    } else { 
        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
        Irp->IoStatus.Information=0; 
    }     
 
    ExInterlockedInsertTailList( 
        &Open->RequestList, 
        &pRequest->ListElement, 
        &Open->RequestSpinLock); 
         
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
    IoDecrement(Open); 
 
    return; 
 
} 
 
 
VOID 
PacketResetComplete( 
    IN NDIS_HANDLE  ProtocolBindingContext, 
    IN NDIS_STATUS  Status 
    ) 
 
{ 
    POPEN_INSTANCE      Open; 
    PIRP                Irp; 
 
    PLIST_ENTRY         ResetListEntry; 
 
    IF_LOUD(DbgPrint("Packet: PacketResetComplte\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); 
 
    if(Status == NDIS_STATUS_SUCCESS) { 
        Irp->IoStatus.Status = STATUS_SUCCESS; 
    } else { 
        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
    } 
    Irp->IoStatus.Information = 0;     
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
    IoDecrement(Open);  
 
    IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");) 
 
    return; 
 
} 
 
 
VOID 
PacketStatus( 
    IN NDIS_HANDLE   ProtocolBindingContext, 
    IN NDIS_STATUS   Status, 
    IN PVOID         StatusBuffer, 
    IN UINT          StatusBufferSize 
    ) 
 
{ 
 
    IF_LOUD(DbgPrint("Packet: Status Indication\n");) 
 
    return; 
 
} 
 
VOID 
PacketStatusComplete( 
    IN NDIS_HANDLE  ProtocolBindingContext 
    ) 
 
{ 
 
    IF_LOUD(DbgPrint("Packet: StatusIndicationComplete\n");) 
 
    return; 
 
} 
 
 
 
NTSTATUS 
PacketCreateSymbolicLink( 
    IN  PUNICODE_STRING  DeviceName, 
    IN  BOOLEAN          Create 
    ) 
 
{ 
 
 
    UNICODE_STRING UnicodeDosDeviceName; 
    NTSTATUS       Status; 
 
    if (DeviceName->Length < sizeof(L"\\Device\\")) { 
 
        return STATUS_UNSUCCESSFUL; 
    } 
 
    RtlInitUnicodeString(&UnicodeDosDeviceName,NULL); 
 
    UnicodeDosDeviceName.MaximumLength=DeviceName->Length+sizeof(L"\\DosDevices")+sizeof(UNICODE_NULL); 
 
    UnicodeDosDeviceName.Buffer=ExAllocatePool( 
                                    NonPagedPool, 
                                    UnicodeDosDeviceName.MaximumLength 
                                    ); 
 
    if (UnicodeDosDeviceName.Buffer != NULL) { 
 
        RtlZeroMemory( 
            UnicodeDosDeviceName.Buffer, 
            UnicodeDosDeviceName.MaximumLength 
            ); 
 
        RtlAppendUnicodeToString( 
            &UnicodeDosDeviceName, 
            L"\\DosDevices\\" 
            ); 
 
        RtlAppendUnicodeToString( 
            &UnicodeDosDeviceName, 
            (DeviceName->Buffer+(sizeof("\\Device"))) 
            ); 
 
        IF_LOUD(DbgPrint("Packet: DosDeviceName is %ws\n",UnicodeDosDeviceName.Buffer);) 
 
        if (Create) { 
 
            Status=IoCreateSymbolicLink(&UnicodeDosDeviceName,DeviceName); 
 
        } else { 
 
            Status=IoDeleteSymbolicLink(&UnicodeDosDeviceName); 
        } 
 
        ExFreePool(UnicodeDosDeviceName.Buffer); 
 
    } 
 
 
    return Status; 
 
} 
 
 
NTSTATUS 
PacketReadRegistry( 
    IN  PWSTR              *MacDriverName, 
    IN  PWSTR              *PacketDriverName, 
    IN  PUNICODE_STRING     RegistryPath 
    ) 
 
{ 
 
    NTSTATUS   Status; 
 
    RTL_QUERY_REGISTRY_TABLE ParamTable[5]; 
 
    PWSTR      Bind       = L"Bind"; 
    PWSTR      Export     = L"Export"; 
    PWSTR      Parameters = L"Parameters"; 
    PWSTR      Linkage    = L"Linkage"; 
 
    PWCHAR     Path; 
 
 
 
    Path=ExAllocatePool( 
             PagedPool, 
             RegistryPath->Length+sizeof(WCHAR) 
             ); 
 
    if (Path == NULL) { 
        return STATUS_INSUFFICIENT_RESOURCES; 
    } 
 
    RtlZeroMemory( 
        Path, 
        RegistryPath->Length+sizeof(WCHAR) 
        ); 
 
    RtlCopyMemory( 
        Path, 
        RegistryPath->Buffer, 
        RegistryPath->Length 
        ); 
 
    IF_LOUD(DbgPrint("Packet: Reg path is %ws\n",RegistryPath->Buffer);) 
 
    RtlZeroMemory( 
        ParamTable, 
        sizeof(ParamTable) 
        ); 
 
 
 
    // 
    //  change to the parameters key 
    // 
 
    ParamTable[0].QueryRoutine = NULL; 
    ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; 
    ParamTable[0].Name = Parameters; 
 
    // 
    //  change to the linkage key 
    // 
 
    ParamTable[1].QueryRoutine = NULL; 
    ParamTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY; 
    ParamTable[1].Name = Linkage; 
 
 
    // 
    //  Get the name of the mac driver we should bind to 
    // 
 
    ParamTable[2].QueryRoutine = PacketQueryRegistryRoutine; 
    ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | 
                          RTL_QUERY_REGISTRY_NOEXPAND; 
 
    ParamTable[2].Name = Bind; 
    ParamTable[2].EntryContext = (PVOID)MacDriverName; 
    ParamTable[2].DefaultType = REG_MULTI_SZ; 
 
    // 
    //  Get the name that we should use for the driver object 
    // 
 
    ParamTable[3].QueryRoutine = PacketQueryRegistryRoutine; 
    ParamTable[3].Flags = RTL_QUERY_REGISTRY_REQUIRED | 
                          RTL_QUERY_REGISTRY_NOEXPAND; 
 
    ParamTable[3].Name = Export; 
    ParamTable[3].EntryContext = (PVOID)PacketDriverName; 
    ParamTable[3].DefaultType = REG_MULTI_SZ; 
 
 
    Status=RtlQueryRegistryValues( 
               RTL_REGISTRY_ABSOLUTE, 
               Path, 
               ParamTable, 
               NULL, 
               NULL 
               ); 
 
 
    ExFreePool(Path); 
 
    return Status; 
 
 
 
 
} 
 
 
NTSTATUS 
PacketQueryRegistryRoutine( 
    IN PWSTR     ValueName, 
    IN ULONG     ValueType, 
    IN PVOID     ValueData, 
    IN ULONG     ValueLength, 
    IN PVOID     Context, 
    IN PVOID     EntryContext 
    ) 
 
{ 
 
    PUCHAR       Buffer; 
 
    IF_LOUD(DbgPrint("Packet: QueryRegistryRoutine\n");) 
 
    if (ValueType != REG_MULTI_SZ) { 
 
        return STATUS_OBJECT_NAME_NOT_FOUND; 
 
    } 
 
    Buffer=ExAllocatePool(NonPagedPool,ValueLength); 
 
    if (Buffer==NULL) { 
 
        return STATUS_INSUFFICIENT_RESOURCES; 
 
    } 
 
    RtlCopyMemory( 
        Buffer, 
        ValueData, 
        ValueLength 
        ); 
 
    *((PUCHAR *)EntryContext)=Buffer; 
 
    return STATUS_SUCCESS; 
 
} 
 
 
VOID 
IoIncrement ( 
    IN  OUT POPEN_INSTANCE  Open 
    )    
 
/*++ 
Routine Description: 
 
    This routine increments the number of requests the device receives 
     
Arguments: 
 
    Open - pointer to the device extension. 
     
Return Value: 
--*/ 
 
{ 
    LONG            result; 
     
    result = InterlockedIncrement(&Open->IrpCount); 
 
    IF_LOUD(DbgPrint("IoIncrement %d\n", result);) 
 
    // 
    // Need to clear event (when IrpCount bumps from 0 to 1)  
    // 
     
    if (result == 1) { 
        // 
        // We need to clear the event 
        // 
        NdisResetEvent(&Open->CleanupEvent); 
    } 
 
    return; 
} 
 
VOID 
IoDecrement ( 
    IN  OUT POPEN_INSTANCE  Open 
    ) 
/*++ 
Routine Description: 
 
    This routine decrements as it complete the request it receives 
 
Arguments: 
 
    Open - pointer to the device extension. 
     
Return Value: 
 
--*/ 
{ 
    LONG            result; 
     
    result = InterlockedDecrement(&Open->IrpCount); 
 
    IF_LOUD(DbgPrint("IoDecrement %d\n", result);) 
 
    if (result == 0) { 
 
        // 
        // Set the event when the count transition from 1 to 0. 
        // 
  
        NdisSetEvent (&Open->CleanupEvent); 
    } 
    return; 
}