[KS]
[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
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 return Status;
884 else
885 goto ProbeMdl;
886 }
887
888 /* probe user mode buffers */
889 if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) )
890 {
891 /* allocate stream header buffer */
892 Irp->AssociatedIrp.SystemBuffer = ExAllocatePool(NonPagedPool, Length);
893
894 if (!Irp->AssociatedIrp.SystemBuffer)
895 {
896 /* no memory */
897 return STATUS_INSUFFICIENT_RESOURCES;
898 }
899
900 _SEH2_TRY
901 {
902 if (ProbeFlags & KSPROBE_STREAMWRITE)
903 {
904 if (ProbeFlags & KSPROBE_MODIFY)
905 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
906 else
907 ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR));
908 }
909 else
910 {
911 /* stream reads means writing */
912 ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
913 }
914
915 /* copy stream buffer */
916 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length);
917 }
918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
919 {
920 /* Exception, get the error code */
921 Status = _SEH2_GetExceptionCode();
922 }_SEH2_END;
923
924 if (!NT_SUCCESS(Status))
925 {
926 /* failed */
927 return Status;
928 }
929
930 if (ProbeFlags & KSPROBE_ALLOCATEMDL)
931 {
932 /* alloc mdls */
933 goto AllocMdl;
934 }
935
936 /* check all stream headers */
937 StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
938
939 _SEH2_TRY
940 {
941 do
942 {
943 if (HeaderSize)
944 {
945 /* does the supplied header size match stream header size and no type changed */
946 if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED))
947 {
948 /* invalid stream header */
949 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
950 }
951 }
952 else
953 {
954 /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */
955 if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7))
956 {
957 /* invalid stream header */
958 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
959 }
960 }
961
962 if (Length < StreamHeader->Size)
963 {
964 /* length is too short */
965 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
966 }
967
968 if (ProbeFlags & KSPROBE_STREAMWRITE)
969 {
970 if (StreamHeader->DataUsed > StreamHeader->FrameExtent)
971 {
972 /* frame extend can never be smaller */
973 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
974 }
975
976 /* is this stream change packet */
977 if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)
978 {
979 if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer)
980 {
981 /* stream changed - must be send in a single packet */
982 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
983 }
984
985 if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE))
986 {
987 /* caller does not permit format changes */
988 ExRaiseStatus(STATUS_INVALID_PARAMETER);
989 }
990
991 if (StreamHeader->FrameExtent)
992 {
993 /* allocate an mdl */
994 Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp);
995
996 if (!Mdl)
997 {
998 /* not enough memory */
999 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
1000 }
1001
1002 /* break out to probe for the irp */
1003 AllocateMdl = TRUE;
1004 break;
1005 }
1006 }
1007 }
1008 else
1009 {
1010 if (StreamHeader->DataUsed)
1011 {
1012 /* DataUsed must be zero for stream read operation */
1013 ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE);
1014 }
1015
1016 if (StreamHeader->OptionsFlags)
1017 {
1018 /* no flags supported for reading */
1019 ExRaiseStatus(STATUS_INVALID_PARAMETER);
1020 }
1021 }
1022
1023 /* move to next stream header */
1024 Length -= StreamHeader->Size;
1025 StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
1026 }while(Length);
1027
1028 }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1029 {
1030 /* Exception, get the error code */
1031 Status = _SEH2_GetExceptionCode();
1032 }_SEH2_END;
1033
1034 /* now probe the allocated mdl's */
1035 if (NT_SUCCESS(Status))
1036 goto AllocMdl;
1037 else
1038 return Status;
1039 }
1040
1041 return STATUS_INVALID_BUFFER_SIZE;
1042 }
1043
1044 /*
1045 @implemented
1046 */
1047 KSDDKAPI
1048 NTSTATUS
1049 NTAPI
1050 KsAllocateExtraData(
1051 IN PIRP Irp,
1052 IN ULONG ExtraSize,
1053 OUT PVOID* ExtraBuffer)
1054 {
1055 PIO_STACK_LOCATION IoStack;
1056 ULONG Count, Index;
1057 PUCHAR Buffer, BufferOrg;
1058 PKSSTREAM_HEADER Header;
1059 NTSTATUS Status = STATUS_SUCCESS;
1060
1061 /* get current irp stack */
1062 IoStack = IoGetCurrentIrpStackLocation(Irp);
1063
1064 /* sanity check */
1065 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
1066
1067 /* get total length */
1068 Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
1069
1070 /* allocate buffer */
1071 Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
1072 if (!Buffer)
1073 return STATUS_INSUFFICIENT_RESOURCES;
1074
1075 _SEH2_TRY
1076 {
1077 /* get input buffer */
1078 Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1079 for(Index = 0; Index < Count; Index++)
1080 {
1081 /* copy stream header */
1082 RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
1083
1084 /* move to next header */
1085 Header++;
1086 /* increment output buffer offset */
1087 Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
1088 }
1089 }
1090 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1091 {
1092 /* Exception, get the error code */
1093 Status = _SEH2_GetExceptionCode();
1094 }
1095 _SEH2_END;
1096
1097 if (!NT_SUCCESS(Status))
1098 {
1099 /* free buffer on exception */
1100 FreeItem(Buffer);
1101 return Status;
1102 }
1103
1104 /* store result */
1105 *ExtraBuffer = BufferOrg;
1106
1107 /* done */
1108 return STATUS_SUCCESS;
1109 }
1110
1111 /*
1112 @implemented
1113 */
1114 KSDDKAPI
1115 VOID
1116 NTAPI
1117 KsNullDriverUnload(
1118 IN PDRIVER_OBJECT DriverObject)
1119 {
1120 }
1121
1122 /*
1123 @implemented
1124 */
1125 KSDDKAPI
1126 NTSTATUS
1127 NTAPI
1128 KsDispatchInvalidDeviceRequest(
1129 IN PDEVICE_OBJECT DeviceObject,
1130 IN PIRP Irp)
1131 {
1132 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1133 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1134
1135 return STATUS_INVALID_DEVICE_REQUEST;
1136 }
1137
1138 /*
1139 @implemented
1140 */
1141 KSDDKAPI
1142 NTSTATUS
1143 NTAPI
1144 KsDefaultDeviceIoCompletion(
1145 IN PDEVICE_OBJECT DeviceObject,
1146 IN PIRP Irp)
1147 {
1148 PIO_STACK_LOCATION IoStack;
1149 NTSTATUS Status;
1150
1151 /* get current irp stack */
1152 IoStack = IoGetCurrentIrpStackLocation(Irp);
1153
1154 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY &&
1155 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
1156 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
1157 {
1158 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
1159 {
1160 /* fake success */
1161 Status = STATUS_SUCCESS;
1162 }
1163 else
1164 {
1165 /* request unsupported */
1166 Status = STATUS_INVALID_DEVICE_REQUEST;
1167 }
1168 }
1169 else
1170 {
1171 /* property / method / event not found */
1172 Status = STATUS_PROPSET_NOT_FOUND;
1173 }
1174
1175 /* complete request */
1176 Irp->IoStatus.Status = Status;
1177 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1178
1179
1180 return Status;
1181 }
1182
1183 /*
1184 @implemented
1185 */
1186 KSDDKAPI
1187 BOOLEAN
1188 NTAPI
1189 KsDispatchFastIoDeviceControlFailure(
1190 IN PFILE_OBJECT FileObject,
1191 IN BOOLEAN Wait,
1192 IN PVOID InputBuffer OPTIONAL,
1193 IN ULONG InputBufferLength,
1194 OUT PVOID OutputBuffer OPTIONAL,
1195 IN ULONG OutputBufferLength,
1196 IN ULONG IoControlCode,
1197 OUT PIO_STATUS_BLOCK IoStatus,
1198 IN PDEVICE_OBJECT DeviceObject)
1199 {
1200 return FALSE;
1201 }
1202
1203 /*
1204 @implemented
1205 */
1206 KSDDKAPI
1207 BOOLEAN
1208 NTAPI
1209 KsDispatchFastReadFailure(
1210 IN PFILE_OBJECT FileObject,
1211 IN PLARGE_INTEGER FileOffset,
1212 IN ULONG Length,
1213 IN BOOLEAN Wait,
1214 IN ULONG LockKey,
1215 OUT PVOID Buffer,
1216 OUT PIO_STATUS_BLOCK IoStatus,
1217 IN PDEVICE_OBJECT DeviceObject)
1218 {
1219 return FALSE;
1220 }
1221
1222
1223 /*
1224 @implemented
1225 */
1226 KSDDKAPI
1227 VOID
1228 NTAPI
1229 KsCancelIo(
1230 IN OUT PLIST_ENTRY QueueHead,
1231 IN PKSPIN_LOCK SpinLock)
1232 {
1233 PDRIVER_CANCEL OldDriverCancel;
1234 PIO_STACK_LOCATION IoStack;
1235 PLIST_ENTRY Entry;
1236 PIRP Irp;
1237 KIRQL OldLevel;
1238
1239 /* acquire spinlock */
1240 KeAcquireSpinLock(SpinLock, &OldLevel);
1241 /* point to first entry */
1242 Entry = QueueHead->Flink;
1243 /* loop all items */
1244 while(Entry != QueueHead)
1245 {
1246 /* get irp offset */
1247 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
1248
1249 /* set cancelled bit */
1250 Irp->Cancel = TRUE;
1251
1252 /* now set the cancel routine */
1253 OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
1254 if (OldDriverCancel)
1255 {
1256 /* this irp hasnt been yet used, so free to cancel */
1257 KeReleaseSpinLock(SpinLock, OldLevel);
1258
1259 /* get current irp stack */
1260 IoStack = IoGetCurrentIrpStackLocation(Irp);
1261
1262 /* acquire cancel spinlock */
1263 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1264
1265 /* call provided cancel routine */
1266 OldDriverCancel(IoStack->DeviceObject, Irp);
1267
1268 /* re-acquire spinlock */
1269 KeAcquireSpinLock(SpinLock, &OldLevel);
1270 }
1271 /* move on to next entry */
1272 Entry = Entry->Flink;
1273 }
1274
1275 /* the irp has already been canceled */
1276 KeReleaseSpinLock(SpinLock, OldLevel);
1277
1278 }
1279
1280 /*
1281 @implemented
1282 */
1283 KSDDKAPI
1284 VOID
1285 NTAPI
1286 KsReleaseIrpOnCancelableQueue(
1287 IN PIRP Irp,
1288 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1289 {
1290 PKSPIN_LOCK SpinLock;
1291 PDRIVER_CANCEL OldDriverCancel;
1292 PIO_STACK_LOCATION IoStack;
1293 KIRQL OldLevel;
1294
1295 /* check for required parameters */
1296 if (!Irp)
1297 return;
1298
1299 if (!DriverCancel)
1300 {
1301 /* default to KsCancelRoutine */
1302 DriverCancel = KsCancelRoutine;
1303 }
1304
1305 /* get current irp stack */
1306 IoStack = IoGetCurrentIrpStackLocation(Irp);
1307
1308 /* get internal queue lock */
1309 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1310
1311 /* acquire spinlock */
1312 KeAcquireSpinLock(SpinLock, &OldLevel);
1313
1314 /* now set the cancel routine */
1315 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1316
1317 if (Irp->Cancel && OldDriverCancel == NULL)
1318 {
1319 /* the irp has already been canceled */
1320 KeReleaseSpinLock(SpinLock, OldLevel);
1321
1322 /* cancel routine requires that cancel spinlock is held */
1323 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1324
1325 /* cancel irp */
1326 DriverCancel(IoStack->DeviceObject, Irp);
1327 }
1328 else
1329 {
1330 /* done */
1331 KeReleaseSpinLock(SpinLock, OldLevel);
1332 }
1333 }
1334
1335 /*
1336 @implemented
1337 */
1338 KSDDKAPI
1339 PIRP
1340 NTAPI
1341 KsRemoveIrpFromCancelableQueue(
1342 IN OUT PLIST_ENTRY QueueHead,
1343 IN PKSPIN_LOCK SpinLock,
1344 IN KSLIST_ENTRY_LOCATION ListLocation,
1345 IN KSIRP_REMOVAL_OPERATION RemovalOperation)
1346 {
1347 PIRP Irp;
1348 PLIST_ENTRY CurEntry;
1349 KIRQL OldIrql;
1350
1351 DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation);
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 DPRINT("KsRemoveSpecificIrpFromCancelableQueue %p\n", Irp);
1578
1579 /* get internal queue lock */
1580 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1581
1582 /* acquire spinlock */
1583 KeAcquireSpinLock(SpinLock, &OldLevel);
1584
1585 /* remove the irp from the list */
1586 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1587
1588 /* release spinlock */
1589 KeReleaseSpinLock(SpinLock, OldLevel);
1590 }
1591
1592
1593 /*
1594 @implemented
1595 */
1596 KSDDKAPI
1597 VOID
1598 NTAPI
1599 KsAddIrpToCancelableQueue(
1600 IN OUT PLIST_ENTRY QueueHead,
1601 IN PKSPIN_LOCK SpinLock,
1602 IN PIRP Irp,
1603 IN KSLIST_ENTRY_LOCATION ListLocation,
1604 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1605 {
1606 PDRIVER_CANCEL OldDriverCancel;
1607 PIO_STACK_LOCATION IoStack;
1608 KIRQL OldLevel;
1609
1610 DPRINT1("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel);
1611 /* check for required parameters */
1612 if (!QueueHead || !SpinLock || !Irp)
1613 return;
1614
1615 if (!DriverCancel)
1616 {
1617 /* default to KsCancelRoutine */
1618 DriverCancel = KsCancelRoutine;
1619 }
1620
1621 /* get current irp stack */
1622 IoStack = IoGetCurrentIrpStackLocation(Irp);
1623
1624 /* acquire spinlock */
1625 KeAcquireSpinLock(SpinLock, &OldLevel);
1626
1627 if (ListLocation == KsListEntryTail)
1628 {
1629 /* insert irp to tail of list */
1630 InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1631 }
1632 else
1633 {
1634 /* insert irp to head of list */
1635 InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1636 }
1637
1638 /* store internal queue lock */
1639 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
1640
1641 /* now set the cancel routine */
1642 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1643
1644 if (Irp->Cancel && OldDriverCancel == NULL)
1645 {
1646 /* the irp has already been canceled */
1647 KeReleaseSpinLock(SpinLock, OldLevel);
1648
1649 /* cancel routine requires that cancel spinlock is held */
1650 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1651
1652 /* cancel irp */
1653 DriverCancel(IoStack->DeviceObject, Irp);
1654 }
1655 else
1656 {
1657 /* done */
1658 KeReleaseSpinLock(SpinLock, OldLevel);
1659 }
1660 }
1661
1662 /*
1663 @implemented
1664 */
1665 KSDDKAPI
1666 VOID
1667 NTAPI
1668 KsCancelRoutine(
1669 IN PDEVICE_OBJECT DeviceObject,
1670 IN PIRP Irp)
1671 {
1672 PKSPIN_LOCK SpinLock;
1673
1674 /* get internal queue lock */
1675 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1676
1677 /* acquire spinlock */
1678 KeAcquireSpinLockAtDpcLevel(SpinLock);
1679
1680 /* sanity check */
1681 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1682
1683 /* release cancel spinlock */
1684 IoReleaseCancelSpinLock(Irp->CancelIrql);
1685
1686 /* remove the irp from the list */
1687 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1688
1689 /* release spinlock */
1690 KeReleaseSpinLockFromDpcLevel(SpinLock);
1691
1692 /* has the irp already been canceled */
1693 if (Irp->IoStatus.Status != STATUS_CANCELLED)
1694 {
1695 /* let's complete it */
1696 Irp->IoStatus.Status = STATUS_CANCELLED;
1697 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1698 }
1699 }
1700
1701 NTSTATUS
1702 FindMatchingCreateItem(
1703 PLIST_ENTRY ListHead,
1704 ULONG BufferSize,
1705 LPWSTR Buffer,
1706 OUT PCREATE_ITEM_ENTRY *OutCreateItem)
1707 {
1708 PLIST_ENTRY Entry;
1709 PCREATE_ITEM_ENTRY CreateItemEntry;
1710
1711 /* remove '\' slash */
1712 Buffer++;
1713 BufferSize -= sizeof(WCHAR);
1714
1715 /* point to first entry */
1716 Entry = ListHead->Flink;
1717
1718 /* loop all device items */
1719 while(Entry != ListHead)
1720 {
1721 /* get create item entry */
1722 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1723
1724 ASSERT(CreateItemEntry->CreateItem);
1725
1726 if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
1727 {
1728 /* create item is default */
1729 *OutCreateItem = CreateItemEntry;
1730 return STATUS_SUCCESS;
1731 }
1732
1733 if (!CreateItemEntry->CreateItem->Create)
1734 {
1735 /* skip free create item */
1736 Entry = Entry->Flink;
1737 continue;
1738 }
1739
1740 ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
1741
1742 DPRINT1("CreateItem %S Length %u Request %S %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
1743 CreateItemEntry->CreateItem->ObjectClass.Length,
1744 Buffer,
1745 BufferSize);
1746
1747 if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
1748 {
1749 /* create item doesnt match in length */
1750 Entry = Entry->Flink;
1751 continue;
1752 }
1753
1754 /* now check if the object class is the same */
1755 if (RtlCompareMemory(CreateItemEntry->CreateItem->ObjectClass.Buffer, Buffer, CreateItemEntry->CreateItem->ObjectClass.Length) == CreateItemEntry->CreateItem->ObjectClass.Length)
1756 {
1757 /* found matching create item */
1758 *OutCreateItem = CreateItemEntry;
1759 return STATUS_SUCCESS;
1760 }
1761 /* iterate to next */
1762 Entry = Entry->Flink;
1763 }
1764
1765 return STATUS_NOT_FOUND;
1766 }
1767
1768 NTSTATUS
1769 NTAPI
1770 KspCreate(
1771 IN PDEVICE_OBJECT DeviceObject,
1772 IN PIRP Irp)
1773 {
1774 PCREATE_ITEM_ENTRY CreateItemEntry;
1775 PIO_STACK_LOCATION IoStack;
1776 PDEVICE_EXTENSION DeviceExtension;
1777 PKSIDEVICE_HEADER DeviceHeader;
1778 PKSIOBJECT_HEADER ObjectHeader;
1779 NTSTATUS Status;
1780
1781 DPRINT("KS / CREATE\n");
1782 /* get current stack location */
1783 IoStack = IoGetCurrentIrpStackLocation(Irp);
1784 /* get device extension */
1785 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1786 /* get device header */
1787 DeviceHeader = DeviceExtension->DeviceHeader;
1788
1789
1790 if (IoStack->FileObject->FileName.Buffer == NULL)
1791 {
1792 /* FIXME Pnp-Issue */
1793 DPRINT("Using reference string hack\n");
1794 Irp->IoStatus.Information = 0;
1795 /* set return status */
1796 Irp->IoStatus.Status = STATUS_SUCCESS;
1797 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1798 return STATUS_SUCCESS;
1799 }
1800
1801 if (IoStack->FileObject->RelatedFileObject != NULL)
1802 {
1803 /* request is to instantiate a pin / node / clock / allocator */
1804 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext2;
1805
1806 /* sanity check */
1807 ASSERT(ObjectHeader);
1808
1809 /* find a matching a create item */
1810 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1811 }
1812 else
1813 {
1814 /* request to create a filter */
1815 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1816 }
1817
1818 if (NT_SUCCESS(Status))
1819 {
1820 /* set object create item */
1821 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1822
1823 /* call create function */
1824 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1825
1826 if (NT_SUCCESS(Status))
1827 {
1828 /* increment create item reference count */
1829 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1830 }
1831 return Status;
1832 }
1833
1834
1835 Irp->IoStatus.Information = 0;
1836 /* set return status */
1837 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1838 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1839 return STATUS_UNSUCCESSFUL;
1840 }
1841
1842 NTSTATUS
1843 NTAPI
1844 KspDispatchIrp(
1845 IN PDEVICE_OBJECT DeviceObject,
1846 IN PIRP Irp)
1847 {
1848 PIO_STACK_LOCATION IoStack;
1849 PDEVICE_EXTENSION DeviceExtension;
1850 PKSIOBJECT_HEADER ObjectHeader;
1851 PKSIDEVICE_HEADER DeviceHeader;
1852 PDRIVER_DISPATCH Dispatch;
1853 NTSTATUS Status;
1854
1855 /* get current stack location */
1856 IoStack = IoGetCurrentIrpStackLocation(Irp);
1857
1858 /* get device extension */
1859 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1860 /* get device header */
1861 DeviceHeader = DeviceExtension->DeviceHeader;
1862
1863 ASSERT(IoStack->FileObject);
1864
1865 /* get object header */
1866 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext2;
1867
1868 if (!ObjectHeader)
1869 {
1870 /* FIXME Pnp-Issue*/
1871 Irp->IoStatus.Status = STATUS_SUCCESS;
1872 Irp->IoStatus.Information = 0;
1873 /* complete and forget */
1874 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1875 return STATUS_SUCCESS;
1876 }
1877
1878 /* sanity check */
1879 ASSERT(ObjectHeader);
1880 /* store create item */
1881 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1882
1883 /* retrieve matching dispatch function */
1884 switch(IoStack->MajorFunction)
1885 {
1886 case IRP_MJ_CLOSE:
1887 Dispatch = ObjectHeader->DispatchTable.Close;
1888 break;
1889 case IRP_MJ_DEVICE_CONTROL:
1890 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
1891 break;
1892 case IRP_MJ_READ:
1893 Dispatch = ObjectHeader->DispatchTable.Read;
1894 break;
1895 case IRP_MJ_WRITE:
1896 Dispatch = ObjectHeader->DispatchTable.Write;
1897 break;
1898 case IRP_MJ_FLUSH_BUFFERS :
1899 Dispatch = ObjectHeader->DispatchTable.Flush;
1900 break;
1901 case IRP_MJ_QUERY_SECURITY:
1902 Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
1903 break;
1904 case IRP_MJ_SET_SECURITY:
1905 Dispatch = ObjectHeader->DispatchTable.SetSecurity;
1906 break;
1907 case IRP_MJ_PNP:
1908 Dispatch = KsDefaultDispatchPnp;
1909 default:
1910 Dispatch = NULL;
1911 }
1912
1913 /* is the request supported */
1914 if (Dispatch)
1915 {
1916 /* now call the dispatch function */
1917 Status = Dispatch(DeviceObject, Irp);
1918 }
1919 else
1920 {
1921 /* not supported request */
1922 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1923 }
1924
1925 /* done */
1926 return Status;
1927 }
1928
1929 /*
1930 @implemented
1931 */
1932 KSDDKAPI
1933 NTSTATUS
1934 NTAPI
1935 KsSetMajorFunctionHandler(
1936 IN PDRIVER_OBJECT DriverObject,
1937 IN ULONG MajorFunction)
1938 {
1939 DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction);
1940 #if 0
1941 // HACK
1942 // for MS PORTCLS
1943 //
1944 DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate;
1945 #endif
1946
1947 switch ( MajorFunction )
1948 {
1949 case IRP_MJ_CREATE:
1950 DriverObject->MajorFunction[MajorFunction] = KspCreate;
1951 break;
1952 case IRP_MJ_DEVICE_CONTROL:
1953 case IRP_MJ_CLOSE:
1954 case IRP_MJ_READ:
1955 case IRP_MJ_WRITE:
1956 case IRP_MJ_FLUSH_BUFFERS :
1957 case IRP_MJ_QUERY_SECURITY:
1958 case IRP_MJ_SET_SECURITY:
1959 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
1960 break;
1961 default:
1962 DPRINT1("NotSupported %x\n", MajorFunction);
1963 return STATUS_INVALID_PARAMETER;
1964 };
1965
1966 return STATUS_SUCCESS;
1967 }
1968
1969 /*
1970 @implemented
1971 */
1972 KSDDKAPI
1973 NTSTATUS
1974 NTAPI
1975 KsDispatchIrp(
1976 IN PDEVICE_OBJECT DeviceObject,
1977 IN PIRP Irp)
1978 {
1979 PIO_STACK_LOCATION IoStack;
1980 PKSIDEVICE_HEADER DeviceHeader;
1981 PDEVICE_EXTENSION DeviceExtension;
1982
1983 DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp);
1984
1985 /* get device extension */
1986 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1987 /* get device header */
1988 DeviceHeader = DeviceExtension->DeviceHeader;
1989
1990
1991 /* get current irp stack */
1992 IoStack = IoGetCurrentIrpStackLocation(Irp);
1993
1994 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
1995 {
1996 if (IoStack->MajorFunction == IRP_MJ_CREATE)
1997 {
1998 /* check internal type */
1999 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2000 {
2001 /* AVStream client */
2002 return IKsDevice_Create(DeviceObject, Irp);
2003 }
2004 else
2005 {
2006 /* external client (portcls) */
2007 return KspCreate(DeviceObject, Irp);
2008 }
2009 }
2010
2011 switch (IoStack->MajorFunction)
2012 {
2013 case IRP_MJ_CLOSE:
2014 case IRP_MJ_READ:
2015 case IRP_MJ_WRITE:
2016 case IRP_MJ_FLUSH_BUFFERS:
2017 case IRP_MJ_QUERY_SECURITY:
2018 case IRP_MJ_SET_SECURITY:
2019 case IRP_MJ_PNP:
2020 case IRP_MJ_DEVICE_CONTROL:
2021 return KspDispatchIrp(DeviceObject, Irp);
2022 default:
2023 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2024 }
2025 }
2026
2027 /* dispatch power */
2028 if (IoStack->MajorFunction == IRP_MJ_POWER)
2029 {
2030 /* check internal type */
2031 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2032 {
2033 /* AVStream client */
2034 return IKsDevice_Power(DeviceObject, Irp);
2035 }
2036 else
2037 {
2038 /* external client (portcls) */
2039 return KsDefaultDispatchPower(DeviceObject, Irp);
2040 }
2041 }
2042 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
2043 {
2044 /* check internal type */
2045 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
2046 {
2047 /* AVStream client */
2048 return IKsDevice_Pnp(DeviceObject, Irp);
2049 }
2050 else
2051 {
2052 /* external client (portcls) */
2053 return KsDefaultDispatchPnp(DeviceObject, Irp);
2054 }
2055 }
2056 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
2057 {
2058 /* forward irp */
2059 return KsDefaultForwardIrp(DeviceObject, Irp);
2060 }
2061 else
2062 {
2063 /* not supported */
2064 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
2065 }
2066 }
2067
2068 /*
2069 @unimplemented
2070 */
2071 KSDDKAPI
2072 ULONG
2073 NTAPI
2074 KsGetNodeIdFromIrp(
2075 IN PIRP Irp)
2076 {
2077 UNIMPLEMENTED
2078 return (ULONG)-1;
2079 }
2080