Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / ksfilter / swenum / swenum.c
diff --git a/drivers/ksfilter/swenum/swenum.c b/drivers/ksfilter/swenum/swenum.c
new file mode 100644 (file)
index 0000000..6fa386c
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/ksfilter/swenum/swenum.c
+ * PURPOSE:         KS Allocator functions
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+
+#include "precomp.h"
+
+const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+
+NTSTATUS
+NTAPI
+SwDispatchPower(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    NTSTATUS Status, PnpStatus;
+    BOOLEAN ChildDevice;
+    PIO_STACK_LOCATION IoStack;
+    PDEVICE_OBJECT PnpDeviceObject = NULL;
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* check if the device object is a child device */
+    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
+
+    /* get bus enum pnp object */
+    PnpStatus = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(PnpStatus))
+    {
+        /* start next power irp */
+        PoStartNextPowerIrp(Irp);
+
+        /* just complete the irp */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+
+        /* complete the irp */
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        /* done */
+        return STATUS_SUCCESS;
+    }
+
+    if (IoStack->MinorFunction == IRP_MN_SET_POWER || IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+    {
+        /* fake success */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+    }
+
+    if (!ChildDevice)
+    {
+        /* forward to pnp device object */
+        PoStartNextPowerIrp(Irp);
+
+        /* skip current location */
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        /* done */
+        return PoCallDriver(PnpDeviceObject, Irp);
+    }
+
+    /* start next power irp */
+    PoStartNextPowerIrp(Irp);
+
+    /* just complete the irp */
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    /* complete the irp */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    /* done */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+SwDispatchPnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    NTSTATUS Status;
+    BOOLEAN ChildDevice;
+    PIO_STACK_LOCATION IoStack;
+    PDEVICE_OBJECT PnpDeviceObject = NULL;
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* check if the device object is a child device */
+    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return Status;
+    }
+
+    DPRINT("SwDispatchPnp ChildDevice %u Request %x\n", ChildDevice, IoStack->MinorFunction);
+
+    /* let ks handle it */
+    Status = KsServiceBusEnumPnpRequest(DeviceObject, Irp);
+
+    /* check if the request was for a pdo */
+    if (ChildDevice)
+    {
+        if (Status != STATUS_NOT_SUPPORTED)
+        {
+            /* store result */
+            Irp->IoStatus.Status = Status;
+        }
+
+        /* complete request */
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        /* done */
+        return Status;
+    }
+
+    DPRINT("SwDispatchPnp KsServiceBusEnumPnpRequest Status %x\n", Status);
+
+    if (NT_SUCCESS(Status))
+    {
+        /* invalid request or not supported */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return Status;
+    }
+
+    /* get bus enum pnp object */
+    Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
+
+    DPRINT("SwDispatchPnp KsGetBusEnumPnpDeviceObject Status %x\n", Status);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to get pnp object */
+        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    /* sanity check */
+    ASSERT(PnpDeviceObject);
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
+    {
+        /* delete the device */
+        IoDeleteDevice(DeviceObject);
+    }
+    else
+    {
+        if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES || IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
+        {
+            /* no resources required */
+            Irp->IoStatus.Information = 0;
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+
+            /* skip current location */
+            IoSkipCurrentIrpStackLocation(Irp);
+
+            /* call the pnp device object */
+            return IoCallDriver(PnpDeviceObject, Irp);
+        }
+
+        if (IoStack->MajorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
+        {
+            /* device cannot be disabled */
+            Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+
+            /* skip current location */
+            IoSkipCurrentIrpStackLocation(Irp);
+
+            /* call the pnp device object */
+            return IoCallDriver(PnpDeviceObject, Irp);
+        }
+
+        if (Status == STATUS_NOT_SUPPORTED)
+        {
+            /* skip current location */
+            IoSkipCurrentIrpStackLocation(Irp);
+
+            /* call the pnp device object */
+            return IoCallDriver(PnpDeviceObject, Irp);
+        }
+    }
+
+    /* complete the request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+SwDispatchSystemControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    NTSTATUS Status;
+    BOOLEAN ChildDevice;
+    PDEVICE_OBJECT PnpDeviceObject;
+
+    /* check if the device object is a child device */
+    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
+
+    /* check for success */
+    if (NT_SUCCESS(Status))
+    {
+        if (!ChildDevice)
+        {
+            /* bus devices dont support internal requests */
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+
+        /* get bus enum pnp object */
+        Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
+
+        /* check for success */
+        if (NT_SUCCESS(Status))
+        {
+            /* skip current location */
+            IoSkipCurrentIrpStackLocation(Irp);
+            /* call the pnp device object */
+            return IoCallDriver(PnpDeviceObject, Irp);
+        }
+
+    }
+
+    /* complete the request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+
+}
+
+NTSTATUS
+NTAPI
+SwDispatchDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_INSTALL_INTERFACE)
+    {
+        /* install interface */
+        Status = KsInstallBusEnumInterface(Irp);
+        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_INSTALL_INTERFACE %x\n", Status);
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_REMOVE_INTERFACE)
+    {
+        /* remove interface */
+        Status = KsRemoveBusEnumInterface(Irp);
+        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_REMOVE_INTERFACE %x\n", Status);
+
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_GET_BUS_ID)
+    {
+        /* get bus id */
+        Status = KsGetBusEnumIdentifier(Irp);
+        DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_GET_BUS_ID %x\n", Status);
+    }
+    else
+    {
+        DPRINT("SwDispatchDeviceControl Unknown IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+    /* store result */
+    Irp->IoStatus.Status = Status;
+
+    /* complete irp */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    /* done */
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SwDispatchCreate(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    NTSTATUS Status;
+    BOOLEAN ChildDevice;
+
+    /* check if the device object is a child device */
+    Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
+
+    DPRINT("SwDispatchCreate %x\n", Status);
+
+    /* check for success */
+    if (NT_SUCCESS(Status))
+    {
+        if (ChildDevice)
+        {
+            /* child devices cant create devices */
+            Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_OBJECT_NAME_NOT_FOUND;
+        }
+        /* perform the create request */
+        Status = KsServiceBusEnumCreateRequest(DeviceObject, Irp);
+        DPRINT("SwDispatchCreate %x\n", Status);
+    }
+
+    /* check the irp is pending */
+    if (Status != STATUS_PENDING)
+    {
+        /* irp is ok to complete */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+SwDispatchClose(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    /* just complete the irp */
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+
+    /* complete the irp */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    /* done */
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+NTAPI
+SwAddDevice(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    NTSTATUS Status;
+    PDEVICE_OBJECT FunctionalDeviceObject;
+
+    DPRINT("SWENUM AddDevice\n");
+    /* create the device */
+    Status = IoCreateDevice(DriverObject, sizeof(KSDEVICE_HEADER), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &FunctionalDeviceObject);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed */
+        return Status;
+    }
+
+    /* create the bus enum object */
+    Status = KsCreateBusEnumObject(L"SW", FunctionalDeviceObject, PhysicalDeviceObject, NULL, &KSMEDIUMSETID_Standard, L"Devices");
+
+    /* check for success */
+    if (NT_SUCCESS(Status))
+    {
+        /* set device flags */
+        FunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
+        FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
+    }
+    else
+    {
+        /* failed to create bus enum object */
+        IoDeleteDevice(FunctionalDeviceObject);
+    }
+
+    /* done */
+    return Status;
+}
+
+VOID
+NTAPI
+SwUnload(
+    IN  PDRIVER_OBJECT DriverObject)
+{
+    /* nop */
+}
+
+NTSTATUS
+NTAPI
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegistryPathName)
+{
+
+    /* setup add device routine */
+    DriverObject->DriverExtension->AddDevice = SwAddDevice;
+
+    /* setup unload routine */
+    DriverObject->DriverUnload = SwUnload;
+
+    /* misc irp handling routines */
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = SwDispatchCreate;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = SwDispatchClose;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = SwDispatchPnp;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = SwDispatchPower;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SwDispatchDeviceControl;
+    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SwDispatchSystemControl;
+
+    DPRINT("SWENUM loaded\n");
+    return STATUS_SUCCESS;
+}
+