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