[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:
Cameron Gutman 2012-01-02 21:38:57 +00:00
parent 2b82fe44ea
commit 80c1df8be2
10 changed files with 926 additions and 0 deletions

View 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)

View 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;
}

View 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;
}
}

View 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;
}

View 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);
}
}

View 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 */

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

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

View 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);
}

View 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;
}