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