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