- Rewrite KsDefaultDispatchPnp to make it actually work
[reactos.git] / reactos / drivers / ksfilter / ks / api.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/api.c
5 * PURPOSE: KS API functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12
13 /*
14 @unimplemented
15 */
16 KSDDKAPI
17 NTSTATUS
18 NTAPI
19 KsAcquireResetValue(
20 IN PIRP Irp,
21 OUT KSRESET* ResetValue)
22 {
23 UNIMPLEMENTED;
24 return STATUS_UNSUCCESSFUL;
25 }
26
27 /*
28 @implemented
29 */
30 KSDDKAPI
31 VOID
32 NTAPI
33 KsAcquireDeviceSecurityLock(
34 IN KSDEVICE_HEADER DevHeader,
35 IN BOOLEAN Exclusive)
36 {
37 NTSTATUS Status;
38 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
39
40 KeEnterCriticalRegion();
41
42 if (Exclusive)
43 {
44 Status = ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
45 }
46 else
47 {
48 Status = ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
49 }
50 }
51
52 /*
53 @implemented
54 */
55 KSDDKAPI
56 VOID
57 NTAPI
58 KsReleaseDeviceSecurityLock(
59 IN KSDEVICE_HEADER DevHeader)
60 {
61 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
62
63 ExReleaseResourceLite(&Header->SecurityLock);
64 KeLeaveCriticalRegion();
65 }
66
67 /*
68 @implemented
69 */
70 KSDDKAPI
71 NTSTATUS
72 NTAPI
73 KsDefaultDispatchPnp(
74 IN PDEVICE_OBJECT DeviceObject,
75 IN PIRP Irp)
76 {
77 PDEVICE_EXTENSION DeviceExtension;
78 PKSIDEVICE_HEADER DeviceHeader;
79 PIO_STACK_LOCATION IoStack;
80 PDEVICE_OBJECT PnpDeviceObject;
81 NTSTATUS Status;
82 ULONG MinorFunction;
83
84 /* get current irp stack */
85 IoStack = IoGetCurrentIrpStackLocation(Irp);
86
87 /* caller wants to add the target device */
88 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
89
90 /* get device header */
91 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
92
93 /* backup PnpBaseObject */
94 PnpDeviceObject = DeviceHeader->PnpDeviceObject;
95
96
97 /* backup minor function code */
98 MinorFunction = IoStack->MinorFunction;
99
100 if(MinorFunction == IRP_MN_REMOVE_DEVICE)
101 {
102 /* remove the device */
103 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
104 }
105
106 /* skip current irp stack */
107 IoSkipCurrentIrpStackLocation(Irp);
108
109 /* call attached pnp device object */
110 Status = IoCallDriver(PnpDeviceObject, Irp);
111
112 if (MinorFunction == IRP_MN_REMOVE_DEVICE)
113 {
114 /* time is over */
115 IoDetachDevice(PnpDeviceObject);
116 /* delete device */
117 IoDeleteDevice(DeviceObject);
118 }
119 /* done */
120 return Status;
121 }
122
123 /*
124 @implemented
125 */
126 KSDDKAPI
127 NTSTATUS
128 NTAPI
129 KsDefaultDispatchPower(
130 IN PDEVICE_OBJECT DeviceObject,
131 IN PIRP Irp)
132 {
133 PDEVICE_EXTENSION DeviceExtension;
134 PKSIDEVICE_HEADER DeviceHeader;
135 PKSIOBJECT_HEADER ObjectHeader;
136 PIO_STACK_LOCATION IoStack;
137 PLIST_ENTRY ListEntry;
138 NTSTATUS Status;
139
140 /* get current irp stack */
141 IoStack = IoGetCurrentIrpStackLocation(Irp);
142
143 /* caller wants to add the target device */
144 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
145
146 /* get device header */
147 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
148
149 /* FIXME locks */
150
151 /* loop our power dispatch list and call registered notification functions */
152 ListEntry = DeviceHeader->PowerDispatchList.Flink;
153 /* let's go */
154 while(ListEntry != &DeviceHeader->PowerDispatchList)
155 {
156 /* get object header */
157 ObjectHeader = (PKSIOBJECT_HEADER)CONTAINING_RECORD(ListEntry, KSIOBJECT_HEADER, PowerDispatchEntry);
158
159 /* does it have still a cb */
160 if (ObjectHeader->PowerDispatch)
161 {
162 /* call the power cb */
163 Status = ObjectHeader->PowerDispatch(ObjectHeader->PowerContext, Irp);
164 ASSERT(NT_SUCCESS(Status));
165 }
166
167 /* iterate to next entry */
168 ListEntry = ListEntry->Flink;
169 }
170
171 /* start next power irp */
172 PoStartNextPowerIrp(Irp);
173
174 /* skip current irp stack location */
175 IoSkipCurrentIrpStackLocation(Irp);
176
177 /* let's roll */
178 Status = PoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
179
180 /* done */
181 return Status;
182 }
183
184 /*
185 @implemented
186 */
187 KSDDKAPI
188 NTSTATUS
189 NTAPI
190 KsDefaultForwardIrp(
191 IN PDEVICE_OBJECT DeviceObject,
192 IN PIRP Irp)
193 {
194 PDEVICE_EXTENSION DeviceExtension;
195 PKSIDEVICE_HEADER DeviceHeader;
196 PIO_STACK_LOCATION IoStack;
197 NTSTATUS Status;
198
199 /* get current irp stack */
200 IoStack = IoGetCurrentIrpStackLocation(Irp);
201
202 /* caller wants to add the target device */
203 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
204
205 /* get device header */
206 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
207
208 /* forward the request to the PDO */
209 Status = IoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
210
211 return Status;
212 }
213
214 /*
215 @implemented
216 */
217 KSDDKAPI
218 VOID
219 NTAPI
220 KsSetDevicePnpAndBaseObject(
221 IN KSDEVICE_HEADER Header,
222 IN PDEVICE_OBJECT PnpDeviceObject,
223 IN PDEVICE_OBJECT BaseDevice)
224 {
225 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
226
227 DeviceHeader->PnpDeviceObject = PnpDeviceObject;
228 DeviceHeader->BaseDevice = BaseDevice;
229 }
230
231 /*
232 @implemented
233 */
234 KSDDKAPI
235 PDEVICE_OBJECT
236 NTAPI
237 KsQueryDevicePnpObject(
238 IN KSDEVICE_HEADER Header)
239 {
240 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
241
242 /* return PnpDeviceObject */
243 return DeviceHeader->PnpDeviceObject;
244
245 }
246
247 /*
248 @unimplemented
249 */
250 KSDDKAPI
251 ACCESS_MASK
252 NTAPI
253 KsQueryObjectAccessMask(
254 IN KSOBJECT_HEADER Header)
255 {
256 UNIMPLEMENTED;
257 return STATUS_UNSUCCESSFUL;
258 }
259
260 /*
261 @unimplemented
262 */
263 KSDDKAPI
264 VOID
265 NTAPI
266 KsRecalculateStackDepth(
267 IN KSDEVICE_HEADER Header,
268 IN BOOLEAN ReuseStackLocation)
269 {
270 UNIMPLEMENTED;
271 }
272
273
274 /*
275 @implemented
276 */
277 KSDDKAPI
278 VOID
279 NTAPI
280 KsSetTargetState(
281 IN KSOBJECT_HEADER Header,
282 IN KSTARGET_STATE TargetState)
283 {
284 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
285
286 /* set target state */
287 DeviceHeader->TargetState = TargetState;
288 }
289
290 /*
291 @implemented
292 */
293 KSDDKAPI
294 VOID
295 NTAPI
296 KsSetTargetDeviceObject(
297 IN KSOBJECT_HEADER Header,
298 IN PDEVICE_OBJECT TargetDevice OPTIONAL)
299 {
300 PDEVICE_EXTENSION DeviceExtension;
301 PKSIDEVICE_HEADER DeviceHeader;
302 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
303
304 if(ObjectHeader->TargetDevice)
305 {
306 /* there is already a target device set */
307 if (!TargetDevice)
308 {
309 /* caller wants to remove the target device */
310 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension;
311
312 /* get device header */
313 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
314
315 /* acquire lock */
316 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
317
318 /* remove entry */
319 RemoveEntryList(&ObjectHeader->TargetDeviceListEntry);
320
321 /* remove device pointer */
322 ObjectHeader->TargetDevice = NULL;
323
324 /* release lock */
325 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
326 }
327 }
328 else
329 {
330 /* no target device yet set */
331 if (TargetDevice)
332 {
333 /* caller wants to add the target device */
334 DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension;
335
336 /* get device header */
337 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
338
339 /* acquire lock */
340 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
341
342 /* insert list entry */
343 InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry);
344
345 /* store target device */
346 ObjectHeader->TargetDevice = TargetDevice;
347
348 /* release lock */
349 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
350 }
351 }
352
353 }
354
355 /*
356 @implemented
357 */
358 KSDDKAPI
359 VOID
360 NTAPI
361 KsSetPowerDispatch(
362 IN KSOBJECT_HEADER Header,
363 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
364 IN PVOID PowerContext OPTIONAL)
365 {
366 PDEVICE_EXTENSION DeviceExtension;
367 PKSIDEVICE_HEADER DeviceHeader;
368 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
369
370 /* caller wants to add the target device */
371 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension;
372
373 /* get device header */
374 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
375
376 /* acquire lock */
377 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
378
379 if (PowerDispatch)
380 {
381 /* add power dispatch entry */
382 InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry);
383
384 /* store function and context */
385 ObjectHeader->PowerDispatch = PowerDispatch;
386 ObjectHeader->PowerContext = PowerContext;
387 }
388 else
389 {
390 /* remove power dispatch entry */
391 RemoveEntryList(&ObjectHeader->PowerDispatchEntry);
392
393 /* store function and context */
394 ObjectHeader->PowerDispatch = NULL;
395 ObjectHeader->PowerContext = NULL;
396
397 }
398
399 /* release lock */
400 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
401 }
402
403
404 /*
405 @unimplemented
406 */
407 KSDDKAPI
408 PKSOBJECT_CREATE_ITEM
409 NTAPI
410 KsQueryObjectCreateItem(
411 IN KSOBJECT_HEADER Header)
412 {
413 UNIMPLEMENTED;
414 return NULL;
415 }
416
417 /*
418 @implemented
419 */
420 KSDDKAPI
421 NTSTATUS
422 NTAPI
423 KsAllocateDeviceHeader(
424 OUT KSDEVICE_HEADER* OutHeader,
425 IN ULONG ItemsCount,
426 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
427 {
428 ULONG Index = 0;
429 PKSIDEVICE_HEADER Header;
430
431 if (!OutHeader)
432 return STATUS_INVALID_PARAMETER;
433
434 /* allocate a device header */
435 Header = ExAllocatePoolWithTag(PagedPool, sizeof(KSIDEVICE_HEADER), TAG_DEVICE_HEADER);
436
437 /* check for success */
438 if (!Header)
439 return STATUS_INSUFFICIENT_RESOURCES;
440
441 /* clear all memory */
442 RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
443
444 /* initialize spin lock */
445 KeInitializeSpinLock(&Header->ItemListLock); //FIXME
446
447 /* initialize device mutex */
448 KeInitializeMutex(&Header->DeviceMutex, 0);
449
450 /* initialize target device list */
451 InitializeListHead(&Header->TargetDeviceList);
452 /* initialize power dispatch list */
453 InitializeListHead(&Header->PowerDispatchList);
454
455 /* are there any create items provided */
456 if (ItemsCount && ItemsList)
457 {
458 /* allocate space for device item list */
459 Header->ItemList = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_ITEM) * ItemsCount, TAG_DEVICE_HEADER);
460 if (!Header->ItemList)
461 {
462 ExFreePoolWithTag(Header, TAG_DEVICE_HEADER);
463 return STATUS_INSUFFICIENT_RESOURCES;
464 }
465 RtlZeroMemory(Header->ItemList, sizeof(DEVICE_ITEM) * ItemsCount);
466
467 for(Index = 0; Index < ItemsCount; Index++)
468 {
469 /* store provided create items */
470 Header->ItemList[Index].CreateItem = &ItemsList[Index];
471 }
472 Header->MaxItems = ItemsCount;
473 }
474
475 /* store result */
476 *OutHeader = Header;
477
478 return STATUS_SUCCESS;
479 }
480
481 /*
482 @unimplemented
483 */
484 KSDDKAPI
485 VOID
486 NTAPI
487 KsFreeDeviceHeader(
488 IN KSDEVICE_HEADER DevHeader)
489 {
490 PKSIDEVICE_HEADER Header;
491
492 Header = (PKSIDEVICE_HEADER)DevHeader;
493
494 if (!DevHeader)
495 return;
496
497 ExFreePoolWithTag(Header->ItemList, TAG_DEVICE_HEADER);
498 ExFreePoolWithTag(Header, TAG_DEVICE_HEADER);
499 }
500
501 /*
502 @implemented
503 */
504 KSDDKAPI
505 NTSTATUS
506 NTAPI
507 KsAllocateObjectHeader(
508 OUT KSOBJECT_HEADER *Header,
509 IN ULONG ItemsCount,
510 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,
511 IN PIRP Irp,
512 IN KSDISPATCH_TABLE* Table)
513 {
514 PIO_STACK_LOCATION IoStack;
515 PDEVICE_EXTENSION DeviceExtension;
516 PKSIDEVICE_HEADER DeviceHeader;
517 PKSIOBJECT_HEADER ObjectHeader;
518
519 if (!Header)
520 return STATUS_INVALID_PARAMETER_1;
521
522 if (!Irp)
523 return STATUS_INVALID_PARAMETER_4;
524
525 if (!Table)
526 return STATUS_INVALID_PARAMETER_5;
527
528 /* get current stack location */
529 IoStack = IoGetCurrentIrpStackLocation(Irp);
530 /* get device extension */
531 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
532 /* get device header */
533 DeviceHeader = DeviceExtension->DeviceHeader;
534
535 /* sanity check */
536 ASSERT(IoStack->FileObject);
537 /* check for an file object */
538
539 /* allocate the object header */
540 ObjectHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(KSIOBJECT_HEADER), TAG_DEVICE_HEADER);
541 if (!ObjectHeader)
542 return STATUS_INSUFFICIENT_RESOURCES;
543
544 /* initialize object header */
545 RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
546
547 /* do we have a name */
548 if (IoStack->FileObject->FileName.Buffer)
549 {
550 /* copy object class */
551 ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
552 ObjectHeader->ObjectClass.Buffer = ExAllocatePoolWithTag(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength, TAG_DEVICE_HEADER);
553 if (!ObjectHeader->ObjectClass.Buffer)
554 {
555 ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
556 return STATUS_INSUFFICIENT_RESOURCES;
557 }
558 RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
559 }
560
561 /* copy dispatch table */
562 RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
563 /* store create items */
564 if (ItemsCount && ItemsList)
565 {
566 ObjectHeader->ItemCount = ItemsCount;
567 ObjectHeader->CreateItem = ItemsList;
568 }
569
570 /* store the object in the file object */
571 ASSERT(IoStack->FileObject->FsContext == NULL);
572 IoStack->FileObject->FsContext = ObjectHeader;
573
574 /* the object header is for a audio filter */
575 ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
576
577 /* store parent device */
578 ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
579
580 /* store result */
581 *Header = ObjectHeader;
582
583
584
585 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
586
587 return STATUS_SUCCESS;
588
589 }
590
591 /*
592 @implemented
593 */
594 KSDDKAPI
595 VOID
596 NTAPI
597 KsFreeObjectHeader(
598 IN PVOID Header)
599 {
600 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
601
602 if (ObjectHeader->ObjectClass.Buffer)
603 {
604 /* release object class buffer */
605 ExFreePoolWithTag(ObjectHeader->ObjectClass.Buffer, TAG_DEVICE_HEADER);
606 }
607
608 if (ObjectHeader->Unknown)
609 {
610 /* release associated object */
611 ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
612 }
613
614 /* FIXME free create items */
615
616 /* free object header */
617 ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
618
619 }
620
621 /*
622 @implemented
623 */
624 KSDDKAPI
625 NTSTATUS
626 NTAPI
627 KsAddObjectCreateItemToDeviceHeader(
628 IN KSDEVICE_HEADER DevHeader,
629 IN PDRIVER_DISPATCH Create,
630 IN PVOID Context,
631 IN PWCHAR ObjectClass,
632 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
633 {
634 PKSIDEVICE_HEADER Header;
635 ULONG FreeIndex, Index;
636
637 Header = (PKSIDEVICE_HEADER)DevHeader;
638
639 DPRINT1("KsAddObjectCreateItemToDeviceHeader entered\n");
640
641 /* check if a device header has been provided */
642 if (!DevHeader)
643 return STATUS_INVALID_PARAMETER_1;
644
645 /* check if a create item has been provided */
646 if (!Create)
647 return STATUS_INVALID_PARAMETER_2;
648
649 /* check if a object class has been provided */
650 if (!ObjectClass)
651 return STATUS_INVALID_PARAMETER_4;
652
653 FreeIndex = (ULONG)-1;
654 /* now scan the list and check for a free item */
655 for(Index = 0; Index < Header->MaxItems; Index++)
656 {
657 ASSERT(Header->ItemList[Index].CreateItem);
658
659 if (Header->ItemList[Index].CreateItem->Create == NULL)
660 {
661 FreeIndex = Index;
662 break;
663 }
664
665 if (!wcsicmp(ObjectClass, Header->ItemList[Index].CreateItem->ObjectClass.Buffer))
666 {
667 /* the same object class already exists */
668 return STATUS_OBJECT_NAME_COLLISION;
669 }
670 }
671 /* found a free index */
672 if (FreeIndex == (ULONG)-1)
673 {
674 /* no empty space found */
675 return STATUS_ALLOTTED_SPACE_EXCEEDED;
676 }
677
678 /* initialize create item */
679 Header->ItemList[FreeIndex].CreateItem->Create = Create;
680 Header->ItemList[FreeIndex].CreateItem->Context = Context;
681 RtlInitUnicodeString(&Header->ItemList[FreeIndex].CreateItem->ObjectClass, ObjectClass);
682 Header->ItemList[FreeIndex].CreateItem->SecurityDescriptor = SecurityDescriptor;
683
684
685 return STATUS_SUCCESS;
686 }
687
688 /*
689 @unimplemented
690 */
691 KSDDKAPI
692 NTSTATUS
693 NTAPI
694 KsAddObjectCreateItemToObjectHeader(
695 IN KSOBJECT_HEADER Header,
696 IN PDRIVER_DISPATCH Create,
697 IN PVOID Context,
698 IN PWCHAR ObjectClass,
699 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
700 {
701 UNIMPLEMENTED;
702 return STATUS_UNSUCCESSFUL;
703 }
704
705 /*
706 @implemented
707 */
708 KSDDKAPI
709 NTSTATUS
710 NTAPI
711 KsAllocateObjectCreateItem(
712 IN KSDEVICE_HEADER DevHeader,
713 IN PKSOBJECT_CREATE_ITEM CreateItem,
714 IN BOOLEAN AllocateEntry,
715 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
716 {
717 PKSIDEVICE_HEADER Header;
718 PKSOBJECT_CREATE_ITEM Item;
719 PDEVICE_ITEM ItemList;
720 KIRQL OldLevel;
721
722 Header = (PKSIDEVICE_HEADER)DevHeader;
723
724 if (!DevHeader)
725 return STATUS_INVALID_PARAMETER_1;
726
727 if (!CreateItem)
728 return STATUS_INVALID_PARAMETER_2;
729
730 /* acquire list lock */
731 KeAcquireSpinLock(&Header->ItemListLock, &OldLevel);
732
733 ItemList = ExAllocatePool(NonPagedPool, sizeof(DEVICE_ITEM) * (Header->MaxItems + 1));
734 if (!ItemList)
735 {
736 return STATUS_INSUFFICIENT_RESOURCES;
737 }
738
739 if (AllocateEntry)
740 {
741 if (!ItemFreeCallback)
742 {
743 /* caller must be notified */
744 ExFreePool(ItemList);
745 /* release lock */
746 KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
747
748 return STATUS_INVALID_PARAMETER_4;
749 }
750 /* allocate create item */
751 Item = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
752 if (!Item)
753 {
754 /* no memory */
755 ExFreePool(ItemList);
756 /* release lock */
757 KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
758
759 return STATUS_INSUFFICIENT_RESOURCES;
760 }
761
762 /* initialize descriptor */
763 Item->Context = CreateItem->Context;
764 Item->Create = CreateItem->Create;
765 Item->Flags = CreateItem->Flags;
766 Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
767 Item->ObjectClass.Length = 0;
768 Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
769
770 /* copy object class */
771 Item->ObjectClass.Buffer = ExAllocatePool(NonPagedPool, Item->ObjectClass.MaximumLength);
772 if (!Item->ObjectClass.Buffer)
773 {
774 /* release resources */
775 ExFreePool(Item);
776 ExFreePool(ItemList);
777
778 /* release lock */
779 KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
780
781 return STATUS_INSUFFICIENT_RESOURCES;
782 }
783
784 RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
785 }
786 else
787 {
788 if (ItemFreeCallback)
789 {
790 /* callback is only accepted when the create item is copied */
791 ExFreePool(ItemList);
792 /* release lock */
793 KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
794
795 return STATUS_INVALID_PARAMETER_4;
796 }
797
798 Item = CreateItem;
799 }
800
801
802 if (Header->MaxItems)
803 {
804 /* copy old create items */
805 RtlMoveMemory(ItemList, Header->ItemList, sizeof(DEVICE_ITEM) * Header->MaxItems);
806 }
807
808 /* initialize item entry */
809 ItemList[Header->MaxItems].CreateItem = Item;
810 ItemList[Header->MaxItems].ItemFreeCallback = ItemFreeCallback;
811
812
813 /* free old item list */
814 ExFreePool(Header->ItemList);
815
816 Header->ItemList = ItemList;
817 Header->MaxItems++;
818
819 /* release lock */
820 KeReleaseSpinLock(&Header->ItemListLock, OldLevel);
821
822 return STATUS_SUCCESS;
823
824 }
825
826 NTSTATUS
827 KspObjectFreeCreateItems(
828 IN KSDEVICE_HEADER Header,
829 IN PKSOBJECT_CREATE_ITEM CreateItem)
830 {
831 UNIMPLEMENTED
832 return STATUS_NOT_IMPLEMENTED;
833 }
834
835 /*
836 @implemented
837 */
838 KSDDKAPI
839 NTSTATUS
840 NTAPI
841 KsFreeObjectCreateItem(
842 IN KSDEVICE_HEADER Header,
843 IN PUNICODE_STRING CreateItem)
844 {
845 KSOBJECT_CREATE_ITEM Item;
846
847 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
848 RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
849
850 return KspObjectFreeCreateItems(Header, &Item);
851 }
852
853
854 /*
855 @implemented
856 */
857 KSDDKAPI
858 NTSTATUS
859 NTAPI
860 KsFreeObjectCreateItemsByContext(
861 IN KSDEVICE_HEADER Header,
862 IN PVOID Context)
863 {
864 KSOBJECT_CREATE_ITEM Item;
865
866 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
867
868 Item.Context = Context;
869
870 return KspObjectFreeCreateItems(Header, &Item);
871 }
872
873 /*
874 @implemented
875 */
876 KSDDKAPI
877 NTSTATUS
878 NTAPI
879 KsCreateDefaultSecurity(
880 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
881 OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
882 {
883 PGENERIC_MAPPING Mapping;
884 SECURITY_SUBJECT_CONTEXT SubjectContext;
885 NTSTATUS Status;
886
887 /* start capturing security context of calling thread */
888 SeCaptureSubjectContext(&SubjectContext);
889 /* get generic mapping */
890 Mapping = IoGetFileObjectGenericMapping();
891 /* build new descriptor */
892 Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
893 /* release security descriptor */
894 SeReleaseSubjectContext(&SubjectContext);
895 /* done */
896 return Status;
897 }
898
899 /*
900 @unimplemented
901 */
902 KSDDKAPI
903 NTSTATUS
904 NTAPI
905 KsForwardIrp(
906 IN PIRP Irp,
907 IN PFILE_OBJECT FileObject,
908 IN BOOLEAN ReuseStackLocation)
909 {
910 UNIMPLEMENTED;
911 return STATUS_UNSUCCESSFUL;
912 }
913
914
915 /*
916 @unimplemented
917 */
918 KSDDKAPI
919 NTSTATUS
920 NTAPI
921 KsForwardAndCatchIrp(
922 IN PDEVICE_OBJECT DeviceObject,
923 IN PIRP Irp,
924 IN PFILE_OBJECT FileObject,
925 IN KSSTACK_USE StackUse)
926 {
927 UNIMPLEMENTED;
928 return STATUS_UNSUCCESSFUL;
929 }
930
931
932 NTSTATUS
933 NTAPI
934 KspSynchronousIoControlDeviceCompletion(
935 IN PDEVICE_OBJECT DeviceObject,
936 IN PIRP Irp,
937 IN PVOID Context)
938 {
939 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
940
941 IoStatusBlock->Information = Irp->IoStatus.Information;
942 IoStatusBlock->Status = Irp->IoStatus.Status;
943
944 return STATUS_SUCCESS;
945 }
946
947 /*
948 @implemented
949 */
950 KSDDKAPI
951 NTSTATUS
952 NTAPI
953 KsSynchronousIoControlDevice(
954 IN PFILE_OBJECT FileObject,
955 IN KPROCESSOR_MODE RequestorMode,
956 IN ULONG IoControl,
957 IN PVOID InBuffer,
958 IN ULONG InSize,
959 OUT PVOID OutBuffer,
960 IN ULONG OutSize,
961 OUT PULONG BytesReturned)
962 {
963 PKSIOBJECT_HEADER ObjectHeader;
964 PDEVICE_OBJECT DeviceObject;
965 KEVENT Event;
966 PIRP Irp;
967 IO_STATUS_BLOCK IoStatusBlock;
968 PIO_STACK_LOCATION IoStack;
969 NTSTATUS Status;
970
971 /* check for valid file object */
972 if (!FileObject)
973 return STATUS_INVALID_PARAMETER;
974
975 /* get device object to send the request to */
976 DeviceObject = IoGetRelatedDeviceObject(FileObject);
977 if (!DeviceObject)
978 return STATUS_UNSUCCESSFUL;
979
980
981 /* get object header */
982 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
983
984 /* check if there is fast device io function */
985 if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
986 {
987 IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
988 IoStatusBlock.Information = 0;
989
990 /* it is send the request */
991 Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
992 /* check if the request was handled */
993 DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
994 if (Status)
995 {
996 /* store bytes returned */
997 *BytesReturned = IoStatusBlock.Information;
998 /* return status */
999 return IoStatusBlock.Status;
1000 }
1001 }
1002
1003 /* initialize the event */
1004 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1005
1006 /* create the irp */
1007 Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
1008
1009 /* HACK */
1010 IoStack = IoGetNextIrpStackLocation(Irp);
1011 IoStack->FileObject = FileObject;
1012
1013 IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
1014
1015 Status = IoCallDriver(DeviceObject, Irp);
1016 if (Status == STATUS_PENDING)
1017 {
1018 KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
1019 Status = IoStatusBlock.Status;
1020 }
1021
1022 *BytesReturned = IoStatusBlock.Information;
1023 return Status;
1024 }
1025
1026 /*
1027 @implemented
1028 */
1029 KSDDKAPI
1030 NTSTATUS
1031 NTAPI
1032 KsUnserializeObjectPropertiesFromRegistry(
1033 IN PFILE_OBJECT FileObject,
1034 IN HANDLE ParentKey OPTIONAL,
1035 IN PUNICODE_STRING RegistryPath OPTIONAL)
1036 {
1037 UNIMPLEMENTED
1038 return STATUS_NOT_IMPLEMENTED;
1039 }
1040
1041
1042 /*
1043 @unimplemented
1044 */
1045 KSDDKAPI
1046 NTSTATUS
1047 NTAPI
1048 KsCacheMedium(
1049 IN PUNICODE_STRING SymbolicLink,
1050 IN PKSPIN_MEDIUM Medium,
1051 IN ULONG PinDirection)
1052 {
1053 UNIMPLEMENTED;
1054 return STATUS_UNSUCCESSFUL;
1055 }
1056