[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / api.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/api.c
5 * PURPOSE: KS API functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 const GUID GUID_NULL = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
13 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
14
15 /*
16 @implemented
17 */
18 KSDDKAPI
19 NTSTATUS
20 NTAPI
21 KsAcquireResetValue(
22 IN PIRP Irp,
23 OUT KSRESET* ResetValue)
24 {
25 PIO_STACK_LOCATION IoStack;
26 KSRESET* Value;
27 NTSTATUS Status = STATUS_SUCCESS;
28
29 /* get current irp stack */
30 IoStack = IoGetCurrentIrpStackLocation(Irp);
31
32 /* check if there is reset value provided */
33 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSRESET))
34 return STATUS_INVALID_PARAMETER;
35
36 if (Irp->RequestorMode == UserMode)
37 {
38 /* need to probe the buffer */
39 _SEH2_TRY
40 {
41 ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSRESET), sizeof(UCHAR));
42 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
43 *ResetValue = *Value;
44 }
45 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
46 {
47 /* Exception, get the error code */
48 Status = _SEH2_GetExceptionCode();
49 }
50 _SEH2_END;
51 }
52 else
53 {
54 Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
55 *ResetValue = *Value;
56 }
57
58 return Status;
59 }
60
61 /*
62 @implemented
63 */
64 KSDDKAPI
65 VOID
66 NTAPI
67 KsAcquireDeviceSecurityLock(
68 IN KSDEVICE_HEADER DevHeader,
69 IN BOOLEAN Exclusive)
70 {
71 NTSTATUS Status;
72 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
73
74 KeEnterCriticalRegion();
75
76 if (Exclusive)
77 {
78 Status = ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
79 }
80 else
81 {
82 Status = ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
83 }
84 }
85
86 /*
87 @implemented
88 */
89 KSDDKAPI
90 VOID
91 NTAPI
92 KsReleaseDeviceSecurityLock(
93 IN KSDEVICE_HEADER DevHeader)
94 {
95 PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
96
97 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 ASSERT(IoStack->FileObject->FsContext == NULL);
691 IoStack->FileObject->FsContext = ObjectHeader;
692
693 /* store parent device */
694 ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
695
696 /* store originating create item */
697 ObjectHeader->OriginalCreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
698
699 /* FIXME store access mask see KsQueryObjectAccessMask */
700 ObjectHeader->AccessMask = IoStack->Parameters.Create.SecurityContext->DesiredAccess;
701
702
703 /* store result */
704 *Header = ObjectHeader;
705
706 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
707
708 return STATUS_SUCCESS;
709
710 }
711
712 /*
713 @implemented
714 */
715 KSDDKAPI
716 VOID
717 NTAPI
718 KsFreeObjectHeader(
719 IN PVOID Header)
720 {
721 PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
722
723 if (ObjectHeader->ObjectClass.Buffer)
724 {
725 /* release object class buffer */
726 ExFreePoolWithTag(ObjectHeader->ObjectClass.Buffer, TAG_DEVICE_HEADER);
727 }
728
729 if (ObjectHeader->Unknown)
730 {
731 /* release associated object */
732 ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
733 }
734
735 /* free create items */
736 KspFreeCreateItems(&ObjectHeader->ItemList);
737
738 /* free object header */
739 ExFreePoolWithTag(ObjectHeader, TAG_DEVICE_HEADER);
740
741 }
742
743 NTSTATUS
744 KspAddObjectCreateItemToList(
745 PLIST_ENTRY ListHead,
746 IN PDRIVER_DISPATCH Create,
747 IN PVOID Context,
748 IN PWCHAR ObjectClass,
749 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
750 {
751 PLIST_ENTRY Entry;
752 PCREATE_ITEM_ENTRY CreateEntry;
753
754 /* point to first entry */
755 Entry = ListHead->Flink;
756
757 while(Entry != ListHead)
758 {
759 /* get create entry */
760 CreateEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
761 /* if the create item has no create routine, then it is free to use */
762 if (CreateEntry->CreateItem->Create == NULL)
763 {
764 /* sanity check */
765 ASSERT(IsListEmpty(&CreateEntry->ObjectItemList));
766 ASSERT(CreateEntry->ReferenceCount == 0);
767 /* use free entry */
768 CreateEntry->CreateItem->Context = Context;
769 CreateEntry->CreateItem->Create = Create;
770 RtlInitUnicodeString(&CreateEntry->CreateItem->ObjectClass, ObjectClass);
771 CreateEntry->CreateItem->SecurityDescriptor = SecurityDescriptor;
772
773 return STATUS_SUCCESS;
774 }
775
776 if (!wcsicmp(ObjectClass, CreateEntry->CreateItem->ObjectClass.Buffer))
777 {
778 /* the same object class already exists */
779 return STATUS_OBJECT_NAME_COLLISION;
780 }
781
782 /* iterate to next entry */
783 Entry = Entry->Flink;
784 }
785 return STATUS_ALLOTTED_SPACE_EXCEEDED;
786 }
787
788 /*
789 @implemented
790 */
791 KSDDKAPI
792 NTSTATUS
793 NTAPI
794 KsAddObjectCreateItemToDeviceHeader(
795 IN KSDEVICE_HEADER DevHeader,
796 IN PDRIVER_DISPATCH Create,
797 IN PVOID Context,
798 IN PWCHAR ObjectClass,
799 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
800 {
801 PKSIDEVICE_HEADER Header;
802 NTSTATUS Status;
803
804 Header = (PKSIDEVICE_HEADER)DevHeader;
805
806 DPRINT1("KsAddObjectCreateItemToDeviceHeader entered\n");
807
808 /* check if a device header has been provided */
809 if (!DevHeader)
810 return STATUS_INVALID_PARAMETER_1;
811
812 /* check if a create item has been provided */
813 if (!Create)
814 return STATUS_INVALID_PARAMETER_2;
815
816 /* check if a object class has been provided */
817 if (!ObjectClass)
818 return STATUS_INVALID_PARAMETER_4;
819
820 /* let others do the work */
821 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
822
823 if (NT_SUCCESS(Status))
824 {
825 /* increment create item count */
826 InterlockedIncrement(&Header->ItemListCount);
827 }
828
829 return Status;
830 }
831
832 /*
833 @implemented
834 */
835 KSDDKAPI
836 NTSTATUS
837 NTAPI
838 KsAddObjectCreateItemToObjectHeader(
839 IN KSOBJECT_HEADER ObjectHeader,
840 IN PDRIVER_DISPATCH Create,
841 IN PVOID Context,
842 IN PWCHAR ObjectClass,
843 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
844 {
845 PKSIOBJECT_HEADER Header;
846 NTSTATUS Status;
847
848 Header = (PKSIOBJECT_HEADER)ObjectHeader;
849
850 DPRINT1("KsAddObjectCreateItemToDeviceHeader entered\n");
851
852 /* check if a device header has been provided */
853 if (!Header)
854 return STATUS_INVALID_PARAMETER_1;
855
856 /* check if a create item has been provided */
857 if (!Create)
858 return STATUS_INVALID_PARAMETER_2;
859
860 /* check if a object class has been provided */
861 if (!ObjectClass)
862 return STATUS_INVALID_PARAMETER_4;
863
864 /* let's work */
865 Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
866
867 if (NT_SUCCESS(Status))
868 {
869 /* increment create item count */
870 InterlockedIncrement(&Header->ItemListCount);
871 }
872
873 return Status;
874 }
875
876 /*
877 @implemented
878 */
879 KSDDKAPI
880 NTSTATUS
881 NTAPI
882 KsAllocateObjectCreateItem(
883 IN KSDEVICE_HEADER DevHeader,
884 IN PKSOBJECT_CREATE_ITEM CreateItem,
885 IN BOOLEAN AllocateEntry,
886 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
887 {
888 PCREATE_ITEM_ENTRY CreateEntry;
889 PKSIDEVICE_HEADER Header;
890 PKSOBJECT_CREATE_ITEM Item;
891
892 Header = (PKSIDEVICE_HEADER)DevHeader;
893
894 if (!DevHeader)
895 return STATUS_INVALID_PARAMETER_1;
896
897 if (!CreateItem)
898 return STATUS_INVALID_PARAMETER_2;
899
900 /* first allocate a create entry */
901 CreateEntry = AllocateItem(NonPagedPool, sizeof(PCREATE_ITEM_ENTRY));
902
903 /* check for allocation success */
904 if (!CreateEntry)
905 {
906 /* not enough resources */
907 return STATUS_INSUFFICIENT_RESOURCES;
908 }
909
910
911 if (AllocateEntry)
912 {
913 /* allocate create item */
914 Item = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
915 if (!Item)
916 {
917 /* no memory */
918 ExFreePool(CreateEntry);
919 return STATUS_INSUFFICIENT_RESOURCES;
920 }
921
922 /* initialize descriptor */
923 Item->Context = CreateItem->Context;
924 Item->Create = CreateItem->Create;
925 Item->Flags = CreateItem->Flags;
926 Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
927 Item->ObjectClass.Length = 0;
928 Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
929
930 /* copy object class */
931 Item->ObjectClass.Buffer = ExAllocatePool(NonPagedPool, Item->ObjectClass.MaximumLength);
932 if (!Item->ObjectClass.Buffer)
933 {
934 /* release resources */
935 FreeItem(Item);
936 FreeItem(CreateEntry);
937
938 return STATUS_INSUFFICIENT_RESOURCES;
939 }
940 RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
941 }
942 else
943 {
944 if (ItemFreeCallback)
945 {
946 /* callback is only accepted when the create item is copied */
947 ItemFreeCallback = NULL;
948 }
949 /* use passed create item */
950 Item = CreateItem;
951 }
952
953 /* initialize create item entry */
954 InitializeListHead(&CreateEntry->ObjectItemList);
955 CreateEntry->ItemFreeCallback = ItemFreeCallback;
956 CreateEntry->CreateItem = Item;
957 CreateEntry->ReferenceCount = 0;
958
959 /* now insert the create item entry */
960 InsertTailList(&Header->ItemList, &CreateEntry->Entry);
961
962 /* increment item count */
963 InterlockedIncrement(&Header->ItemListCount);
964
965 return STATUS_SUCCESS;
966 }
967
968 NTSTATUS
969 KspObjectFreeCreateItems(
970 IN KSDEVICE_HEADER Header,
971 IN PKSOBJECT_CREATE_ITEM CreateItem)
972 {
973 UNIMPLEMENTED
974 return STATUS_NOT_IMPLEMENTED;
975 }
976
977 /*
978 @implemented
979 */
980 KSDDKAPI
981 NTSTATUS
982 NTAPI
983 KsFreeObjectCreateItem(
984 IN KSDEVICE_HEADER Header,
985 IN PUNICODE_STRING CreateItem)
986 {
987 KSOBJECT_CREATE_ITEM Item;
988
989 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
990 RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
991
992 return KspObjectFreeCreateItems(Header, &Item);
993 }
994
995
996 /*
997 @implemented
998 */
999 KSDDKAPI
1000 NTSTATUS
1001 NTAPI
1002 KsFreeObjectCreateItemsByContext(
1003 IN KSDEVICE_HEADER Header,
1004 IN PVOID Context)
1005 {
1006 KSOBJECT_CREATE_ITEM Item;
1007
1008 RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
1009
1010 Item.Context = Context;
1011
1012 return KspObjectFreeCreateItems(Header, &Item);
1013 }
1014
1015 /*
1016 @implemented
1017 */
1018 KSDDKAPI
1019 NTSTATUS
1020 NTAPI
1021 KsCreateDefaultSecurity(
1022 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
1023 OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
1024 {
1025 PGENERIC_MAPPING Mapping;
1026 SECURITY_SUBJECT_CONTEXT SubjectContext;
1027 NTSTATUS Status;
1028
1029 /* start capturing security context of calling thread */
1030 SeCaptureSubjectContext(&SubjectContext);
1031 /* get generic mapping */
1032 Mapping = IoGetFileObjectGenericMapping();
1033 /* build new descriptor */
1034 Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
1035 /* release security descriptor */
1036 SeReleaseSubjectContext(&SubjectContext);
1037 /* done */
1038 return Status;
1039 }
1040
1041 /*
1042 @unimplemented
1043 */
1044 KSDDKAPI
1045 NTSTATUS
1046 NTAPI
1047 KsForwardIrp(
1048 IN PIRP Irp,
1049 IN PFILE_OBJECT FileObject,
1050 IN BOOLEAN ReuseStackLocation)
1051 {
1052 UNIMPLEMENTED;
1053 return STATUS_UNSUCCESSFUL;
1054 }
1055
1056
1057 /*
1058 @unimplemented
1059 */
1060 KSDDKAPI
1061 NTSTATUS
1062 NTAPI
1063 KsForwardAndCatchIrp(
1064 IN PDEVICE_OBJECT DeviceObject,
1065 IN PIRP Irp,
1066 IN PFILE_OBJECT FileObject,
1067 IN KSSTACK_USE StackUse)
1068 {
1069 UNIMPLEMENTED;
1070 return STATUS_UNSUCCESSFUL;
1071 }
1072
1073
1074 NTSTATUS
1075 NTAPI
1076 KspSynchronousIoControlDeviceCompletion(
1077 IN PDEVICE_OBJECT DeviceObject,
1078 IN PIRP Irp,
1079 IN PVOID Context)
1080 {
1081 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
1082
1083 IoStatusBlock->Information = Irp->IoStatus.Information;
1084 IoStatusBlock->Status = Irp->IoStatus.Status;
1085
1086 return STATUS_SUCCESS;
1087 }
1088
1089 /*
1090 @implemented
1091 */
1092 KSDDKAPI
1093 NTSTATUS
1094 NTAPI
1095 KsSynchronousIoControlDevice(
1096 IN PFILE_OBJECT FileObject,
1097 IN KPROCESSOR_MODE RequestorMode,
1098 IN ULONG IoControl,
1099 IN PVOID InBuffer,
1100 IN ULONG InSize,
1101 OUT PVOID OutBuffer,
1102 IN ULONG OutSize,
1103 OUT PULONG BytesReturned)
1104 {
1105 PKSIOBJECT_HEADER ObjectHeader;
1106 PDEVICE_OBJECT DeviceObject;
1107 KEVENT Event;
1108 PIRP Irp;
1109 IO_STATUS_BLOCK IoStatusBlock;
1110 PIO_STACK_LOCATION IoStack;
1111 NTSTATUS Status;
1112
1113 /* check for valid file object */
1114 if (!FileObject)
1115 return STATUS_INVALID_PARAMETER;
1116
1117 /* get device object to send the request to */
1118 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1119 if (!DeviceObject)
1120 return STATUS_UNSUCCESSFUL;
1121
1122
1123 /* get object header */
1124 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
1125
1126 /* check if there is fast device io function */
1127 if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
1128 {
1129 IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
1130 IoStatusBlock.Information = 0;
1131
1132 /* it is send the request */
1133 Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
1134 /* check if the request was handled */
1135 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
1136 if (Status)
1137 {
1138 /* store bytes returned */
1139 *BytesReturned = IoStatusBlock.Information;
1140 /* return status */
1141 return IoStatusBlock.Status;
1142 }
1143 }
1144
1145 /* initialize the event */
1146 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1147
1148 /* create the irp */
1149 Irp = IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
1150
1151 if (!Irp)
1152 {
1153 /* no memory to allocate the irp */
1154 return STATUS_INSUFFICIENT_RESOURCES;
1155 }
1156
1157
1158 /* Store Fileobject */
1159 IoStack = IoGetNextIrpStackLocation(Irp);
1160 IoStack->FileObject = FileObject;
1161
1162 if (IoControl == IOCTL_KS_WRITE_STREAM)
1163 {
1164 Irp->AssociatedIrp.SystemBuffer = OutBuffer;
1165 }
1166 else if (IoControl == IOCTL_KS_READ_STREAM)
1167 {
1168 Irp->AssociatedIrp.SystemBuffer = InBuffer;
1169 }
1170
1171 IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
1172
1173 Status = IoCallDriver(DeviceObject, Irp);
1174 if (Status == STATUS_PENDING)
1175 {
1176 KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
1177 Status = IoStatusBlock.Status;
1178 }
1179
1180 *BytesReturned = IoStatusBlock.Information;
1181 return Status;
1182 }
1183
1184 /*
1185 @unimplemented
1186 */
1187 KSDDKAPI
1188 NTSTATUS
1189 NTAPI
1190 KsUnserializeObjectPropertiesFromRegistry(
1191 IN PFILE_OBJECT FileObject,
1192 IN HANDLE ParentKey OPTIONAL,
1193 IN PUNICODE_STRING RegistryPath OPTIONAL)
1194 {
1195 UNIMPLEMENTED
1196 return STATUS_NOT_IMPLEMENTED;
1197 }
1198
1199
1200 /*
1201 @implemented
1202 */
1203 KSDDKAPI
1204 NTSTATUS
1205 NTAPI
1206 KsCacheMedium(
1207 IN PUNICODE_STRING SymbolicLink,
1208 IN PKSPIN_MEDIUM Medium,
1209 IN ULONG PinDirection)
1210 {
1211 HANDLE hKey;
1212 UNICODE_STRING Path;
1213 UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1214 UNICODE_STRING GuidString;
1215 NTSTATUS Status;
1216 OBJECT_ATTRIBUTES ObjectAttributes;
1217 BOOLEAN PathAdjusted = FALSE;
1218 ULONG Value = 0;
1219
1220 /* first check if the medium is standard */
1221 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) ||
1222 IsEqualGUIDAligned(&GUID_NULL, &Medium->Set))
1223 {
1224 /* no need to cache that */
1225 return STATUS_SUCCESS;
1226 }
1227
1228 /* convert guid to string */
1229 Status = RtlStringFromGUID(&Medium->Set, &GuidString);
1230 if (!NT_SUCCESS(Status))
1231 return Status;
1232
1233 /* allocate path buffer */
1234 Path.Length = 0;
1235 Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR);
1236 Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength);
1237 if (!Path.Buffer)
1238 {
1239 /* not enough resources */
1240 RtlFreeUnicodeString(&GuidString);
1241 return STATUS_INSUFFICIENT_RESOURCES;
1242 }
1243
1244 RtlAppendUnicodeStringToString(&Path, &BasePath);
1245 RtlAppendUnicodeStringToString(&Path, &GuidString);
1246 RtlAppendUnicodeToString(&Path, L"-");
1247 /* FIXME append real instance id */
1248 RtlAppendUnicodeToString(&Path, L"0");
1249 RtlAppendUnicodeToString(&Path, L"-");
1250 /* FIXME append real instance id */
1251 RtlAppendUnicodeToString(&Path, L"0");
1252
1253 /* free guid string */
1254 RtlFreeUnicodeString(&GuidString);
1255
1256 /* initialize object attributes */
1257 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
1258 /* create the key */
1259 Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
1260
1261 /* free path buffer */
1262 FreeItem(Path.Buffer);
1263
1264 if (NT_SUCCESS(Status))
1265 {
1266 /* store symbolic link */
1267 if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?')
1268 {
1269 /* replace kernel path with user mode path */
1270 SymbolicLink->Buffer[1] = L'\\';
1271 PathAdjusted = TRUE;
1272 }
1273
1274 /* store the key */
1275 Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG));
1276
1277 if (PathAdjusted)
1278 {
1279 /* restore kernel path */
1280 SymbolicLink->Buffer[1] = L'?';
1281 }
1282
1283 ZwClose(hKey);
1284 }
1285
1286 /* done */
1287 return Status;
1288 }
1289
1290 /*
1291 @implemented
1292 */
1293 NTSTATUS
1294 NTAPI
1295 DllInitialize(
1296 PUNICODE_STRING RegistryPath)
1297 {
1298 return STATUS_SUCCESS;
1299 }
1300
1301
1302 NTSTATUS
1303 NTAPI
1304 KopDispatchClose(
1305 IN PDEVICE_OBJECT DeviceObject,
1306 IN PIRP Irp)
1307 {
1308 PKO_OBJECT_HEADER Header;
1309 PIO_STACK_LOCATION IoStack;
1310 PDEVICE_EXTENSION DeviceExtension;
1311
1312 /* get current irp stack location */
1313 IoStack = IoGetCurrentIrpStackLocation(Irp);
1314
1315 /* get ko object header */
1316 Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2;
1317
1318 /* free ks object header */
1319 KsFreeObjectHeader(Header->ObjectHeader);
1320
1321 /* free ko object header */
1322 FreeItem(Header);
1323
1324 /* get device extension */
1325 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1326
1327 /* release bus object */
1328 KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1329
1330 /* complete request */
1331 Irp->IoStatus.Status = STATUS_SUCCESS;
1332 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1333
1334 return STATUS_SUCCESS;
1335 }
1336
1337
1338
1339 static KSDISPATCH_TABLE KoDispatchTable =
1340 {
1341 KsDispatchInvalidDeviceRequest,
1342 KsDispatchInvalidDeviceRequest,
1343 KsDispatchInvalidDeviceRequest,
1344 KsDispatchInvalidDeviceRequest,
1345 KopDispatchClose,
1346 KsDispatchQuerySecurity,
1347 KsDispatchSetSecurity,
1348 KsDispatchFastIoDeviceControlFailure,
1349 KsDispatchFastReadFailure,
1350 KsDispatchFastReadFailure,
1351 };
1352
1353
1354 NTSTATUS
1355 NTAPI
1356 KopDispatchCreate(
1357 IN PDEVICE_OBJECT DeviceObject,
1358 IN PIRP Irp)
1359 {
1360 PKO_OBJECT_HEADER Header = NULL;
1361 PIO_STACK_LOCATION IoStack;
1362 PKO_DRIVER_EXTENSION DriverObjectExtension;
1363 NTSTATUS Status;
1364
1365 /* get current irp stack location */
1366 IoStack = IoGetCurrentIrpStackLocation(Irp);
1367
1368 if (!IoStack->FileObject)
1369 {
1370 DPRINT1("FileObject not attached!\n");
1371 Status = STATUS_UNSUCCESSFUL;
1372 goto cleanup;
1373 }
1374
1375 /* get driver object extension */
1376 DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize);
1377 if (!DriverObjectExtension)
1378 {
1379 DPRINT1("FileObject not attached!\n");
1380 Status = STATUS_UNSUCCESSFUL;
1381 goto cleanup;
1382 }
1383
1384 /* allocate ko object header */
1385 Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER));
1386 if (!Header)
1387 {
1388 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1389 Status = STATUS_INSUFFICIENT_RESOURCES;
1390 goto cleanup;
1391 }
1392
1393 /* initialize create item */
1394 Header->CreateItem.Create = KopDispatchCreate;
1395 RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject);
1396
1397
1398 /* now allocate the object header */
1399 Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 /* failed */
1403 goto cleanup;
1404 }
1405
1406 /* FIXME
1407 * extract clsid and interface id from irp
1408 * call the standard create handler
1409 */
1410
1411 UNIMPLEMENTED
1412
1413 IoStack->FileObject->FsContext2 = (PVOID)Header;
1414
1415 Irp->IoStatus.Status = Status;
1416 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1417
1418 return Status;
1419
1420 cleanup:
1421
1422 if (Header && Header->ObjectHeader)
1423 KsFreeObjectHeader(Header->ObjectHeader);
1424
1425 if (Header)
1426 FreeItem(Header);
1427
1428 Irp->IoStatus.Status = Status;
1429 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1430 return Status;
1431 }
1432
1433
1434
1435 NTSTATUS
1436 NTAPI
1437 KopAddDevice(
1438 IN PDRIVER_OBJECT DriverObject,
1439 IN PDEVICE_OBJECT PhysicalDeviceObject)
1440 {
1441 NTSTATUS Status = STATUS_DEVICE_REMOVED;
1442 PDEVICE_OBJECT FunctionalDeviceObject= NULL;
1443 PDEVICE_OBJECT NextDeviceObject;
1444 PDEVICE_EXTENSION DeviceExtension;
1445 PKSOBJECT_CREATE_ITEM CreateItem;
1446
1447 /* create the device object */
1448 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
1449 if (!NT_SUCCESS(Status))
1450 return Status;
1451
1452 /* allocate the create item */
1453 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
1454
1455 if (!CreateItem)
1456 {
1457 /* not enough memory */
1458 IoDeleteDevice(FunctionalDeviceObject);
1459 return STATUS_INSUFFICIENT_RESOURCES;
1460 }
1461
1462 /* initialize create item */
1463 CreateItem->Create = KopDispatchCreate;
1464 RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject);
1465
1466 /* get device extension */
1467 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
1468
1469 /* now allocate the device header */
1470 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem);
1471 if (!NT_SUCCESS(Status))
1472 {
1473 /* failed */
1474 IoDeleteDevice(FunctionalDeviceObject);
1475 FreeItem(CreateItem);
1476 return Status;
1477 }
1478
1479 /* now attach to device stack */
1480 NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
1481 if (NextDeviceObject)
1482 {
1483 /* store pnp base object */
1484 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject);
1485 /* set device flags */
1486 FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
1487 FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
1488 }
1489 else
1490 {
1491 /* failed */
1492 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1493 FreeItem(CreateItem);
1494 IoDeleteDevice(FunctionalDeviceObject);
1495 Status = STATUS_DEVICE_REMOVED;
1496 }
1497
1498 /* return result */
1499 return Status;
1500 }
1501
1502
1503 /*
1504 @implemented
1505 */
1506 COMDDKAPI
1507 NTSTATUS
1508 NTAPI
1509 KoDeviceInitialize(
1510 IN PDEVICE_OBJECT DeviceObject)
1511 {
1512 PDEVICE_EXTENSION DeviceExtension;
1513
1514 /* get device extension */
1515 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1516
1517 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL);
1518 }
1519
1520 /*
1521 @implemented
1522 */
1523 COMDDKAPI
1524 NTSTATUS
1525 NTAPI
1526 KoDriverInitialize(
1527 IN PDRIVER_OBJECT DriverObject,
1528 IN PUNICODE_STRING RegistryPathName,
1529 IN KoCreateObjectHandler CreateObjectHandler)
1530 {
1531 PKO_DRIVER_EXTENSION DriverObjectExtension;
1532 NTSTATUS Status;
1533
1534 /* allocate driver object extension */
1535 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
1536
1537 /* did it work */
1538 if (NT_SUCCESS(Status))
1539 {
1540 /* store create handler */
1541 DriverObjectExtension->CreateObjectHandler = CreateObjectHandler;
1542
1543 /* Setting our IRP handlers */
1544 DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp;
1545 DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
1546 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
1547
1548 /* The driver unload routine */
1549 DriverObject->DriverUnload = KsNullDriverUnload;
1550
1551 /* The driver-supplied AddDevice */
1552 DriverObject->DriverExtension->AddDevice = KopAddDevice;
1553
1554 /* KS handles these */
1555 DPRINT1("Setting KS function handlers\n");
1556 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
1557 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
1558 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
1559
1560 }
1561
1562 return Status;
1563 }
1564
1565 /*
1566 @unimplemented
1567 */
1568 COMDDKAPI
1569 VOID
1570 NTAPI
1571 KoRelease(
1572 IN REFCLSID ClassId)
1573 {
1574
1575 }
1576
1577 /*
1578 @implemented
1579 */
1580 KSDDKAPI
1581 VOID
1582 NTAPI
1583 KsAcquireControl(
1584 IN PVOID Object)
1585 {
1586 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1587
1588 /* sanity check */
1589 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1590
1591 KeWaitForSingleObject(&BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
1592
1593 }
1594
1595 /*
1596 @implemented
1597 */
1598 VOID
1599 NTAPI
1600 KsReleaseControl(
1601 IN PVOID Object)
1602 {
1603 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1604
1605 /* sanity check */
1606 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1607
1608 KeReleaseMutex(&BasicHeader->ControlMutex, FALSE);
1609 }
1610
1611
1612
1613 /*
1614 @implemented
1615 */
1616 KSDDKAPI
1617 VOID
1618 NTAPI
1619 KsAcquireDevice(
1620 IN PKSDEVICE Device)
1621 {
1622 IKsDevice *KsDevice;
1623 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1624
1625 /* get device interface*/
1626 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1627
1628 /* acquire device mutex */
1629 KsDevice->lpVtbl->AcquireDevice(KsDevice);
1630 }
1631
1632 /*
1633 @implemented
1634 */
1635 VOID
1636 NTAPI
1637 KsReleaseDevice(
1638 IN PKSDEVICE Device)
1639 {
1640 IKsDevice *KsDevice;
1641 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1642
1643 /* get device interface*/
1644 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1645
1646 /* release device mutex */
1647 KsDevice->lpVtbl->ReleaseDevice(KsDevice);
1648 }
1649
1650 /*
1651 @implemented
1652 */
1653 KSDDKAPI
1654 VOID
1655 NTAPI
1656 KsTerminateDevice(
1657 IN PDEVICE_OBJECT DeviceObject)
1658 {
1659 IKsDevice *KsDevice;
1660 PKSIDEVICE_HEADER DeviceHeader;
1661 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1662
1663 /* get device header */
1664 DeviceHeader = DeviceExtension->DeviceHeader;
1665
1666 /* get device interface*/
1667 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1668
1669 /* now free device header */
1670 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
1671
1672 /* release interface when available */
1673 if (KsDevice)
1674 {
1675 /* delete IKsDevice interface */
1676 KsDevice->lpVtbl->Release(KsDevice);
1677 }
1678 }
1679
1680 /*
1681 @implemented
1682 */
1683 KSDDKAPI
1684 VOID
1685 NTAPI
1686 KsCompletePendingRequest(
1687 IN PIRP Irp)
1688 {
1689 PIO_STACK_LOCATION IoStack;
1690
1691 /* get current irp stack location */
1692 IoStack = IoGetCurrentIrpStackLocation(Irp);
1693
1694 /* sanity check */
1695 ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
1696
1697 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
1698 {
1699 /* can be completed immediately */
1700 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1701 return;
1702 }
1703
1704 /* did close operation fail */
1705 if (!NT_SUCCESS(Irp->IoStatus.Status))
1706 {
1707 /* closing failed, complete irp */
1708 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1709 return;
1710 }
1711
1712 /* FIXME
1713 * delete object / device header
1714 * remove dead pin / filter instance
1715 */
1716 UNIMPLEMENTED
1717
1718 }
1719
1720 /*
1721 @implemented
1722 */
1723 KSDDKAPI
1724 NTSTATUS
1725 NTAPI
1726 KsCreateBusEnumObject(
1727 IN PWCHAR BusIdentifier,
1728 IN PDEVICE_OBJECT BusDeviceObject,
1729 IN PDEVICE_OBJECT PhysicalDeviceObject,
1730 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL,
1731 IN REFGUID InterfaceGuid OPTIONAL,
1732 IN PWCHAR ServiceRelativePath OPTIONAL)
1733 {
1734 ULONG Length;
1735 NTSTATUS Status = STATUS_SUCCESS;
1736 UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1737 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
1738 PDEVICE_EXTENSION DeviceExtension;
1739
1740 /* calculate sizeof bus enum device extension */
1741 Length = wcslen(BusIdentifier) * sizeof(WCHAR);
1742 Length += sizeof(BUS_ENUM_DEVICE_EXTENSION);
1743
1744 BusDeviceExtension = ExAllocatePool(NonPagedPool, Length);
1745 if (!BusDeviceExtension)
1746 {
1747 /* not enough memory */
1748 return STATUS_INSUFFICIENT_RESOURCES;
1749 }
1750
1751 /* zero device extension */
1752 RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION));
1753
1754 /* initialize bus device extension */
1755 wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier);
1756
1757 /* allocate service path string */
1758 Length = ServiceKeyPath.MaximumLength;
1759 Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength;
1760
1761 if (ServiceRelativePath)
1762 {
1763 /* relative path for devices */
1764 Length += wcslen(ServiceRelativePath) + 2 * sizeof(WCHAR);
1765 }
1766
1767 BusDeviceExtension->ServicePath.Length = 0;
1768 BusDeviceExtension->ServicePath.MaximumLength = Length;
1769 BusDeviceExtension->ServicePath.Buffer = ExAllocatePool(NonPagedPool, Length);
1770
1771 if (!BusDeviceExtension->ServicePath.Buffer)
1772 {
1773 /* not enough memory */
1774 ExFreePool(BusDeviceExtension);
1775 return STATUS_INSUFFICIENT_RESOURCES;
1776 }
1777
1778 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath);
1779 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName);
1780
1781 if (ServiceRelativePath)
1782 {
1783 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\");
1784 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath);
1785 }
1786
1787 if (InterfaceGuid)
1788 {
1789 /* register an device interface */
1790 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->SymbolicLinkName);
1791
1792 /* check for success */
1793 if (!NT_SUCCESS(Status))
1794 {
1795 ExFreePool(BusDeviceExtension->ServicePath.Buffer);
1796 ExFreePool(BusDeviceExtension);
1797 return Status;
1798 }
1799
1800 /* now enable device interface */
1801 Status = IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, TRUE);
1802
1803 if (!NT_SUCCESS(Status))
1804 {
1805 ExFreePool(BusDeviceExtension->ServicePath.Buffer);
1806 ExFreePool(BusDeviceExtension);
1807 return Status;
1808 }
1809
1810 /* set state enabled */
1811 BusDeviceExtension->Enabled = TRUE;
1812 }
1813
1814 /* store device objects */
1815 BusDeviceExtension->BusDeviceObject = BusDeviceObject;
1816 BusDeviceExtension->PnpDeviceObject = PnpDeviceObject;
1817 BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
1818
1819 if (!PnpDeviceObject)
1820 {
1821 BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject);
1822
1823 if (!BusDeviceExtension->PnpDeviceObject)
1824 {
1825 /* failed to attach device */
1826 if (BusDeviceExtension->Enabled)
1827 {
1828 IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, FALSE);
1829 RtlFreeUnicodeString(&BusDeviceExtension->SymbolicLinkName);
1830 }
1831
1832 /* free device extension */
1833 ExFreePool(BusDeviceExtension->ServicePath.Buffer);
1834 ExFreePool(BusDeviceExtension);
1835
1836 return STATUS_DEVICE_REMOVED;
1837 }
1838 }
1839
1840 /* attach device extension */
1841 DeviceExtension = (PDEVICE_EXTENSION)BusDeviceObject->DeviceExtension;
1842 DeviceExtension->DeviceHeader = (PKSIDEVICE_HEADER)BusDeviceExtension;
1843
1844 /* FIXME scan bus and invalidate device relations */
1845 return Status;
1846 }
1847
1848 NTSTATUS
1849 NTAPI
1850 KspSetGetBusDataCompletion(
1851 IN PDEVICE_OBJECT DeviceObject,
1852 IN PIRP Irp,
1853 IN PVOID Context)
1854 {
1855 /* signal completion */
1856 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
1857
1858 /* more work needs be done, so dont free the irp */
1859 return STATUS_MORE_PROCESSING_REQUIRED;
1860
1861 }
1862
1863 NTSTATUS
1864 KspDeviceSetGetBusData(
1865 IN PDEVICE_OBJECT DeviceObject,
1866 IN ULONG DataType,
1867 IN PVOID Buffer,
1868 IN ULONG Offset,
1869 IN ULONG Length,
1870 IN BOOL bGet)
1871 {
1872 PIO_STACK_LOCATION IoStack;
1873 PIRP Irp;
1874 NTSTATUS Status;
1875 KEVENT Event;
1876
1877 /* allocate the irp */
1878 Irp = IoAllocateIrp(1, /*FIXME */
1879 FALSE);
1880
1881 if (!Irp)
1882 return STATUS_INSUFFICIENT_RESOURCES;
1883
1884 /* initialize the event */
1885 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1886
1887 /* get next stack location */
1888 IoStack = IoGetNextIrpStackLocation(Irp);
1889
1890 /* setup a completion routine */
1891 IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1892
1893 /* setup parameters */
1894 IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
1895 IoStack->Parameters.ReadWriteConfig.Length = Length;
1896 IoStack->Parameters.ReadWriteConfig.Offset = Offset;
1897 IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
1898 /* setup function code */
1899 IoStack->MajorFunction = IRP_MJ_PNP;
1900 IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
1901
1902 /* lets call the driver */
1903 Status = IoCallDriver(DeviceObject, Irp);
1904
1905 /* is the request still pending */
1906 if (Status == STATUS_PENDING)
1907 {
1908 /* have a nap */
1909 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1910 /* update status */
1911 Status = Irp->IoStatus.Status;
1912 }
1913
1914 /* free the irp */
1915 IoFreeIrp(Irp);
1916 /* done */
1917 return Status;
1918 }
1919
1920 /*
1921 @implemented
1922 */
1923 KSDDKAPI
1924 ULONG
1925 NTAPI
1926 KsDeviceSetBusData(
1927 IN PKSDEVICE Device,
1928 IN ULONG DataType,
1929 IN PVOID Buffer,
1930 IN ULONG Offset,
1931 IN ULONG Length)
1932 {
1933 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1934 DataType, Buffer, Offset, Length, FALSE);
1935 }
1936
1937
1938 /*
1939 @implemented
1940 */
1941 KSDDKAPI
1942 ULONG
1943 NTAPI
1944 KsDeviceGetBusData(
1945 IN PKSDEVICE Device,
1946 IN ULONG DataType,
1947 IN PVOID Buffer,
1948 IN ULONG Offset,
1949 IN ULONG Length)
1950 {
1951 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1952 DataType, Buffer, Offset, Length, TRUE);
1953
1954 }
1955
1956 /*
1957 @unimplemented
1958 */
1959 KSDDKAPI
1960 void
1961 NTAPI
1962 KsDeviceRegisterAdapterObject(
1963 IN PKSDEVICE Device,
1964 IN PADAPTER_OBJECT AdapterObject,
1965 IN ULONG MaxMappingsByteCount,
1966 IN ULONG MappingTableStride)
1967 {
1968 UNIMPLEMENTED
1969 }
1970
1971 /*
1972 @unimplemented
1973 */
1974 KSDDKAPI
1975 NTSTATUS
1976 NTAPI
1977 KsGetBusEnumIdentifier(
1978 IN PIRP Irp)
1979 {
1980 UNIMPLEMENTED
1981 return STATUS_UNSUCCESSFUL;
1982 }
1983
1984 /*
1985 @unimplemented
1986 */
1987 KSDDKAPI
1988 NTSTATUS
1989 NTAPI
1990 KsGetBusEnumParentFDOFromChildPDO(
1991 IN PDEVICE_OBJECT DeviceObject,
1992 OUT PDEVICE_OBJECT *FunctionalDeviceObject)
1993 {
1994 UNIMPLEMENTED
1995 return STATUS_UNSUCCESSFUL;
1996 }
1997
1998 /*
1999 @unimplemented
2000 */
2001 KSDDKAPI
2002 NTSTATUS
2003 NTAPI
2004 KsGetBusEnumPnpDeviceObject(
2005 IN PDEVICE_OBJECT DeviceObject,
2006 IN PDEVICE_OBJECT *PnpDeviceObject)
2007 {
2008 UNIMPLEMENTED
2009 return STATUS_UNSUCCESSFUL;
2010 }
2011
2012 /*
2013 @implemented
2014 */
2015 KSDDKAPI
2016 PVOID
2017 NTAPI
2018 KsGetFirstChild(
2019 IN PVOID Object)
2020 {
2021 PKSBASIC_HEADER BasicHeader;
2022
2023 /* get the basic header */
2024 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
2025
2026 /* type has to be either a device or a filter factory */
2027 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory);
2028
2029 return (PVOID)BasicHeader->FirstChild.Filter;
2030 }
2031
2032 /*
2033 @implemented
2034 */
2035 KSDDKAPI
2036 PVOID
2037 NTAPI
2038 KsGetNextSibling(
2039 IN PVOID Object)
2040 {
2041 PKSBASIC_HEADER BasicHeader;
2042
2043 /* get the basic header */
2044 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
2045
2046 ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory ||
2047 BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
2048
2049 return (PVOID)BasicHeader->Next.Pin;
2050 }
2051
2052 /*
2053 @unimplemented
2054 */
2055 KSDDKAPI
2056 NTSTATUS
2057 NTAPI
2058 KsInstallBusEnumInterface(
2059 PIRP Irp)
2060 {
2061 UNIMPLEMENTED
2062 return STATUS_UNSUCCESSFUL;
2063 }
2064
2065 /*
2066 @unimplemented
2067 */
2068 KSDDKAPI
2069 NTSTATUS
2070 NTAPI
2071 KsIsBusEnumChildDevice(
2072 IN PDEVICE_OBJECT DeviceObject,
2073 OUT PBOOLEAN ChildDevice)
2074 {
2075 UNIMPLEMENTED
2076 return STATUS_UNSUCCESSFUL;
2077 }
2078
2079 ULONG
2080 KspCountMethodSets(
2081 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2082 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2083 {
2084 ULONG Index, SubIndex, Count;
2085 BOOL bFound;
2086
2087 if (!AutomationTableA)
2088 return AutomationTableB->MethodSetsCount;
2089
2090 if (!AutomationTableB)
2091 return AutomationTableA->MethodSetsCount;
2092
2093 /* sanity check */
2094 ASSERT(AutomationTableA->MethodItemSize == AutomationTableB->MethodItemSize);
2095
2096 /* now iterate all property sets and compare their guids */
2097 Count = AutomationTableA->MethodSetsCount;
2098
2099 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
2100 {
2101 /* set found to false */
2102 bFound = FALSE;
2103
2104 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
2105 {
2106 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
2107 {
2108 /* same property set found */
2109 bFound = TRUE;
2110 break;
2111 }
2112 }
2113
2114 if (!bFound)
2115 Count++;
2116 }
2117
2118 return Count;
2119 }
2120
2121 ULONG
2122 KspCountEventSets(
2123 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2124 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2125 {
2126 ULONG Index, SubIndex, Count;
2127 BOOL bFound;
2128
2129 if (!AutomationTableA)
2130 return AutomationTableB->EventSetsCount;
2131
2132 if (!AutomationTableB)
2133 return AutomationTableA->EventSetsCount;
2134
2135 /* sanity check */
2136 ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize);
2137
2138 /* now iterate all Event sets and compare their guids */
2139 Count = AutomationTableA->EventSetsCount;
2140
2141 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
2142 {
2143 /* set found to false */
2144 bFound = FALSE;
2145
2146 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
2147 {
2148 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
2149 {
2150 /* same Event set found */
2151 bFound = TRUE;
2152 break;
2153 }
2154 }
2155
2156 if (!bFound)
2157 Count++;
2158 }
2159
2160 return Count;
2161 }
2162
2163
2164 ULONG
2165 KspCountPropertySets(
2166 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2167 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2168 {
2169 ULONG Index, SubIndex, Count;
2170 BOOL bFound;
2171
2172 if (!AutomationTableA)
2173 return AutomationTableB->PropertySetsCount;
2174
2175 if (!AutomationTableB)
2176 return AutomationTableA->PropertySetsCount;
2177
2178 /* sanity check */
2179 ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
2180
2181 /* now iterate all property sets and compare their guids */
2182 Count = AutomationTableA->PropertySetsCount;
2183
2184 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2185 {
2186 /* set found to false */
2187 bFound = FALSE;
2188
2189 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2190 {
2191 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2192 {
2193 /* same property set found */
2194 bFound = TRUE;
2195 break;
2196 }
2197 }
2198
2199 if (!bFound)
2200 Count++;
2201 }
2202
2203 return Count;
2204 }
2205
2206 NTSTATUS
2207 KspCopyMethodSets(
2208 OUT PKSAUTOMATION_TABLE Table,
2209 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2210 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2211 {
2212 ULONG Index, SubIndex, Count;
2213 BOOL bFound;
2214
2215 if (!AutomationTableA)
2216 {
2217 /* copy of property set */
2218 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, Table->MethodItemSize * AutomationTableB->MethodSetsCount);
2219 return STATUS_SUCCESS;
2220 }
2221 else if (!AutomationTableB)
2222 {
2223 /* copy of property set */
2224 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, Table->MethodItemSize * AutomationTableA->MethodSetsCount);
2225 return STATUS_SUCCESS;
2226 }
2227
2228 /* first copy all property items from dominant table */
2229 RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, Table->MethodItemSize * AutomationTableA->MethodSetsCount);
2230 /* set counter */
2231 Count = AutomationTableA->MethodSetsCount;
2232
2233 /* now copy entries which arent available in the dominant table */
2234 for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
2235 {
2236 /* set found to false */
2237 bFound = FALSE;
2238
2239 for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
2240 {
2241 if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
2242 {
2243 /* same property set found */
2244 bFound = TRUE;
2245 break;
2246 }
2247 }
2248
2249 if (!bFound)
2250 {
2251 /* copy new property item set */
2252 RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], Table->MethodItemSize);
2253 Count++;
2254 }
2255 }
2256
2257 return STATUS_SUCCESS;
2258 }
2259
2260
2261 NTSTATUS
2262 KspCopyPropertySets(
2263 OUT PKSAUTOMATION_TABLE Table,
2264 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2265 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2266 {
2267 ULONG Index, SubIndex, Count;
2268 BOOL bFound;
2269
2270 if (!AutomationTableA)
2271 {
2272 /* copy of property set */
2273 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, Table->PropertyItemSize * AutomationTableB->PropertySetsCount);
2274 return STATUS_SUCCESS;
2275 }
2276 else if (!AutomationTableB)
2277 {
2278 /* copy of property set */
2279 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, Table->PropertyItemSize * AutomationTableA->PropertySetsCount);
2280 return STATUS_SUCCESS;
2281 }
2282
2283 /* first copy all property items from dominant table */
2284 RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, Table->PropertyItemSize * AutomationTableA->PropertySetsCount);
2285 /* set counter */
2286 Count = AutomationTableA->PropertySetsCount;
2287
2288 /* now copy entries which arent available in the dominant table */
2289 for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
2290 {
2291 /* set found to false */
2292 bFound = FALSE;
2293
2294 for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
2295 {
2296 if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
2297 {
2298 /* same property set found */
2299 bFound = TRUE;
2300 break;
2301 }
2302 }
2303
2304 if (!bFound)
2305 {
2306 /* copy new property item set */
2307 RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], Table->PropertyItemSize);
2308 Count++;
2309 }
2310 }
2311
2312 return STATUS_SUCCESS;
2313 }
2314
2315 NTSTATUS
2316 KspCopyEventSets(
2317 OUT PKSAUTOMATION_TABLE Table,
2318 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2319 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL)
2320 {
2321 ULONG Index, SubIndex, Count;
2322 BOOL bFound;
2323
2324 if (!AutomationTableA)
2325 {
2326 /* copy of Event set */
2327 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, Table->EventItemSize * AutomationTableB->EventSetsCount);
2328 return STATUS_SUCCESS;
2329 }
2330 else if (!AutomationTableB)
2331 {
2332 /* copy of Event set */
2333 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, Table->EventItemSize * AutomationTableA->EventSetsCount);
2334 return STATUS_SUCCESS;
2335 }
2336
2337 /* first copy all Event items from dominant table */
2338 RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, Table->EventItemSize * AutomationTableA->EventSetsCount);
2339 /* set counter */
2340 Count = AutomationTableA->EventSetsCount;
2341
2342 /* now copy entries which arent available in the dominant table */
2343 for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
2344 {
2345 /* set found to false */
2346 bFound = FALSE;
2347
2348 for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
2349 {
2350 if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
2351 {
2352 /* same Event set found */
2353 bFound = TRUE;
2354 break;
2355 }
2356 }
2357
2358 if (!bFound)
2359 {
2360 /* copy new Event item set */
2361 RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], Table->EventItemSize);
2362 Count++;
2363 }
2364 }
2365
2366 return STATUS_SUCCESS;
2367 }
2368
2369
2370 /*
2371 @implemented
2372 */
2373 NTSTATUS
2374 NTAPI
2375 KsMergeAutomationTables(
2376 OUT PKSAUTOMATION_TABLE *AutomationTableAB,
2377 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
2378 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
2379 IN KSOBJECT_BAG Bag OPTIONAL)
2380 {
2381 PKSAUTOMATION_TABLE Table;
2382 NTSTATUS Status = STATUS_SUCCESS;
2383
2384 if (!AutomationTableA && !AutomationTableB)
2385 {
2386 /* nothing to merge */
2387 return STATUS_SUCCESS;
2388 }
2389
2390 /* allocate an automation table */
2391 Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE));
2392 if (!Table)
2393 return STATUS_INSUFFICIENT_RESOURCES;
2394
2395 if (Bag)
2396 {
2397 /* add table to object bag */
2398 Status = KsAddItemToObjectBag(Bag, Table, NULL);
2399 /* check for success */
2400 if (!NT_SUCCESS(Status))
2401 {
2402 /* free table */
2403 FreeItem(Table);
2404 return Status;
2405 }
2406 }
2407
2408 /* count property sets */
2409 Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB);
2410
2411 if (Table->PropertySetsCount)
2412 {
2413 if (AutomationTableA)
2414 {
2415 /* use item size from dominant automation table */
2416 Table->PropertyItemSize = AutomationTableA->PropertyItemSize;
2417 }
2418 else
2419 {
2420 /* use item size from 2nd automation table */
2421 Table->PropertyItemSize = AutomationTableB->PropertyItemSize;
2422 }
2423
2424 /* now allocate the property sets */
2425 Table->PropertySets = AllocateItem(NonPagedPool, Table->PropertyItemSize * Table->PropertySetsCount);
2426
2427 if (!Table->PropertySets)
2428 {
2429 /* not enough memory */
2430 goto cleanup;
2431 }
2432
2433 if (Bag)
2434 {
2435 /* add set to property bag */
2436 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL);
2437 /* check for success */
2438 if (!NT_SUCCESS(Status))
2439 {
2440 /* cleanup table */
2441 goto cleanup;
2442 }
2443 }
2444 /* now copy the property sets */
2445 Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB);
2446 if(!NT_SUCCESS(Status))
2447 goto cleanup;
2448
2449 }
2450
2451 /* now count the method sets */
2452 Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB);
2453
2454 if (Table->MethodSetsCount)
2455 {
2456 if (AutomationTableA)
2457 {
2458 /* use item size from dominant automation table */
2459 Table->MethodItemSize = AutomationTableA->MethodItemSize;
2460 }
2461 else
2462 {
2463 /* use item size from 2nd automation table */
2464 Table->MethodItemSize = AutomationTableB->MethodItemSize;
2465 }
2466
2467 /* now allocate the property sets */
2468 Table->MethodSets = AllocateItem(NonPagedPool, Table->MethodItemSize * Table->MethodSetsCount);
2469
2470 if (!Table->MethodSets)
2471 {
2472 /* not enough memory */
2473 goto cleanup;
2474 }
2475
2476 if (Bag)
2477 {
2478 /* add set to property bag */
2479 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL);
2480 /* check for success */
2481 if (!NT_SUCCESS(Status))
2482 {
2483 /* cleanup table */
2484 goto cleanup;
2485 }
2486 }
2487 /* now copy the property sets */
2488 Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB);
2489 if(!NT_SUCCESS(Status))
2490 goto cleanup;
2491 }
2492
2493
2494 /* now count the event sets */
2495 Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB);
2496
2497 if (Table->EventSetsCount)
2498 {
2499 if (AutomationTableA)
2500 {
2501 /* use item size from dominant automation table */
2502 Table->EventItemSize = AutomationTableA->EventItemSize;
2503 }
2504 else
2505 {
2506 /* use item size from 2nd automation table */
2507 Table->EventItemSize = AutomationTableB->EventItemSize;
2508 }
2509
2510 /* now allocate the property sets */
2511 Table->EventSets = AllocateItem(NonPagedPool, Table->EventItemSize * Table->EventSetsCount);
2512
2513 if (!Table->EventSets)
2514 {
2515 /* not enough memory */
2516 goto cleanup;
2517 }
2518
2519 if (Bag)
2520 {
2521 /* add set to property bag */
2522 Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL);
2523 /* check for success */
2524 if (!NT_SUCCESS(Status))
2525 {
2526 /* cleanup table */
2527 goto cleanup;
2528 }
2529 }
2530 /* now copy the property sets */
2531 Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB);
2532 if(!NT_SUCCESS(Status))
2533 goto cleanup;
2534 }
2535
2536 /* store result */
2537 *AutomationTableAB = Table;
2538
2539 return Status;
2540
2541
2542 cleanup:
2543
2544 if (Table)
2545 {
2546 if (Table->PropertySets)
2547 {
2548 /* clean property sets */
2549 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE)))
2550 FreeItem((PVOID)Table->PropertySets);
2551 }
2552
2553 if (Table->MethodSets)
2554 {
2555 /* clean property sets */
2556 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE)))
2557 FreeItem((PVOID)Table->MethodSets);
2558 }
2559
2560 if (Table->EventSets)
2561 {
2562 /* clean property sets */
2563 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE)))
2564 FreeItem((PVOID)Table->EventSets);
2565 }
2566
2567 if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE)))
2568 FreeItem(Table);
2569 }
2570
2571 return STATUS_INSUFFICIENT_RESOURCES;
2572 }
2573
2574 /*
2575 @unimplemented
2576 */
2577 KSDDKAPI
2578 NTSTATUS
2579 NTAPI
2580 KsServiceBusEnumCreateRequest(
2581 IN PDEVICE_OBJECT DeviceObject,
2582 IN OUT PIRP Irp)
2583 {
2584 UNIMPLEMENTED
2585 return STATUS_UNSUCCESSFUL;
2586 }
2587
2588
2589 /*
2590 @unimplemented
2591 */
2592 KSDDKAPI
2593 NTSTATUS
2594 NTAPI
2595 KsServiceBusEnumPnpRequest(
2596 IN PDEVICE_OBJECT DeviceObject,
2597 IN OUT PIRP Irp)
2598 {
2599 UNIMPLEMENTED
2600 return STATUS_UNSUCCESSFUL;
2601 }
2602
2603 VOID
2604 NTAPI
2605 KspRemoveBusInterface(
2606 PVOID Ctx)
2607 {
2608 PKSREMOVE_BUS_INTERFACE_CTX Context =(PKSREMOVE_BUS_INTERFACE_CTX)Ctx;
2609
2610 /* TODO
2611 * get SWENUM_INSTALL_INTERFACE struct
2612 * open device key and delete the keys
2613 */
2614
2615 UNIMPLEMENTED
2616
2617 /* set status */
2618 Context->Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
2619
2620
2621 /* signal completion */
2622 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
2623 }
2624
2625 /*
2626 @unimplemented
2627 */
2628 KSDDKAPI
2629 NTSTATUS
2630 NTAPI
2631 KsRemoveBusEnumInterface(
2632 IN PIRP Irp)
2633 {
2634 KPROCESSOR_MODE Mode;
2635 LUID luid;
2636 KSREMOVE_BUS_INTERFACE_CTX Ctx;
2637 WORK_QUEUE_ITEM WorkItem;
2638
2639 /* get previous mode */
2640 Mode = ExGetPreviousMode();
2641
2642 /* convert to luid */
2643 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
2644
2645 /* perform access check */
2646 if (!SeSinglePrivilegeCheck(luid, Mode))
2647 {
2648 /* insufficient privileges */
2649 return STATUS_PRIVILEGE_NOT_HELD;
2650 }
2651 /* initialize event */
2652 KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);
2653
2654 /* store irp in ctx */
2655 Ctx.Irp = Irp;
2656
2657 /* initialize work item */
2658 ExInitializeWorkItem(&WorkItem, KspRemoveBusInterface, (PVOID)&Ctx);
2659
2660 /* now queue the work item */
2661 ExQueueWorkItem(&WorkItem, DelayedWorkQueue);
2662
2663 /* wait for completion */
2664 KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
2665
2666 /* return result */
2667 return Ctx.Irp->IoStatus.Status;
2668
2669 }
2670
2671
2672 /*
2673 @unimplemented
2674 */
2675 KSDDKAPI
2676 PUNKNOWN
2677 NTAPI
2678 KsRegisterAggregatedClientUnknown(
2679 IN PVOID Object,
2680 IN PUNKNOWN ClientUnknown)
2681 {
2682 UNIMPLEMENTED
2683 return NULL;
2684 }
2685
2686 /*
2687 @unimplemented
2688 */
2689 NTSTATUS
2690 NTAPI
2691 KsRegisterFilterWithNoKSPins(
2692 IN PDEVICE_OBJECT DeviceObject,
2693 IN const GUID* InterfaceClassGUID,
2694 IN ULONG PinCount,
2695 IN BOOL* PinDirection,
2696 IN KSPIN_MEDIUM* MediumList,
2697 IN GUID* CategoryList OPTIONAL)
2698 {
2699 ULONG Size, Index;
2700 NTSTATUS Status;
2701 PWSTR SymbolicLinkList;
2702 //PUCHAR Buffer;
2703 HANDLE hKey;
2704 UNICODE_STRING InterfaceString;
2705 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2706
2707 if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
2708 {
2709 /* all these parameters are required */
2710 return STATUS_INVALID_PARAMETER;
2711 }
2712
2713 /* calculate filter data value size */
2714 Size = PinCount * sizeof(KSPIN_MEDIUM);
2715 if (CategoryList)
2716 {
2717 /* add category list */
2718 Size += PinCount * sizeof(GUID);
2719 }
2720
2721 /* FIXME generate filter data blob */
2722 UNIMPLEMENTED
2723
2724 /* get symbolic link list */
2725 Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
2726 if (NT_SUCCESS(Status))
2727 {
2728 /* initialize first symbolic link */
2729 RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
2730
2731 /* open first device interface registry key */
2732 Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
2733
2734 if (NT_SUCCESS(Status))
2735 {
2736 /* write filter data */
2737 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2738
2739 /* close the key */
2740 ZwClose(hKey);
2741 }
2742
2743 if (PinCount)
2744 {
2745 /* update medium cache */
2746 for(Index = 0; Index < PinCount; Index++)
2747 {
2748 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
2749 }
2750 }
2751
2752 /* free the symbolic link list */
2753 ExFreePool(SymbolicLinkList);
2754 }
2755
2756 return Status;
2757 }