- Partly Implement KsCacheMedium
[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 KsDispatchSpecificProperty(
124 IN PIRP Irp,
125 IN PFNKSHANDLER Handler)
126 {
127 UNIMPLEMENTED;
128 return STATUS_UNSUCCESSFUL;
129 }
130
131 /*
132 @unimplemented
133 */
134 KSDDKAPI
135 NTSTATUS
136 NTAPI
137 KsDispatchSpecificMethod(
138 IN PIRP Irp,
139 IN PFNKSHANDLER Handler)
140 {
141 UNIMPLEMENTED;
142 return STATUS_UNSUCCESSFUL;
143 }
144
145
146 /*
147 @implemented
148 */
149 KSDDKAPI
150 NTSTATUS
151 NTAPI
152 KsReadFile(
153 IN PFILE_OBJECT FileObject,
154 IN PKEVENT Event OPTIONAL,
155 IN PVOID PortContext OPTIONAL,
156 OUT PIO_STATUS_BLOCK IoStatusBlock,
157 OUT PVOID Buffer,
158 IN ULONG Length,
159 IN ULONG Key OPTIONAL,
160 IN KPROCESSOR_MODE RequestorMode)
161 {
162 PDEVICE_OBJECT DeviceObject;
163 PIRP Irp;
164 NTSTATUS Status;
165 BOOLEAN Result;
166 KEVENT LocalEvent;
167
168 if (Event)
169 {
170 /* make sure event is reset */
171 KeClearEvent(Event);
172 }
173
174 if (RequestorMode == UserMode)
175 {
176 /* probe the user buffer */
177 _SEH2_TRY
178 {
179 ProbeForWrite(Buffer, Length, sizeof(UCHAR));
180 Status = STATUS_SUCCESS;
181 }
182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
183 {
184 /* Exception, get the error code */
185 Status = _SEH2_GetExceptionCode();
186 }
187 _SEH2_END;
188
189 if (!NT_SUCCESS(Status))
190 {
191 DPRINT1("Invalid user buffer provided\n");
192 return Status;
193 }
194 }
195
196 /* get corresponding device object */
197 DeviceObject = IoGetRelatedDeviceObject(FileObject);
198
199 /* fast-io read is only available for kernel mode clients */
200 if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
201 DeviceObject->DriverObject->FastIoDispatch->FastIoRead)
202 {
203 /* call fast io write */
204 Result = DeviceObject->DriverObject->FastIoDispatch->FastIoRead(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
205
206 if (Result && NT_SUCCESS(IoStatusBlock->Status))
207 {
208 /* request was handeled and succeeded */
209 return STATUS_SUCCESS;
210 }
211 }
212
213 /* do the slow way */
214 if (!Event)
215 {
216 /* initialize temp event */
217 KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
218 Event = &LocalEvent;
219 }
220
221 /* build the irp packet */
222 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
223 if (!Irp)
224 {
225 /* not enough resources */
226 return STATUS_INSUFFICIENT_RESOURCES;
227 }
228
229 /* send the packet */
230 Status = IoCallDriver(DeviceObject, Irp);
231
232 if (Status == STATUS_PENDING)
233 {
234 /* operation is pending, is sync file object */
235 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
236 {
237 /* it is so wait */
238 KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
239 Status = IoStatusBlock->Status;
240 }
241 }
242 /* return result */
243 return Status;
244 }
245
246 /*
247 @implemented
248 */
249 KSDDKAPI
250 NTSTATUS
251 NTAPI
252 KsWriteFile(
253 IN PFILE_OBJECT FileObject,
254 IN PKEVENT Event OPTIONAL,
255 IN PVOID PortContext OPTIONAL,
256 OUT PIO_STATUS_BLOCK IoStatusBlock,
257 IN PVOID Buffer,
258 IN ULONG Length,
259 IN ULONG Key OPTIONAL,
260 IN KPROCESSOR_MODE RequestorMode)
261 {
262 PDEVICE_OBJECT DeviceObject;
263 PIRP Irp;
264 NTSTATUS Status;
265 BOOLEAN Result;
266 KEVENT LocalEvent;
267
268 if (Event)
269 {
270 /* make sure event is reset */
271 KeClearEvent(Event);
272 }
273
274 if (RequestorMode == UserMode)
275 {
276 /* probe the user buffer */
277 _SEH2_TRY
278 {
279 ProbeForRead(Buffer, Length, sizeof(UCHAR));
280 Status = STATUS_SUCCESS;
281 }
282 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
283 {
284 /* Exception, get the error code */
285 Status = _SEH2_GetExceptionCode();
286 }
287 _SEH2_END;
288
289 if (!NT_SUCCESS(Status))
290 {
291 DPRINT1("Invalid user buffer provided\n");
292 return Status;
293 }
294 }
295
296 /* get corresponding device object */
297 DeviceObject = IoGetRelatedDeviceObject(FileObject);
298
299 /* fast-io write is only available for kernel mode clients */
300 if (RequestorMode == KernelMode && ExGetPreviousMode() == KernelMode &&
301 DeviceObject->DriverObject->FastIoDispatch->FastIoWrite)
302 {
303 /* call fast io write */
304 Result = DeviceObject->DriverObject->FastIoDispatch->FastIoWrite(FileObject, &FileObject->CurrentByteOffset, Length, TRUE, Key, Buffer, IoStatusBlock, DeviceObject);
305
306 if (Result && NT_SUCCESS(IoStatusBlock->Status))
307 {
308 /* request was handeled and succeeded */
309 return STATUS_SUCCESS;
310 }
311 }
312
313 /* do the slow way */
314 if (!Event)
315 {
316 /* initialize temp event */
317 KeInitializeEvent(&LocalEvent, NotificationEvent, FALSE);
318 Event = &LocalEvent;
319 }
320
321 /* build the irp packet */
322 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer, Length, &FileObject->CurrentByteOffset, Event, IoStatusBlock);
323 if (!Irp)
324 {
325 /* not enough resources */
326 return STATUS_INSUFFICIENT_RESOURCES;
327 }
328
329 /* send the packet */
330 Status = IoCallDriver(DeviceObject, Irp);
331
332 if (Status == STATUS_PENDING)
333 {
334 /* operation is pending, is sync file object */
335 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
336 {
337 /* it is so wait */
338 KeWaitForSingleObject(Event, Executive, RequestorMode, FALSE, NULL);
339 Status = IoStatusBlock->Status;
340 }
341 }
342 /* return result */
343 return Status;
344 }
345
346 /*
347 @unimplemented
348 */
349 KSDDKAPI
350 NTSTATUS
351 NTAPI
352 KsQueryInformationFile(
353 IN PFILE_OBJECT FileObject,
354 OUT PVOID FileInformation,
355 IN ULONG Length,
356 IN FILE_INFORMATION_CLASS FileInformationClass)
357 {
358 PDEVICE_OBJECT DeviceObject;
359 PFAST_IO_DISPATCH FastIoDispatch;
360 IO_STATUS_BLOCK IoStatus;
361
362 /* get related file object */
363 DeviceObject = IoGetRelatedDeviceObject(FileObject);
364
365 /* get fast i/o table */
366 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
367
368 /* is there a fast table */
369 if (FastIoDispatch)
370 {
371 /* check the class */
372 if (FileInformationClass == FileBasicInformation)
373 {
374 /* use FastIoQueryBasicInfo routine */
375 if (FastIoDispatch->FastIoQueryBasicInfo)
376 {
377 return FastIoDispatch->FastIoQueryBasicInfo(FileObject, TRUE, (PFILE_BASIC_INFORMATION)FileInformation, &IoStatus, DeviceObject);
378 }
379 }
380 else if (FileInformationClass == FileStandardInformation)
381 {
382 /* use FastIoQueryBasicInfo routine */
383 if (FastIoDispatch->FastIoQueryBasicInfo)
384 {
385 return FastIoDispatch->FastIoQueryStandardInfo(FileObject, TRUE, (PFILE_STANDARD_INFORMATION)FileInformation, &IoStatus, DeviceObject);
386 }
387 }
388 }
389
390 /* Implement Me */
391
392 return STATUS_UNSUCCESSFUL;
393 }
394
395 /*
396 @implemented
397 */
398 KSDDKAPI
399 NTSTATUS
400 NTAPI
401 KsSetInformationFile(
402 IN PFILE_OBJECT FileObject,
403 IN PVOID FileInformation,
404 IN ULONG Length,
405 IN FILE_INFORMATION_CLASS FileInformationClass)
406 {
407 PIO_STACK_LOCATION IoStack;
408 PDEVICE_OBJECT DeviceObject;
409 PIRP Irp;
410 PVOID Buffer;
411 KEVENT Event;
412 LARGE_INTEGER Offset;
413 IO_STATUS_BLOCK IoStatus;
414 NTSTATUS Status;
415
416 /* get related device object */
417 DeviceObject = IoGetRelatedDeviceObject(FileObject);
418
419 /* copy file information */
420 Buffer = AllocateItem(NonPagedPool, Length);
421 if (!Buffer)
422 return STATUS_INSUFFICIENT_RESOURCES;
423
424 _SEH2_TRY
425 {
426 ProbeForRead(Buffer, Length, sizeof(UCHAR));
427 RtlMoveMemory(Buffer, FileInformation, Length);
428 Status = STATUS_SUCCESS;
429 }
430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
431 {
432 /* Exception, get the error code */
433 Status = _SEH2_GetExceptionCode();
434 }
435 _SEH2_END;
436
437 if (!NT_SUCCESS(Status))
438 {
439 /* invalid user buffer */
440 FreeItem(Buffer);
441 return Status;
442 }
443
444 /* initialize the event */
445 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
446
447 /* zero offset */
448 Offset.QuadPart = 0LL;
449
450 /* build the irp */
451 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus);
452
453 if (!Irp)
454 {
455 /* failed to allocate irp */
456 FreeItem(Buffer);
457 return STATUS_INSUFFICIENT_RESOURCES;
458 }
459
460 /* get next stack location */
461 IoStack = IoGetNextIrpStackLocation(Irp);
462
463 /* set irp parameters */
464 IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass;
465 IoStack->Parameters.SetFile.Length = Length;
466 IoStack->Parameters.SetFile.FileObject = FileObject;
467 Irp->AssociatedIrp.SystemBuffer = Buffer;
468 Irp->UserBuffer = FileInformation;
469
470 /* dispatch the irp */
471 Status = IoCallDriver(DeviceObject, Irp);
472
473 if (Status == STATUS_PENDING)
474 {
475 /* wait untill the operation has completed */
476 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
477 /* is a sync file object */
478 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
479 Status = FileObject->FinalStatus;
480 else
481 Status = IoStatus.Status;
482 }
483 /* done */
484 return Status;
485 }
486
487 /*
488 @implemented
489 */
490 KSDDKAPI
491 NTSTATUS
492 NTAPI
493 KsStreamIo(
494 IN PFILE_OBJECT FileObject,
495 IN PKEVENT Event OPTIONAL,
496 IN PVOID PortContext OPTIONAL,
497 IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
498 IN PVOID CompletionContext OPTIONAL,
499 IN KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL,
500 OUT PIO_STATUS_BLOCK IoStatusBlock,
501 IN OUT PVOID StreamHeaders,
502 IN ULONG Length,
503 IN ULONG Flags,
504 IN KPROCESSOR_MODE RequestorMode)
505 {
506 PIRP Irp;
507 PIO_STACK_LOCATION IoStack;
508 PDEVICE_OBJECT DeviceObject;
509 ULONG Code;
510 NTSTATUS Status;
511 LARGE_INTEGER Offset;
512 PKSIOBJECT_HEADER ObjectHeader;
513
514
515 if (Flags == KSSTREAM_READ)
516 Code = IRP_MJ_READ;
517 else if (Flags == KSSTREAM_WRITE)
518 Code = IRP_MJ_WRITE;
519 else
520 return STATUS_INVALID_PARAMETER;
521
522 DeviceObject = IoGetRelatedDeviceObject(FileObject);
523 if (!DeviceObject)
524 return STATUS_INVALID_PARAMETER;
525
526 if (Event)
527 {
528 KeResetEvent(Event);
529 }
530
531 //ASSERT(DeviceObject->DeviceType == FILE_DEVICE_KS);
532 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
533 ASSERT(ObjectHeader);
534 if (Code == IRP_MJ_READ)
535 {
536 if (ObjectHeader->DispatchTable.FastRead)
537 {
538 if (ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
539 {
540 return STATUS_SUCCESS;
541 }
542 }
543 }
544 else
545 {
546 if (ObjectHeader->DispatchTable.FastWrite)
547 {
548 if (ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject))
549 {
550 return STATUS_SUCCESS;
551 }
552 }
553 }
554
555 Offset.QuadPart = 0LL;
556 Irp = IoBuildSynchronousFsdRequest(Code, DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
557 if (!Irp)
558 {
559 return STATUS_UNSUCCESSFUL;
560 }
561
562
563 if (CompletionRoutine)
564 {
565 IoSetCompletionRoutine(Irp,
566 CompletionRoutine,
567 CompletionContext,
568 (CompletionInvocationFlags & KsInvokeOnSuccess),
569 (CompletionInvocationFlags & KsInvokeOnError),
570 (CompletionInvocationFlags & KsInvokeOnCancel));
571 }
572
573 IoStack = IoGetNextIrpStackLocation(Irp);
574 IoStack->FileObject = FileObject;
575
576 Status = IoCallDriver(DeviceObject, Irp);
577 return Status;
578 }
579
580
581 /*
582 @unimplemented
583 */
584 KSDDKAPI
585 NTSTATUS
586 NTAPI
587 KsProbeStreamIrp(
588 IN PIRP Irp,
589 IN ULONG ProbeFlags,
590 IN ULONG HeaderSize)
591 {
592 UNIMPLEMENTED;
593 return STATUS_UNSUCCESSFUL;
594 }
595
596 /*
597 @implemented
598 */
599 KSDDKAPI
600 NTSTATUS
601 NTAPI
602 KsAllocateExtraData(
603 IN PIRP Irp,
604 IN ULONG ExtraSize,
605 OUT PVOID* ExtraBuffer)
606 {
607 PIO_STACK_LOCATION IoStack;
608 ULONG Count, Index;
609 PUCHAR Buffer, BufferOrg;
610 PKSSTREAM_HEADER Header;
611 NTSTATUS Status = STATUS_SUCCESS;
612
613 /* get current irp stack */
614 IoStack = IoGetCurrentIrpStackLocation(Irp);
615
616 /* sanity check */
617 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
618
619 /* get total length */
620 Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
621
622 /* allocate buffer */
623 Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
624 if (!Buffer)
625 return STATUS_INSUFFICIENT_RESOURCES;
626
627 _SEH2_TRY
628 {
629 /* get input buffer */
630 Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
631 for(Index = 0; Index < Count; Index++)
632 {
633 /* copy stream header */
634 RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
635
636 /* move to next header */
637 Header++;
638 /* increment output buffer offset */
639 Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
640 }
641 }
642 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
643 {
644 /* Exception, get the error code */
645 Status = _SEH2_GetExceptionCode();
646 }
647 _SEH2_END;
648
649 if (!NT_SUCCESS(Status))
650 {
651 /* free buffer on exception */
652 FreeItem(Buffer);
653 return Status;
654 }
655
656 /* store result */
657 *ExtraBuffer = BufferOrg;
658
659 /* done */
660 return STATUS_SUCCESS;
661 }
662
663 /*
664 @implemented
665 */
666 KSDDKAPI
667 VOID
668 NTAPI
669 KsNullDriverUnload(
670 IN PDRIVER_OBJECT DriverObject)
671 {
672 }
673
674 /*
675 @implemented
676 */
677 KSDDKAPI
678 NTSTATUS
679 NTAPI
680 KsDispatchInvalidDeviceRequest(
681 IN PDEVICE_OBJECT DeviceObject,
682 IN PIRP Irp)
683 {
684 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
685 IoCompleteRequest(Irp, IO_NO_INCREMENT);
686
687 return STATUS_INVALID_DEVICE_REQUEST;
688 }
689
690 /*
691 @implemented
692 */
693 KSDDKAPI
694 NTSTATUS
695 NTAPI
696 KsDefaultDeviceIoCompletion(
697 IN PDEVICE_OBJECT DeviceObject,
698 IN PIRP Irp)
699 {
700 PIO_STACK_LOCATION IoStack;
701 NTSTATUS Status;
702
703 /* get current irp stack */
704 IoStack = IoGetCurrentIrpStackLocation(Irp);
705
706 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY &&
707 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
708 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
709 {
710 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
711 {
712 /* fake success */
713 Status = STATUS_SUCCESS;
714 }
715 else
716 {
717 /* request unsupported */
718 Status = STATUS_INVALID_DEVICE_REQUEST;
719 }
720 }
721 else
722 {
723 /* property / method / event not found */
724 Status = STATUS_PROPSET_NOT_FOUND;
725 }
726
727 /* complete request */
728 Irp->IoStatus.Status = Status;
729 IoCompleteRequest(Irp, IO_NO_INCREMENT);
730
731
732 return Status;
733 }
734
735 /*
736 @implemented
737 */
738 KSDDKAPI
739 BOOLEAN
740 NTAPI
741 KsDispatchFastIoDeviceControlFailure(
742 IN PFILE_OBJECT FileObject,
743 IN BOOLEAN Wait,
744 IN PVOID InputBuffer OPTIONAL,
745 IN ULONG InputBufferLength,
746 OUT PVOID OutputBuffer OPTIONAL,
747 IN ULONG OutputBufferLength,
748 IN ULONG IoControlCode,
749 OUT PIO_STATUS_BLOCK IoStatus,
750 IN PDEVICE_OBJECT DeviceObject)
751 {
752 return FALSE;
753 }
754
755 /*
756 @implemented
757 */
758 KSDDKAPI
759 BOOLEAN
760 NTAPI
761 KsDispatchFastReadFailure(
762 IN PFILE_OBJECT FileObject,
763 IN PLARGE_INTEGER FileOffset,
764 IN ULONG Length,
765 IN BOOLEAN Wait,
766 IN ULONG LockKey,
767 OUT PVOID Buffer,
768 OUT PIO_STATUS_BLOCK IoStatus,
769 IN PDEVICE_OBJECT DeviceObject)
770 {
771 return FALSE;
772 }
773
774
775 /*
776 @implemented
777 */
778 KSDDKAPI
779 VOID
780 NTAPI
781 KsCancelIo(
782 IN OUT PLIST_ENTRY QueueHead,
783 IN PKSPIN_LOCK SpinLock)
784 {
785 PDRIVER_CANCEL OldDriverCancel;
786 PIO_STACK_LOCATION IoStack;
787 PLIST_ENTRY Entry;
788 PIRP Irp;
789 KIRQL OldLevel;
790
791 /* acquire spinlock */
792 KeAcquireSpinLock(SpinLock, &OldLevel);
793 /* point to first entry */
794 Entry = QueueHead->Flink;
795 /* loop all items */
796 while(Entry != QueueHead)
797 {
798 /* get irp offset */
799 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
800
801 /* set cancelled bit */
802 Irp->Cancel = TRUE;
803
804 /* now set the cancel routine */
805 OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
806 if (OldDriverCancel)
807 {
808 /* this irp hasnt been yet used, so free to cancel */
809 KeReleaseSpinLock(SpinLock, OldLevel);
810
811 /* get current irp stack */
812 IoStack = IoGetCurrentIrpStackLocation(Irp);
813
814 /* acquire cancel spinlock */
815 IoAcquireCancelSpinLock(&Irp->CancelIrql);
816
817 /* call provided cancel routine */
818 OldDriverCancel(IoStack->DeviceObject, Irp);
819
820 /* re-acquire spinlock */
821 KeAcquireSpinLock(SpinLock, &OldLevel);
822 }
823 /* move on to next entry */
824 Entry = Entry->Flink;
825 }
826
827 /* the irp has already been canceled */
828 KeReleaseSpinLock(SpinLock, OldLevel);
829
830 }
831
832 /*
833 @implemented
834 */
835 KSDDKAPI
836 VOID
837 NTAPI
838 KsReleaseIrpOnCancelableQueue(
839 IN PIRP Irp,
840 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
841 {
842 PKSPIN_LOCK SpinLock;
843 PDRIVER_CANCEL OldDriverCancel;
844 PIO_STACK_LOCATION IoStack;
845 KIRQL OldLevel;
846
847 /* check for required parameters */
848 if (!Irp)
849 return;
850
851 if (!DriverCancel)
852 {
853 /* default to KsCancelRoutine */
854 DriverCancel = KsCancelRoutine;
855 }
856
857 /* get current irp stack */
858 IoStack = IoGetCurrentIrpStackLocation(Irp);
859
860 /* get internal queue lock */
861 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
862
863 /* acquire spinlock */
864 KeAcquireSpinLock(SpinLock, &OldLevel);
865
866 /* now set the cancel routine */
867 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
868
869 if (Irp->Cancel && OldDriverCancel == NULL)
870 {
871 /* the irp has already been canceled */
872 KeReleaseSpinLock(SpinLock, OldLevel);
873
874 /* cancel routine requires that cancel spinlock is held */
875 IoAcquireCancelSpinLock(&Irp->CancelIrql);
876
877 /* cancel irp */
878 DriverCancel(IoStack->DeviceObject, Irp);
879 }
880 else
881 {
882 /* done */
883 KeReleaseSpinLock(SpinLock, OldLevel);
884 }
885 }
886
887 /*
888 @implemented
889 */
890 KSDDKAPI
891 PIRP
892 NTAPI
893 KsRemoveIrpFromCancelableQueue(
894 IN OUT PLIST_ENTRY QueueHead,
895 IN PKSPIN_LOCK SpinLock,
896 IN KSLIST_ENTRY_LOCATION ListLocation,
897 IN KSIRP_REMOVAL_OPERATION RemovalOperation)
898 {
899 PIRP Irp;
900 PLIST_ENTRY CurEntry;
901 KIRQL OldIrql;
902
903 /* check parameters */
904 if (!QueueHead || !SpinLock)
905 return NULL;
906
907 /* check if parameter ListLocation is valid */
908 if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead)
909 return NULL;
910
911 /* acquire list lock */
912 KeAcquireSpinLock(SpinLock, &OldIrql);
913
914 /* point to queue head */
915 CurEntry = QueueHead;
916
917 do
918 {
919 /* reset irp to null */
920 Irp = NULL;
921
922 /* iterate to next entry */
923 if (ListLocation == KsListEntryHead)
924 CurEntry = CurEntry->Flink;
925 else
926 CurEntry = CurEntry->Blink;
927
928 /* is the end of list reached */
929 if (CurEntry == QueueHead)
930 {
931 /* reached end of list */
932 break;
933 }
934
935 /* get irp offset */
936 Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry);
937
938 if (Irp->Cancel)
939 {
940 /* irp has been canceled */
941 break;
942 }
943
944 if (Irp->CancelRoutine)
945 {
946 /* remove cancel routine */
947 Irp->CancelRoutine = NULL;
948
949 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
950 {
951 /* remove irp from list */
952 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
953 }
954
955 if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem)
956 break;
957 }
958
959 }while(TRUE);
960
961 /* release lock */
962 KeReleaseSpinLock(SpinLock, OldIrql);
963
964 if (!Irp || Irp->CancelRoutine == NULL)
965 {
966 /* either an irp has been acquired or nothing found */
967 return Irp;
968 }
969
970 /* time to remove the canceled irp */
971 IoAcquireCancelSpinLock(&OldIrql);
972 /* acquire list lock */
973 KeAcquireSpinLockAtDpcLevel(SpinLock);
974
975 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
976 {
977 /* remove it */
978 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
979 }
980
981 /* release list lock */
982 KeReleaseSpinLockFromDpcLevel(SpinLock);
983
984 /* release cancel spinlock */
985 IoReleaseCancelSpinLock(OldIrql);
986 /* no non canceled irp has been found */
987 return NULL;
988 }
989
990 /*
991 @unimplemented
992 */
993 KSDDKAPI
994 NTSTATUS
995 NTAPI
996 KsMoveIrpsOnCancelableQueue(
997 IN OUT PLIST_ENTRY SourceList,
998 IN PKSPIN_LOCK SourceLock,
999 IN OUT PLIST_ENTRY DestinationList,
1000 IN PKSPIN_LOCK DestinationLock OPTIONAL,
1001 IN KSLIST_ENTRY_LOCATION ListLocation,
1002 IN PFNKSIRPLISTCALLBACK ListCallback,
1003 IN PVOID Context)
1004 {
1005 UNIMPLEMENTED;
1006 return STATUS_UNSUCCESSFUL;
1007 }
1008
1009 /*
1010 @implemented
1011 */
1012 KSDDKAPI
1013 VOID
1014 NTAPI
1015 KsRemoveSpecificIrpFromCancelableQueue(
1016 IN PIRP Irp)
1017 {
1018 PKSPIN_LOCK SpinLock;
1019 KIRQL OldLevel;
1020
1021 /* get internal queue lock */
1022 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1023
1024 /* acquire spinlock */
1025 KeAcquireSpinLock(SpinLock, &OldLevel);
1026
1027 /* remove the irp from the list */
1028 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1029
1030 /* release spinlock */
1031 KeReleaseSpinLock(SpinLock, OldLevel);
1032 }
1033
1034
1035 /*
1036 @implemented
1037 */
1038 KSDDKAPI
1039 VOID
1040 NTAPI
1041 KsAddIrpToCancelableQueue(
1042 IN OUT PLIST_ENTRY QueueHead,
1043 IN PKSPIN_LOCK SpinLock,
1044 IN PIRP Irp,
1045 IN KSLIST_ENTRY_LOCATION ListLocation,
1046 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1047 {
1048 PDRIVER_CANCEL OldDriverCancel;
1049 PIO_STACK_LOCATION IoStack;
1050 KIRQL OldLevel;
1051
1052 /* check for required parameters */
1053 if (!QueueHead || !SpinLock || !Irp)
1054 return;
1055
1056 if (!DriverCancel)
1057 {
1058 /* default to KsCancelRoutine */
1059 DriverCancel = KsCancelRoutine;
1060 }
1061
1062 /* get current irp stack */
1063 IoStack = IoGetCurrentIrpStackLocation(Irp);
1064
1065 /* acquire spinlock */
1066 KeAcquireSpinLock(SpinLock, &OldLevel);
1067
1068 if (ListLocation == KsListEntryTail)
1069 {
1070 /* insert irp to tail of list */
1071 InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1072 }
1073 else
1074 {
1075 /* insert irp to head of list */
1076 InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1077 }
1078
1079 /* store internal queue lock */
1080 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
1081
1082 /* now set the cancel routine */
1083 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1084
1085 if (Irp->Cancel && OldDriverCancel == NULL)
1086 {
1087 /* the irp has already been canceled */
1088 KeReleaseSpinLock(SpinLock, OldLevel);
1089
1090 /* cancel routine requires that cancel spinlock is held */
1091 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1092
1093 /* cancel irp */
1094 DriverCancel(IoStack->DeviceObject, Irp);
1095 }
1096 else
1097 {
1098 /* done */
1099 KeReleaseSpinLock(SpinLock, OldLevel);
1100 }
1101 }
1102
1103 /*
1104 @implemented
1105 */
1106 KSDDKAPI
1107 VOID
1108 NTAPI
1109 KsCancelRoutine(
1110 IN PDEVICE_OBJECT DeviceObject,
1111 IN PIRP Irp)
1112 {
1113 PKSPIN_LOCK SpinLock;
1114 KIRQL OldLevel;
1115
1116 /* get internal queue lock */
1117 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1118
1119 /* acquire spinlock */
1120 KeAcquireSpinLock(SpinLock, &OldLevel);
1121
1122 /* sanity check */
1123 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1124
1125 /* release cancel spinlock */
1126 IoReleaseCancelSpinLock(DISPATCH_LEVEL);
1127
1128 /* remove the irp from the list */
1129 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1130
1131 /* release spinlock */
1132 KeReleaseSpinLock(SpinLock, OldLevel);
1133
1134 /* has the irp already been canceled */
1135 if (Irp->IoStatus.Status != STATUS_CANCELLED)
1136 {
1137 /* let's complete it */
1138 Irp->IoStatus.Status = STATUS_CANCELLED;
1139 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1140 }
1141 }
1142
1143 NTSTATUS
1144 FindMatchingCreateItem(
1145 PLIST_ENTRY ListHead,
1146 ULONG BufferSize,
1147 LPWSTR Buffer,
1148 OUT PCREATE_ITEM_ENTRY *OutCreateItem)
1149 {
1150 PLIST_ENTRY Entry;
1151 PCREATE_ITEM_ENTRY CreateItemEntry;
1152
1153 /* remove '\' slash */
1154 Buffer++;
1155 BufferSize -= sizeof(WCHAR);
1156
1157 /* point to first entry */
1158 Entry = ListHead->Flink;
1159
1160 /* loop all device items */
1161 while(Entry != ListHead)
1162 {
1163 /* get create item entry */
1164 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1165
1166 ASSERT(CreateItemEntry->CreateItem);
1167
1168 if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
1169 {
1170 /* create item is default */
1171 *OutCreateItem = CreateItemEntry;
1172 return STATUS_SUCCESS;
1173 }
1174
1175 if (!CreateItemEntry->CreateItem->Create)
1176 {
1177 /* skip free create item */
1178 Entry = Entry->Flink;
1179 continue;
1180 }
1181
1182 ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
1183
1184 DPRINT1("CreateItem %S Length %u Request %S %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
1185 CreateItemEntry->CreateItem->ObjectClass.Length,
1186 Buffer,
1187 BufferSize);
1188
1189 if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
1190 {
1191 /* create item doesnt match in length */
1192 Entry = Entry->Flink;
1193 continue;
1194 }
1195
1196 /* now check if the object class is the same */
1197 if (RtlCompareMemory(CreateItemEntry->CreateItem->ObjectClass.Buffer, Buffer, CreateItemEntry->CreateItem->ObjectClass.Length) == CreateItemEntry->CreateItem->ObjectClass.Length)
1198 {
1199 /* found matching create item */
1200 *OutCreateItem = CreateItemEntry;
1201 return STATUS_SUCCESS;
1202 }
1203 /* iterate to next */
1204 Entry = Entry->Flink;
1205 }
1206
1207 return STATUS_NOT_FOUND;
1208 }
1209
1210 NTSTATUS
1211 NTAPI
1212 KspCreate(
1213 IN PDEVICE_OBJECT DeviceObject,
1214 IN PIRP Irp)
1215 {
1216 PCREATE_ITEM_ENTRY CreateItemEntry;
1217 PIO_STACK_LOCATION IoStack;
1218 PDEVICE_EXTENSION DeviceExtension;
1219 PKSIDEVICE_HEADER DeviceHeader;
1220 PKSIOBJECT_HEADER ObjectHeader;
1221 NTSTATUS Status;
1222
1223 DPRINT("KS / CREATE\n");
1224 /* get current stack location */
1225 IoStack = IoGetCurrentIrpStackLocation(Irp);
1226 /* get device extension */
1227 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1228 /* get device header */
1229 DeviceHeader = DeviceExtension->DeviceHeader;
1230
1231 if (IoStack->FileObject->FileName.Buffer == NULL && DeviceHeader->ItemListCount == 1)
1232 {
1233 /* hack for bug 4566 */
1234 ASSERT(!IsListEmpty(&DeviceHeader->ItemList));
1235 /* get create item entry */
1236 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(DeviceHeader->ItemList.Flink, CREATE_ITEM_ENTRY, Entry);
1237
1238 ASSERT(CreateItemEntry->CreateItem);
1239
1240 if (!CreateItemEntry->CreateItem->Create)
1241 {
1242 /* no valid create item */
1243 Irp->IoStatus.Information = 0;
1244 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1245 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1246 /* return status */
1247 return STATUS_UNSUCCESSFUL;
1248 }
1249
1250 /* set object create item */
1251 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1252
1253 /* call create function */
1254 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1255
1256 if (NT_SUCCESS(Status))
1257 {
1258 /* increment create item reference count */
1259 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1260 }
1261 /* return result */
1262 return Status;
1263 }
1264
1265
1266 /* hack for bug 4566 */
1267 if (IoStack->FileObject->FileName.Buffer == NULL)
1268 {
1269 DPRINT("Using reference string hack\n");
1270 Irp->IoStatus.Information = 0;
1271 /* set return status */
1272 Irp->IoStatus.Status = STATUS_SUCCESS;
1273 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1274 return STATUS_SUCCESS;
1275 }
1276
1277
1278 if (IoStack->FileObject->RelatedFileObject != NULL)
1279 {
1280 /* request is to instantiate a pin / node / clock / allocator */
1281 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext;
1282
1283 /* sanity check */
1284 ASSERT(ObjectHeader);
1285
1286 /* find a matching a create item */
1287 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1288 }
1289 else
1290 {
1291 /* request to create a filter */
1292 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1293 }
1294
1295 if (NT_SUCCESS(Status))
1296 {
1297 /* set object create item */
1298 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1299
1300 /* call create function */
1301 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1302
1303 if (NT_SUCCESS(Status))
1304 {
1305 /* increment create item reference count */
1306 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1307 }
1308 return Status;
1309 }
1310
1311
1312 Irp->IoStatus.Information = 0;
1313 /* set return status */
1314 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1315 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1316 return STATUS_UNSUCCESSFUL;
1317 }
1318
1319 NTSTATUS
1320 RosDeviceInterfaceReferenceStringHack(
1321 IN PDEVICE_OBJECT DeviceObject,
1322 IN PIRP Irp)
1323 {
1324 PIO_STACK_LOCATION IoStack;
1325 PKSIDEVICE_HEADER DeviceHeader;
1326 PDEVICE_EXTENSION DeviceExtension;
1327 PCREATE_ITEM_ENTRY CreateItemEntry;
1328 PLIST_ENTRY Entry;
1329 LPWSTR Buffer;
1330 ULONG Length;
1331
1332 /* get current stack location */
1333 IoStack = IoGetCurrentIrpStackLocation(Irp);
1334
1335 /* get device extension */
1336 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1337 /* get device header */
1338 DeviceHeader = DeviceExtension->DeviceHeader;
1339
1340 /* retrieve all available reference strings registered */
1341 Length = 0;
1342 Entry = DeviceHeader->ItemList.Flink;
1343 while(Entry != &DeviceHeader->ItemList)
1344 {
1345 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1346
1347 ASSERT(CreateItemEntry->CreateItem);
1348 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1349 Length += wcslen(CreateItemEntry->CreateItem->ObjectClass.Buffer) + 1;
1350
1351 Entry = Entry->Flink;
1352 }
1353
1354 /* add extra zero */
1355 Length += 1;
1356
1357 /* allocate the buffer */
1358 Buffer = ExAllocatePool(NonPagedPool, Length * sizeof(WCHAR));
1359 if (!Buffer)
1360 {
1361 Irp->IoStatus.Information = 0;
1362 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1363 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1364 return STATUS_INSUFFICIENT_RESOURCES;
1365 }
1366
1367
1368 *((LPWSTR*)Irp->UserBuffer) = Buffer;
1369 Irp->IoStatus.Status = STATUS_SUCCESS;
1370 Irp->IoStatus.Information = sizeof(LPWSTR);
1371
1372 Entry = DeviceHeader->ItemList.Flink;
1373 while(Entry != &DeviceHeader->ItemList)
1374 {
1375 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1376
1377 ASSERT(CreateItemEntry->CreateItem);
1378 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1379 {
1380 wcscpy(Buffer, CreateItemEntry->CreateItem->ObjectClass.Buffer);
1381 Buffer += wcslen(Buffer) + 1;
1382 }
1383 Entry = Entry->Flink;
1384 }
1385
1386
1387
1388 *Buffer = L'\0';
1389 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1390 return STATUS_SUCCESS;
1391
1392 }
1393
1394 NTSTATUS
1395 NTAPI
1396 KspDeviceControl(
1397 IN PDEVICE_OBJECT DeviceObject,
1398 IN PIRP Irp)
1399 {
1400 PIO_STACK_LOCATION IoStack;
1401 PKSIOBJECT_HEADER ObjectHeader;
1402 PKSIDEVICE_HEADER DeviceHeader;
1403 PDEVICE_EXTENSION DeviceExtension;
1404
1405
1406
1407 /* get current stack location */
1408 IoStack = IoGetCurrentIrpStackLocation(Irp);
1409
1410 /* get device extension */
1411 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1412 /* get device header */
1413 DeviceHeader = DeviceExtension->DeviceHeader;
1414
1415 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
1416 {
1417 /* hack for bug 4566 */
1418 return RosDeviceInterfaceReferenceStringHack(DeviceObject, Irp);
1419 }
1420
1421 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1422
1423 ASSERT(ObjectHeader);
1424 //KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
1425
1426 return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
1427 }
1428
1429 NTSTATUS
1430 NTAPI
1431 KspDispatchIrp(
1432 IN PDEVICE_OBJECT DeviceObject,
1433 IN PIRP Irp)
1434 {
1435 PIO_STACK_LOCATION IoStack;
1436 PDEVICE_EXTENSION DeviceExtension;
1437 PKSIOBJECT_HEADER ObjectHeader;
1438 PKSIDEVICE_HEADER DeviceHeader;
1439 PDRIVER_DISPATCH Dispatch;
1440 NTSTATUS Status;
1441
1442 /* get current stack location */
1443 IoStack = IoGetCurrentIrpStackLocation(Irp);
1444
1445 /* get device extension */
1446 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1447 /* get device header */
1448 DeviceHeader = DeviceExtension->DeviceHeader;
1449
1450 /* get object header */
1451 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1452
1453 if (!ObjectHeader)
1454 {
1455 /* hack for bug 4566 */
1456 Irp->IoStatus.Status = STATUS_SUCCESS;
1457 Irp->IoStatus.Information = 0;
1458 /* complete and forget */
1459 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1460 return STATUS_SUCCESS;
1461 }
1462
1463 /* sanity check */
1464 ASSERT(ObjectHeader);
1465 /* store create item */
1466 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1467
1468 /* retrieve matching dispatch function */
1469 switch(IoStack->MajorFunction)
1470 {
1471 case IRP_MJ_CLOSE:
1472 Dispatch = ObjectHeader->DispatchTable.Close;
1473 break;
1474 case IRP_MJ_DEVICE_CONTROL:
1475 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
1476 break;
1477 case IRP_MJ_READ:
1478 Dispatch = ObjectHeader->DispatchTable.Read;
1479 break;
1480 case IRP_MJ_WRITE:
1481 Dispatch = ObjectHeader->DispatchTable.Write;
1482 break;
1483 case IRP_MJ_FLUSH_BUFFERS :
1484 Dispatch = ObjectHeader->DispatchTable.Flush;
1485 break;
1486 case IRP_MJ_QUERY_SECURITY:
1487 Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
1488 break;
1489 case IRP_MJ_SET_SECURITY:
1490 Dispatch = ObjectHeader->DispatchTable.SetSecurity;
1491 break;
1492 case IRP_MJ_PNP:
1493 Dispatch = KsDefaultDispatchPnp;
1494 default:
1495 Dispatch = NULL;
1496 }
1497
1498 /* is the request supported */
1499 if (Dispatch)
1500 {
1501 /* now call the dispatch function */
1502 Status = Dispatch(DeviceObject, Irp);
1503 }
1504 else
1505 {
1506 /* not supported request */
1507 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1508 }
1509
1510 /* done */
1511 return Status;
1512 }
1513
1514 /*
1515 @implemented
1516 */
1517 KSDDKAPI
1518 NTSTATUS
1519 NTAPI
1520 KsSetMajorFunctionHandler(
1521 IN PDRIVER_OBJECT DriverObject,
1522 IN ULONG MajorFunction)
1523 {
1524 switch ( MajorFunction )
1525 {
1526 case IRP_MJ_CREATE:
1527 DriverObject->MajorFunction[MajorFunction] = KspCreate;
1528 break;
1529 break;
1530 case IRP_MJ_DEVICE_CONTROL:
1531 DriverObject->MajorFunction[MajorFunction] = KspDeviceControl;
1532 break;
1533 case IRP_MJ_CLOSE:
1534 case IRP_MJ_READ:
1535 case IRP_MJ_WRITE:
1536 case IRP_MJ_FLUSH_BUFFERS :
1537 case IRP_MJ_QUERY_SECURITY:
1538 case IRP_MJ_SET_SECURITY:
1539 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
1540 break;
1541 default:
1542 return STATUS_INVALID_PARAMETER;
1543 };
1544
1545 return STATUS_SUCCESS;
1546 }
1547
1548 /*
1549 @implemented
1550 */
1551 KSDDKAPI
1552 NTSTATUS
1553 NTAPI
1554 KsDispatchIrp(
1555 IN PDEVICE_OBJECT DeviceObject,
1556 IN PIRP Irp)
1557 {
1558 PIO_STACK_LOCATION IoStack;
1559 PKSIDEVICE_HEADER DeviceHeader;
1560 PDEVICE_EXTENSION DeviceExtension;
1561
1562 /* get device extension */
1563 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1564 /* get device header */
1565 DeviceHeader = DeviceExtension->DeviceHeader;
1566
1567
1568 /* get current irp stack */
1569 IoStack = IoGetCurrentIrpStackLocation(Irp);
1570
1571 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
1572 {
1573 if (IoStack->MajorFunction == IRP_MJ_CREATE)
1574 {
1575 /* check internal type */
1576 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1577 {
1578 /* AVStream client */
1579 return IKsDevice_Create(DeviceObject, Irp);
1580 }
1581 else
1582 {
1583 /* external client (portcls) */
1584 return KspCreate(DeviceObject, Irp);
1585 }
1586 }
1587
1588 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1589 {
1590 /* handle device requests */
1591 return KspDeviceControl(DeviceObject, Irp);
1592 }
1593
1594 switch (IoStack->MajorFunction)
1595 {
1596 case IRP_MJ_CLOSE:
1597 case IRP_MJ_READ:
1598 case IRP_MJ_WRITE:
1599 case IRP_MJ_FLUSH_BUFFERS:
1600 case IRP_MJ_QUERY_SECURITY:
1601 case IRP_MJ_SET_SECURITY:
1602 case IRP_MJ_PNP:
1603 return KspDispatchIrp(DeviceObject, Irp);
1604 default:
1605 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1606 }
1607 }
1608
1609 /* dispatch power */
1610 if (IoStack->MajorFunction == IRP_MJ_POWER)
1611 {
1612 /* check internal type */
1613 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1614 {
1615 /* AVStream client */
1616 return IKsDevice_Power(DeviceObject, Irp);
1617 }
1618 else
1619 {
1620 /* external client (portcls) */
1621 return KsDefaultDispatchPower(DeviceObject, Irp);
1622 }
1623 }
1624 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
1625 {
1626 /* check internal type */
1627 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1628 {
1629 /* AVStream client */
1630 return IKsDevice_Pnp(DeviceObject, Irp);
1631 }
1632 else
1633 {
1634 /* external client (portcls) */
1635 return KsDefaultDispatchPnp(DeviceObject, Irp);
1636 }
1637 }
1638 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
1639 {
1640 /* forward irp */
1641 return KsDefaultForwardIrp(DeviceObject, Irp);
1642 }
1643 else
1644 {
1645 /* not supported */
1646 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1647 }
1648 }
1649
1650 /*
1651 @unimplemented
1652 */
1653 KSDDKAPI
1654 ULONG
1655 NTAPI
1656 KsGetNodeIdFromIrp(
1657 IN PIRP Irp)
1658 {
1659 UNIMPLEMENTED
1660 return (ULONG)-1;
1661 }
1662