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