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