mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[NDISUIO]
- Add the NDISUIO driver to allow communication between user-mode and kernel-mode NIC drivers - Only the IOCTLs required for WLAN are implemented right now - Initial source drop without build testing svn path=/branches/wlan-bringup/; revision=54810
This commit is contained in:
parent
2b82fe44ea
commit
80c1df8be2
10 changed files with 926 additions and 0 deletions
22
drivers/network/ndisuio/CMakeLists.txt
Normal file
22
drivers/network/ndisuio/CMakeLists.txt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
add_definitions(
|
||||||
|
-DNDIS50
|
||||||
|
-D_NTDRIVER_)
|
||||||
|
|
||||||
|
spec2def(ndisuio.sys ndisuio.spec)
|
||||||
|
|
||||||
|
list(APPEND SOURCE
|
||||||
|
main.c
|
||||||
|
ndisuio.rc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/ndisuio.def)
|
||||||
|
|
||||||
|
add_library(ndisuio SHARED ${SOURCE})
|
||||||
|
|
||||||
|
target_link_libraries(ndisuio
|
||||||
|
${PSEH_LIB})
|
||||||
|
|
||||||
|
set_module_type(ndisuio kernelmodedriver)
|
||||||
|
add_importlibs(ndisuio ndis ntoskrnl hal)
|
||||||
|
|
||||||
|
add_pch(ndisuio ndisuio.h)
|
||||||
|
|
||||||
|
add_cd_file(TARGET ndisuio DESTINATION reactos/system32/drivers FOR all)
|
64
drivers/network/ndisuio/createclose.c
Normal file
64
drivers/network/ndisuio/createclose.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: createclose.c
|
||||||
|
* PURPOSE: IRP_MJ_CREATE and IRP_MJ_CLOSE handling
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* This is associated with an adapter during IOCTL_NDISUIO_OPEN_(WRITE_)DEVICE */
|
||||||
|
IrpSp->FileObject->FsContext = NULL;
|
||||||
|
IrpSp->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Completed successfully */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = FILE_OPENED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchClose(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* Check if this handle was ever associated with an adapter */
|
||||||
|
if (AdapterContext != NULL)
|
||||||
|
{
|
||||||
|
ASSERT(OpenEntry != NULL);
|
||||||
|
|
||||||
|
/* Call the our helper */
|
||||||
|
DereferenceAdapterContextWithOpenEntry(AdapterContext, OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
247
drivers/network/ndisuio/ioctl.c
Normal file
247
drivers/network/ndisuio/ioctl.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: ioctl.c
|
||||||
|
* PURPOSE: IOCTL handling
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_SET_OID SetOidRequest;
|
||||||
|
NDIS_REQUEST NdisRequest;
|
||||||
|
ULONG RequestLength;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
SetOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
|
||||||
|
{
|
||||||
|
/* Setup the NDIS request */
|
||||||
|
NdisRequest.RequestType = NdisRequestSetInformation;
|
||||||
|
NdisRequest.Oid = SetOidRequest->Oid;
|
||||||
|
NdisRequest.InformationBuffer = SetOidRequest->Data;
|
||||||
|
NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
|
||||||
|
|
||||||
|
/* Dispatch the request */
|
||||||
|
NdisRequest(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
&NdisRequest);
|
||||||
|
|
||||||
|
/* Wait for the request */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the bytes read */
|
||||||
|
if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesRead;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bad parameters */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_QUERY_OID QueryOidRequest;
|
||||||
|
NDIS_REQUEST NdisRequest;
|
||||||
|
ULONG RequestLength;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
QueryOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
|
||||||
|
{
|
||||||
|
/* Setup the NDIS request */
|
||||||
|
NdisRequest.RequestType = NdisRequestQueryInformation;
|
||||||
|
NdisRequest.Oid = QueryOidRequest->Oid;
|
||||||
|
NdisRequest.InformationBuffer = QueryOidRequest->Data;
|
||||||
|
NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
|
||||||
|
|
||||||
|
/* Dispatch the request */
|
||||||
|
NdisRequest(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
&NdisRequest);
|
||||||
|
|
||||||
|
/* Wait for the request */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the bytes written */
|
||||||
|
if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesWritten;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bad parameters */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
ULONG NameLength;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
|
||||||
|
NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (NameLength != 0)
|
||||||
|
{
|
||||||
|
DeviceName.MaximumLength = DeviceName.Length = NameLength;
|
||||||
|
DeviceName.Buffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
|
||||||
|
/* Check if this already has a context */
|
||||||
|
AdapterContext = FindAdapterContextByName(&DeviceName);
|
||||||
|
if (AdapterContext == NULL)
|
||||||
|
{
|
||||||
|
/* Create a new context */
|
||||||
|
Status = BindAdapterByName(&DeviceName, &AdapterContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Reference the existing context */
|
||||||
|
ReferenceAdapterContext(AdapterContext, FALSE);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the bind succeeded */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
|
||||||
|
if (OpenEntry)
|
||||||
|
{
|
||||||
|
/* Set the file object pointer */
|
||||||
|
OpenEntry->FileObject = FileObject;
|
||||||
|
|
||||||
|
/* Associate this FO with the adapter */
|
||||||
|
FileObject->FsContext = AdapterContext;
|
||||||
|
FileObject->FsContext2 = OpenEntry;
|
||||||
|
|
||||||
|
/* Add it to the adapter's list */
|
||||||
|
ExInterlockedInsertTailList(&AdapterContext->OpenEntryList,
|
||||||
|
&OpenEntry->ListEntry,
|
||||||
|
&AdapterContext->Spinlock);
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove the reference we added */
|
||||||
|
DereferenceAdapterContext(AdapterContext, NULL);
|
||||||
|
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
/* FIXME: Handle this correctly */
|
||||||
|
return OpenDeviceReadWrite(Irp, IrpSp);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* Handle open IOCTLs first */
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_NDISUIO_OPEN_DEVICE:
|
||||||
|
return OpenDeviceReadWrite(Irp, IrpSp);
|
||||||
|
|
||||||
|
case IOCTL_NDISUIO_OPEN_WRITE_DEVICE:
|
||||||
|
return OpenDeviceWrite(Irp, IrpSp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Fail if this file object has no adapter associated */
|
||||||
|
if (IrpSp->FileObject->FsContext == NULL)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now handle other IOCTLs */
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_NDISUIO_QUERY_OID_VALUE:
|
||||||
|
return QueryAdapterOid(Irp, IrpSp);
|
||||||
|
|
||||||
|
case IOCTL_NDISUIO_SET_OID_VALUE:
|
||||||
|
return SetAdapterOid(Irp, IrpSp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("Unimplemented\n");
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
88
drivers/network/ndisuio/main.c
Normal file
88
drivers/network/ndisuio/main.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: main.c
|
||||||
|
* PURPOSE: Driver entry point and protocol initialization
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
PDEVICE_OBJECT GlobalDeviceObject;
|
||||||
|
NDIS_HANDLE GlobalProtocolHandle;
|
||||||
|
|
||||||
|
VOID NTAPI NduUnload(PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
IoDeleteDevice(GlobalDeviceObject);
|
||||||
|
|
||||||
|
DPRINT("NDISUIO: Unloaded\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
|
PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
NDIS_PROTOCOL_CHARACTERISTICS Chars;
|
||||||
|
|
||||||
|
/* Setup dispatch functions */
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = NduDispatchCreate;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NduDispatchClose;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NduDispatchDeviceControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_READ] = NduDispatchRead;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = NduDispatchWrite;
|
||||||
|
DriverObject->DriverUnload = NduUnload;
|
||||||
|
|
||||||
|
/* Create the NDISUIO device object */
|
||||||
|
Status = IoCreateDevice(DriverObject,
|
||||||
|
0,
|
||||||
|
NULL, // FIXME
|
||||||
|
NDISUIO_DEVICE_NAME,
|
||||||
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
|
FALSE,
|
||||||
|
&GlobalDeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create device object with status 0x%x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register the protocol with NDIS */
|
||||||
|
RtlZeroMemory(&Chars, sizeof(Chars));
|
||||||
|
Chars.MajorNdisVersion = NDIS_MAJOR_VERSION;
|
||||||
|
Chars.MinorNdisVersion = NDIS_MINOR_VERSION;
|
||||||
|
Chars.OpenAdapterCompleteHandler = NduOpenAdapterComplete;
|
||||||
|
Chars.CloseAdapterCompleteHandler = NduCloseAdapterComplete;
|
||||||
|
Chars.SendCompleteHandler = NduSendComplete;
|
||||||
|
Chars.TransferDataCompleteHandler = NduTransferDataComplete;
|
||||||
|
Chars.ResetCompleteHandler = NduResetComplete;
|
||||||
|
Chars.RequestCompleteHandler = NduRequestComplete;
|
||||||
|
Chars.ReceiveHandler = NduReceive;
|
||||||
|
Chars.ReceiveComplete = NduReceiveComplete;
|
||||||
|
Chars.StatusHandler = NduStatus;
|
||||||
|
Chars.StatusCompleteHandler = NduStatusComplete;
|
||||||
|
Chars.Name = NULL; //FIXME
|
||||||
|
Chars.ReceivePacketHandler = NULL; //NduReceivePacket
|
||||||
|
Chars.BindAdapterHandler = NduBindAdapter;
|
||||||
|
Chars.UnbindAdapterHandler = NduUnbindAdapter;
|
||||||
|
Chars.PnPEventHandler = NduPnPEvent;
|
||||||
|
|
||||||
|
NdisRegisterProtocol(&Status,
|
||||||
|
&GlobalProtocolHandle,
|
||||||
|
&Chars,
|
||||||
|
sizeof(Chars));
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to register protocol with status 0x%x\n", Status);
|
||||||
|
IoDeleteDevice(GlobalDeviceObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("NDISUIO: Loaded\n");
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
113
drivers/network/ndisuio/misc.c
Normal file
113
drivers/network/ndisuio/misc.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: misc.c
|
||||||
|
* PURPOSE: Helper functions
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT
|
||||||
|
FindAdapterContextByName(PNDIS_STRING DeviceName)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
||||||
|
CurrentEntry = GlobalAdapterList.Flink;
|
||||||
|
while (CurrentEntry != &GlobalAdapterList)
|
||||||
|
{
|
||||||
|
AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry);
|
||||||
|
|
||||||
|
/* Check if the device name matches */
|
||||||
|
if (RtlEqualUnicodeString(&AdapterContext->DeviceName, DeviceName, TRUE))
|
||||||
|
{
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&AdapterContext->Spinlock);
|
||||||
|
|
||||||
|
/* Check that it's not being destroyed */
|
||||||
|
if (AdapterContext->OpenCount > 0)
|
||||||
|
{
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&AdapterContext->Spinlock);
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
return AdapterContext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&Adaptercontext->Spinlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext, BOOLEAN Locked)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Lock if needed */
|
||||||
|
if (!Locked)
|
||||||
|
{
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the open count */
|
||||||
|
AdapterContext->OpenCount++;
|
||||||
|
|
||||||
|
/* Unlock if needed */
|
||||||
|
if (!Locked)
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Lock the adapter context */
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
|
||||||
|
/* Decrement the open count */
|
||||||
|
AdapterContext->OpenCount--;
|
||||||
|
|
||||||
|
/* Cleanup the open entry if we were given one */
|
||||||
|
if (OpenEntry != NULL)
|
||||||
|
{
|
||||||
|
/* Remove the open entry */
|
||||||
|
RemoveEntryList(&OpenEntry->ListEntry);
|
||||||
|
|
||||||
|
/* Invalidate the FO */
|
||||||
|
OpenEntry->FileObject->FsContext = NULL;
|
||||||
|
OpenEntry->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Free the open entry */
|
||||||
|
ExFreePool(OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if this binding can be destroyed */
|
||||||
|
if (AdapterContext->OpenCount == 0)
|
||||||
|
{
|
||||||
|
/* Unlock the context */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
|
||||||
|
/* Destroy the adapter context */
|
||||||
|
UnbindAdapterByContext(AdapterContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Still more references on it */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
}
|
||||||
|
}
|
55
drivers/network/ndisuio/ndisuio.h
Normal file
55
drivers/network/ndisuio/ndisuio.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: ndisuio.h
|
||||||
|
* PURPOSE: NDISUIO definitions
|
||||||
|
*/
|
||||||
|
#ifndef __NDISUIO_H
|
||||||
|
#define __NDISUIO_H
|
||||||
|
|
||||||
|
#include <wdm.h>
|
||||||
|
#include <ndis.h>
|
||||||
|
//#include <nuiouser.h>
|
||||||
|
#include <ndistapi.h>
|
||||||
|
#include <ndisguid.h>
|
||||||
|
|
||||||
|
struct _NDISUIO_ADAPTER_CONTEXT
|
||||||
|
{
|
||||||
|
/* Asynchronous completion */
|
||||||
|
NDIS_STATUS AsyncStatus;
|
||||||
|
KEVENT AsyncEvent;
|
||||||
|
|
||||||
|
/* NDIS binding information */
|
||||||
|
NDIS_HANDLE BindingHandle;
|
||||||
|
|
||||||
|
/* Reference count information */
|
||||||
|
ULONG OpenCount;
|
||||||
|
LIST_ENTRY OpenEntryList;
|
||||||
|
|
||||||
|
/* Receive packet list */
|
||||||
|
LIST_ENTRY PacketList;
|
||||||
|
|
||||||
|
/* Cancel read */
|
||||||
|
BOOLEAN CancelRead;
|
||||||
|
|
||||||
|
/* Global list entry */
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
/* Spin lock */
|
||||||
|
KSPIN_LOCK Spinlock;
|
||||||
|
} NDISUIO_ADAPTER_CONTEXT, *PNDISUIO_ADAPTER_CONTEXT;
|
||||||
|
|
||||||
|
struct _NDISUIO_OPEN_ENTRY
|
||||||
|
{
|
||||||
|
/* File object */
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
|
/* List entry */
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
} NDISUIO_OPEN_ENTRY, *PNDISUIO_OPEN_ENTRY;
|
||||||
|
|
||||||
|
/* NDIS version info */
|
||||||
|
#define NDIS_MAJOR_VERISON 5
|
||||||
|
#define NDIS_MINOR_VERSION 0
|
||||||
|
|
||||||
|
#endif /* __NDISUIO_H */
|
14
drivers/network/ndisuio/ndisuio.rbuild
Normal file
14
drivers/network/ndisuio/ndisuio.rbuild
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="ndisuio" type="kernelmodedriver" installbase="system32/drivers" installname="ndisuio.sys">
|
||||||
|
<include base="ndisuio">.</include>
|
||||||
|
<define name="NDIS50" />
|
||||||
|
<define name="_NTDRIVER_" />
|
||||||
|
<library>ndis</library>
|
||||||
|
<library>pseh</library>
|
||||||
|
<library>ntoskrnl</library>
|
||||||
|
<library>hal</library>
|
||||||
|
<pch>ndisuio.h</pch>
|
||||||
|
<file>main.c</file>
|
||||||
|
<file>ndisuio.rc</file>
|
||||||
|
</module>
|
5
drivers/network/ndisuio/ndisuio.rc
Normal file
5
drivers/network/ndisuio/ndisuio.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define REACTOS_VERSION_DLL
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "NDIS User-Mode I/O Protocol Driver\0"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "ndisuio\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "ndisuio.sys\0"
|
||||||
|
#include <reactos/version.rc>
|
278
drivers/network/ndisuio/protocol.c
Normal file
278
drivers/network/ndisuio/protocol.c
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: protocol.c
|
||||||
|
* PURPOSE: Protocol stuff
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
PNDIS_MEDIUM SupportedMedia = {NdisMedium802_3};
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
NDIS_STATUS OpenStatus)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter open completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter close completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduSendComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement send/receive */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
UINT BytesTransferred)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement send/receive */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduResetComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter reset completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduRequestComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_REQUEST NdisRequest,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter request completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
NTAPI
|
||||||
|
NduReceive(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE MacReceiveContext,
|
||||||
|
PVOID HeaderBuffer,
|
||||||
|
UINT HeaderBufferSize,
|
||||||
|
PVOID LookAheadBuffer,
|
||||||
|
UINT LookaheadBufferSize,
|
||||||
|
UINT PacketSize)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement send/receive */
|
||||||
|
return NDIS_STATUS_NOT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext)
|
||||||
|
{
|
||||||
|
/* No op */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatus(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS GeneralStatus,
|
||||||
|
PVOID StatusBuffer,
|
||||||
|
UINT StatusBufferSize)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement status tracking */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatusComplete(NDIS_HANDLE ProtocolBindingContext)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement status tracking */
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PLIST_ENTRY CurrentOpenEntry;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
|
||||||
|
/* Invalidate all handles to this adapter */
|
||||||
|
CurrentOpenEntry = AdapterContext->OpenEntryList.Flink;
|
||||||
|
while (CurrentOpenEntry != &AdapterContext->OpenEntryList)
|
||||||
|
{
|
||||||
|
OpenEntry = CONTAINING_RECORD(CurrentOpenEntry, NDISUIO_OPEN_ENTRY, ListEntry);
|
||||||
|
|
||||||
|
/* Make sure the entry is sane */
|
||||||
|
ASSERT(OpenEntry->FileObject);
|
||||||
|
|
||||||
|
/* Remove the adapter context pointer */
|
||||||
|
ASSERT(AdapterContext == OpenEntry->FileObject->FsContext);
|
||||||
|
OpenEntry->FileObject->FsContext = NULL;
|
||||||
|
AdapterContext->OpenCount--;
|
||||||
|
|
||||||
|
/* Remove the open entry pointer */
|
||||||
|
ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2);
|
||||||
|
OpenEntry->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Move to the next entry */
|
||||||
|
CurrentOpenEntry = CurrentOpenEntry->Flink;
|
||||||
|
|
||||||
|
/* Free the open entry */
|
||||||
|
ExFreePool(OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this fails, we have a refcount mismatch somewhere */
|
||||||
|
ASSERT(AdapterContext->OpenCount == 0);
|
||||||
|
|
||||||
|
/* Remove the adapter context from the global list */
|
||||||
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
||||||
|
RemoveEntryList(&AdapterContext->ListEntry);
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
|
||||||
|
/* Send the close request */
|
||||||
|
NdisCloseAdapter(Status,
|
||||||
|
AdapterContext->BindingHandle);
|
||||||
|
|
||||||
|
/* Wait for a pending close */
|
||||||
|
if (*Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
*Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the context */
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
BindAdapterByName(PNDIS_STRING DeviceName, PNDISUIO_ADAPTER_CONTEXT *Context)
|
||||||
|
{
|
||||||
|
NDIS_STATUS OpenErrorStatus;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
UINT SelectedMedium;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
/* Allocate the adapter context */
|
||||||
|
AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext));
|
||||||
|
if (!AdapterContext)
|
||||||
|
{
|
||||||
|
return NDIS_STATUS_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the adapter context */
|
||||||
|
RtlZeroMemory(AdapterContext, sizeof(*AdapterContext));
|
||||||
|
KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE);
|
||||||
|
KeInitializeSpinLock(&AdapterContext->Spinlock);
|
||||||
|
InitializeListHead(&AdapterContext->PacketList);
|
||||||
|
InitializeListHead(&AdapterContext->OpenEntryList);
|
||||||
|
AdapterContext->OpenCount = 1;
|
||||||
|
|
||||||
|
/* Send the open request */
|
||||||
|
NdisOpenAdapter(&Status,
|
||||||
|
&OpenErrorStatus,
|
||||||
|
&AdapterContext->BindingHandle,
|
||||||
|
&SelectedMedium,
|
||||||
|
SupportedMedia,
|
||||||
|
sizeof(SupportedMedia),
|
||||||
|
GlobalProtocolHandle,
|
||||||
|
AdapterContext,
|
||||||
|
DeviceName,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Wait for a pending open */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the final status */
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open adapter for bind with status 0x%x\n", *Status);
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the adapter context to the global list */
|
||||||
|
ExInterlockedInsertTailList(&GlobalAdapterList,
|
||||||
|
&AdapterContext->ListEntry,
|
||||||
|
&GlobalAdapterListLock);
|
||||||
|
|
||||||
|
/* Return the context */
|
||||||
|
*Context = AdapterContext;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduBindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE BindContext,
|
||||||
|
PNDIS_STRING DeviceName,
|
||||||
|
PVOID SystemSpecific1,
|
||||||
|
PVOID SystemSpecific2)
|
||||||
|
{
|
||||||
|
/* We don't bind like this */
|
||||||
|
*Status = NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduUnbindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE UnbindContext)
|
||||||
|
{
|
||||||
|
/* This is forced unbind. UnbindAdapterByContext() will take care of
|
||||||
|
* invalidating file handles pointer to this adapter for us */
|
||||||
|
*Status = UnbindAdapterByContext(ProtocolBindingContext);
|
||||||
|
}
|
||||||
|
|
40
drivers/network/ndisuio/readwrite.c
Normal file
40
drivers/network/ndisuio/readwrite.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: readwrite.c
|
||||||
|
* PURPOSE: Handles IRP_MJ_READ and IRP_MJ_WRITE
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduDispatchRead(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* FIXME: Not implemented */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduDispatchWrite(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* FIXME: Not implemented */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
Loading…
Reference in a new issue