a874abce4d0df2eb568f4835f52fd96413cdc5e9
[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->FsContext2;
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 @implemented
639 */
640 KSDDKAPI
641 NTSTATUS
642 NTAPI
643 KsProbeStreamIrp(
644 IN PIRP Irp,
645 IN ULONG ProbeFlags,
646 IN ULONG HeaderSize)
647 {
648 PMDL Mdl;
649 PVOID Buffer;
650 LOCK_OPERATION Operation;
651 NTSTATUS Status = STATUS_SUCCESS;
652 PKSSTREAM_HEADER StreamHeader;
653 PIO_STACK_LOCATION IoStack;
654 ULONG Length;
655 BOOLEAN AllocateMdl = FALSE;
656
657 /* get current irp stack */
658 IoStack = IoGetCurrentIrpStackLocation(Irp);
659
660 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
661
662 if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer)
663 {
664 AllocMdl:
665 /* check if alloc mdl flag is passed */
666 if (!(ProbeFlags & KSPROBE_ALLOCATEMDL))
667 {
668 /* nothing more to do */
669 return STATUS_SUCCESS;
670 }
671 if (Irp->MdlAddress)
672 {
673 ProbeMdl:
674 if (ProbeFlags & KSPROBE_PROBEANDLOCK)
675 {
676 if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL))
677 {
678 if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
679 {
680 _SEH2_TRY
681 {
682 /* loop through all mdls and probe them */
683 Mdl = Irp->MdlAddress;
684 do
685 {
686 /* the mapping can fail */
687 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
688
689 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
690 {
691 /* no need to probe these pages */
692 Buffer = Mdl->MappedSystemVa;
693 }
694 else
695 {
696 /* probe that mdl */
697 Buffer = MmMapLockedPages(Mdl, KernelMode);
698 }
699
700 /* check if the mapping succeeded */
701 if (!Buffer)
702 {
703 /* raise exception we'll catch */
704 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
705 }
706
707 /* iterate to next mdl */
708 Mdl = Mdl->Next;
709
710 }while(Mdl);
711 }
712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
713 {
714 /* Exception, get the error code */
715 Status = _SEH2_GetExceptionCode();
716 } _SEH2_END;
717 }
718 }
719 else
720 {
721 _SEH2_TRY
722 {
723 /* loop through all mdls and probe them */
724 Mdl = Irp->MdlAddress;
725
726 /* determine operation */
727 Operation = (ProbeFlags & KSPROBE_STREAMWRITE) ? IoWriteAccess : IoReadAccess;
728
729 do
730 {
731 /* probe the pages */
732 MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
733
734 if (ProbeFlags & KSPROBE_SYSTEMADDRESS)
735 {
736 /* the mapping can fail */
737 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
738
739 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
740 {
741 /* no need to probe these pages */
742 Buffer = Mdl->MappedSystemVa;
743 }
744 else
745 {
746 /* probe that mdl */
747 Buffer = MmMapLockedPages(Mdl, KernelMode);
748 }
749
750 /* check if the mapping succeeded */
751 if (!Buffer)
752 {
753 /* raise exception we'll catch */
754 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
755 }
756 }
757
758 /* iterate to next mdl */
759 Mdl = Mdl->Next;
760
761 }while(Mdl);
762 }
763 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
764 {
765 /* Exception, get the error code */
766 Status = _SEH2_GetExceptionCode();
767 } _SEH2_END;
768 }
769 }
770 return Status;
771 }
772
773 /* check all stream headers */
774 StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
775 ASSERT(StreamHeader);
776 _SEH2_TRY
777 {
778 do
779 {
780 if (HeaderSize)
781 {
782 /* does the supplied header size match stream header size and no type changed */
783 if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
784 {
785 /* invalid stream header */
786 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
787 }
788 }
789 else
790 {
791 /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
792 if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
793 {
794 /* invalid stream header */
795 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
796 }
797 }
798
799 if (Length < StreamHeader->Size)
800 {
801 /* length is too short */
802 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
803 }
804
805 if (ProbeFlags & KSPROBE_STREAMWRITE)
806 {
807 if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
808 {
809 /* frame extend can never be smaller */
810 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
811 }
812
813 /* is this stream change packet */
814 if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
815 {
816 if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
817 {
818 /* stream changed - must be send in a single packet */
819 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
820 }
821
822 if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
823 {
824 /* caller does not permit format changes */
825 ExRaiseStatus(STATUS_INVALID_PARAMETER);
826 }
827
828 if (StreamHeader->FrameExtent)
829 {
830 /* allocate an mdl */
831 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
832
833 if (!Mdl)
834 {
835 /* not enough memory */
836 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
837 }
838
839 /* break-out to probe for the irp */
840 break;
841 }
842 }
843 }
844 else
845 {
846 if (StreamHeader->DataUsed)
847 {
848 /* DataUsed must be zero for stream read operation */
849 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
850 }
851
852 if (StreamHeader->OptionsFlags)
853 {
854 /* no flags supported for reading */
855 ExRaiseStatus(STATUS_INVALID_PARAMETER);
856 }
857 }
858
859 if (StreamHeader->FrameExtent)
860 {
861 /* allocate an mdl */
862 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, Irp->MdlAddress != NULL, TRUE, Irp);
863 if (!Mdl)
864 {
865 /* not enough memory */
866 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
867 }
868 }
869
870 /* move to next stream header */
871 Length -= StreamHeader->Size;
872 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
873 }while(Length);
874 }
875 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
876 {
877 /* Exception, get the error code */
878 Status = _SEH2_GetExceptionCode();
879 }_SEH2_END;
880
881 /* now probe the allocated mdl's */
882 if (!NT_SUCCESS(Status))
883 {
884 DPRINT("Status %x\n", Status);
885 return Status;
886 }
887 else
888 goto ProbeMdl;
889 }
890
891 /* probe user mode buffers */
892 if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
893 {
894 /* allocate stream header buffer */
895 Irp->AssociatedIrp.SystemBuffer = ExAllocatePool(NonPagedPool, Length);
896
897 if (!Irp->AssociatedIrp.SystemBuffer)
898 {
899 /* no memory */
900 return STATUS_INSUFFICIENT_RESOURCES;
901 }
902
903 _SEH2_TRY
904 {
905 if (ProbeFlags & KSPROBE_STREAMWRITE)
906 {
907 if (ProbeFlags & KSPROBE_MODIFY)
908 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
909 else
910 ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR));
911 }
912 else
913 {
914 /* stream reads means writing */
915 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
916 }
917
918 /* copy stream buffer */
919 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length);
920 }
921 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
922 {
923 /* Exception, get the error code */
924 Status = _SEH2_GetExceptionCode();
925 }_SEH2_END;
926
927 if (!NT_SUCCESS(Status))
928 {
929 /* failed */
930 return Status;
931 }
932
933 if (ProbeFlags & KSPROBE_ALLOCATEMDL)
934 {
935 /* alloc mdls */
936 goto AllocMdl;
937 }
938
939 /* check all stream headers */
940 StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
941
942 _SEH2_TRY
943 {
944 do
945 {
946 if (HeaderSize)
947 {
948 /* does the supplied header size match stream header size and no type changed */
949 if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
950 {
951 /* invalid stream header */
952 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
953 }
954 }
955 else
956 {
957 /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
958 if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
959 {
960 /* invalid stream header */
961 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
962 }
963 }
964
965 if (Length < StreamHeader->Size)
966 {
967 /* length is too short */
968 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
969 }
970
971 if (ProbeFlags & KSPROBE_STREAMWRITE)
972 {
973 if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
974 {
975 /* frame extend can never be smaller */
976 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
977 }
978
979 /* is this stream change packet */
980 if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
981 {
982 if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
983 {
984 /* stream changed - must be send in a single packet */
985 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
986 }
987
988 if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
989 {
990 /* caller does not permit format changes */
991 ExRaiseStatus(STATUS_INVALID_PARAMETER);
992 }
993
994 if (StreamHeader->FrameExtent)
995 {
996 /* allocate an mdl */
997 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
998
999 if (!Mdl)
1000 {
1001 /* not enough memory */
1002 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
1003 }
1004
1005 /* break out to probe for the irp */
1006 AllocateMdl = TRUE;
1007 break;
1008 }
1009 }
1010 }
1011 else
1012 {
1013 if (StreamHeader->DataUsed)
1014 {
1015 /* DataUsed must be zero for stream read operation */
1016 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1017 }
1018
1019 if (StreamHeader->OptionsFlags)
1020 {
1021 /* no flags supported for reading */
1022 ExRaiseStatus(STATUS_INVALID_PARAMETER);
1023 }
1024 }
1025
1026 /* move to next stream header */
1027 Length -= StreamHeader->Size;
1028 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
1029 }while(Length);
1030
1031 }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1032 {
1033 /* Exception, get the error code */
1034 Status = _SEH2_GetExceptionCode();
1035 }_SEH2_END;
1036
1037 /* now probe the allocated mdl's */
1038 if (NT_SUCCESS(Status))
1039 goto AllocMdl;
1040 else
1041 return Status;
1042 }
1043
1044 return STATUS_INVALID_BUFFER_SIZE;
1045 }
1046
1047 /*
1048 @implemented
1049 */
1050 KSDDKAPI
1051 NTSTATUS
1052 NTAPI
1053 KsAllocateExtraData(
1054 IN PIRP Irp,
1055 IN ULONG ExtraSize,
1056 OUT PVOID* ExtraBuffer)
1057 {
1058 PIO_STACK_LOCATION IoStack;
1059 ULONG Count, Index;
1060 PUCHAR Buffer, BufferOrg;
1061 PKSSTREAM_HEADER Header;
1062 NTSTATUS Status = STATUS_SUCCESS;
1063
1064 /* get current irp stack */
1065 IoStack = IoGetCurrentIrpStackLocation(Irp);
1066
1067 /* sanity check */
1068 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
1069
1070 /* get total length */
1071 Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
1072
1073 /* allocate buffer */
1074 Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
1075 if (!Buffer)
1076 return STATUS_INSUFFICIENT_RESOURCES;
1077
1078 _SEH2_TRY
1079 {
1080 /* get input buffer */
1081 Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1082 for(Index = 0; Index < Count; Index++)
1083 {
1084 /* copy stream header */
1085 RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
1086
1087 /* move to next header */
1088 Header++;
1089 /* increment output buffer offset */
1090 Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
1091 }
1092 }
1093 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1094 {
1095 /* Exception, get the error code */
1096 Status = _SEH2_GetExceptionCode();
1097 }
1098 _SEH2_END;
1099
1100 if (!NT_SUCCESS(Status))
1101 {
1102 /* free buffer on exception */
1103 FreeItem(Buffer);
1104 return Status;
1105 }
1106
1107 /* store result */
1108 *ExtraBuffer = BufferOrg;
1109
1110 /* done */
1111 return STATUS_SUCCESS;
1112 }
1113
1114 /*
1115 @implemented
1116 */
1117 KSDDKAPI
1118 VOID
1119 NTAPI
1120 KsNullDriverUnload(
1121 IN PDRIVER_OBJECT DriverObject)
1122 {
1123 }
1124
1125 /*
1126 @implemented
1127 */
1128 KSDDKAPI
1129 NTSTATUS
1130 NTAPI
1131 KsDispatchInvalidDeviceRequest(
1132 IN PDEVICE_OBJECT DeviceObject,
1133 IN PIRP Irp)
1134 {
1135 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1136 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1137
1138 return STATUS_INVALID_DEVICE_REQUEST;
1139 }
1140
1141 /*
1142 @implemented
1143 */
1144 KSDDKAPI
1145 NTSTATUS
1146 NTAPI
1147 KsDefaultDeviceIoCompletion(
1148 IN PDEVICE_OBJECT DeviceObject,
1149 IN PIRP Irp)
1150 {
1151 PIO_STACK_LOCATION IoStack;
1152 NTSTATUS Status;
1153
1154 /* get current irp stack */
1155 IoStack = IoGetCurrentIrpStackLocation(Irp);
1156
1157 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY &&
1158 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
1159 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
1160 {
1161 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
1162 {
1163 /* fake success */
1164 Status = STATUS_SUCCESS;
1165 }
1166 else
1167 {
1168 /* request unsupported */
1169 Status = STATUS_INVALID_DEVICE_REQUEST;
1170 }
1171 }
1172 else
1173 {
1174 /* property / method / event not found */
1175 Status = STATUS_PROPSET_NOT_FOUND;
1176 }
1177
1178 /* complete request */
1179 Irp->IoStatus.Status = Status;
1180 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1181
1182
1183 return Status;
1184 }
1185
1186 /*
1187 @implemented
1188 */
1189 KSDDKAPI
1190 BOOLEAN
1191 NTAPI
1192 KsDispatchFastIoDeviceControlFailure(
1193 IN PFILE_OBJECT FileObject,
1194 IN BOOLEAN Wait,
1195 IN PVOID InputBuffer OPTIONAL,
1196 IN ULONG InputBufferLength,
1197 OUT PVOID OutputBuffer OPTIONAL,
1198 IN ULONG OutputBufferLength,
1199 IN ULONG IoControlCode,
1200 OUT PIO_STATUS_BLOCK IoStatus,
1201 IN PDEVICE_OBJECT DeviceObject)
1202 {
1203 return FALSE;
1204 }
1205
1206 /*
1207 @implemented
1208 */
1209 KSDDKAPI
1210 BOOLEAN
1211 NTAPI
1212 KsDispatchFastReadFailure(
1213 IN PFILE_OBJECT FileObject,
1214 IN PLARGE_INTEGER FileOffset,
1215 IN ULONG Length,
1216 IN BOOLEAN Wait,
1217 IN ULONG LockKey,
1218 OUT PVOID Buffer,
1219 OUT PIO_STATUS_BLOCK IoStatus,
1220 IN PDEVICE_OBJECT DeviceObject)
1221 {
1222 return FALSE;
1223 }
1224
1225
1226 /*
1227 @implemented
1228 */
1229 KSDDKAPI
1230 VOID
1231 NTAPI
1232 KsCancelIo(
1233 IN OUT PLIST_ENTRY QueueHead,
1234 IN PKSPIN_LOCK SpinLock)
1235 {
1236 PDRIVER_CANCEL OldDriverCancel;
1237 PIO_STACK_LOCATION IoStack;
1238 PLIST_ENTRY Entry;
1239 PIRP Irp;
1240 KIRQL OldLevel;
1241
1242 /* acquire spinlock */
1243 KeAcquireSpinLock(SpinLock, &OldLevel);
1244 /* point to first entry */
1245 Entry = QueueHead->Flink;
1246 /* loop all items */
1247 while(Entry != QueueHead)
1248 {
1249 /* get irp offset */
1250 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
1251
1252 /* set cancelled bit */
1253 Irp->Cancel = TRUE;
1254
1255 /* now set the cancel routine */
1256 OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
1257 if (OldDriverCancel)
1258 {
1259 /* this irp hasnt been yet used, so free to cancel */
1260 KeReleaseSpinLock(SpinLock, OldLevel);
1261
1262 /* get current irp stack */
1263 IoStack = IoGetCurrentIrpStackLocation(Irp);
1264
1265 /* acquire cancel spinlock */
1266 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1267
1268 /* call provided cancel routine */
1269 OldDriverCancel(IoStack->DeviceObject, Irp);
1270
1271 /* re-acquire spinlock */
1272 KeAcquireSpinLock(SpinLock, &OldLevel);
1273 }
1274 /* move on to next entry */
1275 Entry = Entry->Flink;
1276 }
1277
1278 /* the irp has already been canceled */
1279 KeReleaseSpinLock(SpinLock, OldLevel);
1280
1281 }
1282
1283 /*
1284 @implemented
1285 */
1286 KSDDKAPI
1287 VOID
1288 NTAPI
1289 KsReleaseIrpOnCancelableQueue(
1290 IN PIRP Irp,
1291 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1292 {
1293 PKSPIN_LOCK SpinLock;
1294 PDRIVER_CANCEL OldDriverCancel;
1295 PIO_STACK_LOCATION IoStack;
1296 KIRQL OldLevel;
1297
1298 /* check for required parameters */
1299 if (!Irp)
1300 return;
1301
1302 if (!DriverCancel)
1303 {
1304 /* default to KsCancelRoutine */
1305 DriverCancel = KsCancelRoutine;
1306 }
1307
1308 /* get current irp stack */
1309 IoStack = IoGetCurrentIrpStackLocation(Irp);
1310
1311 /* get internal queue lock */
1312 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1313
1314 /* acquire spinlock */
1315 KeAcquireSpinLock(SpinLock, &OldLevel);
1316
1317 /* now set the cancel routine */
1318 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1319
1320 if (Irp->Cancel && OldDriverCancel == NULL)
1321 {
1322 /* the irp has already been canceled */
1323 KeReleaseSpinLock(SpinLock, OldLevel);
1324
1325 /* cancel routine requires that cancel spinlock is held */
1326 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1327
1328 /* cancel irp */
1329 DriverCancel(IoStack->DeviceObject, Irp);
1330 }
1331 else
1332 {
1333 /* done */
1334 KeReleaseSpinLock(SpinLock, OldLevel);
1335 }
1336 }
1337
1338 /*
1339 @implemented
1340 */
1341 KSDDKAPI
1342 PIRP
1343 NTAPI
1344 KsRemoveIrpFromCancelableQueue(
1345 IN OUT PLIST_ENTRY QueueHead,
1346 IN PKSPIN_LOCK SpinLock,
1347 IN KSLIST_ENTRY_LOCATION ListLocation,
1348 IN KSIRP_REMOVAL_OPERATION RemovalOperation)
1349 {
1350 PIRP Irp;
1351 PLIST_ENTRY CurEntry;
1352 KIRQL OldIrql;
1353
1354 DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
1355
1356 /* check parameters */
1357 if (!QueueHead || !SpinLock)
1358 return NULL;
1359
1360 /* check if parameter ListLocation is valid */
1361 if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead)
1362 return NULL;
1363
1364 /* acquire list lock */
1365 KeAcquireSpinLock(SpinLock, &OldIrql);
1366
1367 /* point to queue head */
1368 CurEntry = QueueHead;
1369
1370 do
1371 {
1372 /* reset irp to null */
1373 Irp = NULL;
1374
1375 /* iterate to next entry */
1376 if (ListLocation == KsListEntryHead)
1377 CurEntry = CurEntry->Flink;
1378 else
1379 CurEntry = CurEntry->Blink;
1380
1381 /* is the end of list reached */
1382 if (CurEntry == QueueHead)
1383 {
1384 /* reached end of list */
1385 break;
1386 }
1387
1388 /* get irp offset */
1389 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1390
1391 if (Irp->Cancel)
1392 {
1393 /* irp has been canceled */
1394 break;
1395 }
1396
1397 if (Irp->CancelRoutine)
1398 {
1399 /* remove cancel routine */
1400 Irp->CancelRoutine = NULL;
1401
1402 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1403 {
1404 /* remove irp from list */
1405 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1406 }
1407
1408 if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem)
1409 break;
1410 }
1411
1412 }while(TRUE);
1413
1414 /* release lock */
1415 KeReleaseSpinLock(SpinLock, OldIrql);
1416
1417 if (!Irp || Irp->CancelRoutine == NULL)
1418 {
1419 /* either an irp has been acquired or nothing found */
1420 return Irp;
1421 }
1422
1423 /* time to remove the canceled irp */
1424 IoAcquireCancelSpinLock(&OldIrql);
1425 /* acquire list lock */
1426 KeAcquireSpinLockAtDpcLevel(SpinLock);
1427
1428 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1429 {
1430 /* remove it */
1431 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1432 }
1433
1434 /* release list lock */
1435 KeReleaseSpinLockFromDpcLevel(SpinLock);
1436
1437 /* release cancel spinlock */
1438 IoReleaseCancelSpinLock(OldIrql);
1439 /* no non canceled irp has been found */
1440 return NULL;
1441 }
1442
1443 /*
1444 @implemented
1445 */
1446 KSDDKAPI
1447 NTSTATUS
1448 NTAPI
1449 KsMoveIrpsOnCancelableQueue(
1450 IN OUT PLIST_ENTRY SourceList,
1451 IN PKSPIN_LOCK SourceLock,
1452 IN OUT PLIST_ENTRY DestinationList,
1453 IN PKSPIN_LOCK DestinationLock OPTIONAL,
1454 IN KSLIST_ENTRY_LOCATION ListLocation,
1455 IN PFNKSIRPLISTCALLBACK ListCallback,
1456 IN PVOID Context)
1457 {
1458 KIRQL OldLevel;
1459 PLIST_ENTRY SrcEntry;
1460 PIRP Irp;
1461 NTSTATUS Status = STATUS_SUCCESS;
1462
1463 if (!DestinationLock)
1464 {
1465 /* no destination lock just acquire the source lock */
1466 KeAcquireSpinLock(SourceLock, &OldLevel);
1467 }
1468 else
1469 {
1470 /* acquire cancel spinlock */
1471 IoAcquireCancelSpinLock(&OldLevel);
1472
1473 /* now acquire source lock */
1474 KeAcquireSpinLockAtDpcLevel(SourceLock);
1475
1476 /* now acquire destination lock */
1477 KeAcquireSpinLockAtDpcLevel(DestinationLock);
1478 }
1479
1480 /* point to list head */
1481 SrcEntry = SourceList;
1482
1483 /* now move all irps */
1484 while(TRUE)
1485 {
1486 if (ListLocation == KsListEntryTail)
1487 {
1488 /* move queue downwards */
1489 SrcEntry = SrcEntry->Flink;
1490 }
1491 else
1492 {
1493 /* move queue upwards */
1494 SrcEntry = SrcEntry->Blink;
1495 }
1496
1497 if (SrcEntry == SourceList)
1498 {
1499 /* eof list reached */
1500 break;
1501 }
1502
1503 /* get irp offset */
1504 Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
1505
1506 /* now check if irp can be moved */
1507 Status = ListCallback(Irp, Context);
1508
1509 /* check if irp can be moved */
1510 if (Status == STATUS_SUCCESS)
1511 {
1512 /* remove irp from src list */
1513 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1514
1515 if (ListLocation == KsListEntryTail)
1516 {
1517 /* insert irp end of list */
1518 InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1519 }
1520 else
1521 {
1522 /* insert irp head of list */
1523 InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1524 }
1525
1526 /* do we need to update the irp lock */
1527 if (DestinationLock)
1528 {
1529 /* update irp lock */
1530 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
1531 }
1532 }
1533 else
1534 {
1535 if (Status != STATUS_NO_MATCH)
1536 {
1537 /* callback decided to stop enumeration */
1538 break;
1539 }
1540
1541 /* reset return value */
1542 Status = STATUS_SUCCESS;
1543 }
1544 }
1545
1546 if (!DestinationLock)
1547 {
1548 /* release source lock */
1549 KeReleaseSpinLock(SourceLock, OldLevel);
1550 }
1551 else
1552 {
1553 /* now release destination lock */
1554 KeReleaseSpinLockFromDpcLevel(DestinationLock);
1555
1556 /* now release source lock */
1557 KeReleaseSpinLockFromDpcLevel(SourceLock);
1558
1559
1560 /* now release cancel spinlock */
1561 IoReleaseCancelSpinLock(OldLevel);
1562 }
1563
1564 /* done */
1565 return Status;
1566 }
1567
1568 /*
1569 @implemented
1570 */
1571 KSDDKAPI
1572 VOID
1573 NTAPI
1574 KsRemoveSpecificIrpFromCancelableQueue(
1575 IN PIRP Irp)
1576 {
1577 PKSPIN_LOCK SpinLock;
1578 KIRQL OldLevel;
1579
1580 DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp);
1581
1582 /* get internal queue lock */
1583 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1584
1585 /* acquire spinlock */
1586 KeAcquireSpinLock(SpinLock, &OldLevel);
1587
1588 /* remove the irp from the list */
1589 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1590
1591 /* release spinlock */
1592 KeReleaseSpinLock(SpinLock, OldLevel);
1593 }
1594
1595
1596 /*
1597 @implemented
1598 */
1599 KSDDKAPI
1600 VOID
1601 NTAPI
1602 KsAddIrpToCancelableQueue(
1603 IN OUT PLIST_ENTRY QueueHead,
1604 IN PKSPIN_LOCK SpinLock,
1605 IN PIRP Irp,
1606 IN KSLIST_ENTRY_LOCATION ListLocation,
1607 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1608 {
1609 PDRIVER_CANCEL OldDriverCancel;
1610 PIO_STACK_LOCATION IoStack;
1611 KIRQL OldLevel;
1612
1613 DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
1614 /* check for required parameters */
1615 if (!QueueHead || !SpinLock || !Irp)
1616 return;
1617
1618 if (!DriverCancel)
1619 {
1620 /* default to KsCancelRoutine */
1621 DriverCancel = KsCancelRoutine;
1622 }
1623
1624 /* get current irp stack */
1625 IoStack = IoGetCurrentIrpStackLocation(Irp);
1626
1627 /* acquire spinlock */
1628 KeAcquireSpinLock(SpinLock, &OldLevel);
1629
1630 if (ListLocation == KsListEntryTail)
1631 {
1632 /* insert irp to tail of list */
1633 InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1634 }
1635 else
1636 {
1637 /* insert irp to head of list */
1638 InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1639 }
1640
1641 /* store internal queue lock */
1642 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
1643
1644 /* now set the cancel routine */
1645 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1646
1647 if (Irp->Cancel && OldDriverCancel == NULL)
1648 {
1649 /* the irp has already been canceled */
1650 KeReleaseSpinLock(SpinLock, OldLevel);
1651
1652 /* cancel routine requires that cancel spinlock is held */
1653 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1654
1655 /* cancel irp */
1656 DriverCancel(IoStack->DeviceObject, Irp);
1657 }
1658 else
1659 {
1660 /* done */
1661 KeReleaseSpinLock(SpinLock, OldLevel);
1662 }
1663 }
1664
1665 /*
1666 @implemented
1667 */
1668 KSDDKAPI
1669 VOID
1670 NTAPI
1671 KsCancelRoutine(
1672 IN PDEVICE_OBJECT DeviceObject,
1673 IN PIRP Irp)
1674 {
1675 PKSPIN_LOCK SpinLock;
1676
1677 /* get internal queue lock */
1678 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1679
1680 /* acquire spinlock */
1681 KeAcquireSpinLockAtDpcLevel(SpinLock);
1682
1683 /* sanity check */
1684 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1685
1686 /* release cancel spinlock */
1687 IoReleaseCancelSpinLock(Irp->CancelIrql);
1688
1689 /* remove the irp from the list */
1690 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1691
1692 /* release spinlock */
1693 KeReleaseSpinLockFromDpcLevel(SpinLock);
1694
1695 /* has the irp already been canceled */
1696 if (Irp->IoStatus.Status != STATUS_CANCELLED)
1697 {
1698 /* let's complete it */
1699 Irp->IoStatus.Status = STATUS_CANCELLED;
1700 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1701 }
1702 }
1703
1704 NTSTATUS
1705 FindMatchingCreateItem(
1706 PLIST_ENTRY ListHead,
1707 ULONG BufferSize,
1708 LPWSTR Buffer,
1709 OUT PCREATE_ITEM_ENTRY *OutCreateItem)
1710 {
1711 PLIST_ENTRY Entry;
1712 PCREATE_ITEM_ENTRY CreateItemEntry;
1713
1714 /* remove '\' slash */
1715 Buffer++;
1716 BufferSize -= sizeof(WCHAR);
1717
1718 /* point to first entry */
1719 Entry = ListHead->Flink;
1720
1721 /* loop all device items */
1722 while(Entry != ListHead)
1723 {
1724 /* get create item entry */
1725 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1726
1727 ASSERT(CreateItemEntry->CreateItem);
1728
1729 if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
1730 {
1731 /* create item is default */
1732 *OutCreateItem = CreateItemEntry;
1733 return STATUS_SUCCESS;
1734 }
1735
1736 if (!CreateItemEntry->CreateItem->Create)
1737 {
1738 /* skip free create item */
1739 Entry = Entry->Flink;
1740 continue;
1741 }
1742
1743 ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
1744
1745 DPRINT1("CreateItem %S Length %u Request %S %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
1746 CreateItemEntry->CreateItem->ObjectClass.Length,
1747 Buffer,
1748 BufferSize);
1749
1750 if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
1751 {
1752 /* create item doesnt match in length */
1753 Entry = Entry->Flink;
1754 continue;
1755 }
1756
1757 /* now check if the object class is the same */
1758 if (RtlCompareMemory(CreateItemEntry->CreateItem->ObjectClass.Buffer, Buffer, CreateItemEntry->CreateItem->ObjectClass.Length) == CreateItemEntry->CreateItem->ObjectClass.Length)
1759 {
1760 /* found matching create item */
1761 *OutCreateItem = CreateItemEntry;
1762 return STATUS_SUCCESS;
1763 }
1764 /* iterate to next */
1765 Entry = Entry->Flink;
1766 }
1767
1768 return STATUS_NOT_FOUND;
1769 }
1770
1771 NTSTATUS
1772 NTAPI
1773 KspCreate(
1774 IN PDEVICE_OBJECT DeviceObject,
1775 IN PIRP Irp)
1776 {
1777 PCREATE_ITEM_ENTRY CreateItemEntry;
1778 PIO_STACK_LOCATION IoStack;
1779 PDEVICE_EXTENSION DeviceExtension;
1780 PKSIDEVICE_HEADER DeviceHeader;
1781 PKSIOBJECT_HEADER ObjectHeader;
1782 NTSTATUS Status;
1783
1784 DPRINT("KS / CREATE\n");
1785 /* get current stack location */
1786 IoStack = IoGetCurrentIrpStackLocation(Irp);
1787 /* get device extension */
1788 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1789 /* get device header */
1790 DeviceHeader = DeviceExtension->DeviceHeader;
1791
1792
1793 if (IoStack->FileObject->FileName.Buffer == NULL)
1794 {
1795 /* FIXME Pnp-Issue */
1796 DPRINT("Using reference string hack\n");
1797 Irp->IoStatus.Information = 0;
1798 /* set return status */
1799 Irp->IoStatus.Status = STATUS_SUCCESS;
1800 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1801 return STATUS_SUCCESS;
1802 }
1803
1804 if (IoStack->FileObject->RelatedFileObject != NULL)
1805 {
1806 /* request is to instantiate a pin / node / clock / allocator */
1807 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
1808
1809 /* sanity check */
1810 ASSERT(ObjectHeader);
1811
1812 /* find a matching a create item */
1813 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1814 }
1815 else
1816 {
1817 /* request to create a filter */
1818 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1819 }
1820
1821 if (NT_SUCCESS(Status))
1822 {
1823 /* set object create item */
1824 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1825
1826 /* call create function */
1827 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1828
1829 if (NT_SUCCESS(Status))
1830 {
1831 /* increment create item reference count */
1832 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1833 }
1834 return Status;
1835 }
1836
1837
1838 Irp->IoStatus.Information = 0;
1839 /* set return status */
1840 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1841 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1842 return STATUS_UNSUCCESSFUL;
1843 }
1844
1845 NTSTATUS
1846 NTAPI
1847 KspDispatchIrp(
1848 IN PDEVICE_OBJECT DeviceObject,
1849 IN PIRP Irp)
1850 {
1851 PIO_STACK_LOCATION IoStack;
1852 PDEVICE_EXTENSION DeviceExtension;
1853 PKSIOBJECT_HEADER ObjectHeader;
1854 PKSIDEVICE_HEADER DeviceHeader;
1855 PDRIVER_DISPATCH Dispatch;
1856 NTSTATUS Status;
1857
1858 /* get current stack location */
1859 IoStack = IoGetCurrentIrpStackLocation(Irp);
1860
1861 /* get device extension */
1862 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1863 /* get device header */
1864 DeviceHeader = DeviceExtension->DeviceHeader;
1865
1866 ASSERT(IoStack->FileObject);
1867
1868 /* get object header */
1869 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2;
1870
1871 if (!ObjectHeader)
1872 {
1873 /* FIXME Pnp-Issue*/
1874 Irp->IoStatus.Status = STATUS_SUCCESS;
1875 Irp->IoStatus.Information = 0;
1876 /* complete and forget */
1877 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1878 return STATUS_SUCCESS;
1879 }
1880
1881 /* sanity check */
1882 ASSERT(ObjectHeader);
1883 /* store create item */
1884 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1885
1886 /* retrieve matching dispatch function */
1887 switch(IoStack->MajorFunction)
1888 {
1889 case IRP_MJ_CLOSE:
1890 Dispatch = ObjectHeader->DispatchTable.Close;
1891 break;
1892 case IRP_MJ_DEVICE_CONTROL:
1893 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
1894 break;
1895 case IRP_MJ_READ:
1896 Dispatch = ObjectHeader->DispatchTable.Read;
1897 break;
1898 case IRP_MJ_WRITE:
1899 Dispatch = ObjectHeader->DispatchTable.Write;
1900 break;
1901 case IRP_MJ_FLUSH_BUFFERS :
1902 Dispatch = ObjectHeader->DispatchTable.Flush;
1903 break;
1904 case IRP_MJ_QUERY_SECURITY:
1905 Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
1906 break;
1907 case IRP_MJ_SET_SECURITY:
1908 Dispatch = ObjectHeader->DispatchTable.SetSecurity;
1909 break;
1910 case IRP_MJ_PNP:
1911 Dispatch = KsDefaultDispatchPnp;
1912 default:
1913 Dispatch = NULL;
1914 }
1915
1916 /* is the request supported */
1917 if (Dispatch)
1918 {
1919 /* now call the dispatch function */
1920 Status = Dispatch(DeviceObject, Irp);
1921 }
1922 else
1923 {
1924 /* not supported request */
1925 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1926 }
1927
1928 /* done */
1929 return Status;
1930 }
1931
1932 /*
1933 @implemented
1934 */
1935 KSDDKAPI
1936 NTSTATUS
1937 NTAPI
1938 KsSetMajorFunctionHandler(
1939 IN PDRIVER_OBJECT DriverObject,
1940 IN ULONG MajorFunction)
1941 {
1942 DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
1943 #if 0
1944 // HACK
1945 // for MS PORTCLS
1946 //
1947 DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate;
1948 #endif
1949
1950 switch ( MajorFunction )
1951 {
1952 case IRP_MJ_CREATE:
1953 DriverObject->MajorFunction[MajorFunction] = KspCreate;
1954 break;
1955 case IRP_MJ_DEVICE_CONTROL:
1956 case IRP_MJ_CLOSE:
1957 case IRP_MJ_READ:
1958 case IRP_MJ_WRITE:
1959 case IRP_MJ_FLUSH_BUFFERS :
1960 case IRP_MJ_QUERY_SECURITY:
1961 case IRP_MJ_SET_SECURITY:
1962 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
1963 break;
1964 default:
1965 DPRINT1("NotSupported %x\n", MajorFunction);
1966 return STATUS_INVALID_PARAMETER;
1967 };
1968
1969 return STATUS_SUCCESS;
1970 }
1971
1972 /*
1973 @implemented
1974 */
1975 KSDDKAPI
1976 NTSTATUS
1977 NTAPI
1978 KsDispatchIrp(
1979 IN PDEVICE_OBJECT DeviceObject,
1980 IN PIRP Irp)
1981 {
1982 PIO_STACK_LOCATION IoStack;
1983 PKSIDEVICE_HEADER DeviceHeader;
1984 PDEVICE_EXTENSION DeviceExtension;
1985
1986 DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
1987
1988 /* get device extension */
1989 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1990 /* get device header */
1991 DeviceHeader = DeviceExtension->DeviceHeader;
1992
1993
1994 /* get current irp stack */
1995 IoStack = IoGetCurrentIrpStackLocation(Irp);
1996
1997 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
1998 {
1999 if (IoStack->MajorFunction == IRP_MJ_CREATE)
2000 {
2001 /* check internal type */
2002 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2003 {
2004 /* AVStream client */
2005 return IKsDevice_Create(DeviceObject, Irp);
2006 }
2007 else
2008 {
2009 /* external client (portcls) */
2010 return KspCreate(DeviceObject, Irp);
2011 }
2012 }
2013
2014 switch (IoStack->MajorFunction)
2015 {
2016 case IRP_MJ_CLOSE:
2017 case IRP_MJ_READ:
2018 case IRP_MJ_WRITE:
2019 case IRP_MJ_FLUSH_BUFFERS:
2020 case IRP_MJ_QUERY_SECURITY:
2021 case IRP_MJ_SET_SECURITY:
2022 case IRP_MJ_PNP:
2023 case IRP_MJ_DEVICE_CONTROL:
2024 return KspDispatchIrp(DeviceObject, Irp);
2025 default:
2026 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2027 }
2028 }
2029
2030 /* dispatch power */
2031 if (IoStack->MajorFunction == IRP_MJ_POWER)
2032 {
2033 /* check internal type */
2034 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2035 {
2036 /* AVStream client */
2037 return IKsDevice_Power(DeviceObject, Irp);
2038 }
2039 else
2040 {
2041 /* external client (portcls) */
2042 return KsDefaultDispatchPower(DeviceObject, Irp);
2043 }
2044 }
2045 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
2046 {
2047 /* check internal type */
2048 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2049 {
2050 /* AVStream client */
2051 return IKsDevice_Pnp(DeviceObject, Irp);
2052 }
2053 else
2054 {
2055 /* external client (portcls) */
2056 return KsDefaultDispatchPnp(DeviceObject, Irp);
2057 }
2058 }
2059 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
2060 {
2061 /* forward irp */
2062 return KsDefaultForwardIrp(DeviceObject, Irp);
2063 }
2064 else
2065 {
2066 /* not supported */
2067 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2068 }
2069 }
2070
2071 /*
2072 @unimplemented
2073 */
2074 KSDDKAPI
2075 ULONG
2076 NTAPI
2077 KsGetNodeIdFromIrp(
2078 IN PIRP Irp)
2079 {
2080 UNIMPLEMENTED
2081 return (ULONG)-1;
2082 }
2083