[TCPIP DRIVER]
[reactos.git] / 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 = AllocateItem(PagedPool, sizeof(KSIDEVICE_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 FreeItem(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 = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_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 = AllocateItem(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength);
663 if (!ObjectHeader->ObjectClass.Buffer)
664 {
665 FreeItem(ObjectHeader);
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 FreeItem(ObjectHeader->ObjectClass.Buffer);
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 FreeItem(ObjectHeader);
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 = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
918 if (!Item)
919 {
920 /* no memory */
921 FreeItem(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 = AllocateItem(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 CompleteRequest(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 CompleteRequest(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 CompleteRequest(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 CompleteRequest(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 CompleteRequest(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 NTSTATUS
1727 NTAPI
1728 KspSetGetBusDataCompletion(
1729 IN PDEVICE_OBJECT DeviceObject,
1730 IN PIRP Irp,
1731 IN PVOID Context)
1732 {
1733 /* signal completion */
1734 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
1735
1736 /* more work needs be done, so dont free the irp */
1737 return STATUS_MORE_PROCESSING_REQUIRED;
1738
1739 }
1740
1741 NTSTATUS
1742 KspDeviceSetGetBusData(
1743 IN PDEVICE_OBJECT DeviceObject,
1744 IN ULONG DataType,
1745 IN PVOID Buffer,
1746 IN ULONG Offset,
1747 IN ULONG Length,
1748 IN BOOL bGet)
1749 {
1750 PIO_STACK_LOCATION IoStack;
1751 PIRP Irp;
1752 NTSTATUS Status;
1753 KEVENT Event;
1754
1755 /* allocate the irp */
1756 Irp = IoAllocateIrp(1, /*FIXME */
1757 FALSE);
1758
1759 if (!Irp)
1760 return STATUS_INSUFFICIENT_RESOURCES;
1761
1762 /* initialize the event */
1763 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1764
1765 /* get next stack location */
1766 IoStack = IoGetNextIrpStackLocation(Irp);
1767
1768 /* setup a completion routine */
1769 IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1770
1771 /* setup parameters */
1772 IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
1773 IoStack->Parameters.ReadWriteConfig.Length = Length;
1774 IoStack->Parameters.ReadWriteConfig.Offset = Offset;
1775 IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
1776 /* setup function code */
1777 IoStack->MajorFunction = IRP_MJ_PNP;
1778 IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
1779
1780 /* lets call the driver */
1781 Status = IoCallDriver(DeviceObject, Irp);
1782
1783 /* is the request still pending */
1784 if (Status == STATUS_PENDING)
1785 {
1786 /* have a nap */
1787 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1788 /* update status */
1789 Status = Irp->IoStatus.Status;
1790 }
1791
1792 /* free the irp */
1793 IoFreeIrp(Irp);
1794 /* done */
1795 return Status;
1796 }
1797
1798 /*
1799 @implemented
1800 */
1801 KSDDKAPI
1802 ULONG
1803 NTAPI
1804 KsDeviceSetBusData(
1805 IN PKSDEVICE Device,
1806 IN ULONG DataType,
1807 IN PVOID Buffer,
1808 IN ULONG Offset,
1809 IN ULONG Length)
1810 {
1811 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1812 DataType, Buffer, Offset, Length, FALSE);
1813 }
1814
1815
1816 /*
1817 @implemented
1818 */
1819 KSDDKAPI
1820 ULONG
1821 NTAPI
1822 KsDeviceGetBusData(
1823 IN PKSDEVICE Device,
1824 IN ULONG DataType,
1825 IN PVOID Buffer,
1826 IN ULONG Offset,
1827 IN ULONG Length)
1828 {
1829 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1830 DataType, Buffer, Offset, Length, TRUE);
1831
1832 }
1833
1834 /*
1835 @implemented
1836 */
1837 KSDDKAPI
1838 void
1839 NTAPI
1840 KsDeviceRegisterAdapterObject(
1841 IN PKSDEVICE Device,
1842 IN PADAPTER_OBJECT AdapterObject,
1843 IN ULONG MaxMappingsByteCount,
1844 IN ULONG MappingTableStride)
1845 {
1846 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1847
1848 DeviceHeader->AdapterObject = AdapterObject;
1849 DeviceHeader->MaxMappingsByteCount = MaxMappingsByteCount;
1850 DeviceHeader->MappingTableStride = MappingTableStride;
1851
1852 }
1853
1854
1855 /*
1856 @implemented
1857 */
1858 KSDDKAPI
1859 PVOID
1860 NTAPI
1861 KsGetFirstChild(
1862 IN PVOID Object)
1863 {
1864 PKSBASIC_HEADER BasicHeader;
1865
1866 /* get the basic header */
1867 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1868
1869 /* type has to be either a device or a filter factory */
1870 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory);
1871
1872 return (PVOID)BasicHeader->FirstChild.Filter;
1873 }
1874
1875 /*
1876 @implemented
1877 */
1878 KSDDKAPI
1879 PVOID
1880 NTAPI
1881 KsGetNextSibling(
1882 IN PVOID Object)
1883 {
1884 PKSBASIC_HEADER BasicHeader;
1885
1886 /* get the basic header */
1887 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1888
1889 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
1890 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1891
1892 return (PVOID)BasicHeader->Next.Pin;
1893 }
1894
1895 ULONG
1896 KspCountMethodSets(
1897 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1898 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1899 {
1900 ULONG Index, SubIndex, Count;
1901 BOOL bFound;
1902
1903 if (!AutomationTableA)
1904 return AutomationTableB->MethodSetsCount;
1905
1906 if (!AutomationTableB)
1907 return AutomationTableA->MethodSetsCount;
1908
1909
1910 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA->MethodItemSize, AutomationTableA->MethodSetsCount);
1911 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB->MethodItemSize, AutomationTableB->MethodSetsCount);
1912
1913 if (AutomationTableA->MethodItemSize && AutomationTableB->MethodItemSize)
1914 {
1915 /* sanity check */
1916 ASSERT(AutomationTableA->MethodItemSize == AutomationTableB->MethodItemSize);
1917 }
1918
1919 /* now iterate all property sets and compare their guids */
1920 Count = AutomationTableA->MethodSetsCount;
1921
1922 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
1923 {
1924 /* set found to false */
1925 bFound = FALSE;
1926
1927 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
1928 {
1929 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
1930 {
1931 /* same property set found */
1932 bFound = TRUE;
1933 break;
1934 }
1935 }
1936
1937 if (!bFound)
1938 Count++;
1939 }
1940
1941 return Count;
1942 }
1943
1944 ULONG
1945 KspCountEventSets(
1946 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1947 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1948 {
1949 ULONG Index, SubIndex, Count;
1950 BOOL bFound;
1951
1952 if (!AutomationTableA)
1953 return AutomationTableB->EventSetsCount;
1954
1955 if (!AutomationTableB)
1956 return AutomationTableA->EventSetsCount;
1957
1958 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA->EventItemSize, AutomationTableA->EventSetsCount);
1959 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB->EventItemSize, AutomationTableB->EventSetsCount);
1960
1961 if (AutomationTableA->EventItemSize && AutomationTableB->EventItemSize)
1962 {
1963 /* sanity check */
1964 ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize);
1965 }
1966
1967 /* now iterate all Event sets and compare their guids */
1968 Count = AutomationTableA->EventSetsCount;
1969
1970 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
1971 {
1972 /* set found to false */
1973 bFound = FALSE;
1974
1975 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
1976 {
1977 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
1978 {
1979 /* same Event set found */
1980 bFound = TRUE;
1981 break;
1982 }
1983 }
1984
1985 if (!bFound)
1986 Count++;
1987 }
1988
1989 return Count;
1990 }
1991
1992
1993 ULONG
1994 KspCountPropertySets(
1995 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1996 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
1997 {
1998 ULONG Index, SubIndex, Count;
1999 BOOL bFound;
2000
2001 if (!AutomationTableA)
2002 return AutomationTableB->PropertySetsCount;
2003
2004 if (!AutomationTableB)
2005 return AutomationTableA->PropertySetsCount;
2006
2007 /* sanity check */
2008 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA->PropertyItemSize, AutomationTableA->PropertySetsCount);
2009 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB->PropertyItemSize, AutomationTableB->PropertySetsCount);
2010 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
2011
2012 /* now iterate all property sets and compare their guids */
2013 Count = AutomationTableA->PropertySetsCount;
2014
2015 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2016 {
2017 /* set found to false */
2018 bFound = FALSE;
2019
2020 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2021 {
2022 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2023 {
2024 /* same property set found */
2025 bFound = TRUE;
2026 break;
2027 }
2028 }
2029
2030 if (!bFound)
2031 Count++;
2032 }
2033
2034 return Count;
2035 }
2036
2037 NTSTATUS
2038 KspCopyMethodSets(
2039 OUT PKSAUTOMATION_TABLE Table,
2040 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2041 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2042 {
2043 ULONG Index, SubIndex, Count;
2044 BOOL bFound;
2045
2046 if (!AutomationTableA)
2047 {
2048 /* copy of property set */
2049 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableB->MethodSetsCount);
2050 return STATUS_SUCCESS;
2051 }
2052 else if (!AutomationTableB)
2053 {
2054 /* copy of property set */
2055 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
2056 return STATUS_SUCCESS;
2057 }
2058
2059 /* first copy all property items from dominant table */
2060 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
2061 /* set counter */
2062 Count = AutomationTableA->MethodSetsCount;
2063
2064 /* now copy entries which arent available in the dominant table */
2065 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
2066 {
2067 /* set found to false */
2068 bFound = FALSE;
2069
2070 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
2071 {
2072 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
2073 {
2074 /* same property set found */
2075 bFound = TRUE;
2076 break;
2077 }
2078 }
2079
2080 if (!bFound)
2081 {
2082 /* copy new property item set */
2083 RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], sizeof(KSMETHOD_SET));
2084 Count++;
2085 }
2086 }
2087
2088 return STATUS_SUCCESS;
2089 }
2090
2091
2092 NTSTATUS
2093 KspCopyPropertySets(
2094 OUT PKSAUTOMATION_TABLE Table,
2095 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2096 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2097 {
2098 ULONG Index, SubIndex, Count;
2099 BOOL bFound;
2100
2101 if (!AutomationTableA)
2102 {
2103 /* copy of property set */
2104 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableB->PropertySetsCount);
2105 return STATUS_SUCCESS;
2106 }
2107 else if (!AutomationTableB)
2108 {
2109 /* copy of property set */
2110 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
2111 return STATUS_SUCCESS;
2112 }
2113
2114 /* first copy all property items from dominant table */
2115 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
2116 /* set counter */
2117 Count = AutomationTableA->PropertySetsCount;
2118
2119 /* now copy entries which arent available in the dominant table */
2120 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2121 {
2122 /* set found to false */
2123 bFound = FALSE;
2124
2125 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2126 {
2127 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2128 {
2129 /* same property set found */
2130 bFound = TRUE;
2131 break;
2132 }
2133 }
2134
2135 if (!bFound)
2136 {
2137 /* copy new property item set */
2138 RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], sizeof(KSPROPERTY_SET));
2139 Count++;
2140 }
2141 }
2142
2143 return STATUS_SUCCESS;
2144 }
2145
2146 NTSTATUS
2147 KspCopyEventSets(
2148 OUT PKSAUTOMATION_TABLE Table,
2149 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2150 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2151 {
2152 ULONG Index, SubIndex, Count;
2153 BOOL bFound;
2154
2155 if (!AutomationTableA)
2156 {
2157 /* copy of Event set */
2158 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, sizeof(KSEVENT_SET) * AutomationTableB->EventSetsCount);
2159 return STATUS_SUCCESS;
2160 }
2161 else if (!AutomationTableB)
2162 {
2163 /* copy of Event set */
2164 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
2165 return STATUS_SUCCESS;
2166 }
2167
2168 /* first copy all Event items from dominant table */
2169 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
2170 /* set counter */
2171 Count = AutomationTableA->EventSetsCount;
2172
2173 /* now copy entries which arent available in the dominant table */
2174 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
2175 {
2176 /* set found to false */
2177 bFound = FALSE;
2178
2179 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
2180 {
2181 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
2182 {
2183 /* same Event set found */
2184 bFound = TRUE;
2185 break;
2186 }
2187 }
2188
2189 if (!bFound)
2190 {
2191 /* copy new Event item set */
2192 RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], sizeof(KSEVENT_SET));
2193 Count++;
2194 }
2195 }
2196
2197 return STATUS_SUCCESS;
2198 }
2199
2200
2201 /*
2202 @implemented
2203 */
2204 NTSTATUS
2205 NTAPI
2206 KsMergeAutomationTables(
2207 OUT PKSAUTOMATION_TABLE *AutomationTableAB,
2208 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2209 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
2210 IN KSOBJECT_BAG Bag OPTIONAL)
2211 {
2212 PKSAUTOMATION_TABLE Table;
2213 NTSTATUS Status = STATUS_SUCCESS;
2214
2215 if (!AutomationTableA && !AutomationTableB)
2216 {
2217 /* nothing to merge */
2218 return STATUS_SUCCESS;
2219 }
2220
2221 /* allocate an automation table */
2222 Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE));
2223 if (!Table)
2224 return STATUS_INSUFFICIENT_RESOURCES;
2225
2226 if (Bag)
2227 {
2228 /* add table to object bag */
2229 Status = KsAddItemToObjectBag(Bag, Table, NULL);
2230 /* check for success */
2231 if (!NT_SUCCESS(Status))
2232 {
2233 /* free table */
2234 FreeItem(Table);
2235 return Status;
2236 }
2237 }
2238
2239 /* count property sets */
2240 Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB);
2241
2242 if (Table->PropertySetsCount)
2243 {
2244 if (AutomationTableA)
2245 {
2246 /* use item size from dominant automation table */
2247 Table->PropertyItemSize = AutomationTableA->PropertyItemSize;
2248 }
2249 else
2250 {
2251 /* use item size from 2nd automation table */
2252 Table->PropertyItemSize = AutomationTableB->PropertyItemSize;
2253 }
2254
2255 /* now allocate the property sets */
2256 Table->PropertySets = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * Table->PropertySetsCount);
2257
2258 if (!Table->PropertySets)
2259 {
2260 /* not enough memory */
2261 goto cleanup;
2262 }
2263
2264 if (Bag)
2265 {
2266 /* add set to property bag */
2267 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL);
2268 /* check for success */
2269 if (!NT_SUCCESS(Status))
2270 {
2271 /* cleanup table */
2272 goto cleanup;
2273 }
2274 }
2275 /* now copy the property sets */
2276 Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB);
2277 if(!NT_SUCCESS(Status))
2278 goto cleanup;
2279
2280 }
2281
2282 /* now count the method sets */
2283 Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB);
2284
2285 if (Table->MethodSetsCount)
2286 {
2287 if (AutomationTableA)
2288 {
2289 /* use item size from dominant automation table */
2290 Table->MethodItemSize = AutomationTableA->MethodItemSize;
2291 }
2292 else
2293 {
2294 /* use item size from 2nd automation table */
2295 Table->MethodItemSize = AutomationTableB->MethodItemSize;
2296 }
2297
2298 /* now allocate the property sets */
2299 Table->MethodSets = AllocateItem(NonPagedPool, sizeof(KSMETHOD_SET) * Table->MethodSetsCount);
2300
2301 if (!Table->MethodSets)
2302 {
2303 /* not enough memory */
2304 goto cleanup;
2305 }
2306
2307 if (Bag)
2308 {
2309 /* add set to property bag */
2310 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL);
2311 /* check for success */
2312 if (!NT_SUCCESS(Status))
2313 {
2314 /* cleanup table */
2315 goto cleanup;
2316 }
2317 }
2318 /* now copy the property sets */
2319 Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB);
2320 if(!NT_SUCCESS(Status))
2321 goto cleanup;
2322 }
2323
2324
2325 /* now count the event sets */
2326 Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB);
2327
2328 if (Table->EventSetsCount)
2329 {
2330 if (AutomationTableA)
2331 {
2332 /* use item size from dominant automation table */
2333 Table->EventItemSize = AutomationTableA->EventItemSize;
2334 }
2335 else
2336 {
2337 /* use item size from 2nd automation table */
2338 Table->EventItemSize = AutomationTableB->EventItemSize;
2339 }
2340
2341 /* now allocate the property sets */
2342 Table->EventSets = AllocateItem(NonPagedPool, sizeof(KSEVENT_SET) * Table->EventSetsCount);
2343
2344 if (!Table->EventSets)
2345 {
2346 /* not enough memory */
2347 goto cleanup;
2348 }
2349
2350 if (Bag)
2351 {
2352 /* add set to property bag */
2353 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL);
2354 /* check for success */
2355 if (!NT_SUCCESS(Status))
2356 {
2357 /* cleanup table */
2358 goto cleanup;
2359 }
2360 }
2361 /* now copy the property sets */
2362 Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB);
2363 if(!NT_SUCCESS(Status))
2364 goto cleanup;
2365 }
2366
2367 /* store result */
2368 *AutomationTableAB = Table;
2369
2370 return Status;
2371
2372
2373 cleanup:
2374
2375 if (Table)
2376 {
2377 if (Table->PropertySets)
2378 {
2379 /* clean property sets */
2380 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE)))
2381 FreeItem((PVOID)Table->PropertySets);
2382 }
2383
2384 if (Table->MethodSets)
2385 {
2386 /* clean property sets */
2387 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE)))
2388 FreeItem((PVOID)Table->MethodSets);
2389 }
2390
2391 if (Table->EventSets)
2392 {
2393 /* clean property sets */
2394 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE)))
2395 FreeItem((PVOID)Table->EventSets);
2396 }
2397
2398 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE)))
2399 FreeItem(Table);
2400 }
2401
2402 return STATUS_INSUFFICIENT_RESOURCES;
2403 }
2404
2405 /*
2406 @unimplemented
2407 */
2408 KSDDKAPI
2409 PUNKNOWN
2410 NTAPI
2411 KsRegisterAggregatedClientUnknown(
2412 IN PVOID Object,
2413 IN PUNKNOWN ClientUnknown)
2414 {
2415 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
2416
2417 /* sanity check */
2418 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
2419 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
2420
2421 if (BasicHeader->ClientAggregate)
2422 {
2423 /* release existing aggregate */
2424 BasicHeader->ClientAggregate->lpVtbl->Release(BasicHeader->ClientAggregate);
2425 }
2426
2427 /* increment reference count */
2428 ClientUnknown->lpVtbl->AddRef(ClientUnknown);
2429
2430 /* store client aggregate */
2431 BasicHeader->ClientAggregate = ClientUnknown;
2432
2433 /* return objects outer unknown */
2434 return BasicHeader->OuterUnknown;
2435 }
2436
2437 /*
2438 @unimplemented
2439 */
2440 NTSTATUS
2441 NTAPI
2442 KsRegisterFilterWithNoKSPins(
2443 IN PDEVICE_OBJECT DeviceObject,
2444 IN const GUID* InterfaceClassGUID,
2445 IN ULONG PinCount,
2446 IN BOOL* PinDirection,
2447 IN KSPIN_MEDIUM* MediumList,
2448 IN GUID* CategoryList OPTIONAL)
2449 {
2450 ULONG Size, Index;
2451 NTSTATUS Status;
2452 PWSTR SymbolicLinkList;
2453 //PUCHAR Buffer;
2454 HANDLE hKey;
2455 UNICODE_STRING InterfaceString;
2456 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2457
2458 if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
2459 {
2460 /* all these parameters are required */
2461 return STATUS_INVALID_PARAMETER;
2462 }
2463
2464 /* calculate filter data value size */
2465 Size = PinCount * sizeof(KSPIN_MEDIUM);
2466 if (CategoryList)
2467 {
2468 /* add category list */
2469 Size += PinCount * sizeof(GUID);
2470 }
2471
2472 /* FIXME generate filter data blob */
2473 UNIMPLEMENTED
2474
2475 /* get symbolic link list */
2476 Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
2477 if (NT_SUCCESS(Status))
2478 {
2479 /* initialize first symbolic link */
2480 RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
2481
2482 /* open first device interface registry key */
2483 Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
2484
2485 if (NT_SUCCESS(Status))
2486 {
2487 /* write filter data */
2488 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2489
2490 /* close the key */
2491 ZwClose(hKey);
2492 }
2493
2494 if (PinCount)
2495 {
2496 /* update medium cache */
2497 for(Index = 0; Index < PinCount; Index++)
2498 {
2499 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
2500 }
2501 }
2502
2503 /* free the symbolic link list */
2504 FreeItem(SymbolicLinkList);
2505 }
2506
2507 return Status;
2508 }