mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +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