📄 lan.c
字号:
}
RtlZeroMemory( Proto, Size );
Proto->Id = DeviceExt->ProtoId++;
Proto->NumEtherTypes = EaInfo->EaValueLength / sizeof(USHORT);
ProtoNumbersToMatch = EaInfo->EaName + EaInfo->EaNameLength + 1;
LA_DbgPrint(MID_TRACE,("NumEtherTypes: %d\n", Proto->NumEtherTypes));
RtlCopyMemory( Proto->EtherType,
ProtoNumbersToMatch,
sizeof(USHORT) * Proto->NumEtherTypes );
InitializeListHead( &Proto->ReadIrpListHead );
FileObject->FsContext = Proto;
LA_DbgPrint(MID_TRACE,("DeviceExt: %x, Proto %x\n", DeviceExt, Proto));
ExInterlockedInsertTailList( &DeviceExt->ProtocolListHead,
&Proto->ListEntry,
&DeviceExt->Lock );
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
LA_DbgPrint(MID_TRACE,("Status %x\n", Irp->IoStatus.Status));
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
LanCloseProtocol( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PLAN_PROTOCOL Proto = FileObject->FsContext;
KIRQL OldIrql;
PLIST_ENTRY ReadIrpListEntry;
PIRP ReadIrp;
NTSTATUS Status;
LA_DbgPrint(MID_TRACE,("Called\n"));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
while( !IsListEmpty( &Proto->ReadIrpListHead ) ) {
ReadIrpListEntry = RemoveHeadList( &Proto->ReadIrpListHead );
ReadIrp = CONTAINING_RECORD( ReadIrpListEntry, IRP,
Tail.Overlay.ListEntry );
ReadIrp->IoStatus.Information = 0;
ReadIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest( ReadIrp, IO_NO_INCREMENT );
}
RemoveEntryList( &Proto->ListEntry );
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
LA_DbgPrint(MID_TRACE,("Deleting %x\n"));
ExFreePool( Proto );
Status = Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Status;
}
PLAN_ADAPTER FindAdapterByIndex( PLAN_DEVICE_EXT DeviceExt, UINT Index ) {
PLIST_ENTRY ListEntry;
PLAN_ADAPTER Current, Target = NULL;
for( ListEntry = DeviceExt->AdapterListHead.Flink;
ListEntry != &DeviceExt->AdapterListHead;
ListEntry = ListEntry->Flink ) {
Current = CONTAINING_RECORD(ListEntry, LAN_ADAPTER, ListEntry);
if( Current->Index == Index ) {
Target = Current;
break;
}
}
return Target;
}
/* Write data to an adapter:
* |<- 16 >| |<-- variable ... -->|
* [indx] [addrtype] [addrlen ] [ptype] [packet-data ...]
*/
NTSTATUS STDCALL
LanWriteData( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_PACKET_HEADER ToWrite = Irp->AssociatedIrp.SystemBuffer;
NTSTATUS Status = STATUS_SUCCESS;
LA_DbgPrint(MID_TRACE,("Called\n"));
Irp->IoStatus.Information =
LANTransmitInternal( ToWrite, IrpSp->Parameters.Write.Length );
Irp->IoStatus.Status = Status;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return Status;
}
NTSTATUS STDCALL
LanReadData( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PLAN_PROTOCOL Proto = FileObject->FsContext;
LA_DbgPrint(MID_TRACE,("Called on %x (%x)\n", Proto, Irp));
ExInterlockedInsertTailList( &Proto->ReadIrpListHead,
&Irp->Tail.Overlay.ListEntry,
&DeviceExt->Lock );
LA_DbgPrint(MID_TRACE,("List: %x %x\n",
Proto->ReadIrpListHead.Flink,
Irp->Tail.Overlay.ListEntry.Flink));
IoMarkIrpPending( Irp );
return STATUS_PENDING;
}
NTSTATUS STDCALL
LanEnumAdapters( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLIST_ENTRY ListEntry;
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
NTSTATUS Status = STATUS_SUCCESS;
PLAN_ADAPTER Adapter;
UINT AdapterCount = 0;
PUINT Output = Irp->AssociatedIrp.SystemBuffer;
KIRQL OldIrql;
LA_DbgPrint(MID_TRACE,("Called\n"));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
for( ListEntry = DeviceExt->AdapterListHead.Flink;
ListEntry != &DeviceExt->AdapterListHead;
ListEntry = ListEntry->Flink ) AdapterCount++;
if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
AdapterCount * sizeof(UINT) ) {
for( ListEntry = DeviceExt->AdapterListHead.Flink;
ListEntry != &DeviceExt->AdapterListHead;
ListEntry = ListEntry->Flink ) {
Adapter = CONTAINING_RECORD(ListEntry, LAN_ADAPTER, ListEntry);
*Output++ = Adapter->Index;
}
} else Status = STATUS_BUFFER_TOO_SMALL;
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
LA_DbgPrint(MID_TRACE,("Ending\n"));
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = (PCHAR)Output -
(PCHAR)Irp->AssociatedIrp.SystemBuffer;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Status;
}
NTSTATUS STDCALL
LanAdapterInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
PLAN_ADAPTER Adapter;
PLAN_ADDRESS_C Address;
PUINT AdapterIndexPtr = Irp->AssociatedIrp.SystemBuffer;
PLIST_ENTRY ListEntry;
UINT BytesNeeded = sizeof( LAN_ADAPTER_INFO ), AddrSize;
NTSTATUS Status = STATUS_SUCCESS;
PCHAR Writing = Irp->AssociatedIrp.SystemBuffer;
PLAN_ADAPTER_INFO_S Info;
KIRQL OldIrql;
LA_DbgPrint(MID_TRACE,("Called\n"));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(*AdapterIndexPtr) )
Adapter = NULL;
else
Adapter = FindAdapterByIndex( DeviceExt, *AdapterIndexPtr );
if( Adapter ) {
/* Local Addresses */
for( ListEntry = Adapter->AddressList.Flink;
ListEntry != &Adapter->AddressList;
ListEntry = ListEntry->Flink ) {
Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, ListEntry);
BytesNeeded += LAN_ADDR_SIZE(Address->ClientPart.AddressLen,
Address->ClientPart.HWAddressLen);
}
/* Foreign Addresses */
for( ListEntry = Adapter->ForeignList.Flink;
ListEntry != &Adapter->ForeignList;
ListEntry = ListEntry->Flink ) {
Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C, ListEntry);
BytesNeeded += LAN_ADDR_SIZE(Address->ClientPart.AddressLen,
Address->ClientPart.HWAddressLen);
}
BytesNeeded += Adapter->RegistryPath.Length;
if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
BytesNeeded ) {
/* Write common info */
Info = (PLAN_ADAPTER_INFO_S)Writing;
Info->Index = Adapter->Index;
Info->Media = Adapter->Media;
Info->Speed = Adapter->Speed;
/* Ethernet specific XXX */
Info->AddressLen = IEEE_802_ADDR_LENGTH;
Info->Overhead = Adapter->HeaderSize;
Info->MTU = Adapter->MTU;
Info->RegKeySize = Adapter->RegistryPath.Length;
/* Copy the name */
Writing += sizeof(*Info);
RtlCopyMemory( Adapter->RegistryPath.Buffer,
Writing,
Adapter->RegistryPath.Length );
/* Write the address info */
Writing += Adapter->RegistryPath.Length;
for( ListEntry = Adapter->AddressList.Flink;
ListEntry != &Adapter->AddressList;
ListEntry = ListEntry->Flink ) {
Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C,
ListEntry);
AddrSize = LAN_ADDR_SIZE(Address->ClientPart.AddressLen,
Address->ClientPart.HWAddressLen);
RtlCopyMemory( Writing, &Address->ClientPart, AddrSize );
Writing += AddrSize;
}
for( ListEntry = Adapter->ForeignList.Flink;
ListEntry != &Adapter->ForeignList;
ListEntry = ListEntry->Flink ) {
Address = CONTAINING_RECORD(ListEntry, LAN_ADDRESS_C,
ListEntry);
AddrSize = LAN_ADDR_SIZE(Address->ClientPart.AddressLen,
Address->ClientPart.HWAddressLen);
RtlCopyMemory( Writing, &Address->ClientPart, AddrSize );
Writing += AddrSize;
}
ASSERT( BytesNeeded == Writing - Irp->AssociatedIrp.SystemBuffer );
} else Status = STATUS_BUFFER_TOO_SMALL;
} else Status = STATUS_NO_SUCH_DEVICE;
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
LA_DbgPrint(MID_TRACE,("Ending (%d bytes)\n", BytesNeeded));
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesNeeded;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Status;
}
NTSTATUS STDCALL
LanSetBufferedMode( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
PLAN_DEVICE_EXT DeviceExt =
(PLAN_DEVICE_EXT)DeviceObject->DeviceExtension;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PLAN_PROTOCOL Proto = FileObject->FsContext;
NTSTATUS Status = STATUS_SUCCESS;
KIRQL OldIrql;
LA_DbgPrint(MID_TRACE,("Called %x\n", Proto));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(Proto->Buffered) )
RtlCopyMemory( &Proto->Buffered, Irp->AssociatedIrp.SystemBuffer,
sizeof(Proto->Buffered) );
else
Status = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
LA_DbgPrint(MID_TRACE,("Set buffered for %x to %d\n", Proto->Buffered));
Status = Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
return Status;
}
NTSTATUS STDCALL
LanDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status = STATUS_SUCCESS;
LA_DbgPrint(MID_TRACE,("LanDispatch: %d\n", IrpSp->MajorFunction));
if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
LA_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
FileObject, IrpSp->FileObject));
ASSERT(FileObject == IrpSp->FileObject);
}
switch(IrpSp->MajorFunction)
{
/* opening and closing handles to the device */
case IRP_MJ_CREATE:
/* Mostly borrowed from the named pipe file system */
return LanCreateProtocol(DeviceObject, Irp, IrpSp);
case IRP_MJ_CLOSE:
/* Ditto the borrowing */
return LanCloseProtocol(DeviceObject, Irp, IrpSp);
/* write data */
case IRP_MJ_WRITE:
return LanWriteData( DeviceObject, Irp, IrpSp );
/* read data */
case IRP_MJ_READ:
return LanReadData( DeviceObject, Irp, IrpSp );
case IRP_MJ_DEVICE_CONTROL:
{
LA_DbgPrint(MID_TRACE,("DeviceIoControl: %x\n",
IrpSp->Parameters.DeviceIoControl.
IoControlCode));
switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
case IOCTL_IF_ENUM_ADAPTERS:
return LanEnumAdapters( DeviceObject, Irp, IrpSp );
case IOCTL_IF_BUFFERED_MODE:
return LanSetBufferedMode( DeviceObject, Irp, IrpSp );
case IOCTL_IF_ADAPTER_INFO:
return LanAdapterInfo( DeviceObject, Irp, IrpSp );
default:
Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
LA_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
IrpSp->Parameters.DeviceIoControl.
IoControlCode));
break;
}
break;
}
/* unsupported operations */
default:
{
Status = STATUS_NOT_IMPLEMENTED;
LA_DbgPrint(MIN_TRACE,
("Irp: Unknown Major code was %x\n",
IrpSp->MajorFunction));
break;
}
}
LA_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return (Status);
}
/* Do i need a global here? I think i need to do this a different way XXX */
VOID STDCALL LanUnload(PDRIVER_OBJECT DriverObject) {
LANUnregisterProtocol();
CloseNdisPools();
}
NTSTATUS STDCALL DriverEntry( PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegsitryPath ) {
PDEVICE_OBJECT DeviceObject;
PLAN_DEVICE_EXT DeviceExt;
UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Lan");
UNICODE_STRING LanString = RTL_CONSTANT_STRING(L"LAN");
NTSTATUS Status;
InitNdisPools();
/* register driver routines */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = LanDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = LanDispatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = LanDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = LanDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = LanDispatch;
DriverObject->DriverUnload = LanUnload;
/* create lan device */
Status = IoCreateDevice
( DriverObject,
sizeof(LAN_DEVICE_EXT),
&wstrDeviceName,
FILE_DEVICE_NAMED_PIPE,
0,
FALSE,
&DeviceObject );
/* failure */
if(!NT_SUCCESS(Status))
{
return (Status);
}
LanDeviceObject = DeviceObject;
DeviceExt = DeviceObject->DeviceExtension;
RtlZeroMemory( DeviceExt, sizeof(*DeviceExt) );
InitializeListHead( &DeviceExt->AdapterListHead );
InitializeListHead( &DeviceExt->ProtocolListHead );
KeInitializeSpinLock( &DeviceExt->Lock );
LANRegisterProtocol( &LanString );
DeviceObject->Flags |= DO_BUFFERED_IO;
LA_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
DeviceObject, DeviceExt));
return (Status);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -