📄 packet.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
packet.c
Abstract:
Author:
Environment:
Kernel mode only.
Notes:
Future:
Revision History:
Fixed bugs and converted to NDIS 5.0. This driver handles
dynamic binding and unbinding to underlying NICs, receives
pnp and power management callbacks, and implements
ReceivePacketHandler.
- Eliyas Yakub June, 1999
--*/
#include "ntddk.h"
#include "ndis.h"
#include "ntddpack.h"
#include "packet.h"
#include "stdio.h"
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:
NT Status code
--*/
{
NDIS_PROTOCOL_CHARACTERISTICS protocolChar;
NTSTATUS status = STATUS_SUCCESS;
NDIS_STRING protoName = NDIS_STRING_CONST("Packet");
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;
BOOLEAN fSymbolicLink = FALSE;
PDEVICE_OBJECT deviceObject;
DebugPrint(("\n\nDriverEntry\n"));
Globals.DriverObject = DriverObject;
//
// Save the RegistryPath.
// 保存注册路径
//
Globals.RegistryPath.MaximumLength = RegistryPath->Length +
sizeof(UNICODE_NULL);
Globals.RegistryPath.Length = RegistryPath->Length;
Globals.RegistryPath.Buffer = ExAllocatePool(
PagedPool,
Globals.RegistryPath.MaximumLength
);
if (!Globals.RegistryPath.Buffer) {
DebugPrint (("Couldn't allocate pool for registry path."));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);
RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
//
// Create a control device object for this driver.
// Application can send an IOCTL to this device to get
// bound adapter information.
// 为本驱动程序创建一个控制设备对象,用户应用程序可以
// 发送的控制命令被发送到该对象,它帮助用户进行参数设定
// 以及获取适配器信息等操作.
//
status = IoCreateDevice (DriverObject,
0,
&ntDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject);
if (!NT_SUCCESS (status)) {
//
// Either not enough memory to create a deviceobject or another
// deviceobject with the same name exits. This could happen
// if you install another instance of this device.
// 出现这种创建控制对象不成功的原因可能是:不存在足够的内存来
// 创建该对象,也可能是已经有相同名字的对象已经存在;后者可能是
// 由于机器上已经安装了本设备的一个实例.
//
goto ERROR;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) // If we couldn't create the link then
{ // abort installation.
goto ERROR;
}
fSymbolicLink = TRUE; // symboliclink is created
deviceObject->Flags |= DO_BUFFERED_IO;
Globals.ControlDeviceObject = deviceObject;
InitializeListHead(&Globals.AdapterList);
KeInitializeSpinLock(&Globals.GlobalLock);
//
// Initialize the protocol characterstic structure
//
NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
protocolChar.MajorNdisVersion = 5;
protocolChar.MinorNdisVersion = 0;
protocolChar.Name = protoName;
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.BindAdapterHandler = PacketBindAdapter;
protocolChar.UnbindAdapterHandler = PacketUnbindAdapter;
protocolChar.UnloadHandler = NULL;
protocolChar.ReceivePacketHandler = PacketReceivePacket;
protocolChar.PnPEventHandler = PacketPNPHandler;
//
// Register as a protocol driver
//
NdisRegisterProtocol(
&status,
&Globals.NdisProtocolHandle,
&protocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (status != NDIS_STATUS_SUCCESS) {
DebugPrint(("Failed to register protocol with NDIS\n"));
status = STATUS_UNSUCCESSFUL;
goto ERROR;
}
//
// Now set only the dispatch points we would like to handle.
// 设定我们需要的分发例程,这些分发例程是本实验的关键所在.
//
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;
return(STATUS_SUCCESS);
ERROR:
if(deviceObject)
IoDeleteDevice(deviceObject);
if(fSymbolicLink)
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.RegistryPath.Buffer)
ExFreePool(Globals.RegistryPath.Buffer);
return status;
}
VOID
PacketUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
NDIS_STATUS status;
UNICODE_STRING win32DeviceName;
DebugPrint(("Unload Enter\n"));
//
// First delete the Control deviceobject and the corresponding
// symbolicLink
//
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.ControlDeviceObject)
IoDeleteDevice(Globals.ControlDeviceObject);
//
// Unbind from all the adapters. The system removes the driver code
// pages from the memory as soon as the unload returns. So you
// must wait for all the CloseAdapterCompleteHandler to finish
// before returning from the unload routine. You don't any callbacks
// to trigger after the driver is unloaded.
//
while(DriverObject->DeviceObject)
{
PacketUnbindAdapter(&status,
DriverObject->DeviceObject->DeviceExtension,
NULL);
}
if(Globals.RegistryPath.Buffer)
ExFreePool(Globals.RegistryPath.Buffer);
DebugPrint(("Deregister\n"));
NdisDeregisterProtocol(
&status,
Globals.NdisProtocolHandle
);
DebugPrint(("Unload Exit\n"));
}
NTSTATUS
PacketIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch routine for Filter OID and Reset requests.
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;
PINTERNAL_REQUEST pRequest;
ULONG functionCode;
NDIS_STATUS status;
ULONG dataLength =0;
DebugPrint(("IoControl\n"));
irpSp = IoGetCurrentIrpStackLocation(Irp);
functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
//
// Check whether this request is to get bound adapter list.
//判断是否请求枚举适配器
//
if (functionCode == IOCTL_ENUM_ADAPTERS) {
//
// If the request is not made to the controlobject, fail
// the request.
//
if(DeviceObject != Globals.ControlDeviceObject) {
status = STATUS_INVALID_DEVICE_REQUEST;
} else {
status = PacketGetAdapterList(
Irp->AssociatedIrp.SystemBuffer,
irpSp->Parameters.DeviceIoControl.OutputBufferLength,
&dataLength
);
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = dataLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
//
// Increment the outstanding IRP count.
//
open = DeviceObject->DeviceExtension;
IoIncrement(open);
//
// Check to see whether you are still bound to the adapter
//
if(!open->Bound)
{
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoDecrement(open);
return status;
}
DebugPrint(("Function code is %08lx buff size=%08lx %08lx\n",
functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength,
irpSp->Parameters.DeviceIoControl.OutputBufferLength));
//
// Important: Since we have marked the IRP pending, we must return
// STATUS_PENDING even we happen to complete the IRP synchronously.
//
IoMarkIrpPending(Irp);
if (functionCode == IOCTL_PROTOCOL_RESET) {
DebugPrint(("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->ResetQueueLock);
NdisReset(
&status,
open->AdapterHandle
);
if (status != NDIS_STATUS_PENDING) {
DebugPrint(("IoControl - ResetComplete being called\n"));
PacketResetComplete(
open,
status
);
}
} else {
//
// See if it is an Ndis request
//
PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer;
pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST));
if(NULL == pRequest)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return STATUS_PENDING;
}
pRequest->Irp=Irp;
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)) {
DebugPrint(("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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -