mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 04:35:07 +00:00
248 lines
7.4 KiB
C
248 lines
7.4 KiB
C
![]() |
/*
|
||
|
* 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;
|
||
|
}
|
||
|
}
|