/* * 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 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; } }