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