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