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