-#include "priv.h"
-
-typedef struct
-{
- IKsDeviceVtbl *lpVtbl;
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel Streaming
+ * FILE: drivers/ksfilter/ks/device.c
+ * PURPOSE: KS IKsDevice interface functions
+ * PROGRAMMER: Johannes Anderwald
+ */
- LONG ref;
- KSDEVICE KsDevice;
-
-}IKsDeviceImpl;
+#include "priv.h"
NTSTATUS
NTAPI
IKsDevice_fnQueryInterface(
IN IKsDevice * iface,
- REFIID InterfaceId,
- PVOID* Interface)
+ REFIID refiid,
+ PVOID* Output)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ NTSTATUS Status;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnQueryInterface %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
+ {
+ *Output = &This->BasicHeader.OuterUnknown;
+ _InterlockedIncrement(&This->ref);
+ return STATUS_SUCCESS;
+ }
+
+ if (This->BasicHeader.ClientAggregate)
+ {
+ /* using client aggregate */
+ Status = This->BasicHeader.ClientAggregate->lpVtbl->QueryInterface(This->BasicHeader.ClientAggregate, refiid, Output);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* client aggregate supports interface */
+ return Status;
+ }
+ }
+
+ DPRINT("IKsDevice_fnQueryInterface no interface\n");
+ return STATUS_NOT_SUPPORTED;
}
ULONG
IKsDevice_fnAddRef(
IN IKsDevice * iface)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
return InterlockedIncrement(&This->ref);
}
IKsDevice_fnRelease(
IN IKsDevice * iface)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
InterlockedDecrement(&This->ref);
- if (This->ref == 0)
- {
- ExFreePoolWithTag(This, TAG_KSDEVICE);
- return 0;
- }
-
return This->ref;
}
-KSDEVICE *
+PKSDEVICE
NTAPI
IKsDevice_fnGetStruct(
IN IKsDevice * iface)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
return &This->KsDevice;
}
NTAPI
IKsDevice_fnInitializeObjectBag(
IN IKsDevice * iface,
- IN struct KSIOBJECTBAG *Bag,
- IN KMUTANT * Mutant)
+ IN PKSIOBJECT_BAG Bag,
+ IN PRKMUTEX Mutex)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnInitializeObjectBag %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ if (!Mutex)
+ {
+ /* use device mutex */
+ Mutex = &This->BagMutex;
+ }
+
+ /* initialize object bag */
+ Bag->BagMutex = Mutex;
+ Bag->DeviceHeader = (PKSIDEVICE_HEADER)This;
+ InitializeListHead(&Bag->ObjectList);
+
+ /* insert bag into device list */
+ InsertTailList(&This->ObjectBags, &Bag->Entry);
+
+ return STATUS_SUCCESS;
}
NTSTATUS
IKsDevice_fnAcquireDevice(
IN IKsDevice * iface)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnAcquireDevice %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ return KeWaitForSingleObject(&This->DeviceMutex, Executive, KernelMode, FALSE, NULL);
}
NTSTATUS
IKsDevice_fnReleaseDevice(
IN IKsDevice * iface)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnReleaseDevice %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ return KeReleaseMutex(&This->DeviceMutex, FALSE);
}
NTSTATUS
NTAPI
IKsDevice_fnGetAdapterObject(
IN IKsDevice * iface,
- IN PADAPTER_OBJECT Object,
- IN PULONG Unknown1,
- IN PULONG Unknown2)
+ IN PADAPTER_OBJECT * Object,
+ IN PULONG MaxMappingsByteCount,
+ IN PULONG MappingTableStride)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnGetAdapterObject %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ *Object = This->AdapterObject;
+ *MaxMappingsByteCount = This->MaxMappingsByteCount;
+ *MappingTableStride = This->MappingTableStride;
+
+ return STATUS_SUCCESS;
}
IN struct KSPOWER_ENTRY * Entry,
IN IKsPowerNotify* Notify)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnAddPowerEntry %p\n", This);
+ UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
IN IKsDevice * iface,
IN struct KSPOWER_ENTRY * Entry)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnRemovePowerEntry %p\n", This);
+ UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
IN KSSTATE OldState,
IN KSSTATE NewState)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnPinStateChange %p\n", This);
+ UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
NTAPI
IKsDevice_fnArbitrateAdapterChannel(
IN IKsDevice * iface,
- IN ULONG ControlCode,
- IN IO_ALLOCATION_ACTION Action,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine,
IN PVOID Context)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
+ NTSTATUS Status;
- DPRINT1("IKsDevice_fnArbitrateAdapterChannel %p\n", This);
- return STATUS_NOT_IMPLEMENTED;
+ DPRINT("IKsDevice_fnArbitrateAdapterChannel NumberOfMapRegisters %lu ExecutionRoutine %p Context %p Irql %lu\n", NumberOfMapRegisters, ExecutionRoutine, Context, KeGetCurrentIrql());
+
+ /* sanity check */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT(This->AdapterObject);
+
+ /* allocate adapter channel */
+ Status = IoAllocateAdapterChannel(This->AdapterObject, This->KsDevice.FunctionalDeviceObject, NumberOfMapRegisters, ExecutionRoutine, Context);
+ /* done */
+ return Status;
}
NTSTATUS
IN IKsDevice * iface,
IN ULONG Unknown)
{
- IKsDeviceImpl * This = (IKsDeviceImpl*)iface;
+ //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
- DPRINT1("IKsDevice_fnCheckIoCapability %p\n", This);
+ UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
};
+VOID
+NTAPI
+IKsDevice_PnpPostStart(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ NTSTATUS Status;
+ PPNP_POSTSTART_CONTEXT Ctx = (PPNP_POSTSTART_CONTEXT)Context;
+
+ /* call driver pnp post routine */
+ Status = Ctx->DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart(&Ctx->DeviceHeader->KsDevice);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* set state to disabled */
+ Ctx->DeviceHeader->TargetState = KSTARGET_STATE_DISABLED;
+ }
+ else
+ {
+ /* set state to enabled */
+ Ctx->DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
+ Status = KspSetFilterFactoriesState(Ctx->DeviceHeader, TRUE);
+ }
+
+ /* free work item */
+ IoFreeWorkItem(Ctx->WorkItem);
+
+ /* free work context */
+ FreeItem(Ctx);
+
+ DPRINT("IKsDevice_PnpPostStart: PostStart Routine returned %x\n", Status);
+}
+
+NTSTATUS
+NTAPI
+IKsDevice_PnpStartDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PDEVICE_EXTENSION DeviceExtension;
+ PKSIDEVICE_HEADER DeviceHeader;
+ PPNP_POSTSTART_CONTEXT Ctx = NULL;
+ NTSTATUS Status;
+ PCM_RESOURCE_LIST TranslatedResourceList;
+ PCM_RESOURCE_LIST UntranslatedResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
+ ULONG Index;
+
+ /* get current stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ /* get device extension */
+ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ /* get device header */
+ DeviceHeader = DeviceExtension->DeviceHeader;
+
+ DPRINT("IKsDevice_PnpStartDevice DeviceHeader %p\n", DeviceHeader);
+
+ /* first forward irp to lower device object */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NextDevice object failed to start with %x\n", Status);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
+ UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
+
+ DPRINT("ResourceDescriptorCount %lu\n", TranslatedResourceList->List[0].PartialResourceList.Count);
+ for (Index = 0; Index < TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
+ {
+ PartialDescriptor = &TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
+ UnPartialDescriptor = &UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
+ DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
+
+ if (PartialDescriptor->Type == CmResourceTypeInterrupt)
+ {
+ DPRINT("CmResourceTypeInterrupt Index %u TRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\n", Index, PartialDescriptor->u.Interrupt.Affinity, PartialDescriptor->u.Interrupt.Level, PartialDescriptor->u.Interrupt.Vector, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
+ DPRINT("CmResourceTypeInterrupt Index %u UNTRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\\n", Index, UnPartialDescriptor->u.Interrupt.Affinity, UnPartialDescriptor->u.Interrupt.Level, UnPartialDescriptor->u.Interrupt.Vector, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
+
+ }
+ else if (PartialDescriptor->Type == CmResourceTypePort)
+ {
+ DPRINT("CmResourceTypePort Index %u TRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, PartialDescriptor->u.Port.Length, PartialDescriptor->u.Port.Start.HighPart, PartialDescriptor->u.Port.Start.LowPart, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
+ DPRINT("CmResourceTypePort Index %u UNTRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Port.Length, UnPartialDescriptor->u.Port.Start.HighPart, UnPartialDescriptor->u.Port.Start.LowPart, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
+ }
+ else if (PartialDescriptor->Type == CmResourceTypeMemory)
+ {
+ DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, PartialDescriptor->u.Memory.Start.LowPart, PartialDescriptor->u.Memory.Length, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
+ DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Memory.Start.LowPart, UnPartialDescriptor->u.Memory.Length, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
+ }
+ }
+
+ ASSERT(DeviceHeader->KsDevice.Descriptor);
+ ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch);
+ ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch->Start);
+
+
+ /* do we have a device descriptor */
+ if (DeviceHeader->KsDevice.Descriptor)
+ {
+ /* does the device want pnp notifications */
+ if (DeviceHeader->KsDevice.Descriptor->Dispatch)
+ {
+ /* does the driver care about IRP_MN_START_DEVICE */
+ if (DeviceHeader->KsDevice.Descriptor->Dispatch->Start)
+ {
+ /* call driver start device routine */
+ Status = DeviceHeader->KsDevice.Descriptor->Dispatch->Start(&DeviceHeader->KsDevice, Irp,
+ TranslatedResourceList,
+ UntranslatedResourceList);
+
+
+ DPRINT("IKsDevice_PnpStartDevice Start %p, Context %p\n", DeviceHeader->KsDevice.Descriptor->Dispatch->Start, DeviceHeader->KsDevice.Context);
+ ASSERT(Status != STATUS_PENDING);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Driver: failed to start %x\n", Status);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* set state to run */
+ DeviceHeader->KsDevice.Started = TRUE;
+
+ }
+
+ /* does the driver need post start routine */
+ if (DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart)
+ {
+ /* allocate pnp post workitem context */
+ Ctx = (PPNP_POSTSTART_CONTEXT)AllocateItem(NonPagedPool, sizeof(PNP_POSTSTART_CONTEXT));
+ if (!Ctx)
+ {
+ /* no memory */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ /* allocate a work item */
+ Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
+
+ if (!Ctx->WorkItem)
+ {
+ /* no memory */
+ FreeItem(Ctx);
+ Ctx = NULL;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ /* store device header for post-start pnp processing */
+ Ctx->DeviceHeader = DeviceHeader;
+ }
+ }
+ }
+ else
+ {
+ /* set state to enabled, IRP_MJ_CREATE request may now succeed */
+ DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
+ Status = KspSetFilterFactoriesState(DeviceHeader, TRUE);
+ }
+ }
+ }
+
+ /* store result */
+ Irp->IoStatus.Status = Status;
+ /* complete request */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ if (Ctx)
+ {
+ /* queue a work item for driver post start routine */
+ IoQueueWorkItem(Ctx->WorkItem, IKsDevice_PnpPostStart, DelayedWorkQueue, (PVOID)Ctx);
+ }
+
+ /* return result */
+ DPRINT1("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsDevice_Pnp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ PDEVICE_EXTENSION DeviceExtension;
+ PKSIDEVICE_HEADER DeviceHeader;
+ PKSDEVICE_DISPATCH Dispatch = NULL;
+ NTSTATUS Status;
+
+ /* get current stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* get device extension */
+ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ /* get device header */
+ DeviceHeader = DeviceExtension->DeviceHeader;
+
+ /* do we have a device descriptor */
+ if (DeviceHeader->KsDevice.Descriptor && DeviceHeader->KsDevice.Descriptor->Dispatch)
+ {
+ /* does the device want pnp notifications */
+ Dispatch = (PKSDEVICE_DISPATCH)DeviceHeader->KsDevice.Descriptor->Dispatch;
+ }
+
+ switch (IoStack->MinorFunction)
+ {
+ case IRP_MN_START_DEVICE:
+ {
+ return IKsDevice_PnpStartDevice(DeviceObject, Irp);
+ }
+
+ case IRP_MN_QUERY_STOP_DEVICE:
+ {
+ Status = STATUS_SUCCESS;
+ /* check for pnp notification support */
+ if (Dispatch)
+ {
+ /* check for query stop support */
+ if (Dispatch->QueryStop)
+ {
+ /* call driver's query stop */
+ Status = Dispatch->QueryStop(&DeviceHeader->KsDevice, Irp);
+ ASSERT(Status != STATUS_PENDING);
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Driver: query stop failed %x\n", Status);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ DPRINT("Next Device: Status %x\n", Status);
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ case IRP_MN_REMOVE_DEVICE:
+ {
+ /* Clean up */
+ if (Dispatch)
+ {
+ /* check for remove support */
+ if (Dispatch->Remove)
+ {
+ /* call driver's stop routine */
+ Dispatch->Remove(&DeviceHeader->KsDevice, Irp);
+ }
+ }
+
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ DPRINT("Next Device: Status %x\n", Status);
+
+ /* FIXME delete device resources */
+
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ case IRP_MN_QUERY_INTERFACE:
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ /* check for pnp notification support */
+ if (Dispatch)
+ {
+ /* check for query interface support */
+ if (Dispatch->QueryInterface)
+ {
+ /* call driver's query interface */
+ Status = Dispatch->QueryInterface(&DeviceHeader->KsDevice, Irp);
+ ASSERT(Status != STATUS_PENDING);
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ /* driver supports a private interface */
+ DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n");
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ case IRP_MN_QUERY_DEVICE_RELATIONS:
+ {
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status);
+
+ //Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+ {
+ /* pass the irp down the driver stack */
+ //Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+ Status = Irp->IoStatus.Status;
+ DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
+
+ //Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+ {
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+ default:
+ DPRINT1("unhandled function %u\n", IoStack->MinorFunction);
+ /* pass the irp down the driver stack */
+ Status = KspForwardIrpSynchronous(DeviceObject, Irp);
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+ }
+}
+
+NTSTATUS
+NTAPI
+IKsDevice_Power(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ UNIMPLEMENTED
+
+ /* TODO */
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+IKsDevice_Create(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PCREATE_ITEM_ENTRY CreateItemEntry;
+ PIO_STACK_LOCATION IoStack;
+ PDEVICE_EXTENSION DeviceExtension;
+ PKSIDEVICE_HEADER DeviceHeader;
+ PKSIOBJECT_HEADER ObjectHeader;
+ NTSTATUS Status;
+
+ DPRINT("IKsDevice_Create\n");
+ /* get current stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ /* get device extension */
+ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ /* get device header */
+ DeviceHeader = DeviceExtension->DeviceHeader;
+
+ /* acquire list lock */
+ IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
+
+ /* sanity check */
+ ASSERT(IoStack->FileObject);
+
+ /* check if the request is relative */
+ if (IoStack->FileObject->RelatedFileObject != NULL)
+ {
+ /* request is to instantiate a pin / node / clock / allocator */
+ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
+
+ /* sanity check */
+ ASSERT(ObjectHeader);
+
+ /* find a matching a create item */
+ Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
+ }
+ else
+ {
+ /* request to create a filter */
+ Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ /* set object create item */
+ KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
+
+ /* call create function */
+ Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* increment create item reference count */
+ InterlockedIncrement(&CreateItemEntry->ReferenceCount);
+ }
+ }
+
+ /* acquire list lock */
+ IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
+
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Information = 0;
+ /* set return status */
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ return Status;
+
+
+}
+
+/*
+ @implemented
+*/
+KSDDKAPI
NTSTATUS
NTAPI
-NewIKsDevice(IKsDevice** OutDevice)
+KsInitializeDevice(
+ IN PDEVICE_OBJECT FunctionalDeviceObject,
+ IN PDEVICE_OBJECT PhysicalDeviceObject,
+ IN PDEVICE_OBJECT NextDeviceObject,
+ IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
{
- IKsDeviceImpl * This;
+ PDEVICE_EXTENSION DeviceExtension;
+ PKSIDEVICE_HEADER Header;
+ ULONG Index;
+ PKSIOBJECT_BAG Bag;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("KsInitializeDevice Descriptor %p\n", Descriptor);
+
+ /* get device extension */
+ DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
+
+ /* first allocate device header */
+ Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 0, NULL);
+
+ /* point to allocated header */
+ Header = DeviceExtension->DeviceHeader;
- This = ExAllocatePoolWithTag(NonPagedPool, sizeof(IKsDeviceImpl), TAG_KSDEVICE);
- if (!This)
- return STATUS_INSUFFICIENT_RESOURCES;
+ DPRINT("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
+
+ if (Descriptor && Descriptor->Dispatch)
+ {
+ DPRINT("Descriptor Add %p\n", Descriptor->Dispatch->Add);
+ DPRINT("Descriptor Start %p\n", Descriptor->Dispatch->Start);
+ DPRINT("Descriptor PostStart %p\n", Descriptor->Dispatch->PostStart);
+ DPRINT("Descriptor QueryStop %p\n", Descriptor->Dispatch->QueryStop);
+ DPRINT("Descriptor CancelStop %p\n", Descriptor->Dispatch->CancelStop);
+ DPRINT("Descriptor Stop %p\n", Descriptor->Dispatch->Stop);
+ DPRINT("Descriptor QueryRemove %p\n", Descriptor->Dispatch->QueryRemove);
+ DPRINT("Descriptor CancelRemove %p\n", Descriptor->Dispatch->CancelRemove);
+ DPRINT("Descriptor Remove %p\n", Descriptor->Dispatch->Remove);
+ DPRINT("Descriptor QueryCapabilities %p\n", Descriptor->Dispatch->QueryCapabilities);
+ DPRINT("Descriptor SurpriseRemoval %p\n", Descriptor->Dispatch->SurpriseRemoval);
+ DPRINT("Descriptor QueryPower %p\n", Descriptor->Dispatch->QueryPower);
+ DPRINT("Descriptor SetPower %p\n", Descriptor->Dispatch->SetPower);
+ DPRINT("Descriptor QueryInterface %p\n", Descriptor->Dispatch->QueryInterface);
+ }
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KsInitializeDevice Failed to allocate device header with %x\n", Status);
+ return Status;
+ }
+
+ /* initialize IKsDevice interface */
+ Header->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsDevice;
+ Header->ref = 1;
+
+ /* allocate object bag */
+ Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
+ if (!Header->KsDevice.Bag)
+ {
+ /* no memory */
+ KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- This->ref = 1;
- This->lpVtbl = &vt_IKsDevice;
+ /* initialize object bag */
+ KeInitializeMutex(&Header->BagMutex, 0);
+ KeInitializeMutex(&Header->DeviceMutex, 0);
+
+ Bag = (PKSIOBJECT_BAG)Header->KsDevice.Bag;
+ Bag->BagMutex = &Header->BagMutex;
+ InitializeListHead(&Header->ObjectBags);
+ InitializeListHead(&Bag->ObjectList);
+ Bag->DeviceHeader = (PVOID)Header;
+
+ /* insert bag into device list */
+ InsertTailList(&Header->ObjectBags, &Bag->Entry);
+
+ /* initialize device header */
+ Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
+ Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
+ Header->KsDevice.NextDeviceObject = NextDeviceObject;
+ Header->KsDevice.Descriptor = Descriptor;
+ Header->KsDevice.SystemPowerState = PowerSystemWorking;
+ Header->KsDevice.DevicePowerState = PowerDeviceD0;
+ Header->KsDevice.Started = FALSE;
+ Header->KsDevice.Context = NULL;
+ KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
+
+
+
+ if (Descriptor)
+ {
+ /* create a filter factory for each filter descriptor */
+ DPRINT("KsInitializeDevice FilterDescriptorCount %lu\n", Descriptor->FilterDescriptorsCount);
+ for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
+ {
+ Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
+
+ DPRINT("KsInitializeDevice Index %lu KspCreateFilterFactory Status %lx\n", Index, Status);
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
+ /* FIXME memory leak */
+ return Status;
+ }
+ }
+
+ /* does the driver pnp notification */
+ if (Descriptor->Dispatch)
+ {
+ /* does the driver care about the add device */
+ Status = Descriptor->Dispatch->Add(&Header->KsDevice);
+
+ DPRINT("Driver: AddHandler Status %x\n", Status);
+ Header->KsDevice.Descriptor = Descriptor;
+ }
+ }
+
+
+ return Status;
+}
+
+/*
+ @implemented
+*/
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsReferenceSoftwareBusObject(
+ IN KSDEVICE_HEADER Header)
+{
+ IKsDevice * Device;
+ PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
+
+ /* get device interface */
+ Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
+
+ if (Device)
+ {
+ /* reference device interface */
+ Device->lpVtbl->AddRef(Device);
+ }
- *OutDevice = (IKsDevice*)This;
return STATUS_SUCCESS;
}
+/*
+ @implemented
+*/
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsReferenceBusObject(
+ IN KSDEVICE_HEADER Header)
+{
+ IKsDevice * Device;
+ PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
+
+ /* get device interface */
+ Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
+
+ if (Device)
+ {
+ /* reference device interface */
+ Device->lpVtbl->AddRef(Device);
+ }
+
+ return STATUS_SUCCESS;
+
+}
+
+/*
+ @implemented
+*/
+KSDDKAPI
+VOID
+NTAPI
+KsDereferenceBusObject(
+ IN KSDEVICE_HEADER Header)
+{
+ IKsDevice * Device;
+ PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
+
+ /* get device interface */
+ Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
+
+ if (Device)
+ {
+ /* release device interface */
+ Device->lpVtbl->Release(Device);
+ }
+}
+
+/*
+ @implemented
+*/
+KSDDKAPI
+VOID
+NTAPI
+KsDereferenceSoftwareBusObject(
+ IN KSDEVICE_HEADER Header)
+{
+ IKsDevice * Device;
+ PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
+
+ DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
+
+ /* get device interface */
+ Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
+
+ if (Device)
+ {
+ /* release device interface */
+ Device->lpVtbl->Release(Device);
+ }
+}