xref: /reactos/drivers/ksfilter/ks/device.c (revision 40462c92)
1 /*
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
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 NTSTATUS
15 NTAPI
16 IKsDevice_fnQueryInterface(
17     IN IKsDevice * iface,
18     REFIID refiid,
19     PVOID* Output)
20 {
21     NTSTATUS Status;
22     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
23 
24     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
25     {
26         *Output = &This->BasicHeader.OuterUnknown;
27         _InterlockedIncrement(&This->ref);
28         return STATUS_SUCCESS;
29     }
30 
31     if (This->BasicHeader.ClientAggregate)
32     {
33          /* using client aggregate */
34          Status = This->BasicHeader.ClientAggregate->lpVtbl->QueryInterface(This->BasicHeader.ClientAggregate, refiid, Output);
35 
36          if (NT_SUCCESS(Status))
37          {
38              /* client aggregate supports interface */
39              return Status;
40          }
41     }
42 
43     DPRINT("IKsDevice_fnQueryInterface no interface\n");
44     return STATUS_NOT_SUPPORTED;
45 }
46 
47 ULONG
48 NTAPI
49 IKsDevice_fnAddRef(
50     IN IKsDevice * iface)
51 {
52     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
53 
54     return InterlockedIncrement(&This->ref);
55 }
56 
57 ULONG
58 NTAPI
59 IKsDevice_fnRelease(
60     IN IKsDevice * iface)
61 {
62     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
63 
64     InterlockedDecrement(&This->ref);
65 
66     return This->ref;
67 }
68 
69 
70 
71 PKSDEVICE
72 NTAPI
73 IKsDevice_fnGetStruct(
74     IN IKsDevice * iface)
75 {
76     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
77 
78     return &This->KsDevice;
79 }
80 
81 NTSTATUS
82 NTAPI
83 IKsDevice_fnInitializeObjectBag(
84     IN IKsDevice * iface,
85     IN PKSIOBJECT_BAG Bag,
86     IN PRKMUTEX Mutex)
87 {
88     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
89 
90     if (!Mutex)
91     {
92         /* use device mutex */
93         Mutex = &This->BagMutex;
94     }
95 
96     /* initialize object bag */
97     Bag->BagMutex = Mutex;
98     Bag->DeviceHeader = (PKSIDEVICE_HEADER)This;
99     InitializeListHead(&Bag->ObjectList);
100 
101     /* insert bag into device list */
102     InsertTailList(&This->ObjectBags, &Bag->Entry);
103 
104     return STATUS_SUCCESS;
105 }
106 
107 NTSTATUS
108 NTAPI
109 IKsDevice_fnAcquireDevice(
110     IN IKsDevice * iface)
111 {
112     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
113 
114     return KeWaitForSingleObject(&This->DeviceMutex, Executive, KernelMode, FALSE, NULL);
115 }
116 
117 NTSTATUS
118 NTAPI
119 IKsDevice_fnReleaseDevice(
120     IN IKsDevice * iface)
121 {
122     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
123 
124     return KeReleaseMutex(&This->DeviceMutex, FALSE);
125 }
126 
127 NTSTATUS
128 NTAPI
129 IKsDevice_fnGetAdapterObject(
130     IN IKsDevice * iface,
131     IN PADAPTER_OBJECT * Object,
132     IN PULONG MaxMappingsByteCount,
133     IN PULONG MappingTableStride)
134 {
135     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
136 
137     *Object = This->AdapterObject;
138     *MaxMappingsByteCount = This->MaxMappingsByteCount;
139     *MappingTableStride = This->MappingTableStride;
140 
141     return STATUS_SUCCESS;
142 
143 }
144 
145 NTSTATUS
146 NTAPI
147 IKsDevice_fnAddPowerEntry(
148     IN IKsDevice * iface,
149     IN struct KSPOWER_ENTRY * Entry,
150     IN IKsPowerNotify* Notify)
151 {
152     //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
153 
154     UNIMPLEMENTED;
155     return STATUS_NOT_IMPLEMENTED;
156 }
157 
158 NTSTATUS
159 NTAPI
160 IKsDevice_fnRemovePowerEntry(
161     IN IKsDevice * iface,
162     IN struct KSPOWER_ENTRY * Entry)
163 {
164     //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
165 
166     UNIMPLEMENTED;
167     return STATUS_NOT_IMPLEMENTED;
168 
169 }
170 
171 NTSTATUS
172 NTAPI
173 IKsDevice_fnPinStateChange(
174     IN IKsDevice * iface,
175     IN KSPIN Pin,
176     IN PIRP Irp,
177     IN KSSTATE OldState,
178     IN KSSTATE NewState)
179 {
180     //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
181 
182     UNIMPLEMENTED;
183     return STATUS_NOT_IMPLEMENTED;
184 
185 }
186 
187 NTSTATUS
188 NTAPI
189 IKsDevice_fnArbitrateAdapterChannel(
190     IN IKsDevice * iface,
191     IN ULONG NumberOfMapRegisters,
192     IN PDRIVER_CONTROL ExecutionRoutine,
193     IN PVOID Context)
194 {
195     PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
196     NTSTATUS Status;
197 
198     DPRINT("IKsDevice_fnArbitrateAdapterChannel NumberOfMapRegisters %lu ExecutionRoutine %p Context %p Irql %lu\n", NumberOfMapRegisters, ExecutionRoutine, Context, KeGetCurrentIrql());
199 
200     /* sanity check */
201     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
202     ASSERT(This->AdapterObject);
203 
204     /* allocate adapter channel */
205     Status = IoAllocateAdapterChannel(This->AdapterObject, This->KsDevice.FunctionalDeviceObject, NumberOfMapRegisters, ExecutionRoutine, Context);
206 
207     /* done */
208     return Status;
209 }
210 
211 NTSTATUS
212 NTAPI
213 IKsDevice_fnCheckIoCapability(
214     IN IKsDevice * iface,
215     IN ULONG Unknown)
216 {
217     //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, BasicHeader.OuterUnknown);
218 
219     UNIMPLEMENTED;
220     return STATUS_NOT_IMPLEMENTED;
221 }
222 
223 static IKsDeviceVtbl vt_IKsDevice =
224 {
225     IKsDevice_fnQueryInterface,
226     IKsDevice_fnAddRef,
227     IKsDevice_fnRelease,
228     IKsDevice_fnGetStruct,
229     IKsDevice_fnInitializeObjectBag,
230     IKsDevice_fnAcquireDevice,
231     IKsDevice_fnReleaseDevice,
232     IKsDevice_fnGetAdapterObject,
233     IKsDevice_fnAddPowerEntry,
234     IKsDevice_fnRemovePowerEntry,
235     IKsDevice_fnPinStateChange,
236     IKsDevice_fnArbitrateAdapterChannel,
237     IKsDevice_fnCheckIoCapability
238 };
239 
240 
241 VOID
242 NTAPI
243 IKsDevice_PnpPostStart(
244     IN PDEVICE_OBJECT  DeviceObject,
245     IN PVOID  Context)
246 {
247     NTSTATUS Status;
248     PPNP_POSTSTART_CONTEXT Ctx = (PPNP_POSTSTART_CONTEXT)Context;
249 
250     /* call driver pnp post routine */
251     Status = Ctx->DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart(&Ctx->DeviceHeader->KsDevice);
252 
253     if (!NT_SUCCESS(Status))
254     {
255         /* set state to disabled */
256         Ctx->DeviceHeader->TargetState  = KSTARGET_STATE_DISABLED;
257     }
258     else
259     {
260         /* set state to enabled */
261         Ctx->DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
262         Status = KspSetFilterFactoriesState(Ctx->DeviceHeader, TRUE);
263     }
264 
265     /* free work item */
266     IoFreeWorkItem(Ctx->WorkItem);
267 
268     /* free work context */
269     FreeItem(Ctx);
270 
271     DPRINT("IKsDevice_PnpPostStart: PostStart Routine returned %x\n", Status);
272 }
273 
274 NTSTATUS
275 NTAPI
276 IKsDevice_PnpStartDevice(
277     IN PDEVICE_OBJECT  DeviceObject,
278     IN PIRP Irp)
279 {
280     PIO_STACK_LOCATION IoStack;
281     PDEVICE_EXTENSION DeviceExtension;
282     PKSIDEVICE_HEADER DeviceHeader;
283     PPNP_POSTSTART_CONTEXT Ctx = NULL;
284     NTSTATUS Status;
285     PCM_RESOURCE_LIST TranslatedResourceList;
286     PCM_RESOURCE_LIST UntranslatedResourceList;
287 
288     /* get current stack location */
289     IoStack = IoGetCurrentIrpStackLocation(Irp);
290     /* get device extension */
291     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
292     /* get device header */
293     DeviceHeader = DeviceExtension->DeviceHeader;
294 
295     DPRINT("IKsDevice_PnpStartDevice DeviceHeader %p\n", DeviceHeader);
296 
297     /* first forward irp to lower device object */
298     Status = KspForwardIrpSynchronous(DeviceObject, Irp);
299 
300     /* check for success */
301     if (!NT_SUCCESS(Status))
302     {
303         DPRINT1("NextDevice object failed to start with %x\n", Status);
304         Irp->IoStatus.Status = Status;
305         CompleteRequest(Irp, IO_NO_INCREMENT);
306         return Status;
307     }
308 
309     TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
310     UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
311 
312     ASSERT(DeviceHeader->KsDevice.Descriptor);
313 
314     /* do we have a device descriptor */
315     if (DeviceHeader->KsDevice.Descriptor)
316     {
317         /* does the device want pnp notifications */
318         if (DeviceHeader->KsDevice.Descriptor->Dispatch)
319         {
320             /* does the driver care about IRP_MN_START_DEVICE */
321             if (DeviceHeader->KsDevice.Descriptor->Dispatch->Start)
322             {
323                 /* call driver start device routine */
324                 Status = DeviceHeader->KsDevice.Descriptor->Dispatch->Start(&DeviceHeader->KsDevice, Irp,
325                                                                    TranslatedResourceList,
326                                                                    UntranslatedResourceList);
327 
328 
329                 DPRINT("IKsDevice_PnpStartDevice Start %p, Context %p\n", DeviceHeader->KsDevice.Descriptor->Dispatch->Start, DeviceHeader->KsDevice.Context);
330                 ASSERT(Status != STATUS_PENDING);
331 
332                 if (!NT_SUCCESS(Status))
333                 {
334                     DPRINT1("Driver: failed to start %x\n", Status);
335                     Irp->IoStatus.Status = Status;
336                     CompleteRequest(Irp, IO_NO_INCREMENT);
337                     return Status;
338                 }
339 
340                 /* set state to run */
341                 DeviceHeader->KsDevice.Started = TRUE;
342 
343             }
344 
345             /* does the driver need post start routine */
346             if (DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart)
347             {
348                 /* allocate pnp post workitem context */
349                 Ctx = (PPNP_POSTSTART_CONTEXT)AllocateItem(NonPagedPool, sizeof(PNP_POSTSTART_CONTEXT));
350                 if (!Ctx)
351                 {
352                     /* no memory */
353                     Status = STATUS_INSUFFICIENT_RESOURCES;
354                 }
355                 else
356                 {
357                     /* allocate a work item */
358                     Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
359 
360                     if (!Ctx->WorkItem)
361                     {
362                          /* no memory */
363                         FreeItem(Ctx);
364                         Ctx = NULL;
365                         Status = STATUS_INSUFFICIENT_RESOURCES;
366                     }
367                     else
368                     {
369                         /* store device header for post-start pnp processing */
370                         Ctx->DeviceHeader = DeviceHeader;
371                     }
372                 }
373             }
374             else
375             {
376                 /* set state to enabled, IRP_MJ_CREATE request may now succeed */
377                 DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
378                 Status = KspSetFilterFactoriesState(DeviceHeader, TRUE);
379             }
380         }
381         else
382         {
383             /* set state to run */
384             DeviceHeader->KsDevice.Started = TRUE;
385         }
386     }
387 
388     /* store result */
389     Irp->IoStatus.Status = Status;
390     /* complete request */
391     CompleteRequest(Irp, IO_NO_INCREMENT);
392 
393     if (Ctx)
394     {
395         /* queue a work item for driver post start routine */
396         IoQueueWorkItem(Ctx->WorkItem, IKsDevice_PnpPostStart, DelayedWorkQueue, (PVOID)Ctx);
397     }
398 
399     /* return result */
400     DPRINT("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
401     return Status;
402 }
403 
404 NTSTATUS
405 NTAPI
406 IKsDevice_Pnp(
407     IN PDEVICE_OBJECT  DeviceObject,
408     IN PIRP Irp)
409 {
410     PIO_STACK_LOCATION IoStack;
411     PDEVICE_EXTENSION DeviceExtension;
412     PKSIDEVICE_HEADER DeviceHeader;
413     PKSDEVICE_DISPATCH Dispatch = NULL;
414     NTSTATUS Status;
415 
416     /* get current stack location */
417     IoStack = IoGetCurrentIrpStackLocation(Irp);
418 
419     /* get device extension */
420     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
421     /* get device header */
422     DeviceHeader = DeviceExtension->DeviceHeader;
423 
424     /* do we have a device descriptor */
425     if (DeviceHeader->KsDevice.Descriptor && DeviceHeader->KsDevice.Descriptor->Dispatch)
426     {
427         /* does the device want pnp notifications */
428         Dispatch = (PKSDEVICE_DISPATCH)DeviceHeader->KsDevice.Descriptor->Dispatch;
429     }
430 
431     switch (IoStack->MinorFunction)
432     {
433         case IRP_MN_START_DEVICE:
434         {
435             return IKsDevice_PnpStartDevice(DeviceObject, Irp);
436         }
437 
438         case IRP_MN_QUERY_STOP_DEVICE:
439         {
440             Status = STATUS_SUCCESS;
441             /* check for pnp notification support */
442             if (Dispatch)
443             {
444                 /* check for query stop support */
445                 if (Dispatch->QueryStop)
446                 {
447                     /* call driver's query stop */
448                     Status = Dispatch->QueryStop(&DeviceHeader->KsDevice, Irp);
449                     ASSERT(Status != STATUS_PENDING);
450                 }
451             }
452 
453             if (!NT_SUCCESS(Status))
454             {
455                 DPRINT1("Driver: query stop failed %x\n", Status);
456                 Irp->IoStatus.Status = Status;
457                 CompleteRequest(Irp, IO_NO_INCREMENT);
458                 return Status;
459             }
460 
461             /* pass the irp down the driver stack */
462             Status = KspForwardIrpSynchronous(DeviceObject, Irp);
463 
464             DPRINT("Next Device: Status %x\n", Status);
465 
466             Irp->IoStatus.Status = Status;
467             CompleteRequest(Irp, IO_NO_INCREMENT);
468             return Status;
469         }
470 
471         case IRP_MN_REMOVE_DEVICE:
472         {
473             /* Clean up */
474             if (Dispatch)
475             {
476                 /* check for remove support */
477                 if (Dispatch->Remove)
478                 {
479                     /* call driver's stop routine */
480                     Dispatch->Remove(&DeviceHeader->KsDevice, Irp);
481                 }
482             }
483 
484             /* pass the irp down the driver stack */
485             Status = KspForwardIrpSynchronous(DeviceObject, Irp);
486 
487             DPRINT("Next Device: Status %x\n", Status);
488 
489             /* FIXME delete device resources */
490 
491 
492             Irp->IoStatus.Status = Status;
493             CompleteRequest(Irp, IO_NO_INCREMENT);
494             return Status;
495         }
496         case IRP_MN_QUERY_INTERFACE:
497         {
498             Status = STATUS_UNSUCCESSFUL;
499             /* check for pnp notification support */
500             if (Dispatch)
501             {
502                 /* check for query interface support */
503                 if (Dispatch->QueryInterface)
504                 {
505                     /* call driver's query interface */
506                     Status = Dispatch->QueryInterface(&DeviceHeader->KsDevice, Irp);
507                     ASSERT(Status != STATUS_PENDING);
508                 }
509             }
510 
511             if (NT_SUCCESS(Status))
512             {
513                 /* driver supports a private interface */
514                 DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n");
515                 Irp->IoStatus.Status = Status;
516                 CompleteRequest(Irp, IO_NO_INCREMENT);
517                 return Status;
518             }
519 
520             /* pass the irp down the driver stack */
521             Status = KspForwardIrpSynchronous(DeviceObject, Irp);
522 
523             DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status);
524             Irp->IoStatus.Status = Status;
525             CompleteRequest(Irp, IO_NO_INCREMENT);
526             return Status;
527         }
528         case IRP_MN_QUERY_DEVICE_RELATIONS:
529         {
530             /* pass the irp down the driver stack */
531             Status = KspForwardIrpSynchronous(DeviceObject, Irp);
532 
533             DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status);
534 
535             //Irp->IoStatus.Status = Status;
536             CompleteRequest(Irp, IO_NO_INCREMENT);
537             return Status;
538         }
539         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
540         {
541             /* pass the irp down the driver stack */
542             //Status = KspForwardIrpSynchronous(DeviceObject, Irp);
543             Status = Irp->IoStatus.Status;
544             DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
545 
546             //Irp->IoStatus.Status = Status;
547             CompleteRequest(Irp, IO_NO_INCREMENT);
548             return Status;
549         }
550        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
551        {
552             /* pass the irp down the driver stack */
553             Status = KspForwardIrpSynchronous(DeviceObject, Irp);
554 
555             DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
556 
557             Irp->IoStatus.Status = Status;
558             CompleteRequest(Irp, IO_NO_INCREMENT);
559             return Status;
560        }
561        default:
562           DPRINT1("unhandled function %u\n", IoStack->MinorFunction);
563           /* pass the irp down the driver stack */
564           Status = KspForwardIrpSynchronous(DeviceObject, Irp);
565 
566           Irp->IoStatus.Status = Status;
567           CompleteRequest(Irp, IO_NO_INCREMENT);
568           return Status;
569     }
570 }
571 
572 NTSTATUS
573 NTAPI
574 IKsDevice_Power(
575     IN PDEVICE_OBJECT  DeviceObject,
576     IN PIRP Irp)
577 {
578     UNIMPLEMENTED;
579 
580     /* TODO */
581 
582     Irp->IoStatus.Status = STATUS_SUCCESS;
583     Irp->IoStatus.Information = 0;
584     CompleteRequest(Irp, IO_NO_INCREMENT);
585 
586     return STATUS_SUCCESS;
587 }
588 
589 NTSTATUS
590 NTAPI
591 IKsDevice_Create(
592     IN PDEVICE_OBJECT  DeviceObject,
593     IN PIRP Irp)
594 {
595     PCREATE_ITEM_ENTRY CreateItemEntry;
596     PIO_STACK_LOCATION IoStack;
597     PDEVICE_EXTENSION DeviceExtension;
598     PKSIDEVICE_HEADER DeviceHeader;
599     PKSIOBJECT_HEADER ObjectHeader;
600     NTSTATUS Status;
601 
602     DPRINT("IKsDevice_Create\n");
603     /* get current stack location */
604     IoStack = IoGetCurrentIrpStackLocation(Irp);
605     /* get device extension */
606     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
607     /* get device header */
608     DeviceHeader = DeviceExtension->DeviceHeader;
609 
610     if (IoStack->FileObject->FileName.Buffer == NULL)
611     {
612         // ReactOS PnPMgr still sucks
613         ASSERT(IoStack->FileObject->FileName.Length == 0);
614         Irp->IoStatus.Status = STATUS_SUCCESS;
615         IoCompleteRequest(Irp, IO_NO_INCREMENT);
616         DPRINT1("ReactOS PnP hack\n");
617         return STATUS_SUCCESS;
618     }
619 
620     /* acquire list lock */
621     IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
622 
623     /* sanity check */
624     ASSERT(IoStack->FileObject);
625 
626     /* check if the request is relative */
627     if (IoStack->FileObject->RelatedFileObject != NULL)
628     {
629         /* request is to instantiate a pin / node / clock / allocator */
630         ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
631 
632         /* sanity check */
633         ASSERT(ObjectHeader);
634 
635         /* find a matching a create item */
636         Status = FindMatchingCreateItem(&ObjectHeader->ItemList,
637                                         &IoStack->FileObject->FileName,
638                                         &CreateItemEntry);
639     }
640     else
641     {
642         /* request to create a filter */
643         Status = FindMatchingCreateItem(&DeviceHeader->ItemList,
644                                         &IoStack->FileObject->FileName,
645                                         &CreateItemEntry);
646     }
647 
648     if (NT_SUCCESS(Status))
649     {
650         /* set object create item */
651         KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
652 
653         /* call create function */
654         Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
655 
656         if (NT_SUCCESS(Status))
657         {
658             /* increment create item reference count */
659             InterlockedIncrement(&CreateItemEntry->ReferenceCount);
660         }
661     }
662 
663     /* release list lock */
664     IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
665 
666     /* done */
667     return Status;
668 
669 
670 }
671 
672 /*
673     @implemented
674 */
675 KSDDKAPI
676 NTSTATUS
677 NTAPI
678 KsInitializeDevice(
679     IN PDEVICE_OBJECT FunctionalDeviceObject,
680     IN PDEVICE_OBJECT PhysicalDeviceObject,
681     IN PDEVICE_OBJECT NextDeviceObject,
682     IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
683 {
684     PDEVICE_EXTENSION DeviceExtension;
685     PKSIDEVICE_HEADER Header;
686     ULONG Index;
687     PKSIOBJECT_BAG Bag;
688     NTSTATUS Status = STATUS_SUCCESS;
689 
690     DPRINT1("KsInitializeDevice Descriptor %p\n", Descriptor);
691 
692     /* get device extension */
693     DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
694 
695     /* first allocate device header */
696     Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 0, NULL);
697 
698     /* point to allocated header */
699     Header = DeviceExtension->DeviceHeader;
700 
701     DPRINT1("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
702 
703     if (Descriptor && Descriptor->Dispatch)
704     {
705         DPRINT("Descriptor Add %p\n", Descriptor->Dispatch->Add);
706         DPRINT("Descriptor Start %p\n", Descriptor->Dispatch->Start);
707         DPRINT("Descriptor PostStart %p\n", Descriptor->Dispatch->PostStart);
708         DPRINT("Descriptor QueryStop %p\n", Descriptor->Dispatch->QueryStop);
709         DPRINT("Descriptor CancelStop %p\n", Descriptor->Dispatch->CancelStop);
710         DPRINT("Descriptor Stop %p\n", Descriptor->Dispatch->Stop);
711         DPRINT("Descriptor QueryRemove %p\n", Descriptor->Dispatch->QueryRemove);
712         DPRINT("Descriptor CancelRemove %p\n", Descriptor->Dispatch->CancelRemove);
713         DPRINT("Descriptor Remove %p\n", Descriptor->Dispatch->Remove);
714         DPRINT("Descriptor QueryCapabilities %p\n", Descriptor->Dispatch->QueryCapabilities);
715         DPRINT("Descriptor SurpriseRemoval %p\n", Descriptor->Dispatch->SurpriseRemoval);
716         DPRINT("Descriptor QueryPower %p\n", Descriptor->Dispatch->QueryPower);
717         DPRINT("Descriptor SetPower %p\n", Descriptor->Dispatch->SetPower);
718         DPRINT("Descriptor QueryInterface %p\n", Descriptor->Dispatch->QueryInterface);
719     }
720 
721     /* check for success */
722     if (!NT_SUCCESS(Status))
723     {
724         DPRINT1("KsInitializeDevice Failed to allocate device header with %x\n", Status);
725         return Status;
726     }
727 
728     /* initialize IKsDevice interface */
729     Header->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsDevice;
730     Header->ref = 1;
731 
732     /* allocate object bag */
733     Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
734     if (!Header->KsDevice.Bag)
735     {
736         /* no memory */
737         KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader);
738         return STATUS_INSUFFICIENT_RESOURCES;
739     }
740 
741     /* initialize object bag */
742     KeInitializeMutex(&Header->BagMutex, 0);
743     KeInitializeMutex(&Header->DeviceMutex, 0);
744 
745     Bag = (PKSIOBJECT_BAG)Header->KsDevice.Bag;
746     Bag->BagMutex = &Header->BagMutex;
747     InitializeListHead(&Header->ObjectBags);
748     InitializeListHead(&Bag->ObjectList);
749     Bag->DeviceHeader = (PVOID)Header;
750 
751     /* insert bag into device list */
752     InsertTailList(&Header->ObjectBags, &Bag->Entry);
753 
754     /* initialize device header */
755     Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
756     Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
757     Header->KsDevice.NextDeviceObject = NextDeviceObject;
758     Header->KsDevice.Descriptor = Descriptor;
759     Header->KsDevice.SystemPowerState = PowerSystemWorking;
760     Header->KsDevice.DevicePowerState = PowerDeviceD0;
761     Header->KsDevice.Started = FALSE;
762     Header->KsDevice.Context = NULL;
763     KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
764 
765 
766 
767     if (Descriptor)
768     {
769         /* create a filter factory for each filter descriptor */
770         DPRINT("KsInitializeDevice FilterDescriptorCount %lu\n", Descriptor->FilterDescriptorsCount);
771         for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
772         {
773             Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
774 
775             DPRINT("KsInitializeDevice Index %lu KspCreateFilterFactory Status %lx\n", Index, Status);
776             /* check for success */
777             if (!NT_SUCCESS(Status))
778             {
779                 DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
780                 /* FIXME memory leak */
781                 return Status;
782             }
783         }
784 
785         /* does the driver care about the add device */
786         if (Descriptor->Dispatch && Descriptor->Dispatch->Add)
787         {
788             Status = Descriptor->Dispatch->Add(&Header->KsDevice);
789             DPRINT("Driver: AddHandler Status %x\n", Status);
790         }
791 
792         Header->KsDevice.Descriptor = Descriptor;
793     }
794 
795 
796    return Status;
797 }
798 
799 /*
800     @implemented
801 */
802 KSDDKAPI
803 NTSTATUS
804 NTAPI
805 KsReferenceSoftwareBusObject(
806     IN KSDEVICE_HEADER  Header)
807 {
808      IKsDevice * Device;
809      PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
810 
811      /* get device interface */
812      Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
813 
814      if (Device)
815      {
816          /* reference device interface */
817          Device->lpVtbl->AddRef(Device);
818      }
819 
820     return STATUS_SUCCESS;
821 }
822 
823 /*
824     @implemented
825 */
826 KSDDKAPI
827 NTSTATUS
828 NTAPI
829 KsReferenceBusObject(
830     IN  KSDEVICE_HEADER Header)
831 {
832      IKsDevice * Device;
833      PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
834 
835      /* get device interface */
836      Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
837 
838      if (Device)
839      {
840          /* reference device interface */
841          Device->lpVtbl->AddRef(Device);
842      }
843 
844     return STATUS_SUCCESS;
845 
846 }
847 
848 /*
849     @implemented
850 */
851 KSDDKAPI
852 VOID
853 NTAPI
854 KsDereferenceBusObject(
855     IN  KSDEVICE_HEADER Header)
856 {
857      IKsDevice * Device;
858      PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
859 
860      /* get device interface */
861      Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
862 
863      if (Device)
864      {
865          /* release device interface */
866          Device->lpVtbl->Release(Device);
867      }
868 }
869 
870 /*
871     @implemented
872 */
873 KSDDKAPI
874 VOID
875 NTAPI
876 KsDereferenceSoftwareBusObject(
877     IN KSDEVICE_HEADER  Header)
878 {
879      IKsDevice * Device;
880      PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
881 
882      DPRINT("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
883 
884      /* get device interface */
885      Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
886 
887      if (Device)
888      {
889          /* release device interface */
890          Device->lpVtbl->Release(Device);
891      }
892 }
893