- Partly Implement KsRegisterFilterWithNoKSPins
[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 /* HACK */
1152 IoStack = IoGetNextIrpStackLocation(Irp);
1153 IoStack->FileObject = FileObject;
1154
1155 IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
1156
1157 Status = IoCallDriver(DeviceObject, Irp);
1158 if (Status == STATUS_PENDING)
1159 {
1160 KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
1161 Status = IoStatusBlock.Status;
1162 }
1163
1164 *BytesReturned = IoStatusBlock.Information;
1165 return Status;
1166 }
1167
1168 /*
1169 @unimplemented
1170 */
1171 KSDDKAPI
1172 NTSTATUS
1173 NTAPI
1174 KsUnserializeObjectPropertiesFromRegistry(
1175 IN PFILE_OBJECT FileObject,
1176 IN HANDLE ParentKey OPTIONAL,
1177 IN PUNICODE_STRING RegistryPath OPTIONAL)
1178 {
1179 UNIMPLEMENTED
1180 return STATUS_NOT_IMPLEMENTED;
1181 }
1182
1183
1184 /*
1185 @implemented
1186 */
1187 KSDDKAPI
1188 NTSTATUS
1189 NTAPI
1190 KsCacheMedium(
1191 IN PUNICODE_STRING SymbolicLink,
1192 IN PKSPIN_MEDIUM Medium,
1193 IN ULONG PinDirection)
1194 {
1195 HANDLE hKey;
1196 UNICODE_STRING Path;
1197 UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1198 UNICODE_STRING GuidString;
1199 NTSTATUS Status;
1200 OBJECT_ATTRIBUTES ObjectAttributes;
1201 BOOLEAN PathAdjusted = FALSE;
1202 ULONG Value = 0;
1203
1204 /* first check if the medium is standard */
1205 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) ||
1206 IsEqualGUIDAligned(&GUID_NULL, &Medium->Set))
1207 {
1208 /* no need to cache that */
1209 return STATUS_SUCCESS;
1210 }
1211
1212 /* convert guid to string */
1213 Status = RtlStringFromGUID(&Medium->Set, &GuidString);
1214 if (!NT_SUCCESS(Status))
1215 return Status;
1216
1217 /* allocate path buffer */
1218 Path.Length = 0;
1219 Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR);
1220 Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength);
1221 if (!Path.Buffer)
1222 {
1223 /* not enough resources */
1224 RtlFreeUnicodeString(&GuidString);
1225 return STATUS_INSUFFICIENT_RESOURCES;
1226 }
1227
1228 RtlAppendUnicodeStringToString(&Path, &BasePath);
1229 RtlAppendUnicodeStringToString(&Path, &GuidString);
1230 RtlAppendUnicodeToString(&Path, L"-");
1231 /* FIXME append real instance id */
1232 RtlAppendUnicodeToString(&Path, L"0");
1233 RtlAppendUnicodeToString(&Path, L"-");
1234 /* FIXME append real instance id */
1235 RtlAppendUnicodeToString(&Path, L"0");
1236
1237 /* free guid string */
1238 RtlFreeUnicodeString(&GuidString);
1239
1240 /* initialize object attributes */
1241 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
1242 /* create the key */
1243 Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
1244
1245 /* free path buffer */
1246 FreeItem(Path.Buffer);
1247
1248 if (NT_SUCCESS(Status))
1249 {
1250 /* store symbolic link */
1251 if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?')
1252 {
1253 /* replace kernel path with user mode path */
1254 SymbolicLink->Buffer[1] = L'\\';
1255 PathAdjusted = TRUE;
1256 }
1257
1258 /* store the key */
1259 Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG));
1260
1261 if (PathAdjusted)
1262 {
1263 /* restore kernel path */
1264 SymbolicLink->Buffer[1] = L'?';
1265 }
1266
1267 ZwClose(hKey);
1268 }
1269
1270 /* done */
1271 return Status;
1272 }
1273
1274 /*
1275 @implemented
1276 */
1277 NTSTATUS
1278 NTAPI
1279 DllInitialize(
1280 PUNICODE_STRING RegistryPath)
1281 {
1282 return STATUS_SUCCESS;
1283 }
1284
1285
1286 NTSTATUS
1287 NTAPI
1288 KopDispatchClose(
1289 IN PDEVICE_OBJECT DeviceObject,
1290 IN PIRP Irp)
1291 {
1292 PKO_OBJECT_HEADER Header;
1293 PIO_STACK_LOCATION IoStack;
1294 PDEVICE_EXTENSION DeviceExtension;
1295
1296 /* get current irp stack location */
1297 IoStack = IoGetCurrentIrpStackLocation(Irp);
1298
1299 /* get ko object header */
1300 Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2;
1301
1302 /* free ks object header */
1303 KsFreeObjectHeader(Header->ObjectHeader);
1304
1305 /* free ko object header */
1306 FreeItem(Header);
1307
1308 /* get device extension */
1309 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1310
1311 /* release bus object */
1312 KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1313
1314 /* complete request */
1315 Irp->IoStatus.Status = STATUS_SUCCESS;
1316 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1317
1318 return STATUS_SUCCESS;
1319 }
1320
1321
1322
1323 static KSDISPATCH_TABLE KoDispatchTable =
1324 {
1325 KsDispatchInvalidDeviceRequest,
1326 KsDispatchInvalidDeviceRequest,
1327 KsDispatchInvalidDeviceRequest,
1328 KsDispatchInvalidDeviceRequest,
1329 KopDispatchClose,
1330 KsDispatchQuerySecurity,
1331 KsDispatchSetSecurity,
1332 KsDispatchFastIoDeviceControlFailure,
1333 KsDispatchFastReadFailure,
1334 KsDispatchFastReadFailure,
1335 };
1336
1337
1338 NTSTATUS
1339 NTAPI
1340 KopDispatchCreate(
1341 IN PDEVICE_OBJECT DeviceObject,
1342 IN PIRP Irp)
1343 {
1344 PKO_OBJECT_HEADER Header = NULL;
1345 PIO_STACK_LOCATION IoStack;
1346 PKO_DRIVER_EXTENSION DriverObjectExtension;
1347 NTSTATUS Status;
1348
1349 /* get current irp stack location */
1350 IoStack = IoGetCurrentIrpStackLocation(Irp);
1351
1352 if (!IoStack->FileObject)
1353 {
1354 DPRINT1("FileObject not attached!\n");
1355 Status = STATUS_UNSUCCESSFUL;
1356 goto cleanup;
1357 }
1358
1359 /* get driver object extension */
1360 DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize);
1361 if (!DriverObjectExtension)
1362 {
1363 DPRINT1("FileObject not attached!\n");
1364 Status = STATUS_UNSUCCESSFUL;
1365 goto cleanup;
1366 }
1367
1368 /* allocate ko object header */
1369 Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER));
1370 if (!Header)
1371 {
1372 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1373 Status = STATUS_INSUFFICIENT_RESOURCES;
1374 goto cleanup;
1375 }
1376
1377 /* initialize create item */
1378 Header->CreateItem.Create = KopDispatchCreate;
1379 RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject);
1380
1381
1382 /* now allocate the object header */
1383 Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable);
1384 if (!NT_SUCCESS(Status))
1385 {
1386 /* failed */
1387 goto cleanup;
1388 }
1389
1390 /* FIXME
1391 * extract clsid and interface id from irp
1392 * call the standard create handler
1393 */
1394
1395 UNIMPLEMENTED
1396
1397 IoStack->FileObject->FsContext2 = (PVOID)Header;
1398
1399 Irp->IoStatus.Status = Status;
1400 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1401
1402 return Status;
1403
1404 cleanup:
1405
1406 if (Header && Header->ObjectHeader)
1407 KsFreeObjectHeader(Header->ObjectHeader);
1408
1409 if (Header)
1410 FreeItem(Header);
1411
1412 Irp->IoStatus.Status = Status;
1413 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1414 return Status;
1415 }
1416
1417
1418
1419 NTSTATUS
1420 NTAPI
1421 KopAddDevice(
1422 IN PDRIVER_OBJECT DriverObject,
1423 IN PDEVICE_OBJECT PhysicalDeviceObject)
1424 {
1425 NTSTATUS Status = STATUS_DEVICE_REMOVED;
1426 PDEVICE_OBJECT FunctionalDeviceObject= NULL;
1427 PDEVICE_OBJECT NextDeviceObject;
1428 PDEVICE_EXTENSION DeviceExtension;
1429 PKSOBJECT_CREATE_ITEM CreateItem;
1430
1431 /* create the device object */
1432 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
1433 if (!NT_SUCCESS(Status))
1434 return Status;
1435
1436 /* allocate the create item */
1437 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
1438
1439 if (!CreateItem)
1440 {
1441 /* not enough memory */
1442 IoDeleteDevice(FunctionalDeviceObject);
1443 return STATUS_INSUFFICIENT_RESOURCES;
1444 }
1445
1446 /* initialize create item */
1447 CreateItem->Create = KopDispatchCreate;
1448 RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject);
1449
1450 /* get device extension */
1451 DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
1452
1453 /* now allocate the device header */
1454 Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem);
1455 if (!NT_SUCCESS(Status))
1456 {
1457 /* failed */
1458 IoDeleteDevice(FunctionalDeviceObject);
1459 FreeItem(CreateItem);
1460 return Status;
1461 }
1462
1463 /* now attach to device stack */
1464 NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
1465 if (NextDeviceObject)
1466 {
1467 /* store pnp base object */
1468 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject);
1469 /* set device flags */
1470 FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
1471 FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
1472 }
1473 else
1474 {
1475 /* failed */
1476 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
1477 FreeItem(CreateItem);
1478 IoDeleteDevice(FunctionalDeviceObject);
1479 Status = STATUS_DEVICE_REMOVED;
1480 }
1481
1482 /* return result */
1483 return Status;
1484 }
1485
1486
1487 /*
1488 @implemented
1489 */
1490 COMDDKAPI
1491 NTSTATUS
1492 NTAPI
1493 KoDeviceInitialize(
1494 IN PDEVICE_OBJECT DeviceObject)
1495 {
1496 PDEVICE_EXTENSION DeviceExtension;
1497
1498 /* get device extension */
1499 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1500
1501 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL);
1502 }
1503
1504 /*
1505 @implemented
1506 */
1507 COMDDKAPI
1508 NTSTATUS
1509 NTAPI
1510 KoDriverInitialize(
1511 IN PDRIVER_OBJECT DriverObject,
1512 IN PUNICODE_STRING RegistryPathName,
1513 IN KoCreateObjectHandler CreateObjectHandler)
1514 {
1515 PKO_DRIVER_EXTENSION DriverObjectExtension;
1516 NTSTATUS Status;
1517
1518 /* allocate driver object extension */
1519 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
1520
1521 /* did it work */
1522 if (NT_SUCCESS(Status))
1523 {
1524 /* store create handler */
1525 DriverObjectExtension->CreateObjectHandler = CreateObjectHandler;
1526
1527 /* Setting our IRP handlers */
1528 DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp;
1529 DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
1530 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
1531
1532 /* The driver unload routine */
1533 DriverObject->DriverUnload = KsNullDriverUnload;
1534
1535 /* The driver-supplied AddDevice */
1536 DriverObject->DriverExtension->AddDevice = KopAddDevice;
1537
1538 /* KS handles these */
1539 DPRINT1("Setting KS function handlers\n");
1540 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
1541 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
1542 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
1543
1544 }
1545
1546 return Status;
1547 }
1548
1549 /*
1550 @unimplemented
1551 */
1552 COMDDKAPI
1553 VOID
1554 NTAPI
1555 KoRelease(
1556 IN REFCLSID ClassId)
1557 {
1558
1559 }
1560
1561 /*
1562 @implemented
1563 */
1564 KSDDKAPI
1565 VOID
1566 NTAPI
1567 KsAcquireControl(
1568 IN PVOID Object)
1569 {
1570 PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
1571
1572 /* sanity check */
1573 ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
1574
1575 KeWaitForSingleObject(&BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
1576
1577 }
1578
1579 /*
1580 @implemented
1581 */
1582 VOID
1583 NTAPI
1584 KsReleaseControl(
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 KeReleaseMutex(&BasicHeader->ControlMutex, FALSE);
1593 }
1594
1595
1596
1597 /*
1598 @implemented
1599 */
1600 KSDDKAPI
1601 VOID
1602 NTAPI
1603 KsAcquireDevice(
1604 IN PKSDEVICE Device)
1605 {
1606 IKsDevice *KsDevice;
1607 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1608
1609 /* get device interface*/
1610 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1611
1612 /* acquire device mutex */
1613 KsDevice->lpVtbl->AcquireDevice(KsDevice);
1614 }
1615
1616 /*
1617 @implemented
1618 */
1619 VOID
1620 NTAPI
1621 KsReleaseDevice(
1622 IN PKSDEVICE Device)
1623 {
1624 IKsDevice *KsDevice;
1625 PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
1626
1627 /* get device interface*/
1628 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1629
1630 /* release device mutex */
1631 KsDevice->lpVtbl->ReleaseDevice(KsDevice);
1632 }
1633
1634 /*
1635 @implemented
1636 */
1637 KSDDKAPI
1638 VOID
1639 NTAPI
1640 KsTerminateDevice(
1641 IN PDEVICE_OBJECT DeviceObject)
1642 {
1643 IKsDevice *KsDevice;
1644 PKSIDEVICE_HEADER DeviceHeader;
1645 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1646
1647 /* get device header */
1648 DeviceHeader = DeviceExtension->DeviceHeader;
1649
1650 /* get device interface*/
1651 KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
1652
1653 /* now free device header */
1654 KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
1655
1656 /* release interface when available */
1657 if (KsDevice)
1658 {
1659 /* delete IKsDevice interface */
1660 KsDevice->lpVtbl->Release(KsDevice);
1661 }
1662 }
1663
1664 /*
1665 @implemented
1666 */
1667 KSDDKAPI
1668 VOID
1669 NTAPI
1670 KsCompletePendingRequest(
1671 IN PIRP Irp)
1672 {
1673 PIO_STACK_LOCATION IoStack;
1674
1675 /* get current irp stack location */
1676 IoStack = IoGetCurrentIrpStackLocation(Irp);
1677
1678 /* sanity check */
1679 ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
1680
1681 if (IoStack->MajorFunction != IRP_MJ_CLOSE)
1682 {
1683 /* can be completed immediately */
1684 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1685 return;
1686 }
1687
1688 /* did close operation fail */
1689 if (!NT_SUCCESS(Irp->IoStatus.Status))
1690 {
1691 /* closing failed, complete irp */
1692 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1693 return;
1694 }
1695
1696 /* FIXME
1697 * delete object / device header
1698 * remove dead pin / filter instance
1699 */
1700 UNIMPLEMENTED
1701
1702 }
1703
1704 /*
1705 @unimplemented
1706 */
1707 KSDDKAPI
1708 NTSTATUS
1709 NTAPI
1710 KsCreateBusEnumObject(
1711 IN PWCHAR BusIdentifier,
1712 IN PDEVICE_OBJECT BusDeviceObject,
1713 IN PDEVICE_OBJECT PhysicalDeviceObject,
1714 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL,
1715 IN REFGUID InterfaceGuid OPTIONAL,
1716 IN PWCHAR ServiceRelativePath OPTIONAL)
1717 {
1718 UNIMPLEMENTED
1719 return STATUS_UNSUCCESSFUL;
1720 }
1721
1722 NTSTATUS
1723 NTAPI
1724 KspSetGetBusDataCompletion(
1725 IN PDEVICE_OBJECT DeviceObject,
1726 IN PIRP Irp,
1727 IN PVOID Context)
1728 {
1729 /* signal completion */
1730 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
1731
1732 /* more work needs be done, so dont free the irp */
1733 return STATUS_MORE_PROCESSING_REQUIRED;
1734
1735 }
1736
1737 NTSTATUS
1738 KspDeviceSetGetBusData(
1739 IN PDEVICE_OBJECT DeviceObject,
1740 IN ULONG DataType,
1741 IN PVOID Buffer,
1742 IN ULONG Offset,
1743 IN ULONG Length,
1744 IN BOOL bGet)
1745 {
1746 PIO_STACK_LOCATION IoStack;
1747 PIRP Irp;
1748 NTSTATUS Status;
1749 KEVENT Event;
1750
1751 /* allocate the irp */
1752 Irp = IoAllocateIrp(1, /*FIXME */
1753 FALSE);
1754
1755 if (!Irp)
1756 return STATUS_INSUFFICIENT_RESOURCES;
1757
1758 /* initialize the event */
1759 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1760
1761 /* get next stack location */
1762 IoStack = IoGetNextIrpStackLocation(Irp);
1763
1764 /* setup a completion routine */
1765 IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
1766
1767 /* setup parameters */
1768 IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
1769 IoStack->Parameters.ReadWriteConfig.Length = Length;
1770 IoStack->Parameters.ReadWriteConfig.Offset = Offset;
1771 IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
1772 /* setup function code */
1773 IoStack->MajorFunction = IRP_MJ_PNP;
1774 IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
1775
1776 /* lets call the driver */
1777 Status = IoCallDriver(DeviceObject, Irp);
1778
1779 /* is the request still pending */
1780 if (Status == STATUS_PENDING)
1781 {
1782 /* have a nap */
1783 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1784 /* update status */
1785 Status = Irp->IoStatus.Status;
1786 }
1787
1788 /* free the irp */
1789 IoFreeIrp(Irp);
1790 /* done */
1791 return Status;
1792 }
1793
1794 /*
1795 @implemented
1796 */
1797 KSDDKAPI
1798 ULONG
1799 NTAPI
1800 KsDeviceSetBusData(
1801 IN PKSDEVICE Device,
1802 IN ULONG DataType,
1803 IN PVOID Buffer,
1804 IN ULONG Offset,
1805 IN ULONG Length)
1806 {
1807 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1808 DataType, Buffer, Offset, Length, FALSE);
1809 }
1810
1811
1812 /*
1813 @implemented
1814 */
1815 KSDDKAPI
1816 ULONG
1817 NTAPI
1818 KsDeviceGetBusData(
1819 IN PKSDEVICE Device,
1820 IN ULONG DataType,
1821 IN PVOID Buffer,
1822 IN ULONG Offset,
1823 IN ULONG Length)
1824 {
1825 return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
1826 DataType, Buffer, Offset, Length, TRUE);
1827
1828 }
1829
1830 /*
1831 @unimplemented
1832 */
1833 KSDDKAPI
1834 void
1835 NTAPI
1836 KsDeviceRegisterAdapterObject(
1837 IN PKSDEVICE Device,
1838 IN PADAPTER_OBJECT AdapterObject,
1839 IN ULONG MaxMappingsByteCount,
1840 IN ULONG MappingTableStride)
1841 {
1842 UNIMPLEMENTED
1843 }
1844
1845 /*
1846 @unimplemented
1847 */
1848 KSDDKAPI
1849 NTSTATUS
1850 NTAPI
1851 KsGetBusEnumIdentifier(
1852 IN PIRP Irp)
1853 {
1854 UNIMPLEMENTED
1855 return STATUS_UNSUCCESSFUL;
1856 }
1857
1858 /*
1859 @unimplemented
1860 */
1861 KSDDKAPI
1862 NTSTATUS
1863 NTAPI
1864 KsGetBusEnumParentFDOFromChildPDO(
1865 IN PDEVICE_OBJECT DeviceObject,
1866 OUT PDEVICE_OBJECT *FunctionalDeviceObject)
1867 {
1868 UNIMPLEMENTED
1869 return STATUS_UNSUCCESSFUL;
1870 }
1871
1872 /*
1873 @unimplemented
1874 */
1875 KSDDKAPI
1876 NTSTATUS
1877 NTAPI
1878 KsGetBusEnumPnpDeviceObject(
1879 IN PDEVICE_OBJECT DeviceObject,
1880 IN PDEVICE_OBJECT *PnpDeviceObject)
1881 {
1882 UNIMPLEMENTED
1883 return STATUS_UNSUCCESSFUL;
1884 }
1885
1886 /*
1887 @unimplemented
1888 */
1889 KSDDKAPI
1890 PVOID
1891 NTAPI
1892 KsGetFirstChild(
1893 IN PVOID Object)
1894 {
1895 UNIMPLEMENTED
1896 return NULL;
1897 }
1898
1899 /*
1900 @unimplemented
1901 */
1902 KSDDKAPI
1903 PVOID
1904 NTAPI
1905 KsGetNextSibling(
1906 IN PVOID Object)
1907 {
1908 UNIMPLEMENTED
1909 return NULL;
1910 }
1911
1912 /*
1913 @unimplemented
1914 */
1915 KSDDKAPI
1916 NTSTATUS
1917 NTAPI
1918 KsInstallBusEnumInterface(
1919 PIRP Irp)
1920 {
1921 UNIMPLEMENTED
1922 return STATUS_UNSUCCESSFUL;
1923 }
1924
1925 /*
1926 @unimplemented
1927 */
1928 KSDDKAPI
1929 NTSTATUS
1930 NTAPI
1931 KsIsBusEnumChildDevice(
1932 IN PDEVICE_OBJECT DeviceObject,
1933 OUT PBOOLEAN ChildDevice)
1934 {
1935 UNIMPLEMENTED
1936 return STATUS_UNSUCCESSFUL;
1937 }
1938
1939 /*
1940 @unimplemented
1941 */
1942 NTSTATUS
1943 NTAPI
1944 KsMergeAutomationTables(
1945 OUT PKSAUTOMATION_TABLE *AutomationTableAB,
1946 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
1947 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL,
1948 IN KSOBJECT_BAG Bag OPTIONAL)
1949 {
1950 UNIMPLEMENTED
1951 return STATUS_UNSUCCESSFUL;
1952 }
1953
1954 /*
1955 @unimplemented
1956 */
1957 KSDDKAPI
1958 NTSTATUS
1959 NTAPI
1960 KsServiceBusEnumCreateRequest(
1961 IN PDEVICE_OBJECT DeviceObject,
1962 IN OUT PIRP Irp)
1963 {
1964 UNIMPLEMENTED
1965 return STATUS_UNSUCCESSFUL;
1966 }
1967
1968
1969 /*
1970 @unimplemented
1971 */
1972 KSDDKAPI
1973 NTSTATUS
1974 NTAPI
1975 KsServiceBusEnumPnpRequest(
1976 IN PDEVICE_OBJECT DeviceObject,
1977 IN OUT PIRP Irp)
1978 {
1979 UNIMPLEMENTED
1980 return STATUS_UNSUCCESSFUL;
1981 }
1982
1983 VOID
1984 NTAPI
1985 KspRemoveBusInterface(
1986 PVOID Ctx)
1987 {
1988 PKSREMOVE_BUS_INTERFACE_CTX Context =(PKSREMOVE_BUS_INTERFACE_CTX)Ctx;
1989
1990 /* TODO
1991 * get SWENUM_INSTALL_INTERFACE struct
1992 * open device key and delete the keys
1993 */
1994
1995 UNIMPLEMENTED
1996
1997 /* set status */
1998 Context->Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1999
2000
2001 /* signal completion */
2002 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
2003 }
2004
2005 /*
2006 @unimplemented
2007 */
2008 KSDDKAPI
2009 NTSTATUS
2010 NTAPI
2011 KsRemoveBusEnumInterface(
2012 IN PIRP Irp)
2013 {
2014 KPROCESSOR_MODE Mode;
2015 LUID luid;
2016 KSREMOVE_BUS_INTERFACE_CTX Ctx;
2017 WORK_QUEUE_ITEM WorkItem;
2018
2019 /* get previous mode */
2020 Mode = ExGetPreviousMode();
2021
2022 /* convert to luid */
2023 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
2024
2025 /* perform access check */
2026 if (!SeSinglePrivilegeCheck(luid, Mode))
2027 {
2028 /* insufficient privileges */
2029 return STATUS_PRIVILEGE_NOT_HELD;
2030 }
2031 /* initialize event */
2032 KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);
2033
2034 /* store irp in ctx */
2035 Ctx.Irp = Irp;
2036
2037 /* initialize work item */
2038 ExInitializeWorkItem(&WorkItem, KspRemoveBusInterface, (PVOID)&Ctx);
2039
2040 /* now queue the work item */
2041 ExQueueWorkItem(&WorkItem, DelayedWorkQueue);
2042
2043 /* wait for completion */
2044 KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
2045
2046 /* return result */
2047 return Ctx.Irp->IoStatus.Status;
2048
2049 }
2050
2051
2052 /*
2053 @unimplemented
2054 */
2055 KSDDKAPI
2056 PUNKNOWN
2057 NTAPI
2058 KsRegisterAggregatedClientUnknown(
2059 IN PVOID Object,
2060 IN PUNKNOWN ClientUnknown)
2061 {
2062 UNIMPLEMENTED
2063 return NULL;
2064 }
2065
2066 /*
2067 @unimplemented
2068 */
2069 NTSTATUS
2070 NTAPI
2071 KsRegisterFilterWithNoKSPins(
2072 IN PDEVICE_OBJECT DeviceObject,
2073 IN const GUID* InterfaceClassGUID,
2074 IN ULONG PinCount,
2075 IN BOOL* PinDirection,
2076 IN KSPIN_MEDIUM* MediumList,
2077 IN GUID* CategoryList OPTIONAL)
2078 {
2079 ULONG Size, Index;
2080 NTSTATUS Status;
2081 PWSTR SymbolicLinkList;
2082 //PUCHAR Buffer;
2083 HANDLE hKey;
2084 UNICODE_STRING InterfaceString;
2085 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2086
2087 if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
2088 {
2089 /* all these parameters are required */
2090 return STATUS_INVALID_PARAMETER;
2091 }
2092
2093 /* calculate filter data value size */
2094 Size = PinCount * sizeof(KSPIN_MEDIUM);
2095 if (CategoryList)
2096 {
2097 /* add category list */
2098 Size += PinCount * sizeof(GUID);
2099 }
2100
2101 /* FIXME generate filter data blob */
2102 UNIMPLEMENTED
2103
2104 /* get symbolic link list */
2105 Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
2106 if (NT_SUCCESS(Status))
2107 {
2108 /* initialize first symbolic link */
2109 RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
2110
2111 /* open first device interface registry key */
2112 Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
2113
2114 if (NT_SUCCESS(Status))
2115 {
2116 /* write filter data */
2117 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2118
2119 /* close the key */
2120 ZwClose(hKey);
2121 }
2122
2123 if (PinCount)
2124 {
2125 /* update medium cache */
2126 for(Index = 0; Index < PinCount; Index++)
2127 {
2128 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
2129 }
2130 }
2131
2132 /* free the symbolic link list */
2133 ExFreePool(SymbolicLinkList);
2134 }
2135
2136 return Status;
2137 }