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 #include "precomp.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
15 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
16
17 /*
18 @implemented
19 */
20 KSDDKAPI
21 NTSTATUS
22 NTAPI
KsAcquireResetValue(IN PIRP Irp,OUT KSRESET * ResetValue)23 KsAcquireResetValue(
24 IN PIRP Irp,
25 OUT KSRESET* ResetValue)
26 {
27 PIO_STACK_LOCATION IoStack;
28 KSRESET* Value;
29 NTSTATUS Status = STATUS_SUCCESS;
30
31 /* get current irp stack */
32 IoStack = IoGetCurrentIrpStackLocation(Irp);
33
34 /* check if there is reset value provided */
35 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSRESET))
36 return STATUS_INVALID_PARAMETER;
37
38 if (Irp->RequestorMode == UserMode)
39 {
40 /* need to probe the buffer */
41 _SEH2_TRY
42 {
43 ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSRESET), sizeof(UCHAR));
44 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
45 *ResetValue = *Value;
46 }
47 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
48 {
49 /* Exception, get the error code */
50 Status = _SEH2_GetExceptionCode();
51 }
52 _SEH2_END;
53 }
54 else
55 {
56 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
57 *ResetValue = *Value;
58 }
59
60 return Status;
61 }
62
63 /*
64 @implemented
65 */
66 KSDDKAPI
67 VOID
68 NTAPI
KsAcquireDeviceSecurityLock(IN KSDEVICE_HEADER DevHeader,IN BOOLEAN Exclusive)69 KsAcquireDeviceSecurityLock(
70 IN KSDEVICE_HEADER DevHeader,
71 IN BOOLEAN Exclusive)
72 {
73 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
74
75 KeEnterCriticalRegion();
76
77 if (Exclusive)
78 {
79 ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
80 }
81 else
82 {
83 ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
84 }
85 }
86
87 /*
88 @implemented
89 */
90 KSDDKAPI
91 VOID
92 NTAPI
KsReleaseDeviceSecurityLock(IN KSDEVICE_HEADER DevHeader)93 KsReleaseDeviceSecurityLock(
94 IN KSDEVICE_HEADER DevHeader)
95 {
96 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
97
98 DPRINT("KsReleaseDevice\n");
99
100 ExReleaseResourceLite(&Header->SecurityLock);
101 KeLeaveCriticalRegion();
102 }
103
104 /*
105 @implemented
106 */
107 KSDDKAPI
108 NTSTATUS
109 NTAPI
KsDefaultDispatchPnp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)110 KsDefaultDispatchPnp(
111 IN PDEVICE_OBJECT DeviceObject,
112 IN PIRP Irp)
113 {
114 PDEVICE_EXTENSION DeviceExtension;
115 PKSIDEVICE_HEADER DeviceHeader;
116 PIO_STACK_LOCATION IoStack;
117 PDEVICE_OBJECT PnpDeviceObject;
118 NTSTATUS Status;
119 ULONG MinorFunction;
120
121 /* get current irp stack */
122 IoStack = IoGetCurrentIrpStackLocation(Irp);
123
124 /* caller wants to add the target device */
125 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
126
127 /* get device header */
128 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
129
130 /* backup PnpBaseObject */
131 PnpDeviceObject = DeviceHeader->PnpDeviceObject;
132
133
134 /* backup minor function code */
135 MinorFunction = IoStack->MinorFunction;
136
137 if(MinorFunction == IRP_MN_REMOVE_DEVICE)
138 {
139 /* remove the device */
140 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
141 }
142
143 /* skip current irp stack */
144 IoSkipCurrentIrpStackLocation(Irp);
145
146 /* call attached pnp device object */
147 Status = IoCallDriver(PnpDeviceObject, Irp);
148
149 if (MinorFunction == IRP_MN_REMOVE_DEVICE)
150 {
151 /* time is over */
152 IoDetachDevice(PnpDeviceObject);
153 /* delete device */
154 IoDeleteDevice(DeviceObject);
155 }
156 /* done */
157 return Status;
158 }
159
160 /*
161 @implemented
162 */
163 KSDDKAPI
164 NTSTATUS
165 NTAPI
KsDefaultDispatchPower(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)166 KsDefaultDispatchPower(
167 IN PDEVICE_OBJECT DeviceObject,
168 IN PIRP Irp)
169 {
170 PDEVICE_EXTENSION DeviceExtension;
171 PKSIDEVICE_HEADER DeviceHeader;
172 PKSIOBJECT_HEADER ObjectHeader;
173 //PIO_STACK_LOCATION IoStack;
174 PLIST_ENTRY ListEntry;
175 NTSTATUS Status;
176
177 /* get current irp stack */
178 //IoStack = IoGetCurrentIrpStackLocation(Irp);
179
180 /* caller wants to add the target device */
181 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
182
183 /* get device header */
184 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
185
186 /* FIXME locks */
187
188 /* loop our power dispatch list and call registered notification functions */
189 ListEntry = DeviceHeader->PowerDispatchList.Flink;
190 /* let's go */
191 while(ListEntry != &DeviceHeader->PowerDispatchList)
192 {
193 /* get object header */
194 ObjectHeader = (PKSIOBJECT_HEADER)CONTAINING_RECORD(ListEntry, KSIOBJECT_HEADER, PowerDispatchEntry);
195
196 /* does it have still a cb */
197 if (ObjectHeader->PowerDispatch)
198 {
199 /* call the power cb */
200 Status = ObjectHeader->PowerDispatch(ObjectHeader->PowerContext, Irp);
201 ASSERT(NT_SUCCESS(Status));
202 }
203
204 /* iterate to next entry */
205 ListEntry = ListEntry->Flink;
206 }
207
208 /* start next power irp */
209 PoStartNextPowerIrp(Irp);
210
211 /* skip current irp stack location */
212 IoSkipCurrentIrpStackLocation(Irp);
213
214 /* let's roll */
215 Status = PoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
216
217 /* done */
218 return Status;
219 }
220
221 /*
222 @implemented
223 */
224 KSDDKAPI
225 NTSTATUS
226 NTAPI
KsDefaultForwardIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)227 KsDefaultForwardIrp(
228 IN PDEVICE_OBJECT DeviceObject,
229 IN PIRP Irp)
230 {
231 PDEVICE_EXTENSION DeviceExtension;
232 PKSIDEVICE_HEADER DeviceHeader;
233 //PIO_STACK_LOCATION IoStack;
234 NTSTATUS Status;
235
236 /* get current irp stack */
237 //IoStack = IoGetCurrentIrpStackLocation(Irp);
238
239 /* caller wants to add the target device */
240 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
241
242 /* get device header */
243 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
244
245 /* forward the request to the PDO */
246 Status = IoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
247
248 return Status;
249 }
250
251 /*
252 @implemented
253 */
254 KSDDKAPI
255 VOID
256 NTAPI
KsSetDevicePnpAndBaseObject(IN KSDEVICE_HEADER Header,IN PDEVICE_OBJECT PnpDeviceObject,IN PDEVICE_OBJECT BaseDevice)257 KsSetDevicePnpAndBaseObject(
258 IN KSDEVICE_HEADER Header,
259 IN PDEVICE_OBJECT PnpDeviceObject,
260 IN PDEVICE_OBJECT BaseDevice)
261 {
262 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
263
264 DeviceHeader->PnpDeviceObject = PnpDeviceObject;
265 DeviceHeader->BaseDevice = BaseDevice;
266 }
267
268 /*
269 @implemented
270 */
271 KSDDKAPI
272 PDEVICE_OBJECT
273 NTAPI
KsQueryDevicePnpObject(IN KSDEVICE_HEADER Header)274 KsQueryDevicePnpObject(
275 IN KSDEVICE_HEADER Header)
276 {
277 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
278
279 /* return PnpDeviceObject */
280 return DeviceHeader->PnpDeviceObject;
281
282 }
283
284 /*
285 @implemented
286 */
287 KSDDKAPI
288 ACCESS_MASK
289 NTAPI
KsQueryObjectAccessMask(IN KSOBJECT_HEADER Header)290 KsQueryObjectAccessMask(
291 IN KSOBJECT_HEADER Header)
292 {
293 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
294
295 /* return access mask */
296 return ObjectHeader->AccessMask;
297
298 }
299
300 /*
301 @unimplemented
302 */
303 KSDDKAPI
304 VOID
305 NTAPI
KsRecalculateStackDepth(IN KSDEVICE_HEADER Header,IN BOOLEAN ReuseStackLocation)306 KsRecalculateStackDepth(
307 IN KSDEVICE_HEADER Header,
308 IN BOOLEAN ReuseStackLocation)
309 {
310 UNIMPLEMENTED;
311 }
312
313
314 /*
315 @implemented
316 */
317 KSDDKAPI
318 VOID
319 NTAPI
KsSetTargetState(IN KSOBJECT_HEADER Header,IN KSTARGET_STATE TargetState)320 KsSetTargetState(
321 IN KSOBJECT_HEADER Header,
322 IN KSTARGET_STATE TargetState)
323 {
324 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
325
326 /* set target state */
327 DeviceHeader->TargetState = TargetState;
328 }
329
330 /*
331 @implemented
332 */
333 KSDDKAPI
334 VOID
335 NTAPI
KsSetTargetDeviceObject(IN KSOBJECT_HEADER Header,IN PDEVICE_OBJECT TargetDevice OPTIONAL)336 KsSetTargetDeviceObject(
337 IN KSOBJECT_HEADER Header,
338 IN PDEVICE_OBJECT TargetDevice OPTIONAL)
339 {
340 PDEVICE_EXTENSION DeviceExtension;
341 PKSIDEVICE_HEADER DeviceHeader;
342 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
343
344 if(ObjectHeader->TargetDevice)
345 {
346 /* there is already a target device set */
347 if (!TargetDevice)
348 {
349 /* caller wants to remove the target device */
350 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension;
351
352 /* get device header */
353 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
354
355 /* acquire lock */
356 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
357
358 /* remove entry */
359 RemoveEntryList(&ObjectHeader->TargetDeviceListEntry);
360
361 /* remove device pointer */
362 ObjectHeader->TargetDevice = NULL;
363
364 /* release lock */
365 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
366 }
367 }
368 else
369 {
370 /* no target device yet set */
371 if (TargetDevice)
372 {
373 /* caller wants to add the target device */
374 DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension;
375
376 /* get device header */
377 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
378
379 /* acquire lock */
380 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
381
382 /* insert list entry */
383 InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry);
384
385 /* store target device */
386 ObjectHeader->TargetDevice = TargetDevice;
387
388 /* release lock */
389 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
390 }
391 }
392
393 }
394
395 /*
396 @implemented
397 */
398 KSDDKAPI
399 VOID
400 NTAPI
KsSetPowerDispatch(IN KSOBJECT_HEADER Header,IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,IN PVOID PowerContext OPTIONAL)401 KsSetPowerDispatch(
402 IN KSOBJECT_HEADER Header,
403 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
404 IN PVOID PowerContext OPTIONAL)
405 {
406 PDEVICE_EXTENSION DeviceExtension;
407 PKSIDEVICE_HEADER DeviceHeader;
408 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
409
410 /* caller wants to add the target device */
411 DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension;
412
413 /* get device header */
414 DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
415
416 /* acquire lock */
417 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
418
419 if (PowerDispatch)
420 {
421 /* add power dispatch entry */
422 InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry);
423
424 /* store function and context */
425 ObjectHeader->PowerDispatch = PowerDispatch;
426 ObjectHeader->PowerContext = PowerContext;
427 }
428 else
429 {
430 /* remove power dispatch entry */
431 RemoveEntryList(&ObjectHeader->PowerDispatchEntry);
432
433 /* store function and context */
434 ObjectHeader->PowerDispatch = NULL;
435 ObjectHeader->PowerContext = NULL;
436
437 }
438
439 /* release lock */
440 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
441 }
442
443
444 /*
445 @implemented
446 */
447 KSDDKAPI
448 PKSOBJECT_CREATE_ITEM
449 NTAPI
KsQueryObjectCreateItem(IN KSOBJECT_HEADER Header)450 KsQueryObjectCreateItem(
451 IN KSOBJECT_HEADER Header)
452 {
453 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
454 return ObjectHeader->OriginalCreateItem;
455 }
456
457 NTSTATUS
KspAddCreateItemToList(OUT PLIST_ENTRY ListHead,IN ULONG ItemsCount,IN PKSOBJECT_CREATE_ITEM ItemsList)458 KspAddCreateItemToList(
459 OUT PLIST_ENTRY ListHead,
460 IN ULONG ItemsCount,
461 IN PKSOBJECT_CREATE_ITEM ItemsList)
462 {
463 ULONG Index;
464 PCREATE_ITEM_ENTRY Entry;
465
466 /* add the items */
467 for(Index = 0; Index < ItemsCount; Index++)
468 {
469 /* allocate item */
470 Entry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
471 if (!Entry)
472 {
473 /* no memory */
474 return STATUS_INSUFFICIENT_RESOURCES;
475 }
476
477 /* initialize entry */
478 InitializeListHead(&Entry->ObjectItemList);
479 Entry->CreateItem = &ItemsList[Index];
480 Entry->ReferenceCount = 0;
481 Entry->ItemFreeCallback = NULL;
482
483 InsertTailList(ListHead, &Entry->Entry);
484 }
485 return STATUS_SUCCESS;
486 }
487
488 VOID
KspFreeCreateItems(PLIST_ENTRY ListHead)489 KspFreeCreateItems(
490 PLIST_ENTRY ListHead)
491 {
492 PCREATE_ITEM_ENTRY Entry;
493
494 while(!IsListEmpty(ListHead))
495 {
496 /* remove create item from list */
497 Entry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(RemoveHeadList(ListHead), CREATE_ITEM_ENTRY, Entry);
498
499 /* caller shouldnt have any references */
500 //ASSERT(Entry->ReferenceCount == 0);
501 //ASSERT(IsListEmpty(&Entry->ObjectItemList));
502
503 /* does the creator wish notification */
504 if (Entry->ItemFreeCallback)
505 {
506 /* notify creator */
507 Entry->ItemFreeCallback(Entry->CreateItem);
508 }
509
510 /* free create item entry */
511 FreeItem(Entry);
512 }
513
514 }
515
516 /*
517 @implemented
518 */
519 KSDDKAPI
520 NTSTATUS
521 NTAPI
KsAllocateDeviceHeader(OUT KSDEVICE_HEADER * OutHeader,IN ULONG ItemsCount,IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)522 KsAllocateDeviceHeader(
523 OUT KSDEVICE_HEADER* OutHeader,
524 IN ULONG ItemsCount,
525 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
526 {
527 NTSTATUS Status = STATUS_SUCCESS;
528 PKSIDEVICE_HEADER Header;
529
530 if (!OutHeader)
531 return STATUS_INVALID_PARAMETER;
532
533 /* allocate a device header */
534 Header = AllocateItem(PagedPool, sizeof(KSIDEVICE_HEADER));
535
536 /* check for success */
537 if (!Header)
538 return STATUS_INSUFFICIENT_RESOURCES;
539
540 /* clear all memory */
541 RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
542
543 /* initialize device mutex */
544 KeInitializeMutex(&Header->DeviceMutex, 0);
545
546 /* initialize target device list */
547 InitializeListHead(&Header->TargetDeviceList);
548 /* initialize power dispatch list */
549 InitializeListHead(&Header->PowerDispatchList);
550 /* initialize object bag lists */
551 InitializeListHead(&Header->ObjectBags);
552
553 /* initialize create item list */
554 InitializeListHead(&Header->ItemList);
555
556 /* initialize basic header */
557 Header->BasicHeader.Type = KsObjectTypeDevice;
558 Header->BasicHeader.KsDevice = &Header->KsDevice;
559 Header->BasicHeader.Parent.KsDevice = &Header->KsDevice;
560
561 /* are there any create items provided */
562 if (ItemsCount && ItemsList)
563 {
564 Status = KspAddCreateItemToList(&Header->ItemList, ItemsCount, ItemsList);
565
566 if (NT_SUCCESS(Status))
567 {
568 /* store item count */
569 Header->ItemListCount = ItemsCount;
570 }
571 else
572 {
573 /* release create items */
574 KspFreeCreateItems(&Header->ItemList);
575 }
576 }
577
578 /* store result */
579 *OutHeader = Header;
580
581 return Status;
582 }
583
584 /*
585 @implemented
586 */
587 KSDDKAPI
588 VOID
589 NTAPI
KsFreeDeviceHeader(IN KSDEVICE_HEADER DevHeader)590 KsFreeDeviceHeader(
591 IN KSDEVICE_HEADER DevHeader)
592 {
593 PKSIDEVICE_HEADER Header;
594
595 Header = (PKSIDEVICE_HEADER)DevHeader;
596
597 if (!DevHeader)
598 return;
599
600 KspFreeCreateItems(&Header->ItemList);
601 FreeItem(Header);
602 }
603
604 /*
605 @implemented
606 */
607 KSDDKAPI
608 NTSTATUS
609 NTAPI
KsAllocateObjectHeader(OUT KSOBJECT_HEADER * Header,IN ULONG ItemsCount,IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,IN PIRP Irp,IN KSDISPATCH_TABLE * Table)610 KsAllocateObjectHeader(
611 OUT KSOBJECT_HEADER *Header,
612 IN ULONG ItemsCount,
613 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,
614 IN PIRP Irp,
615 IN KSDISPATCH_TABLE* Table)
616 {
617 PIO_STACK_LOCATION IoStack;
618 //PDEVICE_EXTENSION DeviceExtension;
619 //PKSIDEVICE_HEADER DeviceHeader;
620 PKSIOBJECT_HEADER ObjectHeader;
621 //PKSOBJECT_CREATE_ITEM CreateItem;
622 NTSTATUS Status;
623
624 if (!Header)
625 return STATUS_INVALID_PARAMETER_1;
626
627 if (!Irp)
628 return STATUS_INVALID_PARAMETER_4;
629
630 if (!Table)
631 return STATUS_INVALID_PARAMETER_5;
632
633 /* get current stack location */
634 IoStack = IoGetCurrentIrpStackLocation(Irp);
635 /* get device extension */
636 //DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
637 /* get device header */
638 //DeviceHeader = DeviceExtension->DeviceHeader;
639
640 /* sanity check */
641 ASSERT(IoStack->FileObject);
642 /* check for an file object */
643
644 /* allocate the object header */
645 ObjectHeader = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_HEADER));
646 if (!ObjectHeader)
647 return STATUS_INSUFFICIENT_RESOURCES;
648
649 /* initialize object header */
650 RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
651
652 /* initialize create item list */
653 InitializeListHead(&ObjectHeader->ItemList);
654
655 /* get create item */
656 //CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
657
658 /* do we have a name */
659 if (IoStack->FileObject->FileName.Buffer)
660 {
661 /* copy object class */
662 ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
663 ObjectHeader->ObjectClass.Buffer = AllocateItem(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength);
664 if (!ObjectHeader->ObjectClass.Buffer)
665 {
666 FreeItem(ObjectHeader);
667 return STATUS_INSUFFICIENT_RESOURCES;
668 }
669 RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
670 }
671
672 /* copy dispatch table */
673 RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
674
675 /* store create items */
676 if (ItemsCount && ItemsList)
677 {
678 Status = KspAddCreateItemToList(&ObjectHeader->ItemList, ItemsCount, ItemsList);
679
680 if (NT_SUCCESS(Status))
681 {
682 /* store item count */
683 ObjectHeader->ItemListCount = ItemsCount;
684 }
685 else
686 {
687 /* destroy header*/
688 KsFreeObjectHeader(ObjectHeader);
689 return Status;
690 }
691 }
692 /* store the object in the file object */
693 IoStack->FileObject->FsContext2 = ObjectHeader;
694
695 /* store parent device */
696 ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
697
698 /* store originating create item */
699 ObjectHeader->OriginalCreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
700
701 /* FIXME store access mask see KsQueryObjectAccessMask */
702 ObjectHeader->AccessMask = IoStack->Parameters.Create.SecurityContext->DesiredAccess;
703
704
705 /* store result */
706 *Header = ObjectHeader;
707
708 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
709
710 return STATUS_SUCCESS;
711
712 }
713
714 /*
715 @implemented
716 */
717 KSDDKAPI
718 VOID
719 NTAPI
KsFreeObjectHeader(IN PVOID Header)720 KsFreeObjectHeader(
721 IN PVOID Header)
722 {
723 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
724
725 DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header, &ObjectHeader->ObjectClass);
726
727 if (ObjectHeader->ObjectClass.Buffer)
728 {
729 /* release object class buffer */
730 FreeItem(ObjectHeader->ObjectClass.Buffer);
731 }
732
733 if (ObjectHeader->Unknown)
734 {
735 /* release associated object */
736 ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
737 }
738
739 /* free create items */
740 KspFreeCreateItems(&ObjectHeader->ItemList);
741
742 /* free object header */
743 FreeItem(ObjectHeader);
744
745 }
746
747 NTSTATUS
KspAddObjectCreateItemToList(PLIST_ENTRY ListHead,IN PDRIVER_DISPATCH Create,IN PVOID Context,IN PWCHAR ObjectClass,IN PSECURITY_DESCRIPTOR SecurityDescriptor)748 KspAddObjectCreateItemToList(
749 PLIST_ENTRY ListHead,
750 IN PDRIVER_DISPATCH Create,
751 IN PVOID Context,
752 IN PWCHAR ObjectClass,
753 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
754 {
755 PLIST_ENTRY Entry;
756 PCREATE_ITEM_ENTRY CreateEntry;
757
758 /* point to first entry */
759 Entry = ListHead->Flink;
760
761 while(Entry != ListHead)
762 {
763 /* get create entry */
764 CreateEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
765 /* if the create item has no create routine, then it is free to use */
766 if (CreateEntry->CreateItem->Create == NULL)
767 {
768 /* sanity check */
769 ASSERT(IsListEmpty(&CreateEntry->ObjectItemList));
770 ASSERT(CreateEntry->ReferenceCount == 0);
771 /* use free entry */
772 CreateEntry->CreateItem->Context = Context;
773 CreateEntry->CreateItem->Create = Create;
774 RtlInitUnicodeString(&CreateEntry->CreateItem->ObjectClass, ObjectClass);
775 CreateEntry->CreateItem->SecurityDescriptor = SecurityDescriptor;
776
777 return STATUS_SUCCESS;
778 }
779
780 if (!_wcsicmp(ObjectClass, CreateEntry->CreateItem->ObjectClass.Buffer))
781 {
782 /* the same object class already exists */
783 return STATUS_OBJECT_NAME_COLLISION;
784 }
785
786 /* iterate to next entry */
787 Entry = Entry->Flink;
788 }
789 return STATUS_ALLOTTED_SPACE_EXCEEDED;
790 }
791
792 /*
793 @implemented
794 */
795 KSDDKAPI
796 NTSTATUS
797 NTAPI
KsAddObjectCreateItemToDeviceHeader(IN KSDEVICE_HEADER DevHeader,IN PDRIVER_DISPATCH Create,IN PVOID Context,IN PWCHAR ObjectClass,IN PSECURITY_DESCRIPTOR SecurityDescriptor)798 KsAddObjectCreateItemToDeviceHeader(
799 IN KSDEVICE_HEADER DevHeader,
800 IN PDRIVER_DISPATCH Create,
801 IN PVOID Context,
802 IN PWCHAR ObjectClass,
803 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
804 {
805 PKSIDEVICE_HEADER Header;
806 NTSTATUS Status;
807
808 Header = (PKSIDEVICE_HEADER)DevHeader;
809
810 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
811
812 /* check if a device header has been provided */
813 if (!DevHeader)
814 return STATUS_INVALID_PARAMETER_1;
815
816 /* check if a create item has been provided */
817 if (!Create)
818 return STATUS_INVALID_PARAMETER_2;
819
820 /* check if a object class has been provided */
821 if (!ObjectClass)
822 return STATUS_INVALID_PARAMETER_4;
823
824 /* let others do the work */
825 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
826
827 if (NT_SUCCESS(Status))
828 {
829 /* increment create item count */
830 InterlockedIncrement(&Header->ItemListCount);
831 }
832 DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status);
833 return Status;
834 }
835
836 /*
837 @implemented
838 */
839 KSDDKAPI
840 NTSTATUS
841 NTAPI
KsAddObjectCreateItemToObjectHeader(IN KSOBJECT_HEADER ObjectHeader,IN PDRIVER_DISPATCH Create,IN PVOID Context,IN PWCHAR ObjectClass,IN PSECURITY_DESCRIPTOR SecurityDescriptor)842 KsAddObjectCreateItemToObjectHeader(
843 IN KSOBJECT_HEADER ObjectHeader,
844 IN PDRIVER_DISPATCH Create,
845 IN PVOID Context,
846 IN PWCHAR ObjectClass,
847 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
848 {
849 PKSIOBJECT_HEADER Header;
850 NTSTATUS Status;
851
852 Header = (PKSIOBJECT_HEADER)ObjectHeader;
853
854 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
855
856 /* check if a device header has been provided */
857 if (!Header)
858 return STATUS_INVALID_PARAMETER_1;
859
860 /* check if a create item has been provided */
861 if (!Create)
862 return STATUS_INVALID_PARAMETER_2;
863
864 /* check if a object class has been provided */
865 if (!ObjectClass)
866 return STATUS_INVALID_PARAMETER_4;
867
868 /* let's work */
869 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
870
871 if (NT_SUCCESS(Status))
872 {
873 /* increment create item count */
874 InterlockedIncrement(&Header->ItemListCount);
875 }
876
877 return Status;
878 }
879
880 /*
881 @implemented
882 */
883 KSDDKAPI
884 NTSTATUS
885 NTAPI
KsAllocateObjectCreateItem(IN KSDEVICE_HEADER DevHeader,IN PKSOBJECT_CREATE_ITEM CreateItem,IN BOOLEAN AllocateEntry,IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)886 KsAllocateObjectCreateItem(
887 IN KSDEVICE_HEADER DevHeader,
888 IN PKSOBJECT_CREATE_ITEM CreateItem,
889 IN BOOLEAN AllocateEntry,
890 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
891 {
892 PCREATE_ITEM_ENTRY CreateEntry;
893 PKSIDEVICE_HEADER Header;
894 PKSOBJECT_CREATE_ITEM Item;
895
896 Header = (PKSIDEVICE_HEADER)DevHeader;
897
898 if (!DevHeader)
899 return STATUS_INVALID_PARAMETER_1;
900
901 if (!CreateItem)
902 return STATUS_INVALID_PARAMETER_2;
903
904 /* first allocate a create entry */
905 CreateEntry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
906
907 /* check for allocation success */
908 if (!CreateEntry)
909 {
910 /* not enough resources */
911 return STATUS_INSUFFICIENT_RESOURCES;
912 }
913
914
915 if (AllocateEntry)
916 {
917 /* allocate create item */
918 Item = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
919 if (!Item)
920 {
921 /* no memory */
922 FreeItem(CreateEntry);
923 return STATUS_INSUFFICIENT_RESOURCES;
924 }
925
926 /* initialize descriptor */
927 Item->Context = CreateItem->Context;
928 Item->Create = CreateItem->Create;
929 Item->Flags = CreateItem->Flags;
930 Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
931 Item->ObjectClass.Length = 0;
932 Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
933
934 /* copy object class */
935 Item->ObjectClass.Buffer = AllocateItem(NonPagedPool, Item->ObjectClass.MaximumLength);
936 if (!Item->ObjectClass.Buffer)
937 {
938 /* release resources */
939 FreeItem(Item);
940 FreeItem(CreateEntry);
941
942 return STATUS_INSUFFICIENT_RESOURCES;
943 }
944 RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
945 }
946 else
947 {
948 if (ItemFreeCallback)
949 {
950 /* callback is only accepted when the create item is copied */
951 ItemFreeCallback = NULL;
952 }
953 /* use passed create item */
954 Item = CreateItem;
955 }
956
957 /* initialize create item entry */
958 InitializeListHead(&CreateEntry->ObjectItemList);
959 CreateEntry->ItemFreeCallback = ItemFreeCallback;
960 CreateEntry->CreateItem = Item;
961 CreateEntry->ReferenceCount = 0;
962
963 /* now insert the create item entry */
964 InsertTailList(&Header->ItemList, &CreateEntry->Entry);
965
966 /* increment item count */
967 InterlockedIncrement(&Header->ItemListCount);
968
969 return STATUS_SUCCESS;
970 }
971
972 NTSTATUS
KspObjectFreeCreateItems(IN KSDEVICE_HEADER Header,IN PKSOBJECT_CREATE_ITEM CreateItem)973 KspObjectFreeCreateItems(
974 IN KSDEVICE_HEADER Header,
975 IN PKSOBJECT_CREATE_ITEM CreateItem)
976 {
977 UNIMPLEMENTED;
978 return STATUS_NOT_IMPLEMENTED;
979 }
980
981 /*
982 @implemented
983 */
984 KSDDKAPI
985 NTSTATUS
986 NTAPI
KsFreeObjectCreateItem(IN KSDEVICE_HEADER Header,IN PUNICODE_STRING CreateItem)987 KsFreeObjectCreateItem(
988 IN KSDEVICE_HEADER Header,
989 IN PUNICODE_STRING CreateItem)
990 {
991 KSOBJECT_CREATE_ITEM Item;
992
993 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
994 RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
995
996 return KspObjectFreeCreateItems(Header, &Item);
997 }
998
999
1000 /*
1001 @implemented
1002 */
1003 KSDDKAPI
1004 NTSTATUS
1005 NTAPI
KsFreeObjectCreateItemsByContext(IN KSDEVICE_HEADER Header,IN PVOID Context)1006 KsFreeObjectCreateItemsByContext(
1007 IN KSDEVICE_HEADER Header,
1008 IN PVOID Context)
1009 {
1010 KSOBJECT_CREATE_ITEM Item;
1011
1012 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
1013
1014 Item.Context = Context;
1015
1016 return KspObjectFreeCreateItems(Header, &Item);
1017 }
1018
1019 /*
1020 @implemented
1021 */
1022 KSDDKAPI
1023 NTSTATUS
1024 NTAPI
KsCreateDefaultSecurity(IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,OUT PSECURITY_DESCRIPTOR * DefaultSecurity)1025 KsCreateDefaultSecurity(
1026 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
1027 OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
1028 {
1029 PGENERIC_MAPPING Mapping;
1030 SECURITY_SUBJECT_CONTEXT SubjectContext;
1031 NTSTATUS Status;
1032
1033 /* start capturing security context of calling thread */
1034 SeCaptureSubjectContext(&SubjectContext);
1035 /* get generic mapping */
1036 Mapping = IoGetFileObjectGenericMapping();
1037 /* build new descriptor */
1038 Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
1039 /* release security descriptor */
1040 SeReleaseSubjectContext(&SubjectContext);
1041 /* done */
1042 return Status;
1043 }
1044
1045 /*
1046 @unimplemented
1047 */
1048 KSDDKAPI
1049 NTSTATUS
1050 NTAPI
KsForwardIrp(IN PIRP Irp,IN PFILE_OBJECT FileObject,IN BOOLEAN ReuseStackLocation)1051 KsForwardIrp(
1052 IN PIRP Irp,
1053 IN PFILE_OBJECT FileObject,
1054 IN BOOLEAN ReuseStackLocation)
1055 {
1056 UNIMPLEMENTED;
1057 return STATUS_UNSUCCESSFUL;
1058 }
1059
1060
1061 /*
1062 @unimplemented
1063 */
1064 KSDDKAPI
1065 NTSTATUS
1066 NTAPI
KsForwardAndCatchIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PFILE_OBJECT FileObject,IN KSSTACK_USE StackUse)1067 KsForwardAndCatchIrp(
1068 IN PDEVICE_OBJECT DeviceObject,
1069 IN PIRP Irp,
1070 IN PFILE_OBJECT FileObject,
1071 IN KSSTACK_USE StackUse)
1072 {
1073 UNIMPLEMENTED;
1074 return STATUS_UNSUCCESSFUL;
1075 }
1076
1077
1078 NTSTATUS
1079 NTAPI
KspSynchronousIoControlDeviceCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)1080 KspSynchronousIoControlDeviceCompletion(
1081 IN PDEVICE_OBJECT DeviceObject,
1082 IN PIRP Irp,
1083 IN PVOID Context)
1084 {
1085 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
1086
1087 IoStatusBlock->Information = Irp->IoStatus.Information;
1088 IoStatusBlock->Status = Irp->IoStatus.Status;
1089
1090 return STATUS_SUCCESS;
1091 }
1092
1093 /*
1094 @implemented
1095 */
1096 KSDDKAPI
1097 NTSTATUS
1098 NTAPI
KsSynchronousIoControlDevice(IN PFILE_OBJECT FileObject,IN KPROCESSOR_MODE RequestorMode,IN ULONG IoControl,IN PVOID InBuffer,IN ULONG InSize,OUT PVOID OutBuffer,IN ULONG OutSize,OUT PULONG BytesReturned)1099 KsSynchronousIoControlDevice(
1100 IN PFILE_OBJECT FileObject,
1101 IN KPROCESSOR_MODE RequestorMode,
1102 IN ULONG IoControl,
1103 IN PVOID InBuffer,
1104 IN ULONG InSize,
1105 OUT PVOID OutBuffer,
1106 IN ULONG OutSize,
1107 OUT PULONG BytesReturned)
1108 {
1109 PKSIOBJECT_HEADER ObjectHeader;
1110 PDEVICE_OBJECT DeviceObject;
1111 KEVENT Event;
1112 PIRP Irp;
1113 IO_STATUS_BLOCK IoStatusBlock;
1114 PIO_STACK_LOCATION IoStack;
1115 NTSTATUS Status;
1116
1117 /* check for valid file object */
1118 if (!FileObject)
1119 return STATUS_INVALID_PARAMETER;
1120
1121 /* get device object to send the request to */
1122 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1123 if (!DeviceObject)
1124 return STATUS_UNSUCCESSFUL;
1125
1126
1127 /* get object header */
1128 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
1129
1130 /* check if there is fast device io function */
1131 if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
1132 {
1133 IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
1134 IoStatusBlock.Information = 0;
1135
1136 /* send the request */
1137 Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
1138 /* check if the request was handled */
1139 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
1140 if (Status)
1141 {
1142 /* store bytes returned */
1143 *BytesReturned = (ULONG)IoStatusBlock.Information;
1144 /* return status */
1145 return IoStatusBlock.Status;
1146 }
1147 }
1148
1149 /* initialize the event */
1150 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1151
1152 /* create the irp */
1153 Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
1154
1155 if (!Irp)
1156 {
1157 /* no memory to allocate the irp */
1158 return STATUS_INSUFFICIENT_RESOURCES;
1159 }
1160
1161
1162 /* Store Fileobject */
1163 IoStack = IoGetNextIrpStackLocation(Irp);
1164 IoStack->FileObject = FileObject;
1165
1166 if (IoControl == IOCTL_KS_WRITE_STREAM)
1167 {
1168 Irp->AssociatedIrp.SystemBuffer = OutBuffer;
1169 }
1170 else if (IoControl == IOCTL_KS_READ_STREAM)
1171 {
1172 Irp->AssociatedIrp.SystemBuffer = InBuffer;
1173 }
1174
1175 IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
1176
1177 Status = IoCallDriver(DeviceObject, Irp);
1178 if (Status == STATUS_PENDING)
1179 {
1180 KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
1181 Status = IoStatusBlock.Status;
1182 }
1183
1184 *BytesReturned = (ULONG)IoStatusBlock.Information;
1185 return Status;
1186 }
1187
1188 /*
1189 @unimplemented
1190 */
1191 KSDDKAPI
1192 NTSTATUS
1193 NTAPI
KsUnserializeObjectPropertiesFromRegistry(IN PFILE_OBJECT FileObject,IN HANDLE ParentKey OPTIONAL,IN PUNICODE_STRING RegistryPath OPTIONAL)1194 KsUnserializeObjectPropertiesFromRegistry(
1195 IN PFILE_OBJECT FileObject,
1196 IN HANDLE ParentKey OPTIONAL,
1197 IN PUNICODE_STRING RegistryPath OPTIONAL)
1198 {
1199 UNIMPLEMENTED;
1200 return STATUS_NOT_IMPLEMENTED;
1201 }
1202
1203
1204 /*
1205 @implemented
1206 */
1207 KSDDKAPI
1208 NTSTATUS
1209 NTAPI
KsCacheMedium(IN PUNICODE_STRING SymbolicLink,IN PKSPIN_MEDIUM Medium,IN ULONG PinDirection)1210 KsCacheMedium(
1211 IN PUNICODE_STRING SymbolicLink,
1212 IN PKSPIN_MEDIUM Medium,
1213 IN ULONG PinDirection)
1214 {
1215 HANDLE hKey;
1216 UNICODE_STRING Path;
1217 UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1218 UNICODE_STRING GuidString;
1219 NTSTATUS Status;
1220 OBJECT_ATTRIBUTES ObjectAttributes;
1221 BOOLEAN PathAdjusted = FALSE;
1222 ULONG Value = 0;
1223
1224 /* first check if the medium is standard */
1225 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) ||
1226 IsEqualGUIDAligned(&GUID_NULL, &Medium->Set))
1227 {
1228 /* no need to cache that */
1229 return STATUS_SUCCESS;
1230 }
1231
1232 /* convert guid to string */
1233 Status = RtlStringFromGUID(&Medium->Set, &GuidString);
1234 if (!NT_SUCCESS(Status))
1235 return Status;
1236
1237 /* allocate path buffer */
1238 Path.Length = 0;
1239 Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR);
1240 Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength);
1241 if (!Path.Buffer)
1242 {
1243 /* not enough resources */
1244 RtlFreeUnicodeString(&GuidString);
1245 return STATUS_INSUFFICIENT_RESOURCES;
1246 }
1247
1248 RtlAppendUnicodeStringToString(&Path, &BasePath);
1249 RtlAppendUnicodeStringToString(&Path, &GuidString);
1250 RtlAppendUnicodeToString(&Path, L"-");
1251 /* FIXME append real instance id */
1252 RtlAppendUnicodeToString(&Path, L"0");
1253 RtlAppendUnicodeToString(&Path, L"-");
1254 /* FIXME append real instance id */
1255 RtlAppendUnicodeToString(&Path, L"0");
1256
1257 /* free guid string */
1258 RtlFreeUnicodeString(&GuidString);
1259
1260 /* initialize object attributes */
1261 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
1262 /* create the key */
1263 Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
1264
1265 /* free path buffer */
1266 FreeItem(Path.Buffer);
1267
1268 if (NT_SUCCESS(Status))
1269 {
1270 /* store symbolic link */
1271 if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?')
1272 {
1273 /* replace kernel path with user mode path */
1274 SymbolicLink->Buffer[1] = L'\\';
1275 PathAdjusted = TRUE;
1276 }
1277
1278 /* store the key */
1279 Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG));
1280
1281 if (PathAdjusted)
1282 {
1283 /* restore kernel path */
1284 SymbolicLink->Buffer[1] = L'?';
1285 }
1286
1287 ZwClose(hKey);
1288 }
1289
1290 /* done */
1291 return Status;
1292 }
1293
1294 /*
1295 @implemented
1296 */
1297 NTSTATUS
1298 NTAPI
DllInitialize(PUNICODE_STRING RegistryPath)1299 DllInitialize(
1300 PUNICODE_STRING RegistryPath)
1301 {
1302 return STATUS_SUCCESS;
1303 }
1304
1305
1306 NTSTATUS
1307 NTAPI
KopDispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1308 KopDispatchClose(
1309 IN PDEVICE_OBJECT DeviceObject,
1310 IN PIRP Irp)
1311 {
1312 PKO_OBJECT_HEADER Header;
1313 PIO_STACK_LOCATION IoStack;
1314 PDEVICE_EXTENSION DeviceExtension;
1315
1316 /* get current irp stack location */
1317 IoStack = IoGetCurrentIrpStackLocation(Irp);
1318
1319 /* get ko object header */
1320 Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2;
1321
1322 /* free ks object header */
1323 KsFreeObjectHeader(Header->ObjectHeader);
1324
1325 /* free ko object header */
1326 FreeItem(Header);
1327
1328 /* get device extension */
1329 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1330
1331 /* release bus object */
1332 KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1333
1334 /* complete request */
1335 Irp->IoStatus.Status = STATUS_SUCCESS;
1336 CompleteRequest(Irp, IO_NO_INCREMENT);
1337
1338 return STATUS_SUCCESS;
1339 }
1340
1341
1342
1343 static KSDISPATCH_TABLE KoDispatchTable =
1344 {
1345 KsDispatchInvalidDeviceRequest,
1346 KsDispatchInvalidDeviceRequest,
1347 KsDispatchInvalidDeviceRequest,
1348 KsDispatchInvalidDeviceRequest,
1349 KopDispatchClose,
1350 KsDispatchQuerySecurity,
1351 KsDispatchSetSecurity,
1352 KsDispatchFastIoDeviceControlFailure,
1353 KsDispatchFastReadFailure,
1354 KsDispatchFastReadFailure,
1355 };
1356
1357
1358 NTSTATUS
1359 NTAPI
KopDispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1360 KopDispatchCreate(
1361 IN PDEVICE_OBJECT DeviceObject,
1362 IN PIRP Irp)
1363 {
1364 PKO_OBJECT_HEADER Header = NULL;
1365 PIO_STACK_LOCATION IoStack;
1366 PKO_DRIVER_EXTENSION DriverObjectExtension;
1367 NTSTATUS Status;
1368
1369 /* get current irp stack location */
1370 IoStack = IoGetCurrentIrpStackLocation(Irp);
1371
1372 if (!IoStack->FileObject)
1373 {
1374 DPRINT1("FileObject not attached!\n");
1375 Status = STATUS_UNSUCCESSFUL;
1376 goto cleanup;
1377 }
1378
1379 /* get driver object extension */
1380 DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize);
1381 if (!DriverObjectExtension)
1382 {
1383 DPRINT1("No DriverObjectExtension!\n");
1384 Status = STATUS_UNSUCCESSFUL;
1385 goto cleanup;
1386 }
1387
1388 /* allocate ko object header */
1389 Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER));
1390 if (!Header)
1391 {
1392 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1393 Status = STATUS_INSUFFICIENT_RESOURCES;
1394 goto cleanup;
1395 }
1396
1397 /* initialize create item */
1398 Header->CreateItem.Create = KopDispatchCreate;
1399 RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject);
1400
1401
1402 /* now allocate the object header */
1403 Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable);
1404 if (!NT_SUCCESS(Status))
1405 {
1406 /* failed */
1407 goto cleanup;
1408 }
1409
1410 /* FIXME
1411 * extract clsid and interface id from irp
1412 * call the standard create handler
1413 */
1414
1415 UNIMPLEMENTED;
1416
1417 IoStack->FileObject->FsContext2 = (PVOID)Header;
1418
1419 Irp->IoStatus.Status = Status;
1420 CompleteRequest(Irp, IO_NO_INCREMENT);
1421
1422 return Status;
1423
1424 cleanup:
1425
1426 if (Header && Header->ObjectHeader)
1427 KsFreeObjectHeader(Header->ObjectHeader);
1428
1429 if (Header)
1430 FreeItem(Header);
1431
1432 Irp->IoStatus.Status = Status;
1433 CompleteRequest(Irp, IO_NO_INCREMENT);
1434 return Status;
1435 }
1436
1437
1438
1439 NTSTATUS
1440 NTAPI
KopAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject)1441 KopAddDevice(
1442 IN PDRIVER_OBJECT DriverObject,
1443 IN PDEVICE_OBJECT PhysicalDeviceObject)
1444 {
1445 NTSTATUS Status = STATUS_DEVICE_REMOVED;
1446 PDEVICE_OBJECT FunctionalDeviceObject= NULL;
1447 PDEVICE_OBJECT NextDeviceObject;
1448 PDEVICE_EXTENSION DeviceExtension;
1449 PKSOBJECT_CREATE_ITEM CreateItem;
1450
1451 /* create the device object */
1452 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
1453 if (!NT_SUCCESS(Status))
1454 return Status;
1455
1456 /* allocate the create item */
1457 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
1458
1459 if (!CreateItem)
1460 {
1461 /* not enough memory */
1462 IoDeleteDevice(FunctionalDeviceObject);
1463 return STATUS_INSUFFICIENT_RESOURCES;
1464 }
1465
1466 /* initialize create item */
1467 CreateItem->Create = KopDispatchCreate;
1468 RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject);
1469
1470 /* get device extension */
1471 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
1472
1473 /* now allocate the device header */
1474 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem);
1475 if (!NT_SUCCESS(Status))
1476 {
1477 /* failed */
1478 IoDeleteDevice(FunctionalDeviceObject);
1479 FreeItem(CreateItem);
1480 return Status;
1481 }
1482
1483 /* now attach to device stack */
1484 NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
1485 if (NextDeviceObject)
1486 {
1487 /* store pnp base object */
1488 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject);
1489 /* set device flags */
1490 FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
1491 FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
1492 }
1493 else
1494 {
1495 /* failed */
1496 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1497 FreeItem(CreateItem);
1498 IoDeleteDevice(FunctionalDeviceObject);
1499 Status = STATUS_DEVICE_REMOVED;
1500 }
1501
1502 /* return result */
1503 return Status;
1504 }
1505
1506
1507 /*
1508 @implemented
1509 */
1510 COMDDKAPI
1511 NTSTATUS
1512 NTAPI
KoDeviceInitialize(IN PDEVICE_OBJECT DeviceObject)1513 KoDeviceInitialize(
1514 IN PDEVICE_OBJECT DeviceObject)
1515 {
1516 PDEVICE_EXTENSION DeviceExtension;
1517
1518 /* get device extension */
1519 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1520
1521 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL);
1522 }
1523
1524 /*
1525 @implemented
1526 */
1527 COMDDKAPI
1528 NTSTATUS
1529 NTAPI
KoDriverInitialize(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPathName,IN KoCreateObjectHandler CreateObjectHandler)1530 KoDriverInitialize(
1531 IN PDRIVER_OBJECT DriverObject,
1532 IN PUNICODE_STRING RegistryPathName,
1533 IN KoCreateObjectHandler CreateObjectHandler)
1534 {
1535 PKO_DRIVER_EXTENSION DriverObjectExtension;
1536 NTSTATUS Status;
1537
1538 /* allocate driver object extension */
1539 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
1540
1541 /* did it work */
1542 if (NT_SUCCESS(Status))
1543 {
1544 /* store create handler */
1545 DriverObjectExtension->CreateObjectHandler = CreateObjectHandler;
1546
1547 /* Setting our IRP handlers */
1548 DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp;
1549 DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
1550 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
1551
1552 /* The driver unload routine */
1553 DriverObject->DriverUnload = KsNullDriverUnload;
1554
1555 /* The driver-supplied AddDevice */
1556 DriverObject->DriverExtension->AddDevice = KopAddDevice;
1557
1558 /* KS handles these */
1559 DPRINT1("Setting KS function handlers\n");
1560 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
1561 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
1562 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
1563
1564 }
1565
1566 return Status;
1567 }
1568
1569 /*
1570 @unimplemented
1571 */
1572 COMDDKAPI
1573 VOID
1574 NTAPI
KoRelease(IN REFCLSID ClassId)1575 KoRelease(
1576 IN REFCLSID ClassId)
1577 {
1578
1579 }
1580
1581 /*
1582 @implemented
1583 */
1584 KSDDKAPI
1585 VOID
1586 NTAPI
KsAcquireControl(IN PVOID Object)1587 KsAcquireControl(
1588 IN PVOID Object)
1589 {
1590 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1591
1592 /* sanity check */
1593 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1594
1595 KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
1596
1597 }
1598
1599 /*
1600 @implemented
1601 */
1602 VOID
1603 NTAPI
KsReleaseControl(IN PVOID Object)1604 KsReleaseControl(
1605 IN PVOID Object)
1606 {
1607 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1608
1609 /* sanity check */
1610 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1611
1612 KeReleaseMutex(BasicHeader->ControlMutex, FALSE);
1613 }
1614
1615
1616
1617 /*
1618 @implemented
1619 */
1620 KSDDKAPI
1621 VOID
1622 NTAPI
KsAcquireDevice(IN PKSDEVICE Device)1623 KsAcquireDevice(
1624 IN PKSDEVICE Device)
1625 {
1626 IKsDevice *KsDevice;
1627 PKSIDEVICE_HEADER DeviceHeader;
1628
1629 DPRINT("KsAcquireDevice\n");
1630 DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1631
1632 /* get device interface*/
1633 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
1634
1635 /* acquire device mutex */
1636 KsDevice->lpVtbl->AcquireDevice(KsDevice);
1637 }
1638
1639 /*
1640 @implemented
1641 */
1642 VOID
1643 NTAPI
KsReleaseDevice(IN PKSDEVICE Device)1644 KsReleaseDevice(
1645 IN PKSDEVICE Device)
1646 {
1647 IKsDevice *KsDevice;
1648 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1649
1650 /* get device interface*/
1651 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
1652
1653 /* release device mutex */
1654 KsDevice->lpVtbl->ReleaseDevice(KsDevice);
1655 }
1656
1657 /*
1658 @implemented
1659 */
1660 KSDDKAPI
1661 VOID
1662 NTAPI
KsTerminateDevice(IN PDEVICE_OBJECT DeviceObject)1663 KsTerminateDevice(
1664 IN PDEVICE_OBJECT DeviceObject)
1665 {
1666 IKsDevice *KsDevice;
1667 PKSIDEVICE_HEADER DeviceHeader;
1668 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1669
1670 /* get device header */
1671 DeviceHeader = DeviceExtension->DeviceHeader;
1672
1673 /* get device interface*/
1674 KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
1675
1676 /* now free device header */
1677 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
1678
1679 /* release interface when available */
1680 if (KsDevice)
1681 {
1682 /* delete IKsDevice interface */
1683 KsDevice->lpVtbl->Release(KsDevice);
1684 }
1685 }
1686
1687 /*
1688 @implemented
1689 */
1690 KSDDKAPI
1691 VOID
1692 NTAPI
KsCompletePendingRequest(IN PIRP Irp)1693 KsCompletePendingRequest(
1694 IN PIRP Irp)
1695 {
1696 PIO_STACK_LOCATION IoStack;
1697
1698 /* get current irp stack location */
1699 IoStack = IoGetCurrentIrpStackLocation(Irp);
1700
1701 /* sanity check */
1702 ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
1703
1704 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
1705 {
1706 /* can be completed immediately */
1707 CompleteRequest(Irp, IO_NO_INCREMENT);
1708 return;
1709 }
1710
1711 /* did close operation fail */
1712 if (!NT_SUCCESS(Irp->IoStatus.Status))
1713 {
1714 /* closing failed, complete irp */
1715 CompleteRequest(Irp, IO_NO_INCREMENT);
1716 return;
1717 }
1718
1719 /* FIXME
1720 * delete object / device header
1721 * remove dead pin / filter instance
1722 */
1723 UNIMPLEMENTED;
1724
1725 }
1726
1727 NTSTATUS
1728 NTAPI
KspSetGetBusDataCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)1729 KspSetGetBusDataCompletion(
1730 IN PDEVICE_OBJECT DeviceObject,
1731 IN PIRP Irp,
1732 IN PVOID Context)
1733 {
1734 /* signal completion */
1735 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
1736
1737 /* more work needs be done, so dont free the irp */
1738 return STATUS_MORE_PROCESSING_REQUIRED;
1739
1740 }
1741
1742 NTSTATUS
KspDeviceSetGetBusData(IN PDEVICE_OBJECT DeviceObject,IN ULONG DataType,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length,IN BOOL bGet)1743 KspDeviceSetGetBusData(
1744 IN PDEVICE_OBJECT DeviceObject,
1745 IN ULONG DataType,
1746 IN PVOID Buffer,
1747 IN ULONG Offset,
1748 IN ULONG Length,
1749 IN BOOL bGet)
1750 {
1751 PIO_STACK_LOCATION IoStack;
1752 PIRP Irp;
1753 NTSTATUS Status;
1754 KEVENT Event;
1755
1756 /* allocate the irp */
1757 Irp = IoAllocateIrp(1, /*FIXME */
1758 FALSE);
1759
1760 if (!Irp)
1761 return STATUS_INSUFFICIENT_RESOURCES;
1762
1763 /* initialize the event */
1764 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1765
1766 /* get next stack location */
1767 IoStack = IoGetNextIrpStackLocation(Irp);
1768
1769 /* setup a completion routine */
1770 IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1771
1772 /* setup parameters */
1773 IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
1774 IoStack->Parameters.ReadWriteConfig.Length = Length;
1775 IoStack->Parameters.ReadWriteConfig.Offset = Offset;
1776 IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
1777 /* setup function code */
1778 IoStack->MajorFunction = IRP_MJ_PNP;
1779 IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
1780
1781 /* lets call the driver */
1782 Status = IoCallDriver(DeviceObject, Irp);
1783
1784 /* is the request still pending */
1785 if (Status == STATUS_PENDING)
1786 {
1787 /* have a nap */
1788 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1789 /* update status */
1790 Status = Irp->IoStatus.Status;
1791 }
1792
1793 /* free the irp */
1794 IoFreeIrp(Irp);
1795 /* done */
1796 return Status;
1797 }
1798
1799 /*
1800 @implemented
1801 */
1802 KSDDKAPI
1803 ULONG
1804 NTAPI
KsDeviceSetBusData(IN PKSDEVICE Device,IN ULONG DataType,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)1805 KsDeviceSetBusData(
1806 IN PKSDEVICE Device,
1807 IN ULONG DataType,
1808 IN PVOID Buffer,
1809 IN ULONG Offset,
1810 IN ULONG Length)
1811 {
1812 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1813 DataType, Buffer, Offset, Length, FALSE);
1814 }
1815
1816
1817 /*
1818 @implemented
1819 */
1820 KSDDKAPI
1821 ULONG
1822 NTAPI
KsDeviceGetBusData(IN PKSDEVICE Device,IN ULONG DataType,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)1823 KsDeviceGetBusData(
1824 IN PKSDEVICE Device,
1825 IN ULONG DataType,
1826 IN PVOID Buffer,
1827 IN ULONG Offset,
1828 IN ULONG Length)
1829 {
1830 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1831 DataType, Buffer, Offset, Length, TRUE);
1832
1833 }
1834
1835 /*
1836 @implemented
1837 */
1838 KSDDKAPI
1839 void
1840 NTAPI
KsDeviceRegisterAdapterObject(IN PKSDEVICE Device,IN PADAPTER_OBJECT AdapterObject,IN ULONG MaxMappingsByteCount,IN ULONG MappingTableStride)1841 KsDeviceRegisterAdapterObject(
1842 IN PKSDEVICE Device,
1843 IN PADAPTER_OBJECT AdapterObject,
1844 IN ULONG MaxMappingsByteCount,
1845 IN ULONG MappingTableStride)
1846 {
1847 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1848
1849 DeviceHeader->AdapterObject = AdapterObject;
1850 DeviceHeader->MaxMappingsByteCount = MaxMappingsByteCount;
1851 DeviceHeader->MappingTableStride = MappingTableStride;
1852
1853 }
1854
1855
1856 /*
1857 @implemented
1858 */
1859 KSDDKAPI
1860 PVOID
1861 NTAPI
KsGetFirstChild(IN PVOID Object)1862 KsGetFirstChild(
1863 IN PVOID Object)
1864 {
1865 PKSBASIC_HEADER BasicHeader;
1866
1867 /* get the basic header */
1868 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1869
1870 /* type has to be either a device or a filter factory */
1871 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory);
1872
1873 return (PVOID)BasicHeader->FirstChild.Filter;
1874 }
1875
1876 /*
1877 @implemented
1878 */
1879 KSDDKAPI
1880 PVOID
1881 NTAPI
KsGetNextSibling(IN PVOID Object)1882 KsGetNextSibling(
1883 IN PVOID Object)
1884 {
1885 PKSBASIC_HEADER BasicHeader;
1886
1887 /* get the basic header */
1888 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1889
1890 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
1891 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1892
1893 return (PVOID)BasicHeader->Next.Pin;
1894 }
1895
1896 ULONG
KspCountMethodSets(IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)1897 KspCountMethodSets(
1898 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1899 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1900 {
1901 ULONG Index, SubIndex, Count;
1902 BOOL bFound;
1903
1904 if (!AutomationTableA)
1905 return AutomationTableB->MethodSetsCount;
1906
1907 if (!AutomationTableB)
1908 return AutomationTableA->MethodSetsCount;
1909
1910
1911 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA->MethodItemSize, AutomationTableA->MethodSetsCount);
1912 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB->MethodItemSize, AutomationTableB->MethodSetsCount);
1913
1914 if (AutomationTableA->MethodItemSize && AutomationTableB->MethodItemSize)
1915 {
1916 /* sanity check */
1917 ASSERT(AutomationTableA->MethodItemSize == AutomationTableB->MethodItemSize);
1918 }
1919
1920 /* now iterate all property sets and compare their guids */
1921 Count = AutomationTableA->MethodSetsCount;
1922
1923 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
1924 {
1925 /* set found to false */
1926 bFound = FALSE;
1927
1928 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
1929 {
1930 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
1931 {
1932 /* same property set found */
1933 bFound = TRUE;
1934 break;
1935 }
1936 }
1937
1938 if (!bFound)
1939 Count++;
1940 }
1941
1942 return Count;
1943 }
1944
1945 ULONG
KspCountEventSets(IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)1946 KspCountEventSets(
1947 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1948 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1949 {
1950 ULONG Index, SubIndex, Count;
1951 BOOL bFound;
1952
1953 if (!AutomationTableA)
1954 return AutomationTableB->EventSetsCount;
1955
1956 if (!AutomationTableB)
1957 return AutomationTableA->EventSetsCount;
1958
1959 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA->EventItemSize, AutomationTableA->EventSetsCount);
1960 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB->EventItemSize, AutomationTableB->EventSetsCount);
1961
1962 if (AutomationTableA->EventItemSize && AutomationTableB->EventItemSize)
1963 {
1964 /* sanity check */
1965 ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize);
1966 }
1967
1968 /* now iterate all Event sets and compare their guids */
1969 Count = AutomationTableA->EventSetsCount;
1970
1971 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
1972 {
1973 /* set found to false */
1974 bFound = FALSE;
1975
1976 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
1977 {
1978 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
1979 {
1980 /* same Event set found */
1981 bFound = TRUE;
1982 break;
1983 }
1984 }
1985
1986 if (!bFound)
1987 Count++;
1988 }
1989
1990 return Count;
1991 }
1992
1993
1994 ULONG
KspCountPropertySets(IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)1995 KspCountPropertySets(
1996 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1997 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1998 {
1999 ULONG Index, SubIndex, Count;
2000 BOOL bFound;
2001
2002 if (!AutomationTableA)
2003 return AutomationTableB->PropertySetsCount;
2004
2005 if (!AutomationTableB)
2006 return AutomationTableA->PropertySetsCount;
2007
2008 /* sanity check */
2009 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA->PropertyItemSize, AutomationTableA->PropertySetsCount);
2010 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB->PropertyItemSize, AutomationTableB->PropertySetsCount);
2011 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
2012
2013 /* now iterate all property sets and compare their guids */
2014 Count = AutomationTableA->PropertySetsCount;
2015
2016 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2017 {
2018 /* set found to false */
2019 bFound = FALSE;
2020
2021 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2022 {
2023 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2024 {
2025 /* same property set found */
2026 bFound = TRUE;
2027 break;
2028 }
2029 }
2030
2031 if (!bFound)
2032 Count++;
2033 }
2034
2035 return Count;
2036 }
2037
2038 NTSTATUS
KspCopyMethodSets(OUT PKSAUTOMATION_TABLE Table,IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)2039 KspCopyMethodSets(
2040 OUT PKSAUTOMATION_TABLE Table,
2041 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2042 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2043 {
2044 ULONG Index, SubIndex, Count;
2045 BOOL bFound;
2046
2047 if (!AutomationTableA)
2048 {
2049 /* copy of property set */
2050 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableB->MethodSetsCount);
2051 return STATUS_SUCCESS;
2052 }
2053 else if (!AutomationTableB)
2054 {
2055 /* copy of property set */
2056 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
2057 return STATUS_SUCCESS;
2058 }
2059
2060 /* first copy all property items from dominant table */
2061 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
2062 /* set counter */
2063 Count = AutomationTableA->MethodSetsCount;
2064
2065 /* now copy entries which aren't available in the dominant table */
2066 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
2067 {
2068 /* set found to false */
2069 bFound = FALSE;
2070
2071 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
2072 {
2073 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
2074 {
2075 /* same property set found */
2076 bFound = TRUE;
2077 break;
2078 }
2079 }
2080
2081 if (!bFound)
2082 {
2083 /* copy new property item set */
2084 RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], sizeof(KSMETHOD_SET));
2085 Count++;
2086 }
2087 }
2088
2089 return STATUS_SUCCESS;
2090 }
2091
2092 VOID
KspAddPropertyItem(OUT PKSPROPERTY_SET OutPropertySet,IN PKSPROPERTY_ITEM PropertyItem,IN ULONG PropertyItemSize)2093 KspAddPropertyItem(
2094 OUT PKSPROPERTY_SET OutPropertySet,
2095 IN PKSPROPERTY_ITEM PropertyItem,
2096 IN ULONG PropertyItemSize)
2097 {
2098 PKSPROPERTY_ITEM CurrentPropertyItem;
2099 ULONG Index;
2100
2101 // check if the property item is already present
2102 CurrentPropertyItem = (PKSPROPERTY_ITEM)OutPropertySet->PropertyItem;
2103 for(Index = 0; Index < OutPropertySet->PropertiesCount; Index++)
2104 {
2105 if (CurrentPropertyItem->PropertyId == PropertyItem->PropertyId)
2106 {
2107 // item already present
2108 return;
2109 }
2110
2111 // next item
2112 CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + PropertyItemSize);
2113 }
2114 // add item
2115 RtlCopyMemory(CurrentPropertyItem, PropertyItem, PropertyItemSize);
2116 OutPropertySet->PropertiesCount++;
2117 }
2118
2119 NTSTATUS
KspMergePropertySet(OUT PKSAUTOMATION_TABLE Table,OUT PKSPROPERTY_SET OutPropertySet,IN PKSPROPERTY_SET PropertySetA,IN PKSPROPERTY_SET PropertySetB,IN KSOBJECT_BAG Bag OPTIONAL)2120 KspMergePropertySet(
2121 OUT PKSAUTOMATION_TABLE Table,
2122 OUT PKSPROPERTY_SET OutPropertySet,
2123 IN PKSPROPERTY_SET PropertySetA,
2124 IN PKSPROPERTY_SET PropertySetB,
2125 IN KSOBJECT_BAG Bag OPTIONAL)
2126 {
2127 ULONG PropertyCount, Index;
2128 PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem;
2129 NTSTATUS Status;
2130
2131 // max properties
2132 PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount;
2133
2134 // allocate items
2135 PropertyItem = AllocateItem(NonPagedPool, Table->PropertyItemSize * PropertyCount);
2136 if (!PropertyItem)
2137 return STATUS_INSUFFICIENT_RESOURCES;
2138
2139 if (Bag)
2140 {
2141 /* add table to object bag */
2142 Status = KsAddItemToObjectBag(Bag, PropertyItem, NULL);
2143 /* check for success */
2144 if (!NT_SUCCESS(Status))
2145 {
2146 /* free table */
2147 FreeItem(Table);
2148 return Status;
2149 }
2150 }
2151
2152 // copy entries from dominant table
2153 RtlCopyMemory(PropertyItem, PropertySetA->PropertyItem, Table->PropertyItemSize * PropertySetA->PropertiesCount);
2154
2155 // init property set
2156 OutPropertySet->PropertiesCount = PropertySetA->PropertiesCount;
2157 OutPropertySet->PropertyItem = PropertyItem;
2158
2159 // copy other entries
2160 CurrentPropertyItem = (PKSPROPERTY_ITEM)PropertySetB->PropertyItem;
2161 for(Index = 0; Index < PropertySetB->PropertiesCount; Index++)
2162 {
2163
2164 // add entries
2165 KspAddPropertyItem(OutPropertySet, CurrentPropertyItem, Table->PropertyItemSize);
2166
2167 // next entry
2168 CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + Table->PropertyItemSize);
2169 }
2170
2171 // done
2172 return STATUS_SUCCESS;
2173 }
2174
2175
2176 NTSTATUS
KspCopyPropertySets(OUT PKSAUTOMATION_TABLE Table,IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,IN KSOBJECT_BAG Bag OPTIONAL)2177 KspCopyPropertySets(
2178 OUT PKSAUTOMATION_TABLE Table,
2179 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2180 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
2181 IN KSOBJECT_BAG Bag OPTIONAL)
2182 {
2183 ULONG Index, SubIndex, Count;
2184 BOOL bFound;
2185 NTSTATUS Status;
2186
2187 if (!AutomationTableA)
2188 {
2189 /* copy of property set */
2190 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableB->PropertySetsCount);
2191 return STATUS_SUCCESS;
2192 }
2193 else if (!AutomationTableB)
2194 {
2195 /* copy of property set */
2196 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
2197 return STATUS_SUCCESS;
2198 }
2199
2200 /* first copy all property items from dominant table */
2201 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
2202 /* set counter */
2203 Count = AutomationTableA->PropertySetsCount;
2204
2205 /* now copy entries which aren't available in the dominant table */
2206 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2207 {
2208 /* set found to false */
2209 bFound = FALSE;
2210
2211 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2212 {
2213 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2214 {
2215 /* same property set found */
2216 bFound = TRUE;
2217 break;
2218 }
2219 }
2220
2221 if (!bFound)
2222 {
2223 /* copy new property item set */
2224 RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], sizeof(KSPROPERTY_SET));
2225 Count++;
2226 }
2227 else
2228 {
2229 // merge property sets
2230 Status = KspMergePropertySet(Table, (PKSPROPERTY_SET)&Table->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableA->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableB->PropertySets[Index], Bag);
2231 if (!NT_SUCCESS(Status))
2232 {
2233 // failed to merge
2234 DPRINT1("[KS] Failed to merge %x\n", Status);
2235 return Status;
2236 }
2237 }
2238 }
2239
2240 return STATUS_SUCCESS;
2241 }
2242
2243 NTSTATUS
KspCopyEventSets(OUT PKSAUTOMATION_TABLE Table,IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)2244 KspCopyEventSets(
2245 OUT PKSAUTOMATION_TABLE Table,
2246 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2247 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2248 {
2249 ULONG Index, SubIndex, Count;
2250 BOOL bFound;
2251
2252 if (!AutomationTableA)
2253 {
2254 /* copy of Event set */
2255 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, sizeof(KSEVENT_SET) * AutomationTableB->EventSetsCount);
2256 return STATUS_SUCCESS;
2257 }
2258 else if (!AutomationTableB)
2259 {
2260 /* copy of Event set */
2261 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
2262 return STATUS_SUCCESS;
2263 }
2264
2265 /* first copy all Event items from dominant table */
2266 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
2267 /* set counter */
2268 Count = AutomationTableA->EventSetsCount;
2269
2270 /* now copy entries which aren't available in the dominant table */
2271 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
2272 {
2273 /* set found to false */
2274 bFound = FALSE;
2275
2276 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
2277 {
2278 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
2279 {
2280 /* same Event set found */
2281 bFound = TRUE;
2282 break;
2283 }
2284 }
2285
2286 if (!bFound)
2287 {
2288 /* copy new Event item set */
2289 RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], sizeof(KSEVENT_SET));
2290 Count++;
2291 }
2292 }
2293
2294 return STATUS_SUCCESS;
2295 }
2296
2297
2298 /*
2299 @implemented
2300 */
2301 NTSTATUS
2302 NTAPI
KsMergeAutomationTables(OUT PKSAUTOMATION_TABLE * AutomationTableAB,IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,IN KSOBJECT_BAG Bag OPTIONAL)2303 KsMergeAutomationTables(
2304 OUT PKSAUTOMATION_TABLE *AutomationTableAB,
2305 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2306 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
2307 IN KSOBJECT_BAG Bag OPTIONAL)
2308 {
2309 PKSAUTOMATION_TABLE Table;
2310 NTSTATUS Status = STATUS_SUCCESS;
2311
2312 if (!AutomationTableA && !AutomationTableB)
2313 {
2314 /* nothing to merge */
2315 return STATUS_SUCCESS;
2316 }
2317
2318 /* allocate an automation table */
2319 Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE));
2320 if (!Table)
2321 return STATUS_INSUFFICIENT_RESOURCES;
2322
2323 if (Bag)
2324 {
2325 /* add table to object bag */
2326 Status = KsAddItemToObjectBag(Bag, Table, NULL);
2327 /* check for success */
2328 if (!NT_SUCCESS(Status))
2329 {
2330 /* free table */
2331 FreeItem(Table);
2332 return Status;
2333 }
2334 }
2335
2336 /* count property sets */
2337 Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB);
2338
2339 if (Table->PropertySetsCount)
2340 {
2341 if (AutomationTableA)
2342 {
2343 /* use item size from dominant automation table */
2344 Table->PropertyItemSize = AutomationTableA->PropertyItemSize;
2345 }
2346 else
2347 {
2348 /* use item size from 2nd automation table */
2349 Table->PropertyItemSize = AutomationTableB->PropertyItemSize;
2350 }
2351
2352 if (AutomationTableA && AutomationTableB)
2353 {
2354 // FIXME handle different property item sizes
2355 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
2356 }
2357
2358 /* now allocate the property sets */
2359 Table->PropertySets = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * Table->PropertySetsCount);
2360
2361 if (!Table->PropertySets)
2362 {
2363 /* not enough memory */
2364 goto cleanup;
2365 }
2366
2367 if (Bag)
2368 {
2369 /* add set to property bag */
2370 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL);
2371 /* check for success */
2372 if (!NT_SUCCESS(Status))
2373 {
2374 /* cleanup table */
2375 goto cleanup;
2376 }
2377 }
2378 /* now copy the property sets */
2379 Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB, Bag);
2380 if(!NT_SUCCESS(Status))
2381 goto cleanup;
2382
2383 }
2384
2385 /* now count the method sets */
2386 Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB);
2387
2388 if (Table->MethodSetsCount)
2389 {
2390 if (AutomationTableA)
2391 {
2392 /* use item size from dominant automation table */
2393 Table->MethodItemSize = AutomationTableA->MethodItemSize;
2394 }
2395 else
2396 {
2397 /* use item size from 2nd automation table */
2398 Table->MethodItemSize = AutomationTableB->MethodItemSize;
2399 }
2400
2401 /* now allocate the property sets */
2402 Table->MethodSets = AllocateItem(NonPagedPool, sizeof(KSMETHOD_SET) * Table->MethodSetsCount);
2403
2404 if (!Table->MethodSets)
2405 {
2406 /* not enough memory */
2407 goto cleanup;
2408 }
2409
2410 if (Bag)
2411 {
2412 /* add set to property bag */
2413 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL);
2414 /* check for success */
2415 if (!NT_SUCCESS(Status))
2416 {
2417 /* cleanup table */
2418 goto cleanup;
2419 }
2420 }
2421 /* now copy the property sets */
2422 Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB);
2423 if(!NT_SUCCESS(Status))
2424 goto cleanup;
2425 }
2426
2427
2428 /* now count the event sets */
2429 Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB);
2430
2431 if (Table->EventSetsCount)
2432 {
2433 if (AutomationTableA)
2434 {
2435 /* use item size from dominant automation table */
2436 Table->EventItemSize = AutomationTableA->EventItemSize;
2437 }
2438 else
2439 {
2440 /* use item size from 2nd automation table */
2441 Table->EventItemSize = AutomationTableB->EventItemSize;
2442 }
2443
2444 /* now allocate the property sets */
2445 Table->EventSets = AllocateItem(NonPagedPool, sizeof(KSEVENT_SET) * Table->EventSetsCount);
2446
2447 if (!Table->EventSets)
2448 {
2449 /* not enough memory */
2450 goto cleanup;
2451 }
2452
2453 if (Bag)
2454 {
2455 /* add set to property bag */
2456 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL);
2457 /* check for success */
2458 if (!NT_SUCCESS(Status))
2459 {
2460 /* cleanup table */
2461 goto cleanup;
2462 }
2463 }
2464 /* now copy the property sets */
2465 Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB);
2466 if(!NT_SUCCESS(Status))
2467 goto cleanup;
2468 }
2469
2470 /* store result */
2471 *AutomationTableAB = Table;
2472
2473 return Status;
2474
2475
2476 cleanup:
2477
2478 if (Table)
2479 {
2480 if (Table->PropertySets)
2481 {
2482 /* clean property sets */
2483 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE)))
2484 FreeItem((PVOID)Table->PropertySets);
2485 }
2486
2487 if (Table->MethodSets)
2488 {
2489 /* clean property sets */
2490 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE)))
2491 FreeItem((PVOID)Table->MethodSets);
2492 }
2493
2494 if (Table->EventSets)
2495 {
2496 /* clean property sets */
2497 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE)))
2498 FreeItem((PVOID)Table->EventSets);
2499 }
2500
2501 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE)))
2502 FreeItem(Table);
2503 }
2504
2505 return STATUS_INSUFFICIENT_RESOURCES;
2506 }
2507
2508 /*
2509 @unimplemented
2510 */
2511 KSDDKAPI
2512 PUNKNOWN
2513 NTAPI
KsRegisterAggregatedClientUnknown(IN PVOID Object,IN PUNKNOWN ClientUnknown)2514 KsRegisterAggregatedClientUnknown(
2515 IN PVOID Object,
2516 IN PUNKNOWN ClientUnknown)
2517 {
2518 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
2519
2520 /* sanity check */
2521 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
2522 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
2523
2524 if (BasicHeader->ClientAggregate)
2525 {
2526 /* release existing aggregate */
2527 BasicHeader->ClientAggregate->lpVtbl->Release(BasicHeader->ClientAggregate);
2528 }
2529
2530 /* increment reference count */
2531 ClientUnknown->lpVtbl->AddRef(ClientUnknown);
2532
2533 /* store client aggregate */
2534 BasicHeader->ClientAggregate = ClientUnknown;
2535
2536 /* return objects outer unknown */
2537 return BasicHeader->OuterUnknown;
2538 }
2539
2540 /*
2541 @unimplemented
2542 */
2543 NTSTATUS
2544 NTAPI
KsRegisterFilterWithNoKSPins(IN PDEVICE_OBJECT DeviceObject,IN const GUID * InterfaceClassGUID,IN ULONG PinCount,IN BOOL * PinDirection,IN KSPIN_MEDIUM * MediumList,IN GUID * CategoryList OPTIONAL)2545 KsRegisterFilterWithNoKSPins(
2546 IN PDEVICE_OBJECT DeviceObject,
2547 IN const GUID* InterfaceClassGUID,
2548 IN ULONG PinCount,
2549 IN BOOL* PinDirection,
2550 IN KSPIN_MEDIUM* MediumList,
2551 IN GUID* CategoryList OPTIONAL)
2552 {
2553 ULONG Size, Index;
2554 NTSTATUS Status;
2555 PWSTR SymbolicLinkList;
2556 //PUCHAR Buffer;
2557 HANDLE hKey;
2558 UNICODE_STRING InterfaceString;
2559 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2560
2561 if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
2562 {
2563 /* all these parameters are required */
2564 return STATUS_INVALID_PARAMETER;
2565 }
2566
2567 /* calculate filter data value size */
2568 Size = PinCount * sizeof(KSPIN_MEDIUM);
2569 if (CategoryList)
2570 {
2571 /* add category list */
2572 Size += PinCount * sizeof(GUID);
2573 }
2574
2575 /* FIXME generate filter data blob */
2576 UNIMPLEMENTED;
2577
2578 /* get symbolic link list */
2579 Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
2580 if (NT_SUCCESS(Status))
2581 {
2582 /* initialize first symbolic link */
2583 RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
2584
2585 /* open first device interface registry key */
2586 Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
2587
2588 if (NT_SUCCESS(Status))
2589 {
2590 /* write filter data */
2591 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2592
2593 /* close the key */
2594 ZwClose(hKey);
2595 }
2596
2597 if (PinCount)
2598 {
2599 /* update medium cache */
2600 for(Index = 0; Index < PinCount; Index++)
2601 {
2602 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
2603 }
2604 }
2605
2606 /* free the symbolic link list */
2607 FreeItem(SymbolicLinkList);
2608 }
2609
2610 return Status;
2611 }
2612