[KS]
[reactos.git] / reactos / 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 #include "priv.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 pnp notification */
786 if (Descriptor->Dispatch)
787 {
788 /* does the driver care about the add device */
789 Status = Descriptor->Dispatch->Add(&Header->KsDevice);
790
791 DPRINT("Driver: AddHandler Status %x\n", Status);
792 Header->KsDevice.Descriptor = Descriptor;
793 }
794 }
795
796
797 return Status;
798 }
799
800 /*
801 @implemented
802 */
803 KSDDKAPI
804 NTSTATUS
805 NTAPI
806 KsReferenceSoftwareBusObject(
807 IN KSDEVICE_HEADER Header)
808 {
809 IKsDevice * Device;
810 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
811
812 /* get device interface */
813 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
814
815 if (Device)
816 {
817 /* reference device interface */
818 Device->lpVtbl->AddRef(Device);
819 }
820
821 return STATUS_SUCCESS;
822 }
823
824 /*
825 @implemented
826 */
827 KSDDKAPI
828 NTSTATUS
829 NTAPI
830 KsReferenceBusObject(
831 IN KSDEVICE_HEADER Header)
832 {
833 IKsDevice * Device;
834 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
835
836 /* get device interface */
837 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
838
839 if (Device)
840 {
841 /* reference device interface */
842 Device->lpVtbl->AddRef(Device);
843 }
844
845 return STATUS_SUCCESS;
846
847 }
848
849 /*
850 @implemented
851 */
852 KSDDKAPI
853 VOID
854 NTAPI
855 KsDereferenceBusObject(
856 IN KSDEVICE_HEADER Header)
857 {
858 IKsDevice * Device;
859 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
860
861 /* get device interface */
862 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
863
864 if (Device)
865 {
866 /* release device interface */
867 Device->lpVtbl->Release(Device);
868 }
869 }
870
871 /*
872 @implemented
873 */
874 KSDDKAPI
875 VOID
876 NTAPI
877 KsDereferenceSoftwareBusObject(
878 IN KSDEVICE_HEADER Header)
879 {
880 IKsDevice * Device;
881 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
882
883 DPRINT("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
884
885 /* get device interface */
886 Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
887
888 if (Device)
889 {
890 /* release device interface */
891 Device->lpVtbl->Release(Device);
892 }
893 }