xref: /reactos/drivers/ksfilter/ks/irp.c (revision a6b281c2)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/ksfilter/ks/factory.c
5  * PURPOSE:         KS Allocator functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #include <ntifs.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /*
17     @implemented
18 */
19 KSDDKAPI
20 NTSTATUS
21 NTAPI
KsDispatchQuerySecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)22 KsDispatchQuerySecurity(
23     IN PDEVICE_OBJECT DeviceObject,
24     IN PIRP Irp)
25 {
26     PKSOBJECT_CREATE_ITEM CreateItem;
27     PIO_STACK_LOCATION IoStack;
28     NTSTATUS Status;
29     ULONG Length;
30 
31     /* get current irp stack */
32     IoStack = IoGetCurrentIrpStackLocation(Irp);
33 
34     /* get create item */
35     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
36 
37     if (!CreateItem || !CreateItem->SecurityDescriptor)
38     {
39         /* no create item */
40         Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
41         CompleteRequest(Irp, IO_NO_INCREMENT);
42         return STATUS_NO_SECURITY_ON_OBJECT;
43     }
44 
45 
46     /* get input length */
47     Length = IoStack->Parameters.QuerySecurity.Length;
48 
49     /* clone the security descriptor */
50     Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)Irp->UserBuffer, &Length, &CreateItem->SecurityDescriptor);
51 
52     DPRINT("SeQuerySecurityDescriptorInfo Status %x\n", Status);
53     /* store result */
54     Irp->IoStatus.Status = Status;
55     Irp->IoStatus.Information = Length;
56 
57     CompleteRequest(Irp, IO_NO_INCREMENT);
58     return Status;
59 }
60 
61 /*
62     @implemented
63 */
64 KSDDKAPI
65 NTSTATUS
66 NTAPI
KsDispatchSetSecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)67 KsDispatchSetSecurity(
68     IN PDEVICE_OBJECT DeviceObject,
69     IN PIRP Irp)
70 {
71     PKSOBJECT_CREATE_ITEM CreateItem;
72     PIO_STACK_LOCATION IoStack;
73     PGENERIC_MAPPING Mapping;
74     PSECURITY_DESCRIPTOR Descriptor;
75     NTSTATUS Status;
76 
77     /* get current irp stack */
78     IoStack = IoGetCurrentIrpStackLocation(Irp);
79 
80     /* get create item */
81     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
82 
83     if (!CreateItem || !CreateItem->SecurityDescriptor)
84     {
85         /* no create item */
86         Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
87         CompleteRequest(Irp, IO_NO_INCREMENT);
88         return STATUS_NO_SECURITY_ON_OBJECT;
89     }
90 
91     /* backup old descriptor */
92     Descriptor = CreateItem->SecurityDescriptor;
93 
94     /* get generic mapping */
95     Mapping = IoGetFileObjectGenericMapping();
96 
97     /* change security descriptor */
98     Status = SeSetSecurityDescriptorInfo(NULL, /*FIXME */
99                                          &IoStack->Parameters.SetSecurity.SecurityInformation,
100                                          IoStack->Parameters.SetSecurity.SecurityDescriptor,
101                                          &CreateItem->SecurityDescriptor,
102                                          NonPagedPool,
103                                          Mapping);
104 
105     if (NT_SUCCESS(Status))
106     {
107         /* free old descriptor */
108         FreeItem(Descriptor);
109 
110        /* mark create item as changed */
111        CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED;
112     }
113 
114     /* store result */
115     Irp->IoStatus.Status = Status;
116     CompleteRequest(Irp, IO_NO_INCREMENT);
117 
118     return Status;
119 }
120 
121 /*
122     @unimplemented
123 */
124 KSDDKAPI
125 NTSTATUS
126 NTAPI
KsDispatchSpecificMethod(IN PIRP Irp,IN PFNKSHANDLER Handler)127 KsDispatchSpecificMethod(
128     IN  PIRP Irp,
129     IN  PFNKSHANDLER Handler)
130 {
131     UNIMPLEMENTED;
132     return STATUS_UNSUCCESSFUL;
133 }
134 
135 
136 /*
137     @implemented
138 */
139 KSDDKAPI
140 NTSTATUS
141 NTAPI
KsReadFile(IN PFILE_OBJECT FileObject,IN PKEVENT Event OPTIONAL,IN PVOID PortContext OPTIONAL,OUT PIO_STATUS_BLOCK IoStatusBlock,OUT PVOID Buffer,IN ULONG Length,IN ULONG Key OPTIONAL,IN KPROCESSOR_MODE RequestorMode)142 KsReadFile(
143     IN  PFILE_OBJECT FileObject,
144     IN  PKEVENT Event OPTIONAL,
145     IN  PVOID PortContext OPTIONAL,
146     OUT PIO_STATUS_BLOCK IoStatusBlock,
147     OUT PVOID Buffer,
148     IN  ULONG Length,
149     IN  ULONG Key OPTIONAL,
150     IN  KPROCESSOR_MODE RequestorMode)
151 {
152     PDEVICE_OBJECT DeviceObject;
153     PIO_STACK_LOCATION IoStack;
154     PIRP Irp;
155     NTSTATUS Status;
156     BOOLEAN Result;
157     KEVENT LocalEvent;
158 
159     if (Event)
160     {
161         /* make sure event is reset */
162         KeClearEvent(Event);
163     }
164 
165     if (RequestorMode == UserMode)
166     {
167         /* probe the user buffer */
168         _SEH2_TRY
169         {
170             ProbeForWrite(Buffer, Length, sizeof(UCHAR));
171             Status = STATUS_SUCCESS;
172         }
173         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
174         {
175             /* Exception, get the error code */
176             Status = _SEH2_GetExceptionCode();
177         }
178         _SEH2_END;
179 
180          if (!NT_SUCCESS(Status))
181          {
182              DPRINT1("Invalid user buffer provided\n");
183              return Status;
184          }
185     }
186 
187     /* get corresponding device object */
188     DeviceObject = IoGetRelatedDeviceObject(FileObject);
189 
190     /* fast-io read is only available for kernel mode clients */
191     if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
192         DeviceObject->DriverObject->FastIoDispatch->FastIoRead)
193     {
194         /* call fast io write */
195         Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
196 
197         if (Result && NT_SUCCESS(IoStatusBlock->Status))
198         {
199             /* request was handled and succeeded */
200             return STATUS_SUCCESS;
201         }
202     }
203 
204     /* do the slow way */
205     if (!Event)
206     {
207         /* initialize temp event */
208         KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
209         Event = &LocalEvent;
210     }
211 
212     /* build the irp packet */
213     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
214     if (!Irp)
215     {
216         /* not enough resources */
217         return STATUS_INSUFFICIENT_RESOURCES;
218     }
219 
220     /* setup the rest of irp */
221     Irp->RequestorMode = RequestorMode;
222     Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
223     Irp->Tail.Overlay.OriginalFileObject = FileObject;
224 
225     /* setup irp stack */
226     IoStack = IoGetNextIrpStackLocation(Irp);
227     IoStack->FileObject = FileObject;
228     IoStack->Parameters.Read.Key = Key;
229 
230     /* send the packet */
231     Status = IoCallDriver(DeviceObject, Irp);
232 
233     if (Status == STATUS_PENDING)
234     {
235         /* operation is pending, is sync file object */
236         if (FileObject->Flags & FO_SYNCHRONOUS_IO)
237         {
238             /* it is so wait */
239             KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
240             Status = IoStatusBlock->Status;
241         }
242     }
243     /* return result */
244     return Status;
245 }
246 
247 /*
248     @implemented
249 */
250 KSDDKAPI
251 NTSTATUS
252 NTAPI
KsWriteFile(IN PFILE_OBJECT FileObject,IN PKEVENT Event OPTIONAL,IN PVOID PortContext OPTIONAL,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PVOID Buffer,IN ULONG Length,IN ULONG Key OPTIONAL,IN KPROCESSOR_MODE RequestorMode)253 KsWriteFile(
254     IN  PFILE_OBJECT FileObject,
255     IN  PKEVENT Event OPTIONAL,
256     IN  PVOID PortContext OPTIONAL,
257     OUT PIO_STATUS_BLOCK IoStatusBlock,
258     IN  PVOID Buffer,
259     IN  ULONG Length,
260     IN  ULONG Key OPTIONAL,
261     IN  KPROCESSOR_MODE RequestorMode)
262 {
263     PDEVICE_OBJECT DeviceObject;
264     PIO_STACK_LOCATION IoStack;
265     PIRP Irp;
266     NTSTATUS Status;
267     BOOLEAN Result;
268     KEVENT LocalEvent;
269 
270     if (Event)
271     {
272         /* make sure event is reset */
273         KeClearEvent(Event);
274     }
275 
276     if (RequestorMode == UserMode)
277     {
278         /* probe the user buffer */
279         _SEH2_TRY
280         {
281             ProbeForRead(Buffer, Length, sizeof(UCHAR));
282             Status = STATUS_SUCCESS;
283         }
284         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
285         {
286             /* Exception, get the error code */
287             Status = _SEH2_GetExceptionCode();
288         }
289         _SEH2_END;
290 
291          if (!NT_SUCCESS(Status))
292          {
293              DPRINT1("Invalid user buffer provided\n");
294              return Status;
295          }
296     }
297 
298     /* get corresponding device object */
299     DeviceObject = IoGetRelatedDeviceObject(FileObject);
300 
301     /* fast-io write is only available for kernel mode clients */
302     if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
303         DeviceObject->DriverObject->FastIoDispatch->FastIoWrite)
304     {
305         /* call fast io write */
306         Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
307 
308         if (Result && NT_SUCCESS(IoStatusBlock->Status))
309         {
310             /* request was handled and succeeded */
311             return STATUS_SUCCESS;
312         }
313     }
314 
315     /* do the slow way */
316     if (!Event)
317     {
318         /* initialize temp event */
319         KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
320         Event = &LocalEvent;
321     }
322 
323     /* build the irp packet */
324     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
325     if (!Irp)
326     {
327         /* not enough resources */
328         return STATUS_INSUFFICIENT_RESOURCES;
329     }
330 
331     /* setup the rest of irp */
332     Irp->RequestorMode = RequestorMode;
333     Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
334     Irp->Tail.Overlay.OriginalFileObject = FileObject;
335 
336     /* setup irp stack */
337     IoStack = IoGetNextIrpStackLocation(Irp);
338     IoStack->FileObject = FileObject;
339     IoStack->Parameters.Write.Key = Key;
340 
341     /* send the packet */
342     Status = IoCallDriver(DeviceObject, Irp);
343 
344     if (Status == STATUS_PENDING)
345     {
346         /* operation is pending, is sync file object */
347         if (FileObject->Flags & FO_SYNCHRONOUS_IO)
348         {
349             /* it is so wait */
350             KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
351             Status = IoStatusBlock->Status;
352         }
353     }
354     /* return result */
355     return Status;
356 }
357 
358 /*
359     @implemented
360 */
361 KSDDKAPI
362 NTSTATUS
363 NTAPI
KsQueryInformationFile(IN PFILE_OBJECT FileObject,OUT PVOID FileInformation,IN ULONG Length,IN FILE_INFORMATION_CLASS FileInformationClass)364 KsQueryInformationFile(
365     IN  PFILE_OBJECT FileObject,
366     OUT PVOID FileInformation,
367     IN  ULONG Length,
368     IN  FILE_INFORMATION_CLASS FileInformationClass)
369 {
370     PDEVICE_OBJECT DeviceObject;
371     PFAST_IO_DISPATCH FastIoDispatch;
372     PIRP Irp;
373     PIO_STACK_LOCATION IoStack;
374     IO_STATUS_BLOCK IoStatusBlock;
375     KEVENT Event;
376     LARGE_INTEGER Offset;
377     NTSTATUS Status;
378 
379     /* get related file object */
380     DeviceObject = IoGetRelatedDeviceObject(FileObject);
381 
382     /* get fast i/o table */
383     FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
384 
385     /* is there a fast table */
386     if (FastIoDispatch)
387     {
388         /* check the class */
389         if (FileInformationClass == FileBasicInformation)
390         {
391             /* use FastIoQueryBasicInfo routine */
392             if (FastIoDispatch->FastIoQueryBasicInfo != NULL &&
393                 FastIoDispatch->FastIoQueryBasicInfo(
394                   FileObject,
395                   TRUE,
396                   (PFILE_BASIC_INFORMATION)FileInformation,
397                   &IoStatusBlock,
398                   DeviceObject))
399             {
400                 /* request was handled */
401                 return IoStatusBlock.Status;
402             }
403         }
404         else if (FileInformationClass == FileStandardInformation)
405         {
406             /* use FastIoQueryStandardInfo routine */
407             if (FastIoDispatch->FastIoQueryStandardInfo != NULL &&
408                 FastIoDispatch->FastIoQueryStandardInfo(
409                   FileObject,
410                   TRUE,
411                   (PFILE_STANDARD_INFORMATION)FileInformation,
412                   &IoStatusBlock,
413                   DeviceObject))
414             {
415                 /* request was handled */
416                 return IoStatusBlock.Status;
417             }
418         }
419     }
420 
421     /* clear event */
422     KeClearEvent(&FileObject->Event);
423 
424     /* initialize event */
425     KeInitializeEvent(&Event, NotificationEvent, FALSE);
426 
427     /* set offset to zero */
428     Offset.QuadPart = 0L;
429 
430     /* build the request */
431     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &IoStatusBlock);
432     if (!Irp)
433         return STATUS_INSUFFICIENT_RESOURCES;
434 
435     /* get next stack location */
436     IoStack = IoGetNextIrpStackLocation(Irp);
437 
438     /* setup parameters */
439     IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
440     IoStack->Parameters.QueryFile.Length = Length;
441     Irp->AssociatedIrp.SystemBuffer = FileInformation;
442 
443 
444     /* call the driver */
445     Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
446 
447     if (Status == STATUS_PENDING)
448     {
449         /* wait for the operation to complete */
450         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
451 
452        /* is object sync */
453        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
454            Status = FileObject->FinalStatus;
455        else
456            Status = IoStatusBlock.Status;
457     }
458 
459     /* done */
460     return Status;
461 }
462 
463 /*
464     @implemented
465 */
466 KSDDKAPI
467 NTSTATUS
468 NTAPI
KsSetInformationFile(IN PFILE_OBJECT FileObject,IN PVOID FileInformation,IN ULONG Length,IN FILE_INFORMATION_CLASS FileInformationClass)469 KsSetInformationFile(
470     IN  PFILE_OBJECT FileObject,
471     IN  PVOID FileInformation,
472     IN  ULONG Length,
473     IN  FILE_INFORMATION_CLASS FileInformationClass)
474 {
475     PIO_STACK_LOCATION IoStack;
476     PDEVICE_OBJECT DeviceObject;
477     PIRP Irp;
478     PVOID Buffer;
479     KEVENT Event;
480     LARGE_INTEGER Offset;
481     IO_STATUS_BLOCK IoStatus;
482     NTSTATUS Status;
483 
484     /* get related device object */
485     DeviceObject = IoGetRelatedDeviceObject(FileObject);
486 
487     /* copy file information */
488     Buffer = AllocateItem(NonPagedPool, Length);
489     if (!Buffer)
490         return STATUS_INSUFFICIENT_RESOURCES;
491 
492     _SEH2_TRY
493     {
494         ProbeForRead(Buffer, Length, sizeof(UCHAR));
495         RtlMoveMemory(Buffer, FileInformation, Length);
496         Status = STATUS_SUCCESS;
497     }
498     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
499     {
500         /* Exception, get the error code */
501         Status = _SEH2_GetExceptionCode();
502     }
503     _SEH2_END;
504 
505     if (!NT_SUCCESS(Status))
506     {
507         /* invalid user buffer */
508         FreeItem(Buffer);
509         return Status;
510     }
511 
512     /* initialize the event */
513     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
514 
515     /* zero offset */
516     Offset.QuadPart = 0LL;
517 
518     /* build the irp */
519     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus);
520     if (!Irp)
521     {
522         /* failed to allocate irp */
523         FreeItem(Buffer);
524         return STATUS_INSUFFICIENT_RESOURCES;
525     }
526 
527     /* get next stack location */
528     IoStack = IoGetNextIrpStackLocation(Irp);
529 
530     /* set irp parameters */
531     IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass;
532     IoStack->Parameters.SetFile.Length = Length;
533     IoStack->Parameters.SetFile.FileObject = FileObject;
534     Irp->AssociatedIrp.SystemBuffer = Buffer;
535     Irp->UserBuffer = FileInformation;
536 
537     /* dispatch the irp */
538     Status = IoCallDriver(DeviceObject, Irp);
539 
540     if (Status == STATUS_PENDING)
541     {
542         /* wait untill the operation has completed */
543         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
544         /* is a sync file object */
545         if (FileObject->Flags & FO_SYNCHRONOUS_IO)
546             Status = FileObject->FinalStatus;
547         else
548             Status = IoStatus.Status;
549     }
550     /* done */
551     return Status;
552 }
553 
554 /*
555     @implemented
556 */
557 KSDDKAPI
558 NTSTATUS
559 NTAPI
KsStreamIo(IN PFILE_OBJECT FileObject,IN PKEVENT Event OPTIONAL,IN PVOID PortContext OPTIONAL,IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,IN PVOID CompletionContext OPTIONAL,IN KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL,OUT PIO_STATUS_BLOCK IoStatusBlock,IN OUT PVOID StreamHeaders,IN ULONG Length,IN ULONG Flags,IN KPROCESSOR_MODE RequestorMode)560 KsStreamIo(
561     IN  PFILE_OBJECT FileObject,
562     IN  PKEVENT Event OPTIONAL,
563     IN  PVOID PortContext OPTIONAL,
564     IN  PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
565     IN  PVOID CompletionContext OPTIONAL,
566     IN  KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL,
567     OUT PIO_STATUS_BLOCK IoStatusBlock,
568     IN  OUT PVOID StreamHeaders,
569     IN  ULONG Length,
570     IN  ULONG Flags,
571     IN  KPROCESSOR_MODE RequestorMode)
572 {
573     PIRP Irp;
574     PIO_STACK_LOCATION IoStack;
575     PDEVICE_OBJECT DeviceObject;
576     NTSTATUS Status;
577     LARGE_INTEGER Offset;
578     PKSIOBJECT_HEADER ObjectHeader;
579     BOOLEAN Ret;
580 
581     /* get related device object */
582     DeviceObject = IoGetRelatedDeviceObject(FileObject);
583     /* sanity check */
584     ASSERT(DeviceObject != NULL);
585 
586     /* is there a event provided */
587     if (Event)
588     {
589         /* reset event */
590         KeClearEvent(Event);
591     }
592 
593     if (RequestorMode || ExGetPreviousMode() == KernelMode)
594     {
595         /* requestor is from kernel land */
596         ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
597 
598         if (ObjectHeader)
599         {
600             /* there is a object header */
601             if (Flags == KSSTREAM_READ)
602             {
603                 /* is fast read supported */
604                 if (ObjectHeader->DispatchTable.FastRead)
605                 {
606                     /* call fast read dispatch routine */
607                     Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
608 
609                     if (Ret)
610                     {
611                         /* the request was handled */
612                         return IoStatusBlock->Status;
613                     }
614                 }
615             }
616             else if (Flags == KSSTREAM_WRITE)
617             {
618                 /* is fast write supported */
619                 if (ObjectHeader->DispatchTable.FastWrite)
620                 {
621                     /* call fast write dispatch routine */
622                     Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
623 
624                     if (Ret)
625                     {
626                         /* the request was handled */
627                         return IoStatusBlock->Status;
628                     }
629                 }
630             }
631         }
632     }
633 
634     /* clear file object event */
635     KeClearEvent(&FileObject->Event);
636 
637     /* set the offset to zero */
638     Offset.QuadPart = 0LL;
639 
640     /* now build the irp */
641     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
642                                        DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
643     if (!Irp)
644     {
645         /* not enough memory */
646         return STATUS_INSUFFICIENT_RESOURCES;
647     }
648 
649     /* setup irp parameters */
650     Irp->RequestorMode = RequestorMode;
651     Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
652     Irp->Tail.Overlay.OriginalFileObject = FileObject;
653     Irp->UserBuffer = StreamHeaders;
654 
655     /* get next irp stack location */
656     IoStack = IoGetNextIrpStackLocation(Irp);
657     /* setup stack parameters */
658     IoStack->FileObject = FileObject;
659     IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
660     IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
661 
662     if (CompletionRoutine)
663     {
664         /* setup completion routine for async processing */
665         IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
666     }
667 
668     /* now call the driver */
669     Status = IoCallDriver(DeviceObject, Irp);
670     /* done */
671     return Status;
672 }
673 
674 /*
675     @implemented
676 */
677 KSDDKAPI
678 NTSTATUS
679 NTAPI
KsProbeStreamIrp(IN PIRP Irp,IN ULONG ProbeFlags,IN ULONG HeaderSize)680 KsProbeStreamIrp(
681     IN  PIRP Irp,
682     IN  ULONG ProbeFlags,
683     IN  ULONG HeaderSize)
684 {
685     PMDL Mdl;
686     PVOID Buffer;
687     LOCK_OPERATION Operation;
688     NTSTATUS Status = STATUS_SUCCESS;
689     PKSSTREAM_HEADER StreamHeader;
690     PIO_STACK_LOCATION IoStack;
691     ULONG Length;
692     //BOOLEAN AllocateMdl = FALSE;
693 
694     /* get current irp stack */
695     IoStack = IoGetCurrentIrpStackLocation(Irp);
696 
697     Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
698 
699     if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer)
700     {
701         if (Irp->RequestorMode == KernelMode)
702         {
703             /* no need to allocate stream header */
704             Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer;
705         }
706 AllocMdl:
707         /* check if alloc mdl flag is passed */
708         if (!(ProbeFlags & KSPROBE_ALLOCATEMDL))
709         {
710             /* nothing more to do */
711             return STATUS_SUCCESS;
712         }
713         if (Irp->MdlAddress)
714         {
715 ProbeMdl:
716             if (ProbeFlags & KSPROBE_PROBEANDLOCK)
717             {
718                 if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL))
719                 {
720                     if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
721                     {
722                         _SEH2_TRY
723                         {
724                             /* loop through all mdls and probe them */
725                             Mdl = Irp->MdlAddress;
726                             do
727                             {
728                                 /* the mapping can fail */
729                                 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
730 
731                                 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
732                                 {
733                                     /* no need to probe these pages */
734                                     Buffer = Mdl->MappedSystemVa;
735                                 }
736                                 else
737                                 {
738                                     /* probe that mdl */
739                                     Buffer = MmMapLockedPages(Mdl, KernelMode);
740                                 }
741 
742                                 /* check if the mapping succeeded */
743                                 if (!Buffer)
744                                 {
745                                     /* raise exception we'll catch */
746                                     ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
747                                 }
748 
749                                 /* iterate to next mdl */
750                                 Mdl = Mdl->Next;
751 
752                             }while(Mdl);
753                         }
754                         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
755                         {
756                             /* Exception, get the error code */
757                             Status = _SEH2_GetExceptionCode();
758                         } _SEH2_END;
759                     }
760                 }
761                 else
762                 {
763                     _SEH2_TRY
764                     {
765                         /* loop through all mdls and probe them */
766                         Mdl = Irp->MdlAddress;
767 
768                         /* determine operation */
769                         if (!(ProbeFlags & KSPROBE_STREAMWRITE) || (ProbeFlags & KSPROBE_MODIFY))
770                         {
771                             /* operation is read / modify stream, need write access */
772                             Operation = IoWriteAccess;
773                         }
774                         else
775                         {
776                             /* operation is write to device, so we need read access */
777                             Operation = IoReadAccess;
778                         }
779 
780                         do
781                         {
782                             /* probe the pages */
783                             MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
784 
785                             if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
786                             {
787                                 /* the mapping can fail */
788                                 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
789 
790                                 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
791                                 {
792                                     /* no need to probe these pages */
793                                     Buffer = Mdl->MappedSystemVa;
794                                 }
795                                 else
796                                 {
797                                     /* probe that mdl */
798                                     Buffer = MmMapLockedPages(Mdl, KernelMode);
799                                 }
800 
801                                 /* check if the mapping succeeded */
802                                 if (!Buffer)
803                                 {
804                                     /* raise exception we'll catch */
805                                     ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
806                                 }
807                             }
808 
809                             /* iterate to next mdl */
810                             Mdl = Mdl->Next;
811 
812                         }while(Mdl);
813                     }
814                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
815                     {
816                         /* Exception, get the error code */
817                         Status = _SEH2_GetExceptionCode();
818                     } _SEH2_END;
819                 }
820             }
821             return Status;
822         }
823 
824         /* check all stream headers */
825         StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
826         ASSERT(StreamHeader);
827         _SEH2_TRY
828         {
829             do
830             {
831                 if (HeaderSize)
832                 {
833                     /* does the supplied header size match stream header size and no type changed */
834                     if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
835                     {
836                         /* invalid stream header */
837                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
838                     }
839                 }
840                 else
841                 {
842                     /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
843                     if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
844                     {
845                         /* invalid stream header */
846                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
847                     }
848                 }
849 
850                 if (Length < StreamHeader->Size)
851                 {
852                     /* length is too short */
853                     ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
854                 }
855 
856                 if (ProbeFlags & KSPROBE_STREAMWRITE)
857                 {
858                     if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
859                     {
860                         /* frame extend can never be smaller */
861                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
862                     }
863 
864                     /* is this stream change packet */
865                     if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
866                     {
867                         if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
868                         {
869                             /* stream changed - must be send in a single packet */
870                             ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
871                         }
872 
873                         if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
874                         {
875                             /* caller does not permit format changes */
876                             ExRaiseStatus(STATUS_INVALID_PARAMETER);
877                         }
878 
879                         if (StreamHeader->FrameExtent)
880                         {
881                             /* allocate an mdl */
882                             Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
883 
884                             if (!Mdl)
885                             {
886                                 /* not enough memory */
887                                 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
888                             }
889 
890                             /* break-out to probe for the irp */
891                             break;
892                         }
893                     }
894                 }
895                 else
896                 {
897                     if (StreamHeader->DataUsed)
898                     {
899                         /* DataUsed must be zero for stream read operation */
900                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
901                     }
902 
903                     if (StreamHeader->OptionsFlags)
904                     {
905                         /* no flags supported for reading */
906                         ExRaiseStatus(STATUS_INVALID_PARAMETER);
907                     }
908                 }
909 
910                 if (StreamHeader->FrameExtent)
911                 {
912                     /* allocate an mdl */
913                     ASSERT(Irp->MdlAddress == NULL);
914                     Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
915                     if (!Mdl)
916                     {
917                         /* not enough memory */
918                         ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
919                     }
920                 }
921 
922                 /* move to next stream header */
923                 Length -= StreamHeader->Size;
924                 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
925             }while(Length);
926         }
927         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
928         {
929             /* Exception, get the error code */
930             Status = _SEH2_GetExceptionCode();
931         }_SEH2_END;
932 
933         /* now probe the allocated mdl's */
934         if (!NT_SUCCESS(Status))
935         {
936             DPRINT("Status %x\n", Status);
937             return Status;
938         }
939         else
940             goto ProbeMdl;
941     }
942 
943     /* probe user mode buffers */
944     if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
945     {
946         /* allocate stream header buffer */
947         Irp->AssociatedIrp.SystemBuffer = AllocateItem(NonPagedPool, Length);
948 
949         if (!Irp->AssociatedIrp.SystemBuffer)
950         {
951             /* no memory */
952             return STATUS_INSUFFICIENT_RESOURCES;
953         }
954 
955         /* mark irp as buffered so that changes the stream headers are propagated back */
956         Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
957 
958         _SEH2_TRY
959         {
960             if (ProbeFlags & KSPROBE_STREAMWRITE)
961             {
962                 if (ProbeFlags & KSPROBE_MODIFY)
963                     ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
964                 else
965                     ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR));
966             }
967             else
968             {
969                 /* stream reads means writing */
970                 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
971 
972                 /* set input operation flags */
973                 Irp->Flags |= IRP_INPUT_OPERATION;
974             }
975 
976             /* copy stream buffer */
977             RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length);
978         }
979         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
980         {
981             /* Exception, get the error code */
982             Status = _SEH2_GetExceptionCode();
983         }_SEH2_END;
984 
985         if (!NT_SUCCESS(Status))
986         {
987             /* failed */
988             return Status;
989         }
990 
991         if (ProbeFlags & KSPROBE_ALLOCATEMDL)
992         {
993             /* alloc mdls */
994             goto AllocMdl;
995         }
996 
997         /* check all stream headers */
998         StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
999 
1000         _SEH2_TRY
1001         {
1002             do
1003             {
1004                 if (HeaderSize)
1005                 {
1006                     /* does the supplied header size match stream header size and no type changed */
1007                     if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
1008                     {
1009                         /* invalid stream header */
1010                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1011                     }
1012                 }
1013                 else
1014                 {
1015                     /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
1016                     if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
1017                     {
1018                         /* invalid stream header */
1019                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1020                     }
1021                 }
1022 
1023                 if (Length < StreamHeader->Size)
1024                 {
1025                     /* length is too short */
1026                     ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1027                 }
1028 
1029                 if (ProbeFlags & KSPROBE_STREAMWRITE)
1030                 {
1031                     if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
1032                     {
1033                         /* frame extend can never be smaller */
1034                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1035                     }
1036 
1037                     /* is this stream change packet */
1038                     if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
1039                     {
1040                         if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
1041                         {
1042                             /* stream changed - must be send in a single packet */
1043                             ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1044                         }
1045 
1046                         if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
1047                         {
1048                             /* caller does not permit format changes */
1049                             ExRaiseStatus(STATUS_INVALID_PARAMETER);
1050                         }
1051 
1052                         if (StreamHeader->FrameExtent)
1053                         {
1054                             /* allocate an mdl */
1055                             Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
1056 
1057                             if (!Mdl)
1058                             {
1059                                 /* not enough memory */
1060                                 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
1061                             }
1062 
1063                             /* break out to probe for the irp */
1064                             //AllocateMdl = TRUE;
1065                             break;
1066                         }
1067                     }
1068                 }
1069                 else
1070                 {
1071                     if (StreamHeader->DataUsed)
1072                     {
1073                         /* DataUsed must be zero for stream read operation */
1074                         ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1075                     }
1076 
1077                     if (StreamHeader->OptionsFlags)
1078                     {
1079                         /* no flags supported for reading */
1080                         ExRaiseStatus(STATUS_INVALID_PARAMETER);
1081                     }
1082                 }
1083 
1084                 /* move to next stream header */
1085                 Length -= StreamHeader->Size;
1086                 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
1087             }while(Length);
1088 
1089         }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1090         {
1091             /* Exception, get the error code */
1092             Status = _SEH2_GetExceptionCode();
1093         }_SEH2_END;
1094 
1095         /* now probe the allocated mdl's */
1096         if (NT_SUCCESS(Status))
1097             goto AllocMdl;
1098         else
1099             return Status;
1100     }
1101 
1102     return STATUS_INVALID_BUFFER_SIZE;
1103 }
1104 
1105 /*
1106     @implemented
1107 */
1108 KSDDKAPI
1109 NTSTATUS
1110 NTAPI
KsAllocateExtraData(IN PIRP Irp,IN ULONG ExtraSize,OUT PVOID * ExtraBuffer)1111 KsAllocateExtraData(
1112     IN  PIRP Irp,
1113     IN  ULONG ExtraSize,
1114     OUT PVOID* ExtraBuffer)
1115 {
1116     PIO_STACK_LOCATION IoStack;
1117     ULONG Count, Index;
1118     PUCHAR Buffer, BufferOrg;
1119     PKSSTREAM_HEADER Header;
1120     NTSTATUS Status = STATUS_SUCCESS;
1121 
1122     /* get current irp stack */
1123     IoStack = IoGetCurrentIrpStackLocation(Irp);
1124 
1125     /* sanity check */
1126     ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
1127 
1128     /* get total length */
1129     Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
1130 
1131     /* allocate buffer */
1132     Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
1133     if (!Buffer)
1134         return STATUS_INSUFFICIENT_RESOURCES;
1135 
1136     _SEH2_TRY
1137     {
1138         /* get input buffer */
1139         Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1140         for(Index = 0; Index < Count; Index++)
1141         {
1142             /* copy stream header */
1143             RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
1144 
1145             /* move to next header */
1146             Header++;
1147             /* increment output buffer offset */
1148             Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
1149         }
1150     }
1151     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1152     {
1153         /* Exception, get the error code */
1154         Status = _SEH2_GetExceptionCode();
1155     }
1156     _SEH2_END;
1157 
1158     if (!NT_SUCCESS(Status))
1159     {
1160         /* free buffer on exception */
1161         FreeItem(Buffer);
1162         return Status;
1163     }
1164 
1165     /* store result */
1166     *ExtraBuffer = BufferOrg;
1167 
1168     /* done */
1169     return STATUS_SUCCESS;
1170 }
1171 
1172 /*
1173     @implemented
1174 */
1175 KSDDKAPI
1176 VOID
1177 NTAPI
KsNullDriverUnload(IN PDRIVER_OBJECT DriverObject)1178 KsNullDriverUnload(
1179     IN  PDRIVER_OBJECT DriverObject)
1180 {
1181 }
1182 
1183 /*
1184     @implemented
1185 */
1186 KSDDKAPI
1187 NTSTATUS
1188 NTAPI
KsDispatchInvalidDeviceRequest(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1189 KsDispatchInvalidDeviceRequest(
1190     IN  PDEVICE_OBJECT DeviceObject,
1191     IN  PIRP Irp)
1192 {
1193     Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1194     CompleteRequest(Irp, IO_NO_INCREMENT);
1195 
1196     return STATUS_INVALID_DEVICE_REQUEST;
1197 }
1198 
1199 /*
1200     @implemented
1201 */
1202 KSDDKAPI
1203 NTSTATUS
1204 NTAPI
KsDefaultDeviceIoCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1205 KsDefaultDeviceIoCompletion(
1206     IN  PDEVICE_OBJECT DeviceObject,
1207     IN  PIRP Irp)
1208 {
1209     PIO_STACK_LOCATION IoStack;
1210     NTSTATUS Status;
1211 
1212     /* get current irp stack */
1213     IoStack = IoGetCurrentIrpStackLocation(Irp);
1214 
1215     if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY &&
1216         IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
1217         IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_ENABLE_EVENT &&
1218         IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_DISABLE_EVENT)
1219     {
1220         if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
1221         {
1222             /* fake success */
1223             Status = STATUS_SUCCESS;
1224         }
1225         else
1226         {
1227             /* request unsupported */
1228             Status = STATUS_INVALID_DEVICE_REQUEST;
1229         }
1230     }
1231     else
1232     {
1233         /* property / method / event not found */
1234         Status = STATUS_PROPSET_NOT_FOUND;
1235     }
1236 
1237     /* complete request */
1238     Irp->IoStatus.Status = Status;
1239     CompleteRequest(Irp, IO_NO_INCREMENT);
1240 
1241 
1242     return Status;
1243 }
1244 
1245 /*
1246     @implemented
1247 */
1248 KSDDKAPI
1249 BOOLEAN
1250 NTAPI
KsDispatchFastIoDeviceControlFailure(IN PFILE_OBJECT FileObject,IN BOOLEAN Wait,IN PVOID InputBuffer OPTIONAL,IN ULONG InputBufferLength,OUT PVOID OutputBuffer OPTIONAL,IN ULONG OutputBufferLength,IN ULONG IoControlCode,OUT PIO_STATUS_BLOCK IoStatus,IN PDEVICE_OBJECT DeviceObject)1251 KsDispatchFastIoDeviceControlFailure(
1252     IN  PFILE_OBJECT FileObject,
1253     IN  BOOLEAN Wait,
1254     IN  PVOID InputBuffer  OPTIONAL,
1255     IN  ULONG InputBufferLength,
1256     OUT PVOID OutputBuffer  OPTIONAL,
1257     IN  ULONG OutputBufferLength,
1258     IN  ULONG IoControlCode,
1259     OUT PIO_STATUS_BLOCK IoStatus,
1260     IN  PDEVICE_OBJECT DeviceObject)
1261 {
1262     return FALSE;
1263 }
1264 
1265 /*
1266     @implemented
1267 */
1268 KSDDKAPI
1269 BOOLEAN
1270 NTAPI
KsDispatchFastReadFailure(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Wait,IN ULONG LockKey,OUT PVOID Buffer,OUT PIO_STATUS_BLOCK IoStatus,IN PDEVICE_OBJECT DeviceObject)1271 KsDispatchFastReadFailure(
1272     IN  PFILE_OBJECT FileObject,
1273     IN  PLARGE_INTEGER FileOffset,
1274     IN  ULONG Length,
1275     IN  BOOLEAN Wait,
1276     IN  ULONG LockKey,
1277     OUT PVOID Buffer,
1278     OUT PIO_STATUS_BLOCK IoStatus,
1279     IN  PDEVICE_OBJECT DeviceObject)
1280 {
1281     return FALSE;
1282 }
1283 
1284 
1285 /*
1286     @implemented
1287 */
1288 KSDDKAPI
1289 VOID
1290 NTAPI
KsCancelIo(IN OUT PLIST_ENTRY QueueHead,IN PKSPIN_LOCK SpinLock)1291 KsCancelIo(
1292     IN  OUT PLIST_ENTRY QueueHead,
1293     IN  PKSPIN_LOCK SpinLock)
1294 {
1295     PDRIVER_CANCEL OldDriverCancel;
1296     PIO_STACK_LOCATION IoStack;
1297     PLIST_ENTRY Entry;
1298     PLIST_ENTRY NextEntry;
1299     PIRP Irp;
1300     KIRQL OldLevel;
1301 
1302     /* acquire spinlock */
1303     KeAcquireSpinLock(SpinLock, &OldLevel);
1304     /* point to first entry */
1305     Entry = QueueHead->Flink;
1306     /* loop all items */
1307     while(Entry != QueueHead)
1308     {
1309         /* get irp offset */
1310         Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
1311 
1312         /* get next entry */
1313         NextEntry = Entry->Flink;
1314 
1315         /* set cancelled bit */
1316         Irp->Cancel = TRUE;
1317 
1318         /* now set the cancel routine */
1319         OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
1320         if (OldDriverCancel)
1321         {
1322             /* this irp hasnt been yet used, so free to cancel */
1323             KeReleaseSpinLock(SpinLock, OldLevel);
1324 
1325             /* get current irp stack */
1326             IoStack = IoGetCurrentIrpStackLocation(Irp);
1327 
1328             /* acquire cancel spinlock */
1329             IoAcquireCancelSpinLock(&Irp->CancelIrql);
1330 
1331             /* call provided cancel routine */
1332             OldDriverCancel(IoStack->DeviceObject, Irp);
1333 
1334             /* re-acquire spinlock */
1335             KeAcquireSpinLock(SpinLock, &OldLevel);
1336         }
1337 
1338         /* move on to next entry */
1339         Entry = NextEntry;
1340     }
1341 
1342     /* the irp has already been canceled */
1343     KeReleaseSpinLock(SpinLock, OldLevel);
1344 
1345 }
1346 
1347 /*
1348     @implemented
1349 */
1350 KSDDKAPI
1351 VOID
1352 NTAPI
KsReleaseIrpOnCancelableQueue(IN PIRP Irp,IN PDRIVER_CANCEL DriverCancel OPTIONAL)1353 KsReleaseIrpOnCancelableQueue(
1354     IN  PIRP Irp,
1355     IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
1356 {
1357     PKSPIN_LOCK SpinLock;
1358     PDRIVER_CANCEL OldDriverCancel;
1359     PIO_STACK_LOCATION IoStack;
1360     KIRQL OldLevel;
1361 
1362     /* check for required parameters */
1363     if (!Irp)
1364         return;
1365 
1366     if (!DriverCancel)
1367     {
1368         /* default to KsCancelRoutine */
1369         DriverCancel = KsCancelRoutine;
1370     }
1371 
1372     /* get current irp stack */
1373     IoStack = IoGetCurrentIrpStackLocation(Irp);
1374 
1375     /* get internal queue lock */
1376     SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1377 
1378     /* acquire spinlock */
1379     KeAcquireSpinLock(SpinLock, &OldLevel);
1380 
1381     /* now set the cancel routine */
1382     OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1383 
1384     if (Irp->Cancel && OldDriverCancel == NULL)
1385     {
1386         /* the irp has already been canceled */
1387         KeReleaseSpinLock(SpinLock, OldLevel);
1388 
1389         /* cancel routine requires that cancel spinlock is held */
1390         IoAcquireCancelSpinLock(&Irp->CancelIrql);
1391 
1392         /* cancel irp */
1393         DriverCancel(IoStack->DeviceObject, Irp);
1394     }
1395     else
1396     {
1397         /* done */
1398         KeReleaseSpinLock(SpinLock, OldLevel);
1399     }
1400 }
1401 
1402 /*
1403     @implemented
1404 */
1405 KSDDKAPI
1406 PIRP
1407 NTAPI
KsRemoveIrpFromCancelableQueue(IN OUT PLIST_ENTRY QueueHead,IN PKSPIN_LOCK SpinLock,IN KSLIST_ENTRY_LOCATION ListLocation,IN KSIRP_REMOVAL_OPERATION RemovalOperation)1408 KsRemoveIrpFromCancelableQueue(
1409     IN  OUT PLIST_ENTRY QueueHead,
1410     IN  PKSPIN_LOCK SpinLock,
1411     IN  KSLIST_ENTRY_LOCATION ListLocation,
1412     IN  KSIRP_REMOVAL_OPERATION RemovalOperation)
1413 {
1414     PIRP Irp;
1415     PLIST_ENTRY CurEntry;
1416     KIRQL OldIrql;
1417 
1418     DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
1419 
1420     /* check parameters */
1421     if (!QueueHead || !SpinLock)
1422         return NULL;
1423 
1424     /* check if parameter ListLocation is valid */
1425     if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead)
1426         return NULL;
1427 
1428     /* acquire list lock */
1429     KeAcquireSpinLock(SpinLock, &OldIrql);
1430 
1431     /* point to queue head */
1432     CurEntry = QueueHead;
1433 
1434     do
1435     {
1436         /* reset irp to null */
1437         Irp = NULL;
1438 
1439         /* iterate to next entry */
1440         if (ListLocation == KsListEntryHead)
1441             CurEntry = CurEntry->Flink;
1442         else
1443             CurEntry = CurEntry->Blink;
1444 
1445         /* is the end of list reached */
1446         if (CurEntry == QueueHead)
1447         {
1448             /* reached end of list */
1449             break;
1450         }
1451 
1452         /* get irp offset */
1453         Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1454 
1455         if (Irp->Cancel)
1456         {
1457             /* irp has been canceled */
1458             break;
1459         }
1460 
1461         if (Irp->CancelRoutine)
1462         {
1463             /* remove cancel routine */
1464             Irp->CancelRoutine = NULL;
1465 
1466             if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1467             {
1468                 /* remove irp from list */
1469                 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1470             }
1471 
1472             if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem)
1473                 break;
1474         }
1475 
1476     }while(TRUE);
1477 
1478     /* release lock */
1479     KeReleaseSpinLock(SpinLock, OldIrql);
1480 
1481     if (!Irp || Irp->CancelRoutine == NULL)
1482     {
1483         /* either an irp has been acquired or nothing found */
1484         return Irp;
1485     }
1486 
1487     /* time to remove the canceled irp */
1488     IoAcquireCancelSpinLock(&OldIrql);
1489     /* acquire list lock */
1490     KeAcquireSpinLockAtDpcLevel(SpinLock);
1491 
1492     if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1493     {
1494         /* remove it */
1495         RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1496     }
1497 
1498     /* release list lock */
1499     KeReleaseSpinLockFromDpcLevel(SpinLock);
1500 
1501     /* release cancel spinlock */
1502     IoReleaseCancelSpinLock(OldIrql);
1503     /* no non canceled irp has been found */
1504     return NULL;
1505 }
1506 
1507 /*
1508     @implemented
1509 */
1510 KSDDKAPI
1511 NTSTATUS
1512 NTAPI
KsMoveIrpsOnCancelableQueue(IN OUT PLIST_ENTRY SourceList,IN PKSPIN_LOCK SourceLock,IN OUT PLIST_ENTRY DestinationList,IN PKSPIN_LOCK DestinationLock OPTIONAL,IN KSLIST_ENTRY_LOCATION ListLocation,IN PFNKSIRPLISTCALLBACK ListCallback,IN PVOID Context)1513 KsMoveIrpsOnCancelableQueue(
1514     IN  OUT PLIST_ENTRY SourceList,
1515     IN  PKSPIN_LOCK SourceLock,
1516     IN  OUT PLIST_ENTRY DestinationList,
1517     IN  PKSPIN_LOCK DestinationLock OPTIONAL,
1518     IN  KSLIST_ENTRY_LOCATION ListLocation,
1519     IN  PFNKSIRPLISTCALLBACK ListCallback,
1520     IN  PVOID Context)
1521 {
1522     KIRQL OldLevel;
1523     PLIST_ENTRY SrcEntry;
1524     PIRP Irp;
1525     NTSTATUS Status = STATUS_SUCCESS;
1526 
1527     if (!DestinationLock)
1528     {
1529         /* no destination lock just acquire the source lock */
1530         KeAcquireSpinLock(SourceLock, &OldLevel);
1531     }
1532     else
1533     {
1534         /* acquire cancel spinlock */
1535         IoAcquireCancelSpinLock(&OldLevel);
1536 
1537         /* now acquire source lock */
1538         KeAcquireSpinLockAtDpcLevel(SourceLock);
1539 
1540         /* now acquire destination lock */
1541         KeAcquireSpinLockAtDpcLevel(DestinationLock);
1542     }
1543 
1544     /* point to list head */
1545     SrcEntry = SourceList;
1546 
1547     /* now move all irps */
1548     while(TRUE)
1549     {
1550         if (ListLocation == KsListEntryTail)
1551         {
1552             /* move queue downwards */
1553             SrcEntry = SrcEntry->Flink;
1554         }
1555         else
1556         {
1557             /* move queue upwards */
1558             SrcEntry = SrcEntry->Blink;
1559         }
1560 
1561         if (SrcEntry == SourceList)
1562         {
1563             /* eof list reached */
1564             break;
1565         }
1566 
1567         /* get irp offset */
1568         Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
1569 
1570         /* now check if irp can be moved */
1571         Status = ListCallback(Irp, Context);
1572 
1573         /* check if irp can be moved */
1574         if (Status == STATUS_SUCCESS)
1575         {
1576             /* remove irp from src list */
1577             RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1578 
1579             if (ListLocation == KsListEntryTail)
1580             {
1581                 /* insert irp end of list */
1582                 InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1583             }
1584             else
1585             {
1586                 /* insert irp head of list */
1587                 InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1588             }
1589 
1590             /* do we need to update the irp lock */
1591             if (DestinationLock)
1592             {
1593                 /* update irp lock */
1594                 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
1595             }
1596         }
1597         else
1598         {
1599             if (Status != STATUS_NO_MATCH)
1600             {
1601                 /* callback decided to stop enumeration */
1602                 break;
1603             }
1604 
1605             /* reset return value */
1606             Status = STATUS_SUCCESS;
1607         }
1608     }
1609 
1610     if (!DestinationLock)
1611     {
1612         /* release source lock */
1613         KeReleaseSpinLock(SourceLock, OldLevel);
1614     }
1615     else
1616     {
1617         /* now release destination lock */
1618         KeReleaseSpinLockFromDpcLevel(DestinationLock);
1619 
1620         /* now release source lock */
1621         KeReleaseSpinLockFromDpcLevel(SourceLock);
1622 
1623 
1624         /* now release cancel spinlock */
1625         IoReleaseCancelSpinLock(OldLevel);
1626     }
1627 
1628     /* done */
1629     return Status;
1630 }
1631 
1632 /*
1633     @implemented
1634 */
1635 KSDDKAPI
1636 VOID
1637 NTAPI
KsRemoveSpecificIrpFromCancelableQueue(IN PIRP Irp)1638 KsRemoveSpecificIrpFromCancelableQueue(
1639     IN  PIRP Irp)
1640 {
1641     PKSPIN_LOCK SpinLock;
1642     KIRQL OldLevel;
1643 
1644     DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp);
1645 
1646     /* get internal queue lock */
1647     SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1648 
1649     /* acquire spinlock */
1650     KeAcquireSpinLock(SpinLock, &OldLevel);
1651 
1652     /* remove the irp from the list */
1653     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1654 
1655     /* release spinlock */
1656     KeReleaseSpinLock(SpinLock, OldLevel);
1657 }
1658 
1659 
1660 /*
1661     @implemented
1662 */
1663 KSDDKAPI
1664 VOID
1665 NTAPI
KsAddIrpToCancelableQueue(IN OUT PLIST_ENTRY QueueHead,IN PKSPIN_LOCK SpinLock,IN PIRP Irp,IN KSLIST_ENTRY_LOCATION ListLocation,IN PDRIVER_CANCEL DriverCancel OPTIONAL)1666 KsAddIrpToCancelableQueue(
1667     IN  OUT PLIST_ENTRY QueueHead,
1668     IN  PKSPIN_LOCK SpinLock,
1669     IN  PIRP Irp,
1670     IN  KSLIST_ENTRY_LOCATION ListLocation,
1671     IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
1672 {
1673     PDRIVER_CANCEL OldDriverCancel;
1674     PIO_STACK_LOCATION IoStack;
1675     KIRQL OldLevel;
1676 
1677     /* check for required parameters */
1678     if (!QueueHead || !SpinLock || !Irp)
1679         return;
1680 
1681     /* get current irp stack */
1682     IoStack = IoGetCurrentIrpStackLocation(Irp);
1683 
1684     DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
1685 
1686     // HACK for ms portcls
1687     if (IoStack->MajorFunction == IRP_MJ_CREATE)
1688     {
1689         // complete the request
1690         DPRINT1("MS HACK\n");
1691         Irp->IoStatus.Status = STATUS_SUCCESS;
1692         CompleteRequest(Irp, IO_NO_INCREMENT);
1693 
1694         return;
1695     }
1696 
1697 
1698     if (!DriverCancel)
1699     {
1700         /* default to KsCancelRoutine */
1701         DriverCancel = KsCancelRoutine;
1702     }
1703 
1704 
1705     /* acquire spinlock */
1706     KeAcquireSpinLock(SpinLock, &OldLevel);
1707 
1708     if (ListLocation == KsListEntryTail)
1709     {
1710         /* insert irp to tail of list */
1711         InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1712     }
1713     else
1714     {
1715         /* insert irp to head of list */
1716         InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1717     }
1718 
1719     /* store internal queue lock */
1720     KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
1721 
1722     /* now set the cancel routine */
1723     OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1724 
1725     if (Irp->Cancel && OldDriverCancel == NULL)
1726     {
1727         /* the irp has already been canceled */
1728         KeReleaseSpinLock(SpinLock, OldLevel);
1729 
1730         /* cancel routine requires that cancel spinlock is held */
1731         IoAcquireCancelSpinLock(&Irp->CancelIrql);
1732 
1733         /* cancel irp */
1734         DriverCancel(IoStack->DeviceObject, Irp);
1735     }
1736     else
1737     {
1738         /* done */
1739         KeReleaseSpinLock(SpinLock, OldLevel);
1740     }
1741 }
1742 
1743 /*
1744     @implemented
1745 */
1746 KSDDKAPI
1747 VOID
1748 NTAPI
KsCancelRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1749 KsCancelRoutine(
1750     IN  PDEVICE_OBJECT DeviceObject,
1751     IN  PIRP Irp)
1752 {
1753     PKSPIN_LOCK SpinLock;
1754 
1755     /* get internal queue lock */
1756     SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1757 
1758     /* acquire spinlock */
1759     KeAcquireSpinLockAtDpcLevel(SpinLock);
1760 
1761     /* sanity check */
1762     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1763 
1764     /* release cancel spinlock */
1765     IoReleaseCancelSpinLock(Irp->CancelIrql);
1766 
1767     /* remove the irp from the list */
1768     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1769 
1770     /* release spinlock */
1771     KeReleaseSpinLock(SpinLock, Irp->CancelIrql);
1772 
1773     /* has the irp already been canceled */
1774     if (Irp->IoStatus.Status != STATUS_CANCELLED)
1775     {
1776         /* let's complete it */
1777         Irp->IoStatus.Status = STATUS_CANCELLED;
1778         CompleteRequest(Irp, IO_NO_INCREMENT);
1779     }
1780 }
1781 
1782 NTSTATUS
FindMatchingCreateItem(PLIST_ENTRY ListHead,PUNICODE_STRING String,OUT PCREATE_ITEM_ENTRY * OutCreateItem)1783 FindMatchingCreateItem(
1784     PLIST_ENTRY ListHead,
1785     PUNICODE_STRING String,
1786     OUT PCREATE_ITEM_ENTRY *OutCreateItem)
1787 {
1788     PLIST_ENTRY Entry;
1789     PCREATE_ITEM_ENTRY CreateItemEntry;
1790     UNICODE_STRING RefString;
1791     LPWSTR pStr;
1792     ULONG Count;
1793 
1794     /* Copy the input string */
1795     RefString = *String;
1796 
1797     /* Check if the string starts with a backslash */
1798     if (String->Buffer[0] == L'\\')
1799     {
1800         /* Skip backslash */
1801         RefString.Buffer++;
1802         RefString.Length -= sizeof(WCHAR);
1803     }
1804     else
1805     {
1806         /* get terminator */
1807         pStr = String->Buffer;
1808         Count = String->Length / sizeof(WCHAR);
1809         while ((Count > 0) && (*pStr != L'\\'))
1810         {
1811             pStr++;
1812             Count--;
1813         }
1814 
1815         /* sanity check */
1816         ASSERT(Count != 0);
1817 
1818         // request is for pin / node / allocator
1819         RefString.Length = (USHORT)((PCHAR)pStr - (PCHAR)String->Buffer);
1820     }
1821 
1822     /* point to first entry */
1823     Entry = ListHead->Flink;
1824 
1825     /* loop all device items */
1826     while (Entry != ListHead)
1827     {
1828         /* get create item entry */
1829         CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry,
1830                                                                 CREATE_ITEM_ENTRY,
1831                                                                 Entry);
1832 
1833         ASSERT(CreateItemEntry->CreateItem);
1834 
1835         if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
1836         {
1837             /* create item is default */
1838             *OutCreateItem = CreateItemEntry;
1839             return STATUS_SUCCESS;
1840         }
1841 
1842         if (!CreateItemEntry->CreateItem->Create)
1843         {
1844             /* skip free create item */
1845             Entry = Entry->Flink;
1846             continue;
1847         }
1848 
1849         DPRINT("CreateItem %S Length %u Request %wZ %u\n",
1850                CreateItemEntry->CreateItem->ObjectClass.Buffer,
1851                CreateItemEntry->CreateItem->ObjectClass.Length,
1852                &RefString,
1853                RefString.Length);
1854 
1855         if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length)
1856         {
1857             /* create item doesnt match in length */
1858             Entry = Entry->Flink;
1859             continue;
1860         }
1861 
1862          /* now check if the object class is the same */
1863         if (!RtlCompareUnicodeString(&CreateItemEntry->CreateItem->ObjectClass,
1864                                      &RefString,
1865                                      TRUE))
1866         {
1867             /* found matching create item */
1868             *OutCreateItem = CreateItemEntry;
1869             return STATUS_SUCCESS;
1870         }
1871         /* iterate to next */
1872         Entry = Entry->Flink;
1873     }
1874 
1875     return STATUS_NOT_FOUND;
1876 }
1877 
1878 NTSTATUS
1879 NTAPI
KspCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1880 KspCreate(
1881     IN  PDEVICE_OBJECT DeviceObject,
1882     IN  PIRP Irp)
1883 {
1884     PCREATE_ITEM_ENTRY CreateItemEntry;
1885     PIO_STACK_LOCATION IoStack;
1886     PDEVICE_EXTENSION DeviceExtension;
1887     PKSIDEVICE_HEADER DeviceHeader;
1888     PKSIOBJECT_HEADER ObjectHeader;
1889     NTSTATUS Status;
1890 
1891     DPRINT("KS / CREATE\n");
1892 
1893     /* get current stack location */
1894     IoStack = IoGetCurrentIrpStackLocation(Irp);
1895     /* get device extension */
1896     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1897     /* get device header */
1898     DeviceHeader = DeviceExtension->DeviceHeader;
1899 
1900 
1901     if (IoStack->FileObject->FileName.Buffer == NULL)
1902     {
1903         /* FIXME Pnp-Issue */
1904         DPRINT("Using reference string hack\n");
1905         Irp->IoStatus.Information = 0;
1906         /* set return status */
1907         Irp->IoStatus.Status = STATUS_SUCCESS;
1908         CompleteRequest(Irp, IO_NO_INCREMENT);
1909         return STATUS_SUCCESS;
1910     }
1911 
1912     if (IoStack->FileObject->RelatedFileObject != NULL)
1913     {
1914         /* request is to instantiate a pin / node / clock / allocator */
1915         ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
1916 
1917         /* sanity check */
1918         ASSERT(ObjectHeader);
1919 
1920         /* find a matching a create item */
1921         Status = FindMatchingCreateItem(&ObjectHeader->ItemList,
1922                                         &IoStack->FileObject->FileName,
1923                                         &CreateItemEntry);
1924     }
1925     else
1926     {
1927         /* request to create a filter */
1928         Status = FindMatchingCreateItem(&DeviceHeader->ItemList,
1929                                         &IoStack->FileObject->FileName,
1930                                         &CreateItemEntry);
1931     }
1932 
1933     if (NT_SUCCESS(Status))
1934     {
1935         /* set object create item */
1936         KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1937 
1938         /* call create function */
1939         Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1940 
1941         if (NT_SUCCESS(Status))
1942         {
1943             /* increment create item reference count */
1944             InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1945         }
1946         return Status;
1947     }
1948 
1949     Irp->IoStatus.Information = 0;
1950     /* set return status */
1951     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1952     CompleteRequest(Irp, IO_NO_INCREMENT);
1953     return STATUS_UNSUCCESSFUL;
1954 }
1955 
1956 NTSTATUS
1957 NTAPI
KspDispatchIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1958 KspDispatchIrp(
1959     IN  PDEVICE_OBJECT DeviceObject,
1960     IN  PIRP Irp)
1961 {
1962     PIO_STACK_LOCATION IoStack;
1963     //PDEVICE_EXTENSION DeviceExtension;
1964     PKSIOBJECT_HEADER ObjectHeader;
1965     //PKSIDEVICE_HEADER DeviceHeader;
1966     PDRIVER_DISPATCH Dispatch;
1967     NTSTATUS Status;
1968 
1969     /* get current stack location */
1970     IoStack = IoGetCurrentIrpStackLocation(Irp);
1971 
1972     /* get device extension */
1973     //DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1974     /* get device header */
1975     //DeviceHeader = DeviceExtension->DeviceHeader;
1976 
1977     ASSERT(IoStack->FileObject);
1978 
1979     /* get object header */
1980     ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2;
1981 
1982     if (!ObjectHeader)
1983     {
1984         /* FIXME Pnp-Issue*/
1985         Irp->IoStatus.Status = STATUS_SUCCESS;
1986         Irp->IoStatus.Information = 0;
1987         /* complete and forget */
1988         CompleteRequest(Irp, IO_NO_INCREMENT);
1989         return STATUS_SUCCESS;
1990     }
1991 
1992     /* sanity check */
1993     ASSERT(ObjectHeader);
1994     /* store create item */
1995     //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1996 
1997     /* retrieve matching dispatch function */
1998     switch(IoStack->MajorFunction)
1999     {
2000         case IRP_MJ_CLOSE:
2001             Dispatch = ObjectHeader->DispatchTable.Close;
2002             break;
2003         case IRP_MJ_DEVICE_CONTROL:
2004             Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
2005             break;
2006         case IRP_MJ_READ:
2007             Dispatch = ObjectHeader->DispatchTable.Read;
2008             break;
2009         case IRP_MJ_WRITE:
2010             Dispatch = ObjectHeader->DispatchTable.Write;
2011             break;
2012         case IRP_MJ_FLUSH_BUFFERS :
2013             Dispatch = ObjectHeader->DispatchTable.Flush;
2014             break;
2015         case IRP_MJ_QUERY_SECURITY:
2016             Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
2017             break;
2018         case IRP_MJ_SET_SECURITY:
2019             Dispatch = ObjectHeader->DispatchTable.SetSecurity;
2020             break;
2021         case IRP_MJ_PNP:
2022             Dispatch = KsDefaultDispatchPnp;
2023             break;
2024         default:
2025             Dispatch = NULL;
2026     }
2027 
2028     /* is the request supported */
2029     if (Dispatch)
2030     {
2031         /* now call the dispatch function */
2032         Status = Dispatch(DeviceObject, Irp);
2033     }
2034     else
2035     {
2036         /* not supported request */
2037         Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2038     }
2039 
2040     /* done */
2041     return Status;
2042 }
2043 
2044 /*
2045     @implemented
2046 */
2047 KSDDKAPI
2048 NTSTATUS
2049 NTAPI
KsSetMajorFunctionHandler(IN PDRIVER_OBJECT DriverObject,IN ULONG MajorFunction)2050 KsSetMajorFunctionHandler(
2051     IN  PDRIVER_OBJECT DriverObject,
2052     IN  ULONG MajorFunction)
2053 {
2054     DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
2055 
2056     switch ( MajorFunction )
2057     {
2058         case IRP_MJ_CREATE:
2059             DriverObject->MajorFunction[MajorFunction] = KspCreate;
2060             break;
2061         case IRP_MJ_DEVICE_CONTROL:
2062         case IRP_MJ_CLOSE:
2063         case IRP_MJ_READ:
2064         case IRP_MJ_WRITE:
2065         case IRP_MJ_FLUSH_BUFFERS :
2066         case IRP_MJ_QUERY_SECURITY:
2067         case IRP_MJ_SET_SECURITY:
2068             DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
2069             break;
2070         default:
2071             DPRINT1("NotSupported %x\n", MajorFunction);
2072             return STATUS_INVALID_PARAMETER;
2073     };
2074 
2075     return STATUS_SUCCESS;
2076 }
2077 
2078 /*
2079     @implemented
2080 */
2081 KSDDKAPI
2082 NTSTATUS
2083 NTAPI
KsDispatchIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)2084 KsDispatchIrp(
2085     IN  PDEVICE_OBJECT DeviceObject,
2086     IN  PIRP Irp)
2087 {
2088     PIO_STACK_LOCATION IoStack;
2089     PKSIDEVICE_HEADER DeviceHeader;
2090     PDEVICE_EXTENSION DeviceExtension;
2091 
2092     DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
2093 
2094     /* get device extension */
2095     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
2096 
2097     /* get device header */
2098     DeviceHeader = DeviceExtension->DeviceHeader;
2099 
2100 
2101     /* get current irp stack */
2102     IoStack = IoGetCurrentIrpStackLocation(Irp);
2103 
2104     if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
2105     {
2106         if (IoStack->MajorFunction == IRP_MJ_CREATE)
2107         {
2108             /* check internal type */
2109             if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
2110             {
2111                 /* AVStream client */
2112                 return IKsDevice_Create(DeviceObject, Irp);
2113             }
2114             else
2115             {
2116                 /* external client (portcls) */
2117                 return KspCreate(DeviceObject, Irp);
2118             }
2119         }
2120 
2121         switch (IoStack->MajorFunction)
2122         {
2123             case IRP_MJ_CLOSE:
2124             case IRP_MJ_READ:
2125             case IRP_MJ_WRITE:
2126             case IRP_MJ_FLUSH_BUFFERS:
2127             case IRP_MJ_QUERY_SECURITY:
2128             case IRP_MJ_SET_SECURITY:
2129             case IRP_MJ_PNP:
2130             case IRP_MJ_DEVICE_CONTROL:
2131                 return KspDispatchIrp(DeviceObject, Irp);
2132             default:
2133                 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2134         }
2135     }
2136 
2137     /* dispatch power */
2138     if (IoStack->MajorFunction == IRP_MJ_POWER)
2139     {
2140         /* check internal type */
2141         if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
2142         {
2143             /* AVStream client */
2144             return IKsDevice_Power(DeviceObject, Irp);
2145         }
2146         else
2147         {
2148             /* external client (portcls) */
2149             return KsDefaultDispatchPower(DeviceObject, Irp);
2150         }
2151     }
2152     else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
2153     {
2154         /* check internal type */
2155         if (DeviceHeader->BasicHeader.OuterUnknown) /* FIXME improve check */
2156         {
2157             /* AVStream client */
2158             return IKsDevice_Pnp(DeviceObject, Irp);
2159         }
2160         else
2161         {
2162             /* external client (portcls) */
2163             return KsDefaultDispatchPnp(DeviceObject, Irp);
2164         }
2165     }
2166     else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
2167     {
2168         /* forward irp */
2169         return KsDefaultForwardIrp(DeviceObject, Irp);
2170     }
2171     else
2172     {
2173         /* not supported */
2174         return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2175     }
2176 }
2177 
2178 /*
2179     @unimplemented
2180 */
2181 KSDDKAPI
2182 ULONG
2183 NTAPI
KsGetNodeIdFromIrp(IN PIRP Irp)2184 KsGetNodeIdFromIrp(
2185     IN PIRP Irp)
2186 {
2187     UNIMPLEMENTED;
2188     return KSFILTER_NODE;
2189 }
2190 
2191