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;
}