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


/*++ 
 
Copyright (c) 1990  Microsoft Corporation 
 
Module Name: 
 
    packet.c 
 
Abstract: 
 
 
Author: 
 
 
Environment: 
 
    Kernel mode only. 
 
Notes: 
 
 
Future: 
 
 
 
Revision History: 
 
--*/ 
 
#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 
 
PDEVICE_EXTENSION GlobalDeviceExtension; 
 
 
 
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; 
 
    PWSTR          BindStringSave; 
    PWSTR          ExportStringSave; 
 
    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("Perf: Failed to read registry\n");) 
 
        goto RegistryError; 
    } 
 
    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, 
                    FALSE, 
                    &DeviceObject 
                    ); 
 
        if (Status != STATUS_SUCCESS) { 
 
            IF_LOUD(DbgPrint("Perf: IoCreateDevice() failed:\n");) 
 
            break; 
        } 
 
        DevicesCreated++; 
 
 
        DeviceObject->Flags |= DO_DIRECT_IO; 
        DeviceExtension  =  (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
        DeviceExtension->DeviceObject = DeviceObject; 
 
        // 
        //  Save the the name of the MAC driver to open in the Device Extension 
        // 
 
        DeviceExtension->AdapterName=MacDriverName; 
 
        if (DevicesCreated == 1) { 
 
            DeviceExtension->BindString   = BindStringSave; 
            DeviceExtension->ExportString = ExportStringSave; 
        } 
 
 
        DeviceExtension->NdisProtocolHandle=NdisProtocolHandle; 
 
 
    } 
 
    if (DevicesCreated > 0) { 
        // 
        //  Managed to create at least on device. 
        // 
        return STATUS_SUCCESS; 
    } 
 
 
 
    ExFreePool(BindStringSave); 
    ExFreePool(ExportStringSave); 
 
RegistryError: 
 
    NdisDeregisterProtocol( 
        &Status, 
        NdisProtocolHandle 
        ); 
 
    Status=STATUS_UNSUCCESSFUL; 
 
    return(Status); 
 
} 
 
 
 
 
VOID 
PacketUnload( 
    IN PDRIVER_OBJECT DriverObject 
    ) 
 
{ 
 
    PDEVICE_OBJECT     DeviceObject; 
    PDEVICE_OBJECT     OldDeviceObject; 
    PDEVICE_EXTENSION  DeviceExtension; 
 
    NDIS_HANDLE        NdisProtocolHandle; 
    NDIS_STATUS        Status; 
 
 
    IF_LOUD(DbgPrint("Packet: Unload\n");) 
 
    DeviceObject    = DriverObject->DeviceObject; 
 
    while (DeviceObject != NULL) { 
 
        DeviceExtension = DeviceObject->DeviceExtension; 
 
        NdisProtocolHandle=DeviceExtension->NdisProtocolHandle; 
 
        if (DeviceExtension->BindString != NULL) { 
 
            ExFreePool(DeviceExtension->BindString); 
 
        } 
 
        if (DeviceExtension->ExportString != NULL) { 
 
            ExFreePool(DeviceExtension->ExportString); 
 
        } 
 
        OldDeviceObject=DeviceObject; 
 
        DeviceObject=DeviceObject->NextDevice; 
 
        IoDeleteDevice(OldDeviceObject); 
 
    } 
 
    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; 
 
    RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, 
                                                &Open->RequestSpinLock); 
 
    if (RequestListEntry == NULL) { 
        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 
        return STATUS_UNSUCCESSFUL; 
    } 
 
 
    pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement); 
    pRequest->Irp=Irp; 
 
 
    IoMarkIrpPending(Irp); 
    Irp->IoStatus.Status = STATUS_PENDING; 
 
 
 
    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");) 
 
        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 
                ); 
 
 
        } 
 
    } 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; 
 
    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.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength; 
 
 
    ExInterlockedInsertTailList( 
        &Open->RequestList, 
        &pRequest->ListElement, 
        &Open->RequestSpinLock); 
 
 
    Irp->IoStatus.Status = Status; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
    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; 
 
} 
 
 
#if 0 
 
 
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; 
 
} 
 
 
 
#endif 
 
 
 
 
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 parmeters 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("Perf: 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; 
 
}