⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
    }

    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 + -