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