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