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