2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/device.c
5 * PURPOSE: KS IKsDevice interface functions
6 * PROGRAMMER: Johannes Anderwald
14 IKsDevice_fnQueryInterface(
19 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
21 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
23 *Output
= &This
->lpVtblIKsDevice
;
24 _InterlockedIncrement(&This
->ref
);
25 return STATUS_SUCCESS
;
28 return STATUS_NOT_SUPPORTED
;
36 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
38 return InterlockedIncrement(&This
->ref
);
46 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
48 InterlockedDecrement(&This
->ref
);
57 IKsDevice_fnGetStruct(
60 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
62 return &This
->KsDevice
;
67 IKsDevice_fnInitializeObjectBag(
69 IN PKSIOBJECT_BAG Bag
,
72 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
76 /* use device mutex */
77 Mutex
= &This
->DeviceMutex
;
80 /* initialize object bag */
81 Bag
->BagMutex
= Mutex
;
82 Bag
->DeviceHeader
= (PKSIDEVICE_HEADER
)This
;
83 InitializeListHead(&Bag
->ObjectList
);
85 /* insert bag into device list */
86 InsertTailList(&This
->ObjectBags
, &Bag
->Entry
);
88 return STATUS_SUCCESS
;
93 IKsDevice_fnAcquireDevice(
96 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
98 return KeWaitForSingleObject(&This
->DeviceMutex
, Executive
, KernelMode
, FALSE
, NULL
);
103 IKsDevice_fnReleaseDevice(
104 IN IKsDevice
* iface
)
106 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
108 return KeReleaseMutex(&This
->DeviceMutex
, FALSE
);
113 IKsDevice_fnGetAdapterObject(
114 IN IKsDevice
* iface
,
115 IN PADAPTER_OBJECT Object
,
119 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
122 return STATUS_NOT_IMPLEMENTED
;
128 IKsDevice_fnAddPowerEntry(
129 IN IKsDevice
* iface
,
130 IN
struct KSPOWER_ENTRY
* Entry
,
131 IN IKsPowerNotify
* Notify
)
133 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
136 return STATUS_NOT_IMPLEMENTED
;
141 IKsDevice_fnRemovePowerEntry(
142 IN IKsDevice
* iface
,
143 IN
struct KSPOWER_ENTRY
* Entry
)
145 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
148 return STATUS_NOT_IMPLEMENTED
;
154 IKsDevice_fnPinStateChange(
155 IN IKsDevice
* iface
,
161 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
164 return STATUS_NOT_IMPLEMENTED
;
170 IKsDevice_fnArbitrateAdapterChannel(
171 IN IKsDevice
* iface
,
172 IN ULONG ControlCode
,
173 IN IO_ALLOCATION_ACTION Action
,
176 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
179 return STATUS_NOT_IMPLEMENTED
;
185 IKsDevice_fnCheckIoCapability(
186 IN IKsDevice
* iface
,
189 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
192 return STATUS_NOT_IMPLEMENTED
;
195 static IKsDeviceVtbl vt_IKsDevice
=
197 IKsDevice_fnQueryInterface
,
200 IKsDevice_fnGetStruct
,
201 IKsDevice_fnInitializeObjectBag
,
202 IKsDevice_fnAcquireDevice
,
203 IKsDevice_fnReleaseDevice
,
204 IKsDevice_fnGetAdapterObject
,
205 IKsDevice_fnAddPowerEntry
,
206 IKsDevice_fnRemovePowerEntry
,
207 IKsDevice_fnPinStateChange
,
208 IKsDevice_fnArbitrateAdapterChannel
,
209 IKsDevice_fnCheckIoCapability
215 IKsDevice_PnpPostStart(
216 IN PDEVICE_OBJECT DeviceObject
,
220 PPNP_POSTSTART_CONTEXT Ctx
= (PPNP_POSTSTART_CONTEXT
)Context
;
222 /* call driver pnp post routine */
223 Status
= Ctx
->DeviceHeader
->Descriptor
->Dispatch
->PostStart(&Ctx
->DeviceHeader
->KsDevice
);
225 if (!NT_SUCCESS(Status
))
227 DPRINT1("Driver: PostStart Routine returned %x\n", Status
);
229 /* set state to disabled */
230 Ctx
->DeviceHeader
->TargetState
= KSTARGET_STATE_DISABLED
;
234 /* set state to enabled */
235 Ctx
->DeviceHeader
->TargetState
= KSTARGET_STATE_ENABLED
;
239 IoFreeWorkItem(Ctx
->WorkItem
);
241 /* free work context */
247 IKsDevice_PnpStartDevice(
248 IN PDEVICE_OBJECT DeviceObject
,
251 PIO_STACK_LOCATION IoStack
;
252 PDEVICE_EXTENSION DeviceExtension
;
253 PKSIDEVICE_HEADER DeviceHeader
;
254 PPNP_POSTSTART_CONTEXT Ctx
= NULL
;
257 /* get current stack location */
258 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
259 /* get device extension */
260 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
261 /* get device header */
262 DeviceHeader
= DeviceExtension
->DeviceHeader
;
264 /* first forward irp to lower device object */
265 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
267 /* check for success */
268 if (!NT_SUCCESS(Status
))
270 DPRINT1("NextDevice object failed to start with %x\n", Status
);
271 Irp
->IoStatus
.Status
= Status
;
272 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
276 /* do we have a device descriptor */
277 if (DeviceHeader
->Descriptor
)
279 /* does the device want pnp notifications */
280 if (DeviceHeader
->Descriptor
->Dispatch
)
282 /* does the driver care about IRP_MN_START_DEVICE */
283 if (DeviceHeader
->Descriptor
->Dispatch
->Start
)
285 /* call driver start device routine */
286 Status
= DeviceHeader
->Descriptor
->Dispatch
->Start(&DeviceHeader
->KsDevice
, Irp
,
287 IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
288 IoStack
->Parameters
.StartDevice
.AllocatedResources
);
290 ASSERT(Status
!= STATUS_PENDING
);
292 if (!NT_SUCCESS(Status
))
294 DPRINT1("Driver: failed to start %x\n", Status
);
295 Irp
->IoStatus
.Status
= Status
;
296 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
300 /* set state to run */
301 DeviceHeader
->KsDevice
.Started
= TRUE
;
305 /* does the driver need post start routine */
306 if (DeviceHeader
->Descriptor
->Dispatch
->PostStart
)
308 /* allocate pnp post workitem context */
309 Ctx
= (PPNP_POSTSTART_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(PNP_POSTSTART_CONTEXT
));
313 Status
= STATUS_INSUFFICIENT_RESOURCES
;
317 /* allocate a work item */
318 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
325 Status
= STATUS_INSUFFICIENT_RESOURCES
;
329 /* store device header for post-start pnp processing */
330 Ctx
->DeviceHeader
= DeviceHeader
;
336 /* set state to enabled, IRP_MJ_CREATE request may now succeed */
337 DeviceHeader
->TargetState
= KSTARGET_STATE_ENABLED
;
343 Irp
->IoStatus
.Status
= Status
;
344 /* complete request */
345 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
349 /* queue a work item for driver post start routine */
350 IoQueueWorkItem(Ctx
->WorkItem
, IKsDevice_PnpPostStart
, DelayedWorkQueue
, (PVOID
)Ctx
);
360 IN PDEVICE_OBJECT DeviceObject
,
363 PIO_STACK_LOCATION IoStack
;
364 PDEVICE_EXTENSION DeviceExtension
;
365 PKSIDEVICE_HEADER DeviceHeader
;
366 PKSDEVICE_DISPATCH Dispatch
= NULL
;
369 /* get current stack location */
370 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
372 /* get device extension */
373 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
374 /* get device header */
375 DeviceHeader
= DeviceExtension
->DeviceHeader
;
377 /* do we have a device descriptor */
378 if (DeviceHeader
->Descriptor
)
380 /* does the device want pnp notifications */
381 Dispatch
= (PKSDEVICE_DISPATCH
)DeviceHeader
->Descriptor
->Dispatch
;
384 switch (IoStack
->MinorFunction
)
386 case IRP_MN_START_DEVICE
:
388 return IKsDevice_PnpStartDevice(DeviceObject
, Irp
);
391 case IRP_MN_QUERY_STOP_DEVICE
:
393 Status
= STATUS_SUCCESS
;
394 /* check for pnp notification support */
397 /* check for query stop support */
398 if (Dispatch
->QueryStop
)
400 /* call driver's query stop */
401 Status
= Dispatch
->QueryStop(&DeviceHeader
->KsDevice
, Irp
);
402 ASSERT(Status
!= STATUS_PENDING
);
406 if (!NT_SUCCESS(Status
))
408 DPRINT1("Driver: query stop failed %x\n", Status
);
409 Irp
->IoStatus
.Status
= Status
;
410 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
414 /* pass the irp down the driver stack */
415 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
417 DPRINT("Next Device: Status %x\n", Status
);
419 Irp
->IoStatus
.Status
= Status
;
420 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
424 case IRP_MN_REMOVE_DEVICE
:
429 /* check for remove support */
430 if (Dispatch
->Remove
)
432 /* call driver's stop routine */
433 Dispatch
->Remove(&DeviceHeader
->KsDevice
, Irp
);
437 /* pass the irp down the driver stack */
438 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
440 DPRINT("Next Device: Status %x\n", Status
);
442 /* FIXME delete device resources */
445 Irp
->IoStatus
.Status
= Status
;
446 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
449 case IRP_MN_QUERY_INTERFACE
:
451 Status
= STATUS_SUCCESS
;
452 /* check for pnp notification support */
455 /* check for query interface support */
456 if (Dispatch
->QueryInterface
)
458 /* call driver's query interface */
459 Status
= Dispatch
->QueryInterface(&DeviceHeader
->KsDevice
, Irp
);
460 ASSERT(Status
!= STATUS_PENDING
);
464 if (NT_SUCCESS(Status
))
466 /* driver supports a private interface */
467 Irp
->IoStatus
.Status
= Status
;
468 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
472 /* pass the irp down the driver stack */
473 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
475 DPRINT("Next Device: Status %x\n", Status
);
477 Irp
->IoStatus
.Status
= Status
;
478 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
481 case IRP_MN_QUERY_DEVICE_RELATIONS
:
483 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
485 /* pass the irp down the driver stack */
486 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
488 DPRINT("Next Device: Status %x\n", Status
);
490 Irp
->IoStatus
.Status
= Status
;
491 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
494 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
496 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
497 /* pass the irp down the driver stack */
498 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
500 DPRINT("Next Device: Status %x\n", Status
);
502 Irp
->IoStatus
.Status
= Status
;
503 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
506 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
508 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
509 /* pass the irp down the driver stack */
510 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
512 DPRINT("Next Device: Status %x\n", Status
);
514 Irp
->IoStatus
.Status
= Status
;
515 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
519 DPRINT1("unhandled function %u\n", IoStack
->MinorFunction
);
520 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
521 return STATUS_NOT_SUPPORTED
;
528 IN PDEVICE_OBJECT DeviceObject
,
535 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
536 Irp
->IoStatus
.Information
= 0;
537 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
539 return STATUS_SUCCESS
;
545 IN PDEVICE_OBJECT DeviceObject
,
548 PCREATE_ITEM_ENTRY CreateItemEntry
;
549 PIO_STACK_LOCATION IoStack
;
550 PDEVICE_EXTENSION DeviceExtension
;
551 PKSIDEVICE_HEADER DeviceHeader
;
552 PKSIOBJECT_HEADER ObjectHeader
;
555 DPRINT("KS / CREATE\n");
556 /* get current stack location */
557 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
558 /* get device extension */
559 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
560 /* get device header */
561 DeviceHeader
= DeviceExtension
->DeviceHeader
;
563 /* acquire list lock */
564 IKsDevice_fnAcquireDevice((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
567 ASSERT(IoStack
->FileObject
);
569 /* check if the request is relative */
570 if (IoStack
->FileObject
->RelatedFileObject
!= NULL
)
572 /* request is to instantiate a pin / node / clock / allocator */
573 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->RelatedFileObject
->FsContext2
;
576 ASSERT(ObjectHeader
);
578 /* find a matching a create item */
579 Status
= FindMatchingCreateItem(&ObjectHeader
->ItemList
, IoStack
->FileObject
->FileName
.Length
, IoStack
->FileObject
->FileName
.Buffer
, &CreateItemEntry
);
583 /* request to create a filter */
584 Status
= FindMatchingCreateItem(&DeviceHeader
->ItemList
, IoStack
->FileObject
->FileName
.Length
, IoStack
->FileObject
->FileName
.Buffer
, &CreateItemEntry
);
587 if (NT_SUCCESS(Status
))
589 /* set object create item */
590 KSCREATE_ITEM_IRP_STORAGE(Irp
) = CreateItemEntry
->CreateItem
;
592 /* call create function */
593 Status
= CreateItemEntry
->CreateItem
->Create(DeviceObject
, Irp
);
595 if (NT_SUCCESS(Status
))
597 /* increment create item reference count */
598 InterlockedIncrement(&CreateItemEntry
->ReferenceCount
);
602 /* acquire list lock */
603 IKsDevice_fnReleaseDevice((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
605 if (Status
!= STATUS_PENDING
)
607 Irp
->IoStatus
.Information
= 0;
608 /* set return status */
609 Irp
->IoStatus
.Status
= Status
;
610 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
625 IN PDEVICE_OBJECT FunctionalDeviceObject
,
626 IN PDEVICE_OBJECT PhysicalDeviceObject
,
627 IN PDEVICE_OBJECT NextDeviceObject
,
628 IN
const KSDEVICE_DESCRIPTOR
* Descriptor OPTIONAL
)
630 PDEVICE_EXTENSION DeviceExtension
;
631 PKSIDEVICE_HEADER Header
;
633 IKsDevice
* KsDevice
;
634 NTSTATUS Status
= STATUS_SUCCESS
;
636 /* get device extension */
637 DeviceExtension
= (PDEVICE_EXTENSION
)FunctionalDeviceObject
->DeviceExtension
;
639 /* first allocate device header */
640 Status
= KsAllocateDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
, 0, NULL
);
642 /* point to allocated header */
643 Header
= DeviceExtension
->DeviceHeader
;
645 /* check for success */
646 if (!NT_SUCCESS(Status
))
648 DPRINT1("Failed to allocate device header with %x\n", Status
);
652 /* initialize IKsDevice interface */
653 Header
->lpVtblIKsDevice
= &vt_IKsDevice
;
656 /* initialize object bag */
657 Header
->KsDevice
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
658 if (!Header
->KsDevice
.Bag
)
661 KsFreeDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
);
662 return STATUS_INSUFFICIENT_RESOURCES
;
665 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->lpVtblIKsDevice
;
666 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, Header
->KsDevice
.Bag
, NULL
);
669 /* initialize device header */
670 Header
->KsDevice
.FunctionalDeviceObject
= FunctionalDeviceObject
;
671 Header
->KsDevice
.PhysicalDeviceObject
= PhysicalDeviceObject
;
672 Header
->KsDevice
.NextDeviceObject
= NextDeviceObject
;
673 Header
->KsDevice
.Descriptor
= Descriptor
;
674 KsSetDevicePnpAndBaseObject(Header
, PhysicalDeviceObject
, NextDeviceObject
);
676 /* FIXME Power state */
680 /* create a filter factory for each filter descriptor */
681 for(Index
= 0; Index
< Descriptor
->FilterDescriptorsCount
; Index
++)
683 Status
= KspCreateFilterFactory(FunctionalDeviceObject
, Descriptor
->FilterDescriptors
[Index
], NULL
, NULL
, 0, NULL
, NULL
, NULL
);
684 /* check for success */
685 if (!NT_SUCCESS(Status
))
687 DPRINT1("KspCreateFilterFactory failed with %x\n", Status
);
688 /* FIXME memory leak */
693 /* does the driver pnp notification */
694 if (Descriptor
->Dispatch
)
696 /* does the driver care about the add device */
697 Status
= Descriptor
->Dispatch
->Add(&Header
->KsDevice
);
699 DPRINT("Driver: AddHandler Status %x\n", Status
);
713 KsReferenceSoftwareBusObject(
714 IN KSDEVICE_HEADER Header
)
717 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
719 /* get device interface */
720 Device
= (IKsDevice
*)DeviceHeader
->lpVtblIKsDevice
;
724 /* reference device interface */
725 Device
->lpVtbl
->AddRef(Device
);
728 return STATUS_SUCCESS
;
737 KsReferenceBusObject(
738 IN KSDEVICE_HEADER Header
)
741 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
743 /* get device interface */
744 Device
= (IKsDevice
*)DeviceHeader
->lpVtblIKsDevice
;
748 /* reference device interface */
749 Device
->lpVtbl
->AddRef(Device
);
752 return STATUS_SUCCESS
;
762 KsDereferenceBusObject(
763 IN KSDEVICE_HEADER Header
)
766 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
768 /* get device interface */
769 Device
= (IKsDevice
*)DeviceHeader
->lpVtblIKsDevice
;
773 /* release device interface */
774 Device
->lpVtbl
->Release(Device
);
784 KsDereferenceSoftwareBusObject(
785 IN KSDEVICE_HEADER Header
)
788 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
790 DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header
);
792 /* get device interface */
793 Device
= (IKsDevice
*)DeviceHeader
->lpVtblIKsDevice
;
797 /* release device interface */
798 Device
->lpVtbl
->Release(Device
);