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
struct KSIOBJECTBAG
*Bag
,
72 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
75 return STATUS_NOT_IMPLEMENTED
;
80 IKsDevice_fnAcquireDevice(
83 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
85 return KeWaitForSingleObject(&This
->DeviceMutex
, Executive
, KernelMode
, FALSE
, NULL
);
90 IKsDevice_fnReleaseDevice(
93 PKSIDEVICE_HEADER This
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(iface
, KSIDEVICE_HEADER
, lpVtblIKsDevice
);
95 return KeReleaseMutex(&This
->DeviceMutex
, FALSE
);
100 IKsDevice_fnGetAdapterObject(
101 IN IKsDevice
* iface
,
102 IN PADAPTER_OBJECT Object
,
106 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
109 return STATUS_NOT_IMPLEMENTED
;
115 IKsDevice_fnAddPowerEntry(
116 IN IKsDevice
* iface
,
117 IN
struct KSPOWER_ENTRY
* Entry
,
118 IN IKsPowerNotify
* Notify
)
120 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
123 return STATUS_NOT_IMPLEMENTED
;
128 IKsDevice_fnRemovePowerEntry(
129 IN IKsDevice
* iface
,
130 IN
struct KSPOWER_ENTRY
* Entry
)
132 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
135 return STATUS_NOT_IMPLEMENTED
;
141 IKsDevice_fnPinStateChange(
142 IN IKsDevice
* iface
,
148 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
151 return STATUS_NOT_IMPLEMENTED
;
157 IKsDevice_fnArbitrateAdapterChannel(
158 IN IKsDevice
* iface
,
159 IN ULONG ControlCode
,
160 IN IO_ALLOCATION_ACTION Action
,
163 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
166 return STATUS_NOT_IMPLEMENTED
;
172 IKsDevice_fnCheckIoCapability(
173 IN IKsDevice
* iface
,
176 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
179 return STATUS_NOT_IMPLEMENTED
;
182 static IKsDeviceVtbl vt_IKsDevice
=
184 IKsDevice_fnQueryInterface
,
187 IKsDevice_fnGetStruct
,
188 IKsDevice_fnInitializeObjectBag
,
189 IKsDevice_fnAcquireDevice
,
190 IKsDevice_fnReleaseDevice
,
191 IKsDevice_fnGetAdapterObject
,
192 IKsDevice_fnAddPowerEntry
,
193 IKsDevice_fnRemovePowerEntry
,
194 IKsDevice_fnPinStateChange
,
195 IKsDevice_fnArbitrateAdapterChannel
,
196 IKsDevice_fnCheckIoCapability
202 IKsDevice_PnpPostStart(
203 IN PDEVICE_OBJECT DeviceObject
,
207 PPNP_POSTSTART_CONTEXT Ctx
= (PPNP_POSTSTART_CONTEXT
)Context
;
209 /* call driver pnp post routine */
210 Status
= Ctx
->DeviceHeader
->Descriptor
->Dispatch
->PostStart(&Ctx
->DeviceHeader
->KsDevice
);
212 if (!NT_SUCCESS(Status
))
214 DPRINT1("Driver: PostStart Routine returned %x\n", Status
);
216 /* set state to disabled */
217 Ctx
->DeviceHeader
->TargetState
= KSTARGET_STATE_DISABLED
;
221 /* set state to enabled */
222 Ctx
->DeviceHeader
->TargetState
= KSTARGET_STATE_ENABLED
;
226 IoFreeWorkItem(Ctx
->WorkItem
);
228 /* free work context */
234 IKsDevice_PnpStartDevice(
235 IN PDEVICE_OBJECT DeviceObject
,
238 PIO_STACK_LOCATION IoStack
;
239 PDEVICE_EXTENSION DeviceExtension
;
240 PKSIDEVICE_HEADER DeviceHeader
;
241 PPNP_POSTSTART_CONTEXT Ctx
= NULL
;
244 /* get current stack location */
245 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
246 /* get device extension */
247 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
248 /* get device header */
249 DeviceHeader
= DeviceExtension
->DeviceHeader
;
251 /* first forward irp to lower device object */
252 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
254 /* check for success */
255 if (!NT_SUCCESS(Status
))
257 DPRINT1("NextDevice object failed to start with %x\n", Status
);
258 Irp
->IoStatus
.Status
= Status
;
259 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
263 /* do we have a device descriptor */
264 if (DeviceHeader
->Descriptor
)
266 /* does the device want pnp notifications */
267 if (DeviceHeader
->Descriptor
->Dispatch
)
269 /* does the driver care about IRP_MN_START_DEVICE */
270 if (DeviceHeader
->Descriptor
->Dispatch
->Start
)
272 /* call driver start device routine */
273 Status
= DeviceHeader
->Descriptor
->Dispatch
->Start(&DeviceHeader
->KsDevice
, Irp
,
274 IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
,
275 IoStack
->Parameters
.StartDevice
.AllocatedResources
);
277 ASSERT(Status
!= STATUS_PENDING
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("Driver: failed to start %x\n", Status
);
282 Irp
->IoStatus
.Status
= Status
;
283 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
287 /* set state to run */
288 DeviceHeader
->KsDevice
.Started
= TRUE
;
292 /* does the driver need post start routine */
293 if (DeviceHeader
->Descriptor
->Dispatch
->PostStart
)
295 /* allocate pnp post workitem context */
296 Ctx
= (PPNP_POSTSTART_CONTEXT
)AllocateItem(NonPagedPool
, sizeof(PNP_POSTSTART_CONTEXT
));
300 Status
= STATUS_INSUFFICIENT_RESOURCES
;
304 /* allocate a work item */
305 Ctx
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
312 Status
= STATUS_INSUFFICIENT_RESOURCES
;
316 /* store device header for post-start pnp processing */
317 Ctx
->DeviceHeader
= DeviceHeader
;
323 /* set state to enabled, IRP_MJ_CREATE request may now succeed */
324 DeviceHeader
->TargetState
= KSTARGET_STATE_ENABLED
;
330 Irp
->IoStatus
.Status
= Status
;
331 /* complete request */
332 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
336 /* queue a work item for driver post start routine */
337 IoQueueWorkItem(Ctx
->WorkItem
, IKsDevice_PnpPostStart
, DelayedWorkQueue
, (PVOID
)Ctx
);
347 IN PDEVICE_OBJECT DeviceObject
,
350 PIO_STACK_LOCATION IoStack
;
351 PDEVICE_EXTENSION DeviceExtension
;
352 PKSIDEVICE_HEADER DeviceHeader
;
353 PKSDEVICE_DISPATCH Dispatch
= NULL
;
356 /* get current stack location */
357 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
359 /* get device extension */
360 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
361 /* get device header */
362 DeviceHeader
= DeviceExtension
->DeviceHeader
;
364 /* do we have a device descriptor */
365 if (DeviceHeader
->Descriptor
)
367 /* does the device want pnp notifications */
368 Dispatch
= (PKSDEVICE_DISPATCH
)DeviceHeader
->Descriptor
->Dispatch
;
371 switch (IoStack
->MinorFunction
)
373 case IRP_MN_START_DEVICE
:
375 return IKsDevice_PnpStartDevice(DeviceObject
, Irp
);
378 case IRP_MN_QUERY_STOP_DEVICE
:
380 Status
= STATUS_SUCCESS
;
381 /* check for pnp notification support */
384 /* check for query stop support */
385 if (Dispatch
->QueryStop
)
387 /* call driver's query stop */
388 Status
= Dispatch
->QueryStop(&DeviceHeader
->KsDevice
, Irp
);
389 ASSERT(Status
!= STATUS_PENDING
);
393 if (!NT_SUCCESS(Status
))
395 DPRINT1("Driver: query stop failed %x\n", Status
);
396 Irp
->IoStatus
.Status
= Status
;
397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
401 /* pass the irp down the driver stack */
402 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
404 DPRINT("Next Device: Status %x\n", Status
);
406 Irp
->IoStatus
.Status
= Status
;
407 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
411 case IRP_MN_REMOVE_DEVICE
:
416 /* check for remove support */
417 if (Dispatch
->Remove
)
419 /* call driver's stop routine */
420 Dispatch
->Remove(&DeviceHeader
->KsDevice
, Irp
);
424 /* pass the irp down the driver stack */
425 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
427 DPRINT("Next Device: Status %x\n", Status
);
429 /* FIXME delete device resources */
432 Irp
->IoStatus
.Status
= Status
;
433 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
436 case IRP_MN_QUERY_INTERFACE
:
438 Status
= STATUS_SUCCESS
;
439 /* check for pnp notification support */
442 /* check for query interface support */
443 if (Dispatch
->QueryInterface
)
445 /* call driver's query interface */
446 Status
= Dispatch
->QueryInterface(&DeviceHeader
->KsDevice
, Irp
);
447 ASSERT(Status
!= STATUS_PENDING
);
451 if (NT_SUCCESS(Status
))
453 /* driver supports a private interface */
454 Irp
->IoStatus
.Status
= Status
;
455 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
459 /* pass the irp down the driver stack */
460 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
462 DPRINT("Next Device: Status %x\n", Status
);
464 Irp
->IoStatus
.Status
= Status
;
465 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
468 case IRP_MN_QUERY_DEVICE_RELATIONS
:
470 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
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_FILTER_RESOURCE_REQUIREMENTS
:
483 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
484 /* pass the irp down the driver stack */
485 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
487 DPRINT("Next Device: Status %x\n", Status
);
489 Irp
->IoStatus
.Status
= Status
;
490 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
493 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
495 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
496 /* pass the irp down the driver stack */
497 Status
= KspForwardIrpSynchronous(DeviceObject
, Irp
);
499 DPRINT("Next Device: Status %x\n", Status
);
501 Irp
->IoStatus
.Status
= Status
;
502 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
506 DPRINT1("unhandled function %u\n", IoStack
->MinorFunction
);
507 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
508 return STATUS_NOT_SUPPORTED
;
515 IN PDEVICE_OBJECT DeviceObject
,
522 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
523 Irp
->IoStatus
.Information
= 0;
524 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
526 return STATUS_SUCCESS
;
532 IN PDEVICE_OBJECT DeviceObject
,
535 PCREATE_ITEM_ENTRY CreateItemEntry
;
536 PIO_STACK_LOCATION IoStack
;
537 PDEVICE_EXTENSION DeviceExtension
;
538 PKSIDEVICE_HEADER DeviceHeader
;
539 PKSIOBJECT_HEADER ObjectHeader
;
542 DPRINT("KS / CREATE\n");
543 /* get current stack location */
544 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
545 /* get device extension */
546 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
547 /* get device header */
548 DeviceHeader
= DeviceExtension
->DeviceHeader
;
550 /* acquire list lock */
551 IKsDevice_fnAcquireDevice((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
554 ASSERT(IoStack
->FileObject
);
556 /* check if the request is relative */
557 if (IoStack
->FileObject
->RelatedFileObject
!= NULL
)
559 /* request is to instantiate a pin / node / clock / allocator */
560 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->RelatedFileObject
->FsContext
;
563 ASSERT(ObjectHeader
);
565 /* find a matching a create item */
566 Status
= FindMatchingCreateItem(&ObjectHeader
->ItemList
, IoStack
->FileObject
->FileName
.Length
, IoStack
->FileObject
->FileName
.Buffer
, &CreateItemEntry
);
570 /* request to create a filter */
571 Status
= FindMatchingCreateItem(&DeviceHeader
->ItemList
, IoStack
->FileObject
->FileName
.Length
, IoStack
->FileObject
->FileName
.Buffer
, &CreateItemEntry
);
574 if (NT_SUCCESS(Status
))
576 /* set object create item */
577 KSCREATE_ITEM_IRP_STORAGE(Irp
) = CreateItemEntry
->CreateItem
;
579 /* call create function */
580 Status
= CreateItemEntry
->CreateItem
->Create(DeviceObject
, Irp
);
582 if (NT_SUCCESS(Status
))
584 /* increment create item reference count */
585 InterlockedIncrement(&CreateItemEntry
->ReferenceCount
);
588 /* acquire list lock */
589 IKsDevice_fnReleaseDevice((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
594 /* acquire list lock */
595 IKsDevice_fnReleaseDevice((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
597 DPRINT1("No item found for Request %p\n", IoStack
->FileObject
->FileName
.Buffer
);
599 Irp
->IoStatus
.Information
= 0;
600 /* set return status */
601 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
602 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
603 return STATUS_UNSUCCESSFUL
;
606 IKsDevice_fnRelease((IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
);
608 Irp
->IoStatus
.Information
= 0;
609 /* set return status */
610 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
611 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
612 return STATUS_UNSUCCESSFUL
;
622 IN PDEVICE_OBJECT FunctionalDeviceObject
,
623 IN PDEVICE_OBJECT PhysicalDeviceObject
,
624 IN PDEVICE_OBJECT NextDeviceObject
,
625 IN
const KSDEVICE_DESCRIPTOR
* Descriptor OPTIONAL
)
627 PDEVICE_EXTENSION DeviceExtension
;
628 PKSIDEVICE_HEADER Header
;
630 NTSTATUS Status
= STATUS_SUCCESS
;
632 /* get device extension */
633 DeviceExtension
= (PDEVICE_EXTENSION
)FunctionalDeviceObject
->DeviceExtension
;
635 /* first allocate device header */
636 Status
= KsAllocateDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
, 0, NULL
);
638 /* point to allocated header */
639 Header
= DeviceExtension
->DeviceHeader
;
641 /* check for success */
642 if (!NT_SUCCESS(Status
))
644 DPRINT1("Failed to allocate device header with %x\n", Status
);
648 /* initialize device header */
649 Header
->KsDevice
.FunctionalDeviceObject
= FunctionalDeviceObject
;
650 Header
->KsDevice
.PhysicalDeviceObject
= PhysicalDeviceObject
;
651 Header
->KsDevice
.NextDeviceObject
= NextDeviceObject
;
652 Header
->KsDevice
.Descriptor
= Descriptor
;
653 KsSetDevicePnpAndBaseObject(Header
, PhysicalDeviceObject
, NextDeviceObject
);
654 /* initialize IKsDevice interface */
655 Header
->lpVtblIKsDevice
= &vt_IKsDevice
;
658 /* FIXME Power state */
662 /* create a filter factory for each filter descriptor */
663 for(Index
= 0; Index
< Descriptor
->FilterDescriptorsCount
; Index
++)
665 Status
= KspCreateFilterFactory(FunctionalDeviceObject
, Descriptor
->FilterDescriptors
[Index
], NULL
, NULL
, 0, NULL
, NULL
, NULL
);
666 /* check for success */
667 if (!NT_SUCCESS(Status
))
669 DPRINT1("KspCreateFilterFactory failed with %x\n", Status
);
670 /* FIXME memory leak */
675 /* does the driver pnp notification */
676 if (Descriptor
->Dispatch
)
678 /* does the driver care about the add device */
679 Status
= Descriptor
->Dispatch
->Add(&Header
->KsDevice
);
681 DPRINT("Driver: AddHandler Status %x\n", Status
);
695 KsReferenceSoftwareBusObject(
696 IN KSDEVICE_HEADER Header
)
699 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
701 /* get device interface */
702 Device
= (IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
;
706 /* reference device interface */
707 Device
->lpVtbl
->AddRef(Device
);
710 return STATUS_SUCCESS
;
719 KsReferenceBusObject(
720 IN KSDEVICE_HEADER Header
)
723 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
725 /* get device interface */
726 Device
= (IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
;
730 /* reference device interface */
731 Device
->lpVtbl
->AddRef(Device
);
734 return STATUS_SUCCESS
;
744 KsDereferenceBusObject(
745 IN KSDEVICE_HEADER Header
)
748 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
750 /* get device interface */
751 Device
= (IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
;
755 /* release device interface */
756 Device
->lpVtbl
->Release(Device
);
766 KsDereferenceSoftwareBusObject(
767 IN KSDEVICE_HEADER Header
)
768 { IKsDevice
* Device
;
769 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
771 /* get device interface */
772 Device
= (IKsDevice
*)&DeviceHeader
->lpVtblIKsDevice
;
776 /* release device interface */
777 Device
->lpVtbl
->Release(Device
);