[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / irp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/factory.c
5 * PURPOSE: KS Allocator functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 /*
13 @implemented
14 */
15 KSDDKAPI
16 NTSTATUS
17 NTAPI
18 KsDispatchQuerySecurity(
19 IN PDEVICE_OBJECT DeviceObject,
20 IN PIRP Irp)
21 {
22 PKSOBJECT_CREATE_ITEM CreateItem;
23 PIO_STACK_LOCATION IoStack;
24 NTSTATUS Status;
25 ULONG Length;
26
27 /* get current irp stack */
28 IoStack = IoGetCurrentIrpStackLocation(Irp);
29
30 /* get create item */
31 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
32
33 if (!CreateItem || !CreateItem->SecurityDescriptor)
34 {
35 /* no create item */
36 Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
37 IoCompleteRequest(Irp, IO_NO_INCREMENT);
38 return STATUS_NO_SECURITY_ON_OBJECT;
39 }
40
41
42 /* get input length */
43 Length = IoStack->Parameters.QuerySecurity.Length;
44
45 /* clone the security descriptor */
46 Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, (PSECURITY_DESCRIPTOR)Irp->UserBuffer, &Length, &CreateItem->SecurityDescriptor);
47
48 DPRINT("SeQuerySecurityDescriptorInfo Status %x\n", Status);
49 /* store result */
50 Irp->IoStatus.Status = Status;
51 Irp->IoStatus.Information = Length;
52
53 IoCompleteRequest(Irp, IO_NO_INCREMENT);
54 return Status;
55 }
56
57 /*
58 @implemented
59 */
60 KSDDKAPI
61 NTSTATUS
62 NTAPI
63 KsDispatchSetSecurity(
64 IN PDEVICE_OBJECT DeviceObject,
65 IN PIRP Irp)
66 {
67 PKSOBJECT_CREATE_ITEM CreateItem;
68 PIO_STACK_LOCATION IoStack;
69 PGENERIC_MAPPING Mapping;
70 PSECURITY_DESCRIPTOR Descriptor;
71 NTSTATUS Status;
72
73 /* get current irp stack */
74 IoStack = IoGetCurrentIrpStackLocation(Irp);
75
76 /* get create item */
77 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
78
79 if (!CreateItem || !CreateItem->SecurityDescriptor)
80 {
81 /* no create item */
82 Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
83 IoCompleteRequest(Irp, IO_NO_INCREMENT);
84 return STATUS_NO_SECURITY_ON_OBJECT;
85 }
86
87 /* backup old descriptor */
88 Descriptor = CreateItem->SecurityDescriptor;
89
90 /* get generic mapping */
91 Mapping = IoGetFileObjectGenericMapping();
92
93 /* change security descriptor */
94 Status = SeSetSecurityDescriptorInfo(NULL, /*FIXME */
95 &IoStack->Parameters.SetSecurity.SecurityInformation,
96 IoStack->Parameters.SetSecurity.SecurityDescriptor,
97 &CreateItem->SecurityDescriptor,
98 NonPagedPool,
99 Mapping);
100
101 if (NT_SUCCESS(Status))
102 {
103 /* free old descriptor */
104 ExFreePool(Descriptor);
105
106 /* mark create item as changed */
107 CreateItem->Flags |= KSCREATE_ITEM_SECURITYCHANGED;
108 }
109
110 /* store result */
111 Irp->IoStatus.Status = Status;
112 IoCompleteRequest(Irp, IO_NO_INCREMENT);
113
114 return Status;
115 }
116
117 /*
118 @unimplemented
119 */
120 KSDDKAPI
121 NTSTATUS
122 NTAPI
123 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 @implemented
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 PIRP Irp;
361 PIO_STACK_LOCATION IoStack;
362 IO_STATUS_BLOCK IoStatus;
363 KEVENT Event;
364 LARGE_INTEGER Offset;
365 IO_STATUS_BLOCK StatusBlock;
366 NTSTATUS Status;
367
368 /* get related file object */
369 DeviceObject = IoGetRelatedDeviceObject(FileObject);
370
371 /* get fast i/o table */
372 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
373
374 /* is there a fast table */
375 if (FastIoDispatch)
376 {
377 /* check the class */
378 if (FileInformationClass == FileBasicInformation)
379 {
380 /* use FastIoQueryBasicInfo routine */
381 if (FastIoDispatch->FastIoQueryBasicInfo)
382 {
383 return FastIoDispatch->FastIoQueryBasicInfo(FileObject, TRUE, (PFILE_BASIC_INFORMATION)FileInformation, &IoStatus, DeviceObject);
384 }
385 }
386 else if (FileInformationClass == FileStandardInformation)
387 {
388 /* use FastIoQueryBasicInfo routine */
389 if (FastIoDispatch->FastIoQueryBasicInfo)
390 {
391 return FastIoDispatch->FastIoQueryStandardInfo(FileObject, TRUE, (PFILE_STANDARD_INFORMATION)FileInformation, &IoStatus, DeviceObject);
392 }
393 }
394 }
395 /* clear event */
396 KeClearEvent(&FileObject->Event);
397
398 /* initialize event */
399 KeInitializeEvent(&Event, NotificationEvent, FALSE);
400
401 /* set offset to zero */
402 Offset.QuadPart = 0L;
403
404 /* build the request */
405 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_QUERY_INFORMATION, IoGetRelatedDeviceObject(FileObject), NULL, 0, &Offset, &Event, &StatusBlock);
406
407 if (!Irp)
408 return STATUS_INSUFFICIENT_RESOURCES;
409
410 /* get next stack location */
411 IoStack = IoGetNextIrpStackLocation(Irp);
412
413 /* setup parameters */
414 IoStack->Parameters.QueryFile.FileInformationClass = FileInformationClass;
415 IoStack->Parameters.QueryFile.Length = Length;
416 Irp->AssociatedIrp.SystemBuffer = FileInformation;
417
418
419 /* call the driver */
420 Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
421
422 if (Status == STATUS_PENDING)
423 {
424 /* wait for the operation to complete */
425 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
426
427 /* is object sync */
428 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
429 Status = FileObject->FinalStatus;
430 else
431 Status = StatusBlock.Status;
432 }
433
434 /* done */
435 return Status;
436 }
437
438 /*
439 @implemented
440 */
441 KSDDKAPI
442 NTSTATUS
443 NTAPI
444 KsSetInformationFile(
445 IN PFILE_OBJECT FileObject,
446 IN PVOID FileInformation,
447 IN ULONG Length,
448 IN FILE_INFORMATION_CLASS FileInformationClass)
449 {
450 PIO_STACK_LOCATION IoStack;
451 PDEVICE_OBJECT DeviceObject;
452 PIRP Irp;
453 PVOID Buffer;
454 KEVENT Event;
455 LARGE_INTEGER Offset;
456 IO_STATUS_BLOCK IoStatus;
457 NTSTATUS Status;
458
459 /* get related device object */
460 DeviceObject = IoGetRelatedDeviceObject(FileObject);
461
462 /* copy file information */
463 Buffer = AllocateItem(NonPagedPool, Length);
464 if (!Buffer)
465 return STATUS_INSUFFICIENT_RESOURCES;
466
467 _SEH2_TRY
468 {
469 ProbeForRead(Buffer, Length, sizeof(UCHAR));
470 RtlMoveMemory(Buffer, FileInformation, Length);
471 Status = STATUS_SUCCESS;
472 }
473 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
474 {
475 /* Exception, get the error code */
476 Status = _SEH2_GetExceptionCode();
477 }
478 _SEH2_END;
479
480 if (!NT_SUCCESS(Status))
481 {
482 /* invalid user buffer */
483 FreeItem(Buffer);
484 return Status;
485 }
486
487 /* initialize the event */
488 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
489
490 /* zero offset */
491 Offset.QuadPart = 0LL;
492
493 /* build the irp */
494 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SET_INFORMATION, DeviceObject, NULL, 0, &Offset, &Event, &IoStatus);
495
496 if (!Irp)
497 {
498 /* failed to allocate irp */
499 FreeItem(Buffer);
500 return STATUS_INSUFFICIENT_RESOURCES;
501 }
502
503 /* get next stack location */
504 IoStack = IoGetNextIrpStackLocation(Irp);
505
506 /* set irp parameters */
507 IoStack->Parameters.SetFile.FileInformationClass = FileInformationClass;
508 IoStack->Parameters.SetFile.Length = Length;
509 IoStack->Parameters.SetFile.FileObject = FileObject;
510 Irp->AssociatedIrp.SystemBuffer = Buffer;
511 Irp->UserBuffer = FileInformation;
512
513 /* dispatch the irp */
514 Status = IoCallDriver(DeviceObject, Irp);
515
516 if (Status == STATUS_PENDING)
517 {
518 /* wait untill the operation has completed */
519 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
520 /* is a sync file object */
521 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
522 Status = FileObject->FinalStatus;
523 else
524 Status = IoStatus.Status;
525 }
526 /* done */
527 return Status;
528 }
529
530 /*
531 @implemented
532 */
533 KSDDKAPI
534 NTSTATUS
535 NTAPI
536 KsStreamIo(
537 IN PFILE_OBJECT FileObject,
538 IN PKEVENT Event OPTIONAL,
539 IN PVOID PortContext OPTIONAL,
540 IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
541 IN PVOID CompletionContext OPTIONAL,
542 IN KSCOMPLETION_INVOCATION CompletionInvocationFlags OPTIONAL,
543 OUT PIO_STATUS_BLOCK IoStatusBlock,
544 IN OUT PVOID StreamHeaders,
545 IN ULONG Length,
546 IN ULONG Flags,
547 IN KPROCESSOR_MODE RequestorMode)
548 {
549 PIRP Irp;
550 PIO_STACK_LOCATION IoStack;
551 PDEVICE_OBJECT DeviceObject;
552 NTSTATUS Status;
553 LARGE_INTEGER Offset;
554 PKSIOBJECT_HEADER ObjectHeader;
555 BOOLEAN Ret;
556
557 /* get related device object */
558 DeviceObject = IoGetRelatedDeviceObject(FileObject);
559 /* sanity check */
560 ASSERT(DeviceObject != NULL);
561
562 /* is there a event provided */
563 if (Event)
564 {
565 /* reset event */
566 KeClearEvent(Event);
567 }
568
569 if (RequestorMode || ExGetPreviousMode() == KernelMode)
570 {
571 /* requestor is from kernel land */
572 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
573
574 if (ObjectHeader)
575 {
576 /* there is a object header */
577 if (Flags == KSSTREAM_READ)
578 {
579 /* is fast read supported */
580 if (ObjectHeader->DispatchTable.FastRead)
581 {
582 /* call fast read dispatch routine */
583 Ret = ObjectHeader->DispatchTable.FastRead(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
584
585 if (Ret)
586 {
587 /* the request was handeled */
588 return IoStatusBlock->Status;
589 }
590 }
591 }
592 else if (Flags == KSSTREAM_WRITE)
593 {
594 /* is fast write supported */
595 if (ObjectHeader->DispatchTable.FastWrite)
596 {
597 /* call fast write dispatch routine */
598 Ret = ObjectHeader->DispatchTable.FastWrite(FileObject, NULL, Length, FALSE, 0, StreamHeaders, IoStatusBlock, DeviceObject);
599
600 if (Ret)
601 {
602 /* the request was handeled */
603 return IoStatusBlock->Status;
604 }
605 }
606 }
607 }
608 }
609
610 /* clear file object event */
611 KeClearEvent(&FileObject->Event);
612
613 /* set the offset to zero */
614 Offset.QuadPart = 0LL;
615
616 /* now build the irp */
617 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_DEVICE_CONTROL,
618 DeviceObject, (PVOID)StreamHeaders, Length, &Offset, Event, IoStatusBlock);
619 if (!Irp)
620 {
621 /* not enough memory */
622 return STATUS_INSUFFICIENT_RESOURCES;
623 }
624
625 /* setup irp parameters */
626 Irp->RequestorMode = RequestorMode;
627 Irp->Overlay.AsynchronousParameters.UserApcContext = PortContext;
628 Irp->Tail.Overlay.OriginalFileObject = FileObject;
629 Irp->UserBuffer = StreamHeaders;
630
631 /* get next irp stack location */
632 IoStack = IoGetNextIrpStackLocation(Irp);
633 /* setup stack parameters */
634 IoStack->FileObject = FileObject;
635 IoStack->Parameters.DeviceIoControl.InputBufferLength = Length;
636 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders;
637 IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
638
639 if (CompletionRoutine)
640 {
641 /* setup completion routine for async processing */
642 IoSetCompletionRoutine(Irp, CompletionRoutine, CompletionContext, (CompletionInvocationFlags & KsInvokeOnSuccess), (CompletionInvocationFlags & KsInvokeOnError), (CompletionInvocationFlags & KsInvokeOnCancel));
643 }
644
645 /* now call the driver */
646 Status = IoCallDriver(DeviceObject, Irp);
647 /* done */
648 return Status;
649 }
650
651 /*
652 @unimplemented
653 */
654 KSDDKAPI
655 NTSTATUS
656 NTAPI
657 KsProbeStreamIrp(
658 IN PIRP Irp,
659 IN ULONG ProbeFlags,
660 IN ULONG HeaderSize)
661 {
662 UNIMPLEMENTED;
663 return STATUS_UNSUCCESSFUL;
664 }
665
666 /*
667 @implemented
668 */
669 KSDDKAPI
670 NTSTATUS
671 NTAPI
672 KsAllocateExtraData(
673 IN PIRP Irp,
674 IN ULONG ExtraSize,
675 OUT PVOID* ExtraBuffer)
676 {
677 PIO_STACK_LOCATION IoStack;
678 ULONG Count, Index;
679 PUCHAR Buffer, BufferOrg;
680 PKSSTREAM_HEADER Header;
681 NTSTATUS Status = STATUS_SUCCESS;
682
683 /* get current irp stack */
684 IoStack = IoGetCurrentIrpStackLocation(Irp);
685
686 /* sanity check */
687 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSSTREAM_HEADER));
688
689 /* get total length */
690 Count = IoStack->Parameters.DeviceIoControl.InputBufferLength / sizeof(KSSTREAM_HEADER);
691
692 /* allocate buffer */
693 Buffer = BufferOrg = AllocateItem(NonPagedPool, Count * (sizeof(KSSTREAM_HEADER) + ExtraSize));
694 if (!Buffer)
695 return STATUS_INSUFFICIENT_RESOURCES;
696
697 _SEH2_TRY
698 {
699 /* get input buffer */
700 Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
701 for(Index = 0; Index < Count; Index++)
702 {
703 /* copy stream header */
704 RtlMoveMemory(Buffer, Header, sizeof(KSSTREAM_HEADER));
705
706 /* move to next header */
707 Header++;
708 /* increment output buffer offset */
709 Buffer += sizeof(KSSTREAM_HEADER) + ExtraSize;
710 }
711 }
712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
713 {
714 /* Exception, get the error code */
715 Status = _SEH2_GetExceptionCode();
716 }
717 _SEH2_END;
718
719 if (!NT_SUCCESS(Status))
720 {
721 /* free buffer on exception */
722 FreeItem(Buffer);
723 return Status;
724 }
725
726 /* store result */
727 *ExtraBuffer = BufferOrg;
728
729 /* done */
730 return STATUS_SUCCESS;
731 }
732
733 /*
734 @implemented
735 */
736 KSDDKAPI
737 VOID
738 NTAPI
739 KsNullDriverUnload(
740 IN PDRIVER_OBJECT DriverObject)
741 {
742 }
743
744 /*
745 @implemented
746 */
747 KSDDKAPI
748 NTSTATUS
749 NTAPI
750 KsDispatchInvalidDeviceRequest(
751 IN PDEVICE_OBJECT DeviceObject,
752 IN PIRP Irp)
753 {
754 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
755 IoCompleteRequest(Irp, IO_NO_INCREMENT);
756
757 return STATUS_INVALID_DEVICE_REQUEST;
758 }
759
760 /*
761 @implemented
762 */
763 KSDDKAPI
764 NTSTATUS
765 NTAPI
766 KsDefaultDeviceIoCompletion(
767 IN PDEVICE_OBJECT DeviceObject,
768 IN PIRP Irp)
769 {
770 PIO_STACK_LOCATION IoStack;
771 NTSTATUS Status;
772
773 /* get current irp stack */
774 IoStack = IoGetCurrentIrpStackLocation(Irp);
775
776 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY &&
777 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_METHOD &&
778 IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
779 {
780 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
781 {
782 /* fake success */
783 Status = STATUS_SUCCESS;
784 }
785 else
786 {
787 /* request unsupported */
788 Status = STATUS_INVALID_DEVICE_REQUEST;
789 }
790 }
791 else
792 {
793 /* property / method / event not found */
794 Status = STATUS_PROPSET_NOT_FOUND;
795 }
796
797 /* complete request */
798 Irp->IoStatus.Status = Status;
799 IoCompleteRequest(Irp, IO_NO_INCREMENT);
800
801
802 return Status;
803 }
804
805 /*
806 @implemented
807 */
808 KSDDKAPI
809 BOOLEAN
810 NTAPI
811 KsDispatchFastIoDeviceControlFailure(
812 IN PFILE_OBJECT FileObject,
813 IN BOOLEAN Wait,
814 IN PVOID InputBuffer OPTIONAL,
815 IN ULONG InputBufferLength,
816 OUT PVOID OutputBuffer OPTIONAL,
817 IN ULONG OutputBufferLength,
818 IN ULONG IoControlCode,
819 OUT PIO_STATUS_BLOCK IoStatus,
820 IN PDEVICE_OBJECT DeviceObject)
821 {
822 return FALSE;
823 }
824
825 /*
826 @implemented
827 */
828 KSDDKAPI
829 BOOLEAN
830 NTAPI
831 KsDispatchFastReadFailure(
832 IN PFILE_OBJECT FileObject,
833 IN PLARGE_INTEGER FileOffset,
834 IN ULONG Length,
835 IN BOOLEAN Wait,
836 IN ULONG LockKey,
837 OUT PVOID Buffer,
838 OUT PIO_STATUS_BLOCK IoStatus,
839 IN PDEVICE_OBJECT DeviceObject)
840 {
841 return FALSE;
842 }
843
844
845 /*
846 @implemented
847 */
848 KSDDKAPI
849 VOID
850 NTAPI
851 KsCancelIo(
852 IN OUT PLIST_ENTRY QueueHead,
853 IN PKSPIN_LOCK SpinLock)
854 {
855 PDRIVER_CANCEL OldDriverCancel;
856 PIO_STACK_LOCATION IoStack;
857 PLIST_ENTRY Entry;
858 PIRP Irp;
859 KIRQL OldLevel;
860
861 /* acquire spinlock */
862 KeAcquireSpinLock(SpinLock, &OldLevel);
863 /* point to first entry */
864 Entry = QueueHead->Flink;
865 /* loop all items */
866 while(Entry != QueueHead)
867 {
868 /* get irp offset */
869 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
870
871 /* set cancelled bit */
872 Irp->Cancel = TRUE;
873
874 /* now set the cancel routine */
875 OldDriverCancel = IoSetCancelRoutine(Irp, NULL);
876 if (OldDriverCancel)
877 {
878 /* this irp hasnt been yet used, so free to cancel */
879 KeReleaseSpinLock(SpinLock, OldLevel);
880
881 /* get current irp stack */
882 IoStack = IoGetCurrentIrpStackLocation(Irp);
883
884 /* acquire cancel spinlock */
885 IoAcquireCancelSpinLock(&Irp->CancelIrql);
886
887 /* call provided cancel routine */
888 OldDriverCancel(IoStack->DeviceObject, Irp);
889
890 /* re-acquire spinlock */
891 KeAcquireSpinLock(SpinLock, &OldLevel);
892 }
893 /* move on to next entry */
894 Entry = Entry->Flink;
895 }
896
897 /* the irp has already been canceled */
898 KeReleaseSpinLock(SpinLock, OldLevel);
899
900 }
901
902 /*
903 @implemented
904 */
905 KSDDKAPI
906 VOID
907 NTAPI
908 KsReleaseIrpOnCancelableQueue(
909 IN PIRP Irp,
910 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
911 {
912 PKSPIN_LOCK SpinLock;
913 PDRIVER_CANCEL OldDriverCancel;
914 PIO_STACK_LOCATION IoStack;
915 KIRQL OldLevel;
916
917 /* check for required parameters */
918 if (!Irp)
919 return;
920
921 if (!DriverCancel)
922 {
923 /* default to KsCancelRoutine */
924 DriverCancel = KsCancelRoutine;
925 }
926
927 /* get current irp stack */
928 IoStack = IoGetCurrentIrpStackLocation(Irp);
929
930 /* get internal queue lock */
931 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
932
933 /* acquire spinlock */
934 KeAcquireSpinLock(SpinLock, &OldLevel);
935
936 /* now set the cancel routine */
937 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
938
939 if (Irp->Cancel && OldDriverCancel == NULL)
940 {
941 /* the irp has already been canceled */
942 KeReleaseSpinLock(SpinLock, OldLevel);
943
944 /* cancel routine requires that cancel spinlock is held */
945 IoAcquireCancelSpinLock(&Irp->CancelIrql);
946
947 /* cancel irp */
948 DriverCancel(IoStack->DeviceObject, Irp);
949 }
950 else
951 {
952 /* done */
953 KeReleaseSpinLock(SpinLock, OldLevel);
954 }
955 }
956
957 /*
958 @implemented
959 */
960 KSDDKAPI
961 PIRP
962 NTAPI
963 KsRemoveIrpFromCancelableQueue(
964 IN OUT PLIST_ENTRY QueueHead,
965 IN PKSPIN_LOCK SpinLock,
966 IN KSLIST_ENTRY_LOCATION ListLocation,
967 IN KSIRP_REMOVAL_OPERATION RemovalOperation)
968 {
969 PIRP Irp;
970 PLIST_ENTRY CurEntry;
971 KIRQL OldIrql;
972
973 /* check parameters */
974 if (!QueueHead || !SpinLock)
975 return NULL;
976
977 /* check if parameter ListLocation is valid */
978 if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead)
979 return NULL;
980
981 /* acquire list lock */
982 KeAcquireSpinLock(SpinLock, &OldIrql);
983
984 /* point to queue head */
985 CurEntry = QueueHead;
986
987 do
988 {
989 /* reset irp to null */
990 Irp = NULL;
991
992 /* iterate to next entry */
993 if (ListLocation == KsListEntryHead)
994 CurEntry = CurEntry->Flink;
995 else
996 CurEntry = CurEntry->Blink;
997
998 /* is the end of list reached */
999 if (CurEntry == QueueHead)
1000 {
1001 /* reached end of list */
1002 break;
1003 }
1004
1005 /* get irp offset */
1006 Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
1007
1008 if (Irp->Cancel)
1009 {
1010 /* irp has been canceled */
1011 break;
1012 }
1013
1014 if (Irp->CancelRoutine)
1015 {
1016 /* remove cancel routine */
1017 Irp->CancelRoutine = NULL;
1018
1019 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1020 {
1021 /* remove irp from list */
1022 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1023 }
1024
1025 if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem)
1026 break;
1027 }
1028
1029 }while(TRUE);
1030
1031 /* release lock */
1032 KeReleaseSpinLock(SpinLock, OldIrql);
1033
1034 if (!Irp || Irp->CancelRoutine == NULL)
1035 {
1036 /* either an irp has been acquired or nothing found */
1037 return Irp;
1038 }
1039
1040 /* time to remove the canceled irp */
1041 IoAcquireCancelSpinLock(&OldIrql);
1042 /* acquire list lock */
1043 KeAcquireSpinLockAtDpcLevel(SpinLock);
1044
1045 if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
1046 {
1047 /* remove it */
1048 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1049 }
1050
1051 /* release list lock */
1052 KeReleaseSpinLockFromDpcLevel(SpinLock);
1053
1054 /* release cancel spinlock */
1055 IoReleaseCancelSpinLock(OldIrql);
1056 /* no non canceled irp has been found */
1057 return NULL;
1058 }
1059
1060 /*
1061 @implemented
1062 */
1063 KSDDKAPI
1064 NTSTATUS
1065 NTAPI
1066 KsMoveIrpsOnCancelableQueue(
1067 IN OUT PLIST_ENTRY SourceList,
1068 IN PKSPIN_LOCK SourceLock,
1069 IN OUT PLIST_ENTRY DestinationList,
1070 IN PKSPIN_LOCK DestinationLock OPTIONAL,
1071 IN KSLIST_ENTRY_LOCATION ListLocation,
1072 IN PFNKSIRPLISTCALLBACK ListCallback,
1073 IN PVOID Context)
1074 {
1075 KIRQL OldLevel;
1076 PLIST_ENTRY SrcEntry;
1077 PIRP Irp;
1078 NTSTATUS Status = STATUS_SUCCESS;
1079
1080 if (!DestinationLock)
1081 {
1082 /* no destination lock just acquire the source lock */
1083 KeAcquireSpinLock(SourceLock, &OldLevel);
1084 }
1085 else
1086 {
1087 /* acquire cancel spinlock */
1088 IoAcquireCancelSpinLock(&OldLevel);
1089
1090 /* now acquire source lock */
1091 KeAcquireSpinLockAtDpcLevel(SourceLock);
1092
1093 /* now acquire destination lock */
1094 KeAcquireSpinLockAtDpcLevel(DestinationLock);
1095 }
1096
1097 /* point to list head */
1098 SrcEntry = SourceList;
1099
1100 /* now move all irps */
1101 while(TRUE)
1102 {
1103 if (ListLocation == KsListEntryTail)
1104 {
1105 /* move queue downwards */
1106 SrcEntry = SrcEntry->Flink;
1107 }
1108 else
1109 {
1110 /* move queue upwards */
1111 SrcEntry = SrcEntry->Blink;
1112 }
1113
1114 if (SrcEntry == SourceList)
1115 {
1116 /* eof list reached */
1117 break;
1118 }
1119
1120 /* get irp offset */
1121 Irp = (PIRP)CONTAINING_RECORD(SrcEntry, IRP, Tail.Overlay.ListEntry);
1122
1123 /* now check if irp can be moved */
1124 Status = ListCallback(Irp, Context);
1125
1126 /* check if irp can be moved */
1127 if (Status == STATUS_SUCCESS)
1128 {
1129 /* remove irp from src list */
1130 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1131
1132 if (ListLocation == KsListEntryTail)
1133 {
1134 /* insert irp end of list */
1135 InsertTailList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1136 }
1137 else
1138 {
1139 /* insert irp head of list */
1140 InsertHeadList(DestinationList, &Irp->Tail.Overlay.ListEntry);
1141 }
1142
1143 /* do we need to update the irp lock */
1144 if (DestinationLock)
1145 {
1146 /* update irp lock */
1147 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = DestinationLock;
1148 }
1149 }
1150 else
1151 {
1152 if (Status != STATUS_NO_MATCH)
1153 {
1154 /* callback decided to stop enumeration */
1155 break;
1156 }
1157
1158 /* reset return value */
1159 Status = STATUS_SUCCESS;
1160 }
1161 }
1162
1163 if (!DestinationLock)
1164 {
1165 /* release source lock */
1166 KeReleaseSpinLock(SourceLock, OldLevel);
1167 }
1168 else
1169 {
1170 /* now release destination lock */
1171 KeReleaseSpinLockFromDpcLevel(DestinationLock);
1172
1173 /* now release source lock */
1174 KeReleaseSpinLockFromDpcLevel(SourceLock);
1175
1176
1177 /* now release cancel spinlock */
1178 IoReleaseCancelSpinLock(OldLevel);
1179 }
1180
1181 /* done */
1182 return Status;
1183 }
1184
1185 /*
1186 @implemented
1187 */
1188 KSDDKAPI
1189 VOID
1190 NTAPI
1191 KsRemoveSpecificIrpFromCancelableQueue(
1192 IN PIRP Irp)
1193 {
1194 PKSPIN_LOCK SpinLock;
1195 KIRQL OldLevel;
1196
1197 /* get internal queue lock */
1198 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1199
1200 /* acquire spinlock */
1201 KeAcquireSpinLock(SpinLock, &OldLevel);
1202
1203 /* remove the irp from the list */
1204 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1205
1206 /* release spinlock */
1207 KeReleaseSpinLock(SpinLock, OldLevel);
1208 }
1209
1210
1211 /*
1212 @implemented
1213 */
1214 KSDDKAPI
1215 VOID
1216 NTAPI
1217 KsAddIrpToCancelableQueue(
1218 IN OUT PLIST_ENTRY QueueHead,
1219 IN PKSPIN_LOCK SpinLock,
1220 IN PIRP Irp,
1221 IN KSLIST_ENTRY_LOCATION ListLocation,
1222 IN PDRIVER_CANCEL DriverCancel OPTIONAL)
1223 {
1224 PDRIVER_CANCEL OldDriverCancel;
1225 PIO_STACK_LOCATION IoStack;
1226 KIRQL OldLevel;
1227
1228 /* check for required parameters */
1229 if (!QueueHead || !SpinLock || !Irp)
1230 return;
1231
1232 if (!DriverCancel)
1233 {
1234 /* default to KsCancelRoutine */
1235 DriverCancel = KsCancelRoutine;
1236 }
1237
1238 /* get current irp stack */
1239 IoStack = IoGetCurrentIrpStackLocation(Irp);
1240
1241 /* acquire spinlock */
1242 KeAcquireSpinLock(SpinLock, &OldLevel);
1243
1244 if (ListLocation == KsListEntryTail)
1245 {
1246 /* insert irp to tail of list */
1247 InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1248 }
1249 else
1250 {
1251 /* insert irp to head of list */
1252 InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
1253 }
1254
1255 /* store internal queue lock */
1256 KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = SpinLock;
1257
1258 /* now set the cancel routine */
1259 OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel);
1260
1261 if (Irp->Cancel && OldDriverCancel == NULL)
1262 {
1263 /* the irp has already been canceled */
1264 KeReleaseSpinLock(SpinLock, OldLevel);
1265
1266 /* cancel routine requires that cancel spinlock is held */
1267 IoAcquireCancelSpinLock(&Irp->CancelIrql);
1268
1269 /* cancel irp */
1270 DriverCancel(IoStack->DeviceObject, Irp);
1271 }
1272 else
1273 {
1274 /* done */
1275 KeReleaseSpinLock(SpinLock, OldLevel);
1276 }
1277 }
1278
1279 /*
1280 @implemented
1281 */
1282 KSDDKAPI
1283 VOID
1284 NTAPI
1285 KsCancelRoutine(
1286 IN PDEVICE_OBJECT DeviceObject,
1287 IN PIRP Irp)
1288 {
1289 PKSPIN_LOCK SpinLock;
1290
1291 /* get internal queue lock */
1292 SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
1293
1294 /* acquire spinlock */
1295 KeAcquireSpinLockAtDpcLevel(SpinLock);
1296
1297 /* sanity check */
1298 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1299
1300 /* release cancel spinlock */
1301 IoReleaseCancelSpinLock(Irp->CancelIrql);
1302
1303 /* remove the irp from the list */
1304 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1305
1306 /* release spinlock */
1307 KeReleaseSpinLockFromDpcLevel(SpinLock);
1308
1309 /* has the irp already been canceled */
1310 if (Irp->IoStatus.Status != STATUS_CANCELLED)
1311 {
1312 /* let's complete it */
1313 Irp->IoStatus.Status = STATUS_CANCELLED;
1314 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1315 }
1316 }
1317
1318 NTSTATUS
1319 FindMatchingCreateItem(
1320 PLIST_ENTRY ListHead,
1321 ULONG BufferSize,
1322 LPWSTR Buffer,
1323 OUT PCREATE_ITEM_ENTRY *OutCreateItem)
1324 {
1325 PLIST_ENTRY Entry;
1326 PCREATE_ITEM_ENTRY CreateItemEntry;
1327
1328 /* remove '\' slash */
1329 Buffer++;
1330 BufferSize -= sizeof(WCHAR);
1331
1332 /* point to first entry */
1333 Entry = ListHead->Flink;
1334
1335 /* loop all device items */
1336 while(Entry != ListHead)
1337 {
1338 /* get create item entry */
1339 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1340
1341 ASSERT(CreateItemEntry->CreateItem);
1342
1343 if(CreateItemEntry->CreateItem->Flags & KSCREATE_ITEM_WILDCARD)
1344 {
1345 /* create item is default */
1346 *OutCreateItem = CreateItemEntry;
1347 return STATUS_SUCCESS;
1348 }
1349
1350 if (!CreateItemEntry->CreateItem->Create)
1351 {
1352 /* skip free create item */
1353 Entry = Entry->Flink;
1354 continue;
1355 }
1356
1357 ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
1358
1359 DPRINT1("CreateItem %S Length %u Request %S %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
1360 CreateItemEntry->CreateItem->ObjectClass.Length,
1361 Buffer,
1362 BufferSize);
1363
1364 if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
1365 {
1366 /* create item doesnt match in length */
1367 Entry = Entry->Flink;
1368 continue;
1369 }
1370
1371 /* now check if the object class is the same */
1372 if (RtlCompareMemory(CreateItemEntry->CreateItem->ObjectClass.Buffer, Buffer, CreateItemEntry->CreateItem->ObjectClass.Length) == CreateItemEntry->CreateItem->ObjectClass.Length)
1373 {
1374 /* found matching create item */
1375 *OutCreateItem = CreateItemEntry;
1376 return STATUS_SUCCESS;
1377 }
1378 /* iterate to next */
1379 Entry = Entry->Flink;
1380 }
1381
1382 return STATUS_NOT_FOUND;
1383 }
1384
1385 NTSTATUS
1386 NTAPI
1387 KspCreate(
1388 IN PDEVICE_OBJECT DeviceObject,
1389 IN PIRP Irp)
1390 {
1391 PCREATE_ITEM_ENTRY CreateItemEntry;
1392 PIO_STACK_LOCATION IoStack;
1393 PDEVICE_EXTENSION DeviceExtension;
1394 PKSIDEVICE_HEADER DeviceHeader;
1395 PKSIOBJECT_HEADER ObjectHeader;
1396 NTSTATUS Status;
1397
1398 DPRINT("KS / CREATE\n");
1399 /* get current stack location */
1400 IoStack = IoGetCurrentIrpStackLocation(Irp);
1401 /* get device extension */
1402 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1403 /* get device header */
1404 DeviceHeader = DeviceExtension->DeviceHeader;
1405
1406 /* hack for bug 4566 */
1407 if (IoStack->FileObject->FileName.Buffer == NULL)
1408 {
1409 DPRINT("Using reference string hack\n");
1410 Irp->IoStatus.Information = 0;
1411 /* set return status */
1412 Irp->IoStatus.Status = STATUS_SUCCESS;
1413 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1414 return STATUS_SUCCESS;
1415 }
1416
1417 if (IoStack->FileObject->RelatedFileObject != NULL)
1418 {
1419 /* request is to instantiate a pin / node / clock / allocator */
1420 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext;
1421
1422 /* sanity check */
1423 ASSERT(ObjectHeader);
1424
1425 /* find a matching a create item */
1426 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1427 }
1428 else
1429 {
1430 /* request to create a filter */
1431 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1432 }
1433
1434 if (NT_SUCCESS(Status))
1435 {
1436 /* set object create item */
1437 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1438
1439 /* call create function */
1440 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1441
1442 if (NT_SUCCESS(Status))
1443 {
1444 /* increment create item reference count */
1445 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1446 }
1447 return Status;
1448 }
1449
1450
1451 Irp->IoStatus.Information = 0;
1452 /* set return status */
1453 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1454 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1455 return STATUS_UNSUCCESSFUL;
1456 }
1457
1458 NTSTATUS
1459 RosDeviceInterfaceReferenceStringHack(
1460 IN PDEVICE_OBJECT DeviceObject,
1461 IN PIRP Irp)
1462 {
1463 PIO_STACK_LOCATION IoStack;
1464 PKSIDEVICE_HEADER DeviceHeader;
1465 PDEVICE_EXTENSION DeviceExtension;
1466 PCREATE_ITEM_ENTRY CreateItemEntry;
1467 PLIST_ENTRY Entry;
1468 LPWSTR Buffer;
1469 ULONG Length;
1470
1471 /* get current stack location */
1472 IoStack = IoGetCurrentIrpStackLocation(Irp);
1473
1474 /* get device extension */
1475 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1476 /* get device header */
1477 DeviceHeader = DeviceExtension->DeviceHeader;
1478
1479 /* retrieve all available reference strings registered */
1480 Length = 0;
1481 Entry = DeviceHeader->ItemList.Flink;
1482 while(Entry != &DeviceHeader->ItemList)
1483 {
1484 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1485
1486 ASSERT(CreateItemEntry->CreateItem);
1487 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1488 Length += wcslen(CreateItemEntry->CreateItem->ObjectClass.Buffer) + 1;
1489
1490 Entry = Entry->Flink;
1491 }
1492
1493 /* add extra zero */
1494 Length += 1;
1495
1496 /* allocate the buffer */
1497 Buffer = ExAllocatePool(NonPagedPool, Length * sizeof(WCHAR));
1498 if (!Buffer)
1499 {
1500 Irp->IoStatus.Information = 0;
1501 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1502 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1503 return STATUS_INSUFFICIENT_RESOURCES;
1504 }
1505
1506
1507 *((LPWSTR*)Irp->UserBuffer) = Buffer;
1508 Irp->IoStatus.Status = STATUS_SUCCESS;
1509 Irp->IoStatus.Information = sizeof(LPWSTR);
1510
1511 Entry = DeviceHeader->ItemList.Flink;
1512 while(Entry != &DeviceHeader->ItemList)
1513 {
1514 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1515
1516 ASSERT(CreateItemEntry->CreateItem);
1517 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1518 {
1519 wcscpy(Buffer, CreateItemEntry->CreateItem->ObjectClass.Buffer);
1520 Buffer += wcslen(Buffer) + 1;
1521 }
1522 Entry = Entry->Flink;
1523 }
1524
1525
1526
1527 *Buffer = L'\0';
1528 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1529 return STATUS_SUCCESS;
1530
1531 }
1532
1533 NTSTATUS
1534 NTAPI
1535 KspDeviceControl(
1536 IN PDEVICE_OBJECT DeviceObject,
1537 IN PIRP Irp)
1538 {
1539 PIO_STACK_LOCATION IoStack;
1540 PKSIOBJECT_HEADER ObjectHeader;
1541 PKSIDEVICE_HEADER DeviceHeader;
1542 PDEVICE_EXTENSION DeviceExtension;
1543
1544
1545
1546 /* get current stack location */
1547 IoStack = IoGetCurrentIrpStackLocation(Irp);
1548
1549 /* get device extension */
1550 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1551 /* get device header */
1552 DeviceHeader = DeviceExtension->DeviceHeader;
1553
1554 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
1555 {
1556 /* hack for bug 4566 */
1557 return RosDeviceInterfaceReferenceStringHack(DeviceObject, Irp);
1558 }
1559
1560 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1561
1562 ASSERT(ObjectHeader);
1563 //KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
1564
1565 return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
1566 }
1567
1568 NTSTATUS
1569 NTAPI
1570 KspDispatchIrp(
1571 IN PDEVICE_OBJECT DeviceObject,
1572 IN PIRP Irp)
1573 {
1574 PIO_STACK_LOCATION IoStack;
1575 PDEVICE_EXTENSION DeviceExtension;
1576 PKSIOBJECT_HEADER ObjectHeader;
1577 PKSIDEVICE_HEADER DeviceHeader;
1578 PDRIVER_DISPATCH Dispatch;
1579 NTSTATUS Status;
1580
1581 /* get current stack location */
1582 IoStack = IoGetCurrentIrpStackLocation(Irp);
1583
1584 /* get device extension */
1585 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1586 /* get device header */
1587 DeviceHeader = DeviceExtension->DeviceHeader;
1588
1589 /* get object header */
1590 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1591
1592 if (!ObjectHeader)
1593 {
1594 /* hack for bug 4566 */
1595 Irp->IoStatus.Status = STATUS_SUCCESS;
1596 Irp->IoStatus.Information = 0;
1597 /* complete and forget */
1598 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1599 return STATUS_SUCCESS;
1600 }
1601
1602 /* sanity check */
1603 ASSERT(ObjectHeader);
1604 /* store create item */
1605 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1606
1607 /* retrieve matching dispatch function */
1608 switch(IoStack->MajorFunction)
1609 {
1610 case IRP_MJ_CLOSE:
1611 Dispatch = ObjectHeader->DispatchTable.Close;
1612 break;
1613 case IRP_MJ_DEVICE_CONTROL:
1614 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
1615 break;
1616 case IRP_MJ_READ:
1617 Dispatch = ObjectHeader->DispatchTable.Read;
1618 break;
1619 case IRP_MJ_WRITE:
1620 Dispatch = ObjectHeader->DispatchTable.Write;
1621 break;
1622 case IRP_MJ_FLUSH_BUFFERS :
1623 Dispatch = ObjectHeader->DispatchTable.Flush;
1624 break;
1625 case IRP_MJ_QUERY_SECURITY:
1626 Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
1627 break;
1628 case IRP_MJ_SET_SECURITY:
1629 Dispatch = ObjectHeader->DispatchTable.SetSecurity;
1630 break;
1631 case IRP_MJ_PNP:
1632 Dispatch = KsDefaultDispatchPnp;
1633 default:
1634 Dispatch = NULL;
1635 }
1636
1637 /* is the request supported */
1638 if (Dispatch)
1639 {
1640 /* now call the dispatch function */
1641 Status = Dispatch(DeviceObject, Irp);
1642 }
1643 else
1644 {
1645 /* not supported request */
1646 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1647 }
1648
1649 /* done */
1650 return Status;
1651 }
1652
1653 /*
1654 @implemented
1655 */
1656 KSDDKAPI
1657 NTSTATUS
1658 NTAPI
1659 KsSetMajorFunctionHandler(
1660 IN PDRIVER_OBJECT DriverObject,
1661 IN ULONG MajorFunction)
1662 {
1663 switch ( MajorFunction )
1664 {
1665 case IRP_MJ_CREATE:
1666 DriverObject->MajorFunction[MajorFunction] = KspCreate;
1667 break;
1668 break;
1669 case IRP_MJ_DEVICE_CONTROL:
1670 DriverObject->MajorFunction[MajorFunction] = KspDeviceControl;
1671 break;
1672 case IRP_MJ_CLOSE:
1673 case IRP_MJ_READ:
1674 case IRP_MJ_WRITE:
1675 case IRP_MJ_FLUSH_BUFFERS :
1676 case IRP_MJ_QUERY_SECURITY:
1677 case IRP_MJ_SET_SECURITY:
1678 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
1679 break;
1680 default:
1681 return STATUS_INVALID_PARAMETER;
1682 };
1683
1684 return STATUS_SUCCESS;
1685 }
1686
1687 /*
1688 @implemented
1689 */
1690 KSDDKAPI
1691 NTSTATUS
1692 NTAPI
1693 KsDispatchIrp(
1694 IN PDEVICE_OBJECT DeviceObject,
1695 IN PIRP Irp)
1696 {
1697 PIO_STACK_LOCATION IoStack;
1698 PKSIDEVICE_HEADER DeviceHeader;
1699 PDEVICE_EXTENSION DeviceExtension;
1700
1701 /* get device extension */
1702 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1703 /* get device header */
1704 DeviceHeader = DeviceExtension->DeviceHeader;
1705
1706
1707 /* get current irp stack */
1708 IoStack = IoGetCurrentIrpStackLocation(Irp);
1709
1710 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
1711 {
1712 if (IoStack->MajorFunction == IRP_MJ_CREATE)
1713 {
1714 /* check internal type */
1715 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1716 {
1717 /* AVStream client */
1718 return IKsDevice_Create(DeviceObject, Irp);
1719 }
1720 else
1721 {
1722 /* external client (portcls) */
1723 return KspCreate(DeviceObject, Irp);
1724 }
1725 }
1726
1727 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1728 {
1729 /* handle device requests */
1730 return KspDeviceControl(DeviceObject, Irp);
1731 }
1732
1733 switch (IoStack->MajorFunction)
1734 {
1735 case IRP_MJ_CLOSE:
1736 case IRP_MJ_READ:
1737 case IRP_MJ_WRITE:
1738 case IRP_MJ_FLUSH_BUFFERS:
1739 case IRP_MJ_QUERY_SECURITY:
1740 case IRP_MJ_SET_SECURITY:
1741 case IRP_MJ_PNP:
1742 return KspDispatchIrp(DeviceObject, Irp);
1743 default:
1744 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1745 }
1746 }
1747
1748 /* dispatch power */
1749 if (IoStack->MajorFunction == IRP_MJ_POWER)
1750 {
1751 /* check internal type */
1752 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1753 {
1754 /* AVStream client */
1755 return IKsDevice_Power(DeviceObject, Irp);
1756 }
1757 else
1758 {
1759 /* external client (portcls) */
1760 return KsDefaultDispatchPower(DeviceObject, Irp);
1761 }
1762 }
1763 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
1764 {
1765 /* check internal type */
1766 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1767 {
1768 /* AVStream client */
1769 return IKsDevice_Pnp(DeviceObject, Irp);
1770 }
1771 else
1772 {
1773 /* external client (portcls) */
1774 return KsDefaultDispatchPnp(DeviceObject, Irp);
1775 }
1776 }
1777 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
1778 {
1779 /* forward irp */
1780 return KsDefaultForwardIrp(DeviceObject, Irp);
1781 }
1782 else
1783 {
1784 /* not supported */
1785 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1786 }
1787 }
1788
1789 /*
1790 @unimplemented
1791 */
1792 KSDDKAPI
1793 ULONG
1794 NTAPI
1795 KsGetNodeIdFromIrp(
1796 IN PIRP Irp)
1797 {
1798 UNIMPLEMENTED
1799 return (ULONG)-1;
1800 }
1801