Revert the sync.
[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 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
20
21 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
22 {
23 *Output = &This->lpVtblIKsDevice;
24 _InterlockedIncrement(&This->ref);
25 return STATUS_SUCCESS;
26 }
27
28 return STATUS_NOT_SUPPORTED;
29 }
30
31 ULONG
32 NTAPI
33 IKsDevice_fnAddRef(
34 IN IKsDevice * iface)
35 {
36 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
37
38 return InterlockedIncrement(&This->ref);
39 }
40
41 ULONG
42 NTAPI
43 IKsDevice_fnRelease(
44 IN IKsDevice * iface)
45 {
46 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
47
48 InterlockedDecrement(&This->ref);
49
50 return This->ref;
51 }
52
53
54
55 PKSDEVICE
56 NTAPI
57 IKsDevice_fnGetStruct(
58 IN IKsDevice * iface)
59 {
60 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
61
62 return &This->KsDevice;
63 }
64
65 NTSTATUS
66 NTAPI
67 IKsDevice_fnInitializeObjectBag(
68 IN IKsDevice * iface,
69 IN PKSIOBJECT_BAG Bag,
70 IN PRKMUTEX Mutex)
71 {
72 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
73
74 if (!Mutex)
75 {
76 /* use device mutex */
77 Mutex = &This->BagMutex;
78 }
79
80 /* initialize object bag */
81 Bag->BagMutex = Mutex;
82 Bag->DeviceHeader = (PKSIDEVICE_HEADER)This;
83 InitializeListHead(&Bag->ObjectList);
84
85 /* insert bag into device list */
86 InsertTailList(&This->ObjectBags, &Bag->Entry);
87
88 return STATUS_SUCCESS;
89 }
90
91 NTSTATUS
92 NTAPI
93 IKsDevice_fnAcquireDevice(
94 IN IKsDevice * iface)
95 {
96 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
97
98 return KeWaitForSingleObject(&This->DeviceMutex, Executive, KernelMode, FALSE, NULL);
99 }
100
101 NTSTATUS
102 NTAPI
103 IKsDevice_fnReleaseDevice(
104 IN IKsDevice * iface)
105 {
106 PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
107
108 return KeReleaseMutex(&This->DeviceMutex, FALSE);
109 }
110
111 NTSTATUS
112 NTAPI
113 IKsDevice_fnGetAdapterObject(
114 IN IKsDevice * iface,
115 IN PADAPTER_OBJECT Object,
116 IN PULONG Unknown1,
117 IN PULONG Unknown2)
118 {
119 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
120
121 UNIMPLEMENTED
122 return STATUS_NOT_IMPLEMENTED;
123
124 }
125
126 NTSTATUS
127 NTAPI
128 IKsDevice_fnAddPowerEntry(
129 IN IKsDevice * iface,
130 IN struct KSPOWER_ENTRY * Entry,
131 IN IKsPowerNotify* Notify)
132 {
133 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
134
135 UNIMPLEMENTED
136 return STATUS_NOT_IMPLEMENTED;
137 }
138
139 NTSTATUS
140 NTAPI
141 IKsDevice_fnRemovePowerEntry(
142 IN IKsDevice * iface,
143 IN struct KSPOWER_ENTRY * Entry)
144 {
145 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
146
147 UNIMPLEMENTED
148 return STATUS_NOT_IMPLEMENTED;
149
150 }
151
152 NTSTATUS
153 NTAPI
154 IKsDevice_fnPinStateChange(
155 IN IKsDevice * iface,
156 IN KSPIN Pin,
157 IN PIRP Irp,
158 IN KSSTATE OldState,
159 IN KSSTATE NewState)
160 {
161 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
162
163 UNIMPLEMENTED
164 return STATUS_NOT_IMPLEMENTED;
165
166 }
167
168 NTSTATUS
169 NTAPI
170 IKsDevice_fnArbitrateAdapterChannel(
171 IN IKsDevice * iface,
172 IN ULONG ControlCode,
173 IN IO_ALLOCATION_ACTION Action,
174 IN PVOID Context)
175 {
176 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
177
178 UNIMPLEMENTED
179 return STATUS_NOT_IMPLEMENTED;
180
181 }
182
183 NTSTATUS
184 NTAPI
185 IKsDevice_fnCheckIoCapability(
186 IN IKsDevice * iface,
187 IN ULONG Unknown)
188 {
189 //PKSIDEVICE_HEADER This = (PKSIDEVICE_HEADER)CONTAINING_RECORD(iface, KSIDEVICE_HEADER, lpVtblIKsDevice);
190
191 UNIMPLEMENTED
192 return STATUS_NOT_IMPLEMENTED;
193 }
194
195 static IKsDeviceVtbl vt_IKsDevice =
196 {
197 IKsDevice_fnQueryInterface,
198 IKsDevice_fnAddRef,
199 IKsDevice_fnRelease,
200 IKsDevice_fnGetStruct,
201 IKsDevice_fnInitializeObjectBag,
202 IKsDevice_fnAcquireDevice,
203 IKsDevice_fnReleaseDevice,
204 IKsDevice_fnGetAdapterObject,
205 IKsDevice_fnAddPowerEntry,
206 IKsDevice_fnRemovePowerEntry,
207 IKsDevice_fnPinStateChange,
208 IKsDevice_fnArbitrateAdapterChannel,
209 IKsDevice_fnCheckIoCapability
210 };
211
212
213 VOID
214 NTAPI
215 IKsDevice_PnpPostStart(
216 IN PDEVICE_OBJECT DeviceObject,
217 IN PVOID Context)
218 {
219 NTSTATUS Status;
220 PPNP_POSTSTART_CONTEXT Ctx = (PPNP_POSTSTART_CONTEXT)Context;
221
222 /* call driver pnp post routine */
223 Status = Ctx->DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart(&Ctx->DeviceHeader->KsDevice);
224
225 if (!NT_SUCCESS(Status))
226 {
227 /* set state to disabled */
228 Ctx->DeviceHeader->TargetState = KSTARGET_STATE_DISABLED;
229 }
230 else
231 {
232 /* set state to enabled */
233 Ctx->DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
234 Status = KspSetFilterFactoriesState(Ctx->DeviceHeader, TRUE);
235 }
236
237 /* free work item */
238 IoFreeWorkItem(Ctx->WorkItem);
239
240 /* free work context */
241 FreeItem(Ctx);
242
243 DPRINT("IKsDevice_PnpPostStart: PostStart Routine returned %x\n", Status);
244 }
245
246 NTSTATUS
247 NTAPI
248 IKsDevice_PnpStartDevice(
249 IN PDEVICE_OBJECT DeviceObject,
250 IN PIRP Irp)
251 {
252 PIO_STACK_LOCATION IoStack;
253 PDEVICE_EXTENSION DeviceExtension;
254 PKSIDEVICE_HEADER DeviceHeader;
255 PPNP_POSTSTART_CONTEXT Ctx = NULL;
256 NTSTATUS Status;
257 PCM_RESOURCE_LIST TranslatedResourceList;
258 PCM_RESOURCE_LIST UntranslatedResourceList;
259 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
260 ULONG Index;
261
262 /* get current stack location */
263 IoStack = IoGetCurrentIrpStackLocation(Irp);
264 /* get device extension */
265 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
266 /* get device header */
267 DeviceHeader = DeviceExtension->DeviceHeader;
268
269 DPRINT("IKsDevice_PnpStartDevice DeviceHeader %p\n", DeviceHeader);
270
271 /* first forward irp to lower device object */
272 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
273
274 /* check for success */
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("NextDevice object failed to start with %x\n", Status);
278 Irp->IoStatus.Status = Status;
279 IoCompleteRequest(Irp, IO_NO_INCREMENT);
280 return Status;
281 }
282
283 TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
284 UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
285
286 DPRINT("ResourceDescriptorCount %lu\n", TranslatedResourceList->List[0].PartialResourceList.Count);
287 for (Index = 0; Index < TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
288 {
289 PartialDescriptor = &TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
290 UnPartialDescriptor = &UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
291 DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
292
293 if (PartialDescriptor->Type == CmResourceTypeInterrupt)
294 {
295 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);
296 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);
297
298 }
299 else if (PartialDescriptor->Type == CmResourceTypePort)
300 {
301 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);
302 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);
303 }
304 else if (PartialDescriptor->Type == CmResourceTypeMemory)
305 {
306 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);
307 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);
308 }
309 }
310
311 ASSERT(DeviceHeader->KsDevice.Descriptor);
312 ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch);
313 ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch->Start);
314
315
316 /* do we have a device descriptor */
317 if (DeviceHeader->KsDevice.Descriptor)
318 {
319 /* does the device want pnp notifications */
320 if (DeviceHeader->KsDevice.Descriptor->Dispatch)
321 {
322 /* does the driver care about IRP_MN_START_DEVICE */
323 if (DeviceHeader->KsDevice.Descriptor->Dispatch->Start)
324 {
325 /* call driver start device routine */
326 Status = DeviceHeader->KsDevice.Descriptor->Dispatch->Start(&DeviceHeader->KsDevice, Irp,
327 TranslatedResourceList,
328 UntranslatedResourceList);
329
330
331 DPRINT("IKsDevice_PnpStartDevice Start %p, Context %p\n", DeviceHeader->KsDevice.Descriptor->Dispatch->Start, DeviceHeader->KsDevice.Context);
332 ASSERT(Status != STATUS_PENDING);
333
334 if (!NT_SUCCESS(Status))
335 {
336 DPRINT1("Driver: failed to start %x\n", Status);
337 Irp->IoStatus.Status = Status;
338 IoCompleteRequest(Irp, IO_NO_INCREMENT);
339 return Status;
340 }
341
342 /* set state to run */
343 DeviceHeader->KsDevice.Started = TRUE;
344
345 }
346
347 /* does the driver need post start routine */
348 if (DeviceHeader->KsDevice.Descriptor->Dispatch->PostStart)
349 {
350 /* allocate pnp post workitem context */
351 Ctx = (PPNP_POSTSTART_CONTEXT)AllocateItem(NonPagedPool, sizeof(PNP_POSTSTART_CONTEXT));
352 if (!Ctx)
353 {
354 /* no memory */
355 Status = STATUS_INSUFFICIENT_RESOURCES;
356 }
357 else
358 {
359 /* allocate a work item */
360 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
361
362 if (!Ctx->WorkItem)
363 {
364 /* no memory */
365 FreeItem(Ctx);
366 Ctx = NULL;
367 Status = STATUS_INSUFFICIENT_RESOURCES;
368 }
369 else
370 {
371 /* store device header for post-start pnp processing */
372 Ctx->DeviceHeader = DeviceHeader;
373 }
374 }
375 }
376 else
377 {
378 /* set state to enabled, IRP_MJ_CREATE request may now succeed */
379 DeviceHeader->TargetState = KSTARGET_STATE_ENABLED;
380 Status = KspSetFilterFactoriesState(DeviceHeader, TRUE);
381 }
382 }
383 }
384
385 /* store result */
386 Irp->IoStatus.Status = Status;
387 /* complete request */
388 IoCompleteRequest(Irp, IO_NO_INCREMENT);
389
390 if (Ctx)
391 {
392 /* queue a work item for driver post start routine */
393 IoQueueWorkItem(Ctx->WorkItem, IKsDevice_PnpPostStart, DelayedWorkQueue, (PVOID)Ctx);
394 }
395
396 /* return result */
397 DPRINT1("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
398 return Status;
399 }
400
401 NTSTATUS
402 NTAPI
403 IKsDevice_Pnp(
404 IN PDEVICE_OBJECT DeviceObject,
405 IN PIRP Irp)
406 {
407 PIO_STACK_LOCATION IoStack;
408 PDEVICE_EXTENSION DeviceExtension;
409 PKSIDEVICE_HEADER DeviceHeader;
410 PKSDEVICE_DISPATCH Dispatch = NULL;
411 NTSTATUS Status;
412
413 /* get current stack location */
414 IoStack = IoGetCurrentIrpStackLocation(Irp);
415
416 /* get device extension */
417 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
418 /* get device header */
419 DeviceHeader = DeviceExtension->DeviceHeader;
420
421 /* do we have a device descriptor */
422 if (DeviceHeader->KsDevice.Descriptor && DeviceHeader->KsDevice.Descriptor->Dispatch)
423 {
424 /* does the device want pnp notifications */
425 Dispatch = (PKSDEVICE_DISPATCH)DeviceHeader->KsDevice.Descriptor->Dispatch;
426 }
427
428 switch (IoStack->MinorFunction)
429 {
430 case IRP_MN_START_DEVICE:
431 {
432 return IKsDevice_PnpStartDevice(DeviceObject, Irp);
433 }
434
435 case IRP_MN_QUERY_STOP_DEVICE:
436 {
437 Status = STATUS_SUCCESS;
438 /* check for pnp notification support */
439 if (Dispatch)
440 {
441 /* check for query stop support */
442 if (Dispatch->QueryStop)
443 {
444 /* call driver's query stop */
445 Status = Dispatch->QueryStop(&DeviceHeader->KsDevice, Irp);
446 ASSERT(Status != STATUS_PENDING);
447 }
448 }
449
450 if (!NT_SUCCESS(Status))
451 {
452 DPRINT1("Driver: query stop failed %x\n", Status);
453 Irp->IoStatus.Status = Status;
454 IoCompleteRequest(Irp, IO_NO_INCREMENT);
455 return Status;
456 }
457
458 /* pass the irp down the driver stack */
459 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
460
461 DPRINT("Next Device: Status %x\n", Status);
462
463 Irp->IoStatus.Status = Status;
464 IoCompleteRequest(Irp, IO_NO_INCREMENT);
465 return Status;
466 }
467
468 case IRP_MN_REMOVE_DEVICE:
469 {
470 /* Clean up */
471 if (Dispatch)
472 {
473 /* check for remove support */
474 if (Dispatch->Remove)
475 {
476 /* call driver's stop routine */
477 Dispatch->Remove(&DeviceHeader->KsDevice, Irp);
478 }
479 }
480
481 /* pass the irp down the driver stack */
482 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
483
484 DPRINT("Next Device: Status %x\n", Status);
485
486 /* FIXME delete device resources */
487
488
489 Irp->IoStatus.Status = Status;
490 IoCompleteRequest(Irp, IO_NO_INCREMENT);
491 return Status;
492 }
493 case IRP_MN_QUERY_INTERFACE:
494 {
495 Status = STATUS_SUCCESS;
496 /* check for pnp notification support */
497 if (Dispatch)
498 {
499 /* check for query interface support */
500 if (Dispatch->QueryInterface)
501 {
502 /* call driver's query interface */
503 Status = Dispatch->QueryInterface(&DeviceHeader->KsDevice, Irp);
504 ASSERT(Status != STATUS_PENDING);
505 }
506 }
507
508 if (NT_SUCCESS(Status))
509 {
510 /* driver supports a private interface */
511 Irp->IoStatus.Status = Status;
512 IoCompleteRequest(Irp, IO_NO_INCREMENT);
513 return Status;
514 }
515
516 /* pass the irp down the driver stack */
517 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
518
519 DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status);
520
521 Irp->IoStatus.Status = Status;
522 IoCompleteRequest(Irp, IO_NO_INCREMENT);
523 return Status;
524 }
525 case IRP_MN_QUERY_DEVICE_RELATIONS:
526 {
527 /* pass the irp down the driver stack */
528 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
529
530 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status);
531
532 //Irp->IoStatus.Status = Status;
533 IoCompleteRequest(Irp, IO_NO_INCREMENT);
534 return Status;
535 }
536 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
537 {
538 /* pass the irp down the driver stack */
539 //Status = KspForwardIrpSynchronous(DeviceObject, Irp);
540 Status = Irp->IoStatus.Status;
541 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
542
543 //Irp->IoStatus.Status = Status;
544 IoCompleteRequest(Irp, IO_NO_INCREMENT);
545 return Status;
546 }
547 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
548 {
549 /* pass the irp down the driver stack */
550 Status = KspForwardIrpSynchronous(DeviceObject, Irp);
551
552 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
553
554 Irp->IoStatus.Status = Status;
555 IoCompleteRequest(Irp, IO_NO_INCREMENT);
556 return Status;
557 }
558 default:
559 DPRINT1("unhandled function %u\n", IoStack->MinorFunction);
560 IoCompleteRequest(Irp, IO_NO_INCREMENT);
561 return STATUS_NOT_SUPPORTED;
562 }
563 }
564
565 NTSTATUS
566 NTAPI
567 IKsDevice_Power(
568 IN PDEVICE_OBJECT DeviceObject,
569 IN PIRP Irp)
570 {
571 UNIMPLEMENTED
572
573 /* TODO */
574
575 Irp->IoStatus.Status = STATUS_SUCCESS;
576 Irp->IoStatus.Information = 0;
577 IoCompleteRequest(Irp, IO_NO_INCREMENT);
578
579 return STATUS_SUCCESS;
580 }
581
582 NTSTATUS
583 NTAPI
584 IKsDevice_Create(
585 IN PDEVICE_OBJECT DeviceObject,
586 IN PIRP Irp)
587 {
588 PCREATE_ITEM_ENTRY CreateItemEntry;
589 PIO_STACK_LOCATION IoStack;
590 PDEVICE_EXTENSION DeviceExtension;
591 PKSIDEVICE_HEADER DeviceHeader;
592 PKSIOBJECT_HEADER ObjectHeader;
593 NTSTATUS Status;
594
595 DPRINT("IKsDevice_Create\n");
596 /* get current stack location */
597 IoStack = IoGetCurrentIrpStackLocation(Irp);
598 /* get device extension */
599 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
600 /* get device header */
601 DeviceHeader = DeviceExtension->DeviceHeader;
602
603 /* acquire list lock */
604 IKsDevice_fnAcquireDevice((IKsDevice*)&DeviceHeader->lpVtblIKsDevice);
605
606 /* sanity check */
607 ASSERT(IoStack->FileObject);
608
609 /* check if the request is relative */
610 if (IoStack->FileObject->RelatedFileObject != NULL)
611 {
612 /* request is to instantiate a pin / node / clock / allocator */
613 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
614
615 /* sanity check */
616 ASSERT(ObjectHeader);
617
618 /* find a matching a create item */
619 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
620 }
621 else
622 {
623 /* request to create a filter */
624 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
625 }
626
627 if (NT_SUCCESS(Status))
628 {
629 /* set object create item */
630 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
631
632 /* call create function */
633 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
634
635 if (NT_SUCCESS(Status))
636 {
637 /* increment create item reference count */
638 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
639 }
640 }
641
642 /* acquire list lock */
643 IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->lpVtblIKsDevice);
644
645 if (Status != STATUS_PENDING)
646 {
647 Irp->IoStatus.Information = 0;
648 /* set return status */
649 Irp->IoStatus.Status = Status;
650 IoCompleteRequest(Irp, IO_NO_INCREMENT);
651 }
652
653 return Status;
654
655
656 }
657
658 /*
659 @implemented
660 */
661 KSDDKAPI
662 NTSTATUS
663 NTAPI
664 KsInitializeDevice(
665 IN PDEVICE_OBJECT FunctionalDeviceObject,
666 IN PDEVICE_OBJECT PhysicalDeviceObject,
667 IN PDEVICE_OBJECT NextDeviceObject,
668 IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL)
669 {
670 PDEVICE_EXTENSION DeviceExtension;
671 PKSIDEVICE_HEADER Header;
672 ULONG Index;
673 PKSIOBJECT_BAG Bag;
674 NTSTATUS Status = STATUS_SUCCESS;
675
676 DPRINT("KsInitializeDevice Descriptor %p\n", Descriptor);
677
678 /* get device extension */
679 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
680
681 /* first allocate device header */
682 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 0, NULL);
683
684 /* point to allocated header */
685 Header = DeviceExtension->DeviceHeader;
686
687 DPRINT("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
688
689
690 /* check for success */
691 if (!NT_SUCCESS(Status))
692 {
693 DPRINT1("KsInitializeDevice Failed to allocate device header with %x\n", Status);
694 return Status;
695 }
696
697 /* initialize IKsDevice interface */
698 Header->lpVtblIKsDevice = &vt_IKsDevice;
699 Header->ref = 1;
700
701 /* allocate object bag */
702 Header->KsDevice.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
703 if (!Header->KsDevice.Bag)
704 {
705 /* no memory */
706 KsFreeDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader);
707 return STATUS_INSUFFICIENT_RESOURCES;
708 }
709
710 /* initialize object bag */
711 KeInitializeMutex(&Header->BagMutex, 0);
712 KeInitializeMutex(&Header->DeviceMutex, 0);
713
714 Bag = (PKSIOBJECT_BAG)Header->KsDevice.Bag;
715 Bag->BagMutex = &Header->BagMutex;
716 InitializeListHead(&Header->ObjectBags);
717 InitializeListHead(&Bag->ObjectList);
718 Bag->DeviceHeader = (PVOID)Header;
719
720 /* insert bag into device list */
721 InsertTailList(&Header->ObjectBags, &Bag->Entry);
722
723 /* initialize device header */
724 Header->KsDevice.FunctionalDeviceObject = FunctionalDeviceObject;
725 Header->KsDevice.PhysicalDeviceObject = PhysicalDeviceObject;
726 Header->KsDevice.NextDeviceObject = NextDeviceObject;
727 Header->KsDevice.Descriptor = Descriptor;
728 Header->KsDevice.SystemPowerState = PowerSystemWorking;
729 Header->KsDevice.DevicePowerState = PowerDeviceD0;
730 Header->KsDevice.Started = FALSE;
731 Header->KsDevice.Context = NULL;
732 KsSetDevicePnpAndBaseObject(Header, PhysicalDeviceObject, NextDeviceObject);
733
734
735
736 if (Descriptor)
737 {
738 /* create a filter factory for each filter descriptor */
739 DPRINT("KsInitializeDevice FilterDescriptorCount %lu\n", Descriptor->FilterDescriptorsCount);
740 for(Index = 0; Index < Descriptor->FilterDescriptorsCount; Index++)
741 {
742 Status = KspCreateFilterFactory(FunctionalDeviceObject, Descriptor->FilterDescriptors[Index], NULL, NULL, 0, NULL, NULL, NULL);
743
744 DPRINT("KsInitializeDevice Index %lu KspCreateFilterFactory Status %lx\n", Index, Status);
745 /* check for success */
746 if (!NT_SUCCESS(Status))
747 {
748 DPRINT1("KspCreateFilterFactory failed with %x\n", Status);
749 /* FIXME memory leak */
750 return Status;
751 }
752 }
753
754 /* does the driver pnp notification */
755 if (Descriptor->Dispatch)
756 {
757 /* does the driver care about the add device */
758 Status = Descriptor->Dispatch->Add(&Header->KsDevice);
759
760 DPRINT("Driver: AddHandler Status %x\n", Status);
761 Header->KsDevice.Descriptor = Descriptor;
762 }
763 }
764
765
766 return Status;
767 }
768
769 /*
770 @implemented
771 */
772 KSDDKAPI
773 NTSTATUS
774 NTAPI
775 KsReferenceSoftwareBusObject(
776 IN KSDEVICE_HEADER Header)
777 {
778 IKsDevice * Device;
779 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
780
781 /* get device interface */
782 Device = (IKsDevice*)DeviceHeader->lpVtblIKsDevice;
783
784 if (Device)
785 {
786 /* reference device interface */
787 Device->lpVtbl->AddRef(Device);
788 }
789
790 return STATUS_SUCCESS;
791 }
792
793 /*
794 @implemented
795 */
796 KSDDKAPI
797 NTSTATUS
798 NTAPI
799 KsReferenceBusObject(
800 IN KSDEVICE_HEADER Header)
801 {
802 IKsDevice * Device;
803 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
804
805 /* get device interface */
806 Device = (IKsDevice*)DeviceHeader->lpVtblIKsDevice;
807
808 if (Device)
809 {
810 /* reference device interface */
811 Device->lpVtbl->AddRef(Device);
812 }
813
814 return STATUS_SUCCESS;
815
816 }
817
818 /*
819 @implemented
820 */
821 KSDDKAPI
822 VOID
823 NTAPI
824 KsDereferenceBusObject(
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->lpVtblIKsDevice;
832
833 if (Device)
834 {
835 /* release device interface */
836 Device->lpVtbl->Release(Device);
837 }
838 }
839
840 /*
841 @implemented
842 */
843 KSDDKAPI
844 VOID
845 NTAPI
846 KsDereferenceSoftwareBusObject(
847 IN KSDEVICE_HEADER Header)
848 {
849 IKsDevice * Device;
850 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
851
852 DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
853
854 /* get device interface */
855 Device = (IKsDevice*)DeviceHeader->lpVtblIKsDevice;
856
857 if (Device)
858 {
859 /* release device interface */
860 Device->lpVtbl->Release(Device);
861 }
862 }