Sunc with trunk revision 58971.
[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 if (IoStack->FileObject->FileName.Buffer == NULL)
609 {
610 // ReactOS PnPMgr still sucks
611 ASSERT(IoStack->FileObject->FileName.Length == 0);
612 Irp->IoStatus.Status = STATUS_SUCCESS;
613 IoCompleteRequest(Irp, IO_NO_INCREMENT);
614 DPRINT1("ReactOS PnP hack\n");
615 return STATUS_SUCCESS;
616 }
617
618 /* acquire list lock */
619 IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
620
621 /* sanity check */
622 ASSERT(IoStack->FileObject);
623
624 /* check if the request is relative */
625 if (IoStack->FileObject->RelatedFileObject != NULL)
626 {
627 /* request is to instantiate a pin / node / clock / allocator */
628 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
629
630 /* sanity check */
631 ASSERT(ObjectHeader);
632
633 /* find a matching a create item */
634 Status = FindMatchingCreateItem(&ObjectHeader->ItemList,
635 &IoStack->FileObject->FileName,
636 &CreateItemEntry);
637 }
638 else
639 {
640 /* request to create a filter */
641 Status = FindMatchingCreateItem(&DeviceHeader->ItemList,
642 &IoStack->FileObject->FileName,
643 &CreateItemEntry);
644 }
645
646 if (NT_SUCCESS(Status))
647 {
648 /* set object create item */
649 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
650
651 /* call create function */
652 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
653
654 if (NT_SUCCESS(Status))
655 {
656 /* increment create item reference count */
657 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
658 }
659 }
660
661 /* release list lock */
662 IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
663
664 /* done */
665 return Status;
666
667
668 }
669
670 /*
671 @implemented
672 */
673 KSDDKAPI
674 NTSTATUS
675 NTAPI
676 KsInitializeDevice(
677 IN PDEVICE_OBJECT FunctionalDeviceObject,
678 IN PDEVICE_OBJECT PhysicalDeviceObject,
679 IN PDEVICE_OBJECT NextDeviceObject,
680 IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
681 {
682 PDEVICE_EXTENSION DeviceExtension;
683 PKSIDEVICE_HEADER Header;
684 ULONG Index;
685 PKSIOBJECT_BAG Bag;
686 NTSTATUS Status = STATUS_SUCCESS;
687
688 DPRINT1("KsInitializeDevice Descriptor %p\n", Descriptor);
689
690 /* get device extension */
691 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
692
693 /* first allocate device header */
694 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 0, NULL);
695
696 /* point to allocated header */
697 Header = DeviceExtension->DeviceHeader;
698
699 DPRINT1("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
700
701 if (Descriptor && Descriptor->Dispatch)
702 {
703 DPRINT("Descriptor Add %p\n", Descriptor->Dispatch->Add);
704 DPRINT("Descriptor Start %p\n", Descriptor->Dispatch->Start);
705 DPRINT("Descriptor PostStart %p\n", Descriptor->Dispatch->PostStart);
706 DPRINT("Descriptor QueryStop %p\n", Descriptor->Dispatch->QueryStop);
707 DPRINT("Descriptor CancelStop %p\n", Descriptor->Dispatch->CancelStop);
708 DPRINT("Descriptor Stop %p\n", Descriptor->Dispatch->Stop);
709 DPRINT("Descriptor QueryRemove %p\n", Descriptor->Dispatch->QueryRemove);
710 DPRINT("Descriptor CancelRemove %p\n", Descriptor->Dispatch->CancelRemove);
711 DPRINT("Descriptor Remove %p\n", Descriptor->Dispatch->Remove);
712 DPRINT("Descriptor QueryCapabilities %p\n", Descriptor->Dispatch->QueryCapabilities);
713 DPRINT("Descriptor SurpriseRemoval %p\n", Descriptor->Dispatch->SurpriseRemoval);
714 DPRINT("Descriptor QueryPower %p\n", Descriptor->Dispatch->QueryPower);
715 DPRINT("Descriptor SetPower %p\n", Descriptor->Dispatch->SetPower);
716 DPRINT("Descriptor QueryInterface %p\n", Descriptor->Dispatch->QueryInterface);
717 }
718
719 /* check for success */
720 if (!NT_SUCCESS(Status))
721 {
722 DPRINT1("KsInitializeDevice Failed to allocate device header with %x\n", Status);
723 return Status;
724 }
725
726 /* initialize IKsDevice interface */
727 Header->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsDevice;
728 Header->ref = 1;
729
730 /* allocate object bag */
731 Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
732 if (!Header->KsDevice.Bag)
733 {
734 /* no memory */
735 KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader);
736 return STATUS_INSUFFICIENT_RESOURCES;
737 }
738
739 /* initialize object bag */
740 KeInitializeMutex(&Header->BagMutex, 0);
741 KeInitializeMutex(&Header->DeviceMutex, 0);
742
743 Bag = (PKSIOBJECT_BAG)Header->KsDevice.Bag;
744 Bag->BagMutex = &Header->BagMutex;
745 InitializeListHead(&Header->ObjectBags);
746 InitializeListHead(&Bag->ObjectList);
747 Bag->DeviceHeader = (PVOID)Header;
748
749 /* insert bag into device list */
750 InsertTailList(&Header->ObjectBags, &Bag->Entry);
751
752 /* initialize device header */
753 Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
754 Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
755 Header->KsDevice.NextDeviceObject = NextDeviceObject;
756 Header->KsDevice.Descriptor = Descriptor;
757 Header->KsDevice.SystemPowerState = PowerSystemWorking;
758 Header->KsDevice.DevicePowerState = PowerDeviceD0;
759 Header->KsDevice.Started = FALSE;
760 Header->KsDevice.Context = NULL;
761 KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
762
763
764
765 if (Descriptor)
766 {
767 /* create a filter factory for each filter descriptor */
768 DPRINT("KsInitializeDevice FilterDescriptorCount %lu\n", Descriptor->FilterDescriptorsCount);
769 for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
770 {
771 Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
772
773 DPRINT("KsInitializeDevice Index %lu KspCreateFilterFactory Status %lx\n", Index, Status);
774 /* check for success */
775 if (!NT_SUCCESS(Status))
776 {
777 DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
778 /* FIXME memory leak */
779 return Status;
780 }
781 }
782
783 /* does the driver pnp notification */
784 if (Descriptor->Dispatch)
785 {
786 /* does the driver care about the add device */
787 Status = Descriptor->Dispatch->Add(&Header->KsDevice);
788
789 DPRINT("Driver: AddHandler Status %x\n", Status);
790 Header->KsDevice.Descriptor = Descriptor;
791 }
792 }
793
794
795 return Status;
796 }
797
798 /*
799 @implemented
800 */
801 KSDDKAPI
802 NTSTATUS
803 NTAPI
804 KsReferenceSoftwareBusObject(
805 IN KSDEVICE_HEADER Header)
806 {
807 IKsDevice * Device;
808 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
809
810 /* get device interface */
811 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
812
813 if (Device)
814 {
815 /* reference device interface */
816 Device->lpVtbl->AddRef(Device);
817 }
818
819 return STATUS_SUCCESS;
820 }
821
822 /*
823 @implemented
824 */
825 KSDDKAPI
826 NTSTATUS
827 NTAPI
828 KsReferenceBusObject(
829 IN KSDEVICE_HEADER Header)
830 {
831 IKsDevice * Device;
832 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
833
834 /* get device interface */
835 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
836
837 if (Device)
838 {
839 /* reference device interface */
840 Device->lpVtbl->AddRef(Device);
841 }
842
843 return STATUS_SUCCESS;
844
845 }
846
847 /*
848 @implemented
849 */
850 KSDDKAPI
851 VOID
852 NTAPI
853 KsDereferenceBusObject(
854 IN KSDEVICE_HEADER Header)
855 {
856 IKsDevice * Device;
857 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
858
859 /* get device interface */
860 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
861
862 if (Device)
863 {
864 /* release device interface */
865 Device->lpVtbl->Release(Device);
866 }
867 }
868
869 /*
870 @implemented
871 */
872 KSDDKAPI
873 VOID
874 NTAPI
875 KsDereferenceSoftwareBusObject(
876 IN KSDEVICE_HEADER Header)
877 {
878 IKsDevice * Device;
879 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
880
881 DPRINT("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
882
883 /* get device interface */
884 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
885
886 if (Device)
887 {
888 /* release device interface */
889 Device->lpVtbl->Release(Device);
890 }
891 }