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