Create a branch for audio work
[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 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
286 ULONG Index;
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 IoCompleteRequest(Irp, IO_NO_INCREMENT);
306 return Status;
307 }
308
309 TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
310 UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
311
312 DPRINT("ResourceDescriptorCount %lu\n", TranslatedResourceList->List[0].PartialResourceList.Count);
313 for (Index = 0; Index < TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
314 {
315 PartialDescriptor = &TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
316 UnPartialDescriptor = &UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
317 DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
318
319 if (PartialDescriptor->Type == CmResourceTypeInterrupt)
320 {
321 DPRINT("CmResourceTypeInterrupt Index %u TRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\n", Index, PartialDescriptor->u.Interrupt.Affinity, PartialDescriptor->u.Interrupt.Level, PartialDescriptor->u.Interrupt.Vector, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
322 DPRINT("CmResourceTypeInterrupt Index %u UNTRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\\n", Index, UnPartialDescriptor->u.Interrupt.Affinity, UnPartialDescriptor->u.Interrupt.Level, UnPartialDescriptor->u.Interrupt.Vector, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
323
324 }
325 else if (PartialDescriptor->Type == CmResourceTypePort)
326 {
327 DPRINT("CmResourceTypePort Index %u TRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, PartialDescriptor->u.Port.Length, PartialDescriptor->u.Port.Start.HighPart, PartialDescriptor->u.Port.Start.LowPart, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
328 DPRINT("CmResourceTypePort Index %u UNTRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Port.Length, UnPartialDescriptor->u.Port.Start.HighPart, UnPartialDescriptor->u.Port.Start.LowPart, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
329 }
330 else if (PartialDescriptor->Type == CmResourceTypeMemory)
331 {
332 DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, PartialDescriptor->u.Memory.Start.LowPart, PartialDescriptor->u.Memory.Length, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
333 DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Memory.Start.LowPart, UnPartialDescriptor->u.Memory.Length, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
334 }
335 }
336
337 ASSERT(DeviceHeader->KsDevice.Descriptor);
338 ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch);
339 ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch->Start);
340
341
342 /* do we have a device descriptor */
343 if (DeviceHeader->KsDevice.Descriptor)
344 {
345 /* does the device want pnp notifications */
346 if (DeviceHeader->KsDevice.Descriptor->Dispatch)
347 {
348 /* does the driver care about IRP_MN_START_DEVICE */
349 if (DeviceHeader->KsDevice.Descriptor->Dispatch->Start)
350 {
351 /* call driver start device routine */
352 Status = DeviceHeader->KsDevice.Descriptor->Dispatch->Start(&DeviceHeader->KsDevice, Irp,
353 TranslatedResourceList,
354 UntranslatedResourceList);
355
356
357 DPRINT("IKsDevice_PnpStartDevice Start %p, Context %p\n", DeviceHeader->KsDevice.Descriptor->Dispatch->Start, DeviceHeader->KsDevice.Context);
358 ASSERT(Status != STATUS_PENDING);
359
360 if (!NT_SUCCESS(Status))
361 {
362 DPRINT1("Driver: failed to start %x\n", Status);
363 Irp->IoStatus.Status = Status;
364 IoCompleteRequest(Irp, IO_NO_INCREMENT);
365 return Status;
366 }
367
368 /* set state to run */
369 DeviceHeader->KsDevice.Started = TRUE;
370
371 }
372
373 /* does the driver need post start routine */
374 if (DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart)
375 {
376 /* allocate pnp post workitem context */
377 Ctx = (PPNP_POSTSTART_CONTEXT)AllocateItem(NonPagedPool, sizeof(PNP_POSTSTART_CONTEXT));
378 if (!Ctx)
379 {
380 /* no memory */
381 Status = STATUS_INSUFFICIENT_RESOURCES;
382 }
383 else
384 {
385 /* allocate a work item */
386 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
387
388 if (!Ctx->WorkItem)
389 {
390 /* no memory */
391 FreeItem(Ctx);
392 Ctx = NULL;
393 Status = STATUS_INSUFFICIENT_RESOURCES;
394 }
395 else
396 {
397 /* store device header for post-start pnp processing */
398 Ctx->DeviceHeader = DeviceHeader;
399 }
400 }
401 }
402 else
403 {
404 /* set state to enabled, IRP_MJ_CREATE request may now succeed */
405 DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
406 Status = KspSetFilterFactoriesState(DeviceHeader, TRUE);
407 }
408 }
409 }
410
411 /* store result */
412 Irp->IoStatus.Status = Status;
413 /* complete request */
414 IoCompleteRequest(Irp, IO_NO_INCREMENT);
415
416 if (Ctx)
417 {
418 /* queue a work item for driver post start routine */
419 IoQueueWorkItem(Ctx->WorkItem, IKsDevice_PnpPostStart, DelayedWorkQueue, (PVOID)Ctx);
420 }
421
422 /* return result */
423 DPRINT1("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
424 return Status;
425 }
426
427 NTSTATUS
428 NTAPI
429 IKsDevice_Pnp(
430 IN PDEVICE_OBJECT DeviceObject,
431 IN PIRP Irp)
432 {
433 PIO_STACK_LOCATION IoStack;
434 PDEVICE_EXTENSION DeviceExtension;
435 PKSIDEVICE_HEADER DeviceHeader;
436 PKSDEVICE_DISPATCH Dispatch = NULL;
437 NTSTATUS Status;
438
439 /* get current stack location */
440 IoStack = IoGetCurrentIrpStackLocation(Irp);
441
442 /* get device extension */
443 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
444 /* get device header */
445 DeviceHeader = DeviceExtension->DeviceHeader;
446
447 /* do we have a device descriptor */
448 if (DeviceHeader->KsDevice.Descriptor && DeviceHeader->KsDevice.Descriptor->Dispatch)
449 {
450 /* does the device want pnp notifications */
451 Dispatch = (PKSDEVICE_DISPATCH)DeviceHeader->KsDevice.Descriptor->Dispatch;
452 }
453
454 switch (IoStack->MinorFunction)
455 {
456 case IRP_MN_START_DEVICE:
457 {
458 return IKsDevice_PnpStartDevice(DeviceObject, Irp);
459 }
460
461 case IRP_MN_QUERY_STOP_DEVICE:
462 {
463 Status = STATUS_SUCCESS;
464 /* check for pnp notification support */
465 if (Dispatch)
466 {
467 /* check for query stop support */
468 if (Dispatch->QueryStop)
469 {
470 /* call driver's query stop */
471 Status = Dispatch->QueryStop(&DeviceHeader->KsDevice, Irp);
472 ASSERT(Status != STATUS_PENDING);
473 }
474 }
475
476 if (!NT_SUCCESS(Status))
477 {
478 DPRINT1("Driver: query stop failed %x\n", Status);
479 Irp->IoStatus.Status = Status;
480 IoCompleteRequest(Irp, IO_NO_INCREMENT);
481 return Status;
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 Irp->IoStatus.Status = Status;
490 IoCompleteRequest(Irp, IO_NO_INCREMENT);
491 return Status;
492 }
493
494 case IRP_MN_REMOVE_DEVICE:
495 {
496 /* Clean up */
497 if (Dispatch)
498 {
499 /* check for remove support */
500 if (Dispatch->Remove)
501 {
502 /* call driver's stop routine */
503 Dispatch->Remove(&DeviceHeader->KsDevice, Irp);
504 }
505 }
506
507 /* pass the irp down the driver stack */
508 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
509
510 DPRINT("Next Device: Status %x\n", Status);
511
512 /* FIXME delete device resources */
513
514
515 Irp->IoStatus.Status = Status;
516 IoCompleteRequest(Irp, IO_NO_INCREMENT);
517 return Status;
518 }
519 case IRP_MN_QUERY_INTERFACE:
520 {
521 Status = STATUS_UNSUCCESSFUL;
522 /* check for pnp notification support */
523 if (Dispatch)
524 {
525 /* check for query interface support */
526 if (Dispatch->QueryInterface)
527 {
528 /* call driver's query interface */
529 Status = Dispatch->QueryInterface(&DeviceHeader->KsDevice, Irp);
530 ASSERT(Status != STATUS_PENDING);
531 }
532 }
533
534 if (NT_SUCCESS(Status))
535 {
536 /* driver supports a private interface */
537 DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n");
538 Irp->IoStatus.Status = Status;
539 IoCompleteRequest(Irp, IO_NO_INCREMENT);
540 return Status;
541 }
542
543 /* pass the irp down the driver stack */
544 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
545
546 DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status);
547 Irp->IoStatus.Status = Status;
548 IoCompleteRequest(Irp, IO_NO_INCREMENT);
549 return Status;
550 }
551 case IRP_MN_QUERY_DEVICE_RELATIONS:
552 {
553 /* pass the irp down the driver stack */
554 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
555
556 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status);
557
558 //Irp->IoStatus.Status = Status;
559 IoCompleteRequest(Irp, IO_NO_INCREMENT);
560 return Status;
561 }
562 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
563 {
564 /* pass the irp down the driver stack */
565 //Status = KspForwardIrpSynchronous(DeviceObject, Irp);
566 Status = Irp->IoStatus.Status;
567 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
568
569 //Irp->IoStatus.Status = Status;
570 IoCompleteRequest(Irp, IO_NO_INCREMENT);
571 return Status;
572 }
573 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
574 {
575 /* pass the irp down the driver stack */
576 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
577
578 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
579
580 Irp->IoStatus.Status = Status;
581 IoCompleteRequest(Irp, IO_NO_INCREMENT);
582 return Status;
583 }
584 default:
585 DPRINT1("unhandled function %u\n", IoStack->MinorFunction);
586 /* pass the irp down the driver stack */
587 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
588
589 Irp->IoStatus.Status = Status;
590 IoCompleteRequest(Irp, IO_NO_INCREMENT);
591 return Status;
592 }
593 }
594
595 NTSTATUS
596 NTAPI
597 IKsDevice_Power(
598 IN PDEVICE_OBJECT DeviceObject,
599 IN PIRP Irp)
600 {
601 UNIMPLEMENTED
602
603 /* TODO */
604
605 Irp->IoStatus.Status = STATUS_SUCCESS;
606 Irp->IoStatus.Information = 0;
607 IoCompleteRequest(Irp, IO_NO_INCREMENT);
608
609 return STATUS_SUCCESS;
610 }
611
612 NTSTATUS
613 NTAPI
614 IKsDevice_Create(
615 IN PDEVICE_OBJECT DeviceObject,
616 IN PIRP Irp)
617 {
618 PCREATE_ITEM_ENTRY CreateItemEntry;
619 PIO_STACK_LOCATION IoStack;
620 PDEVICE_EXTENSION DeviceExtension;
621 PKSIDEVICE_HEADER DeviceHeader;
622 PKSIOBJECT_HEADER ObjectHeader;
623 NTSTATUS Status;
624
625 DPRINT("IKsDevice_Create\n");
626 /* get current stack location */
627 IoStack = IoGetCurrentIrpStackLocation(Irp);
628 /* get device extension */
629 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
630 /* get device header */
631 DeviceHeader = DeviceExtension->DeviceHeader;
632
633 /* acquire list lock */
634 IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
635
636 /* sanity check */
637 ASSERT(IoStack->FileObject);
638
639 /* check if the request is relative */
640 if (IoStack->FileObject->RelatedFileObject != NULL)
641 {
642 /* request is to instantiate a pin / node / clock / allocator */
643 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
644
645 /* sanity check */
646 ASSERT(ObjectHeader);
647
648 /* find a matching a create item */
649 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
650 }
651 else
652 {
653 /* request to create a filter */
654 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
655 }
656
657 if (NT_SUCCESS(Status))
658 {
659 /* set object create item */
660 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
661
662 /* call create function */
663 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
664
665 if (NT_SUCCESS(Status))
666 {
667 /* increment create item reference count */
668 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
669 }
670 }
671
672 /* acquire list lock */
673 IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
674
675 if (Status != STATUS_PENDING)
676 {
677 Irp->IoStatus.Information = 0;
678 /* set return status */
679 Irp->IoStatus.Status = Status;
680 IoCompleteRequest(Irp, IO_NO_INCREMENT);
681 }
682
683 return Status;
684
685
686 }
687
688 /*
689 @implemented
690 */
691 KSDDKAPI
692 NTSTATUS
693 NTAPI
694 KsInitializeDevice(
695 IN PDEVICE_OBJECT FunctionalDeviceObject,
696 IN PDEVICE_OBJECT PhysicalDeviceObject,
697 IN PDEVICE_OBJECT NextDeviceObject,
698 IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
699 {
700 PDEVICE_EXTENSION DeviceExtension;
701 PKSIDEVICE_HEADER Header;
702 ULONG Index;
703 PKSIOBJECT_BAG Bag;
704 NTSTATUS Status = STATUS_SUCCESS;
705
706 DPRINT("KsInitializeDevice Descriptor %p\n", Descriptor);
707
708 /* get device extension */
709 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
710
711 /* first allocate device header */
712 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 0, NULL);
713
714 /* point to allocated header */
715 Header = DeviceExtension->DeviceHeader;
716
717 DPRINT("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
718
719 if (Descriptor && Descriptor->Dispatch)
720 {
721 DPRINT("Descriptor Add %p\n", Descriptor->Dispatch->Add);
722 DPRINT("Descriptor Start %p\n", Descriptor->Dispatch->Start);
723 DPRINT("Descriptor PostStart %p\n", Descriptor->Dispatch->PostStart);
724 DPRINT("Descriptor QueryStop %p\n", Descriptor->Dispatch->QueryStop);
725 DPRINT("Descriptor CancelStop %p\n", Descriptor->Dispatch->CancelStop);
726 DPRINT("Descriptor Stop %p\n", Descriptor->Dispatch->Stop);
727 DPRINT("Descriptor QueryRemove %p\n", Descriptor->Dispatch->QueryRemove);
728 DPRINT("Descriptor CancelRemove %p\n", Descriptor->Dispatch->CancelRemove);
729 DPRINT("Descriptor Remove %p\n", Descriptor->Dispatch->Remove);
730 DPRINT("Descriptor QueryCapabilities %p\n", Descriptor->Dispatch->QueryCapabilities);
731 DPRINT("Descriptor SurpriseRemoval %p\n", Descriptor->Dispatch->SurpriseRemoval);
732 DPRINT("Descriptor QueryPower %p\n", Descriptor->Dispatch->QueryPower);
733 DPRINT("Descriptor SetPower %p\n", Descriptor->Dispatch->SetPower);
734 DPRINT("Descriptor QueryInterface %p\n", Descriptor->Dispatch->QueryInterface);
735 }
736
737 /* check for success */
738 if (!NT_SUCCESS(Status))
739 {
740 DPRINT1("KsInitializeDevice Failed to allocate device header with %x\n", Status);
741 return Status;
742 }
743
744 /* initialize IKsDevice interface */
745 Header->BasicHeader.OuterUnknown = (PUNKNOWN)&vt_IKsDevice;
746 Header->ref = 1;
747
748 /* allocate object bag */
749 Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
750 if (!Header->KsDevice.Bag)
751 {
752 /* no memory */
753 KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader);
754 return STATUS_INSUFFICIENT_RESOURCES;
755 }
756
757 /* initialize object bag */
758 KeInitializeMutex(&Header->BagMutex, 0);
759 KeInitializeMutex(&Header->DeviceMutex, 0);
760
761 Bag = (PKSIOBJECT_BAG)Header->KsDevice.Bag;
762 Bag->BagMutex = &Header->BagMutex;
763 InitializeListHead(&Header->ObjectBags);
764 InitializeListHead(&Bag->ObjectList);
765 Bag->DeviceHeader = (PVOID)Header;
766
767 /* insert bag into device list */
768 InsertTailList(&Header->ObjectBags, &Bag->Entry);
769
770 /* initialize device header */
771 Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
772 Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
773 Header->KsDevice.NextDeviceObject = NextDeviceObject;
774 Header->KsDevice.Descriptor = Descriptor;
775 Header->KsDevice.SystemPowerState = PowerSystemWorking;
776 Header->KsDevice.DevicePowerState = PowerDeviceD0;
777 Header->KsDevice.Started = FALSE;
778 Header->KsDevice.Context = NULL;
779 KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
780
781
782
783 if (Descriptor)
784 {
785 /* create a filter factory for each filter descriptor */
786 DPRINT("KsInitializeDevice FilterDescriptorCount %lu\n", Descriptor->FilterDescriptorsCount);
787 for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
788 {
789 Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
790
791 DPRINT("KsInitializeDevice Index %lu KspCreateFilterFactory Status %lx\n", Index, Status);
792 /* check for success */
793 if (!NT_SUCCESS(Status))
794 {
795 DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
796 /* FIXME memory leak */
797 return Status;
798 }
799 }
800
801 /* does the driver pnp notification */
802 if (Descriptor->Dispatch)
803 {
804 /* does the driver care about the add device */
805 Status = Descriptor->Dispatch->Add(&Header->KsDevice);
806
807 DPRINT("Driver: AddHandler Status %x\n", Status);
808 Header->KsDevice.Descriptor = Descriptor;
809 }
810 }
811
812
813 return Status;
814 }
815
816 /*
817 @implemented
818 */
819 KSDDKAPI
820 NTSTATUS
821 NTAPI
822 KsReferenceSoftwareBusObject(
823 IN KSDEVICE_HEADER Header)
824 {
825 IKsDevice * Device;
826 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
827
828 /* get device interface */
829 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
830
831 if (Device)
832 {
833 /* reference device interface */
834 Device->lpVtbl->AddRef(Device);
835 }
836
837 return STATUS_SUCCESS;
838 }
839
840 /*
841 @implemented
842 */
843 KSDDKAPI
844 NTSTATUS
845 NTAPI
846 KsReferenceBusObject(
847 IN KSDEVICE_HEADER Header)
848 {
849 IKsDevice * Device;
850 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
851
852 /* get device interface */
853 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
854
855 if (Device)
856 {
857 /* reference device interface */
858 Device->lpVtbl->AddRef(Device);
859 }
860
861 return STATUS_SUCCESS;
862
863 }
864
865 /*
866 @implemented
867 */
868 KSDDKAPI
869 VOID
870 NTAPI
871 KsDereferenceBusObject(
872 IN KSDEVICE_HEADER Header)
873 {
874 IKsDevice * Device;
875 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
876
877 /* get device interface */
878 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
879
880 if (Device)
881 {
882 /* release device interface */
883 Device->lpVtbl->Release(Device);
884 }
885 }
886
887 /*
888 @implemented
889 */
890 KSDDKAPI
891 VOID
892 NTAPI
893 KsDereferenceSoftwareBusObject(
894 IN KSDEVICE_HEADER Header)
895 {
896 IKsDevice * Device;
897 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
898
899 DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
900
901 /* get device interface */
902 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
903
904 if (Device)
905 {
906 /* release device interface */
907 Device->lpVtbl->Release(Device);
908 }
909 }