[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;
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 == DestinationList)
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 if (IoStack->FileObject->FileName.Buffer == NULL && DeviceHeader->ItemListCount == 1)
1407 {
1408 /* hack for bug 4566 */
1409 ASSERT(!IsListEmpty(&DeviceHeader->ItemList));
1410 /* get create item entry */
1411 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(DeviceHeader->ItemList.Flink, CREATE_ITEM_ENTRY, Entry);
1412
1413 ASSERT(CreateItemEntry->CreateItem);
1414
1415 if (!CreateItemEntry->CreateItem->Create)
1416 {
1417 /* no valid create item */
1418 Irp->IoStatus.Information = 0;
1419 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1420 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1421 /* return status */
1422 return STATUS_UNSUCCESSFUL;
1423 }
1424
1425 /* set object create item */
1426 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1427
1428 /* call create function */
1429 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1430
1431 if (NT_SUCCESS(Status))
1432 {
1433 /* increment create item reference count */
1434 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1435 }
1436 /* return result */
1437 return Status;
1438 }
1439
1440
1441 /* hack for bug 4566 */
1442 if (IoStack->FileObject->FileName.Buffer == NULL)
1443 {
1444 DPRINT("Using reference string hack\n");
1445 Irp->IoStatus.Information = 0;
1446 /* set return status */
1447 Irp->IoStatus.Status = STATUS_SUCCESS;
1448 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1449 return STATUS_SUCCESS;
1450 }
1451
1452
1453 if (IoStack->FileObject->RelatedFileObject != NULL)
1454 {
1455 /* request is to instantiate a pin / node / clock / allocator */
1456 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->RelatedFileObject->FsContext;
1457
1458 /* sanity check */
1459 ASSERT(ObjectHeader);
1460
1461 /* find a matching a create item */
1462 Status = FindMatchingCreateItem(&ObjectHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1463 }
1464 else
1465 {
1466 /* request to create a filter */
1467 Status = FindMatchingCreateItem(&DeviceHeader->ItemList, IoStack->FileObject->FileName.Length, IoStack->FileObject->FileName.Buffer, &CreateItemEntry);
1468 }
1469
1470 if (NT_SUCCESS(Status))
1471 {
1472 /* set object create item */
1473 KSCREATE_ITEM_IRP_STORAGE(Irp) = CreateItemEntry->CreateItem;
1474
1475 /* call create function */
1476 Status = CreateItemEntry->CreateItem->Create(DeviceObject, Irp);
1477
1478 if (NT_SUCCESS(Status))
1479 {
1480 /* increment create item reference count */
1481 InterlockedIncrement(&CreateItemEntry->ReferenceCount);
1482 }
1483 return Status;
1484 }
1485
1486
1487 Irp->IoStatus.Information = 0;
1488 /* set return status */
1489 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1490 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1491 return STATUS_UNSUCCESSFUL;
1492 }
1493
1494 NTSTATUS
1495 RosDeviceInterfaceReferenceStringHack(
1496 IN PDEVICE_OBJECT DeviceObject,
1497 IN PIRP Irp)
1498 {
1499 PIO_STACK_LOCATION IoStack;
1500 PKSIDEVICE_HEADER DeviceHeader;
1501 PDEVICE_EXTENSION DeviceExtension;
1502 PCREATE_ITEM_ENTRY CreateItemEntry;
1503 PLIST_ENTRY Entry;
1504 LPWSTR Buffer;
1505 ULONG Length;
1506
1507 /* get current stack location */
1508 IoStack = IoGetCurrentIrpStackLocation(Irp);
1509
1510 /* get device extension */
1511 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1512 /* get device header */
1513 DeviceHeader = DeviceExtension->DeviceHeader;
1514
1515 /* retrieve all available reference strings registered */
1516 Length = 0;
1517 Entry = DeviceHeader->ItemList.Flink;
1518 while(Entry != &DeviceHeader->ItemList)
1519 {
1520 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1521
1522 ASSERT(CreateItemEntry->CreateItem);
1523 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1524 Length += wcslen(CreateItemEntry->CreateItem->ObjectClass.Buffer) + 1;
1525
1526 Entry = Entry->Flink;
1527 }
1528
1529 /* add extra zero */
1530 Length += 1;
1531
1532 /* allocate the buffer */
1533 Buffer = ExAllocatePool(NonPagedPool, Length * sizeof(WCHAR));
1534 if (!Buffer)
1535 {
1536 Irp->IoStatus.Information = 0;
1537 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1538 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1539 return STATUS_INSUFFICIENT_RESOURCES;
1540 }
1541
1542
1543 *((LPWSTR*)Irp->UserBuffer) = Buffer;
1544 Irp->IoStatus.Status = STATUS_SUCCESS;
1545 Irp->IoStatus.Information = sizeof(LPWSTR);
1546
1547 Entry = DeviceHeader->ItemList.Flink;
1548 while(Entry != &DeviceHeader->ItemList)
1549 {
1550 CreateItemEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
1551
1552 ASSERT(CreateItemEntry->CreateItem);
1553 if (CreateItemEntry->CreateItem->Create && CreateItemEntry->CreateItem->ObjectClass.Buffer)
1554 {
1555 wcscpy(Buffer, CreateItemEntry->CreateItem->ObjectClass.Buffer);
1556 Buffer += wcslen(Buffer) + 1;
1557 }
1558 Entry = Entry->Flink;
1559 }
1560
1561
1562
1563 *Buffer = L'\0';
1564 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1565 return STATUS_SUCCESS;
1566
1567 }
1568
1569 NTSTATUS
1570 NTAPI
1571 KspDeviceControl(
1572 IN PDEVICE_OBJECT DeviceObject,
1573 IN PIRP Irp)
1574 {
1575 PIO_STACK_LOCATION IoStack;
1576 PKSIOBJECT_HEADER ObjectHeader;
1577 PKSIDEVICE_HEADER DeviceHeader;
1578 PDEVICE_EXTENSION DeviceExtension;
1579
1580
1581
1582 /* get current stack location */
1583 IoStack = IoGetCurrentIrpStackLocation(Irp);
1584
1585 /* get device extension */
1586 DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
1587 /* get device header */
1588 DeviceHeader = DeviceExtension->DeviceHeader;
1589
1590 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
1591 {
1592 /* hack for bug 4566 */
1593 return RosDeviceInterfaceReferenceStringHack(DeviceObject, Irp);
1594 }
1595
1596 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1597
1598 ASSERT(ObjectHeader);
1599 //KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
1600
1601 return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
1602 }
1603
1604 NTSTATUS
1605 NTAPI
1606 KspDispatchIrp(
1607 IN PDEVICE_OBJECT DeviceObject,
1608 IN PIRP Irp)
1609 {
1610 PIO_STACK_LOCATION IoStack;
1611 PDEVICE_EXTENSION DeviceExtension;
1612 PKSIOBJECT_HEADER ObjectHeader;
1613 PKSIDEVICE_HEADER DeviceHeader;
1614 PDRIVER_DISPATCH Dispatch;
1615 NTSTATUS Status;
1616
1617 /* get current stack location */
1618 IoStack = IoGetCurrentIrpStackLocation(Irp);
1619
1620 /* get device extension */
1621 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1622 /* get device header */
1623 DeviceHeader = DeviceExtension->DeviceHeader;
1624
1625 /* get object header */
1626 ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
1627
1628 if (!ObjectHeader)
1629 {
1630 /* hack for bug 4566 */
1631 Irp->IoStatus.Status = STATUS_SUCCESS;
1632 Irp->IoStatus.Information = 0;
1633 /* complete and forget */
1634 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1635 return STATUS_SUCCESS;
1636 }
1637
1638 /* sanity check */
1639 ASSERT(ObjectHeader);
1640 /* store create item */
1641 //KSCREATE_ITEM_IRP_STORAGE(Irp) = (PKSOBJECT_CREATE_ITEM)0x12345678; //ObjectHeader->CreateItem;
1642
1643 /* retrieve matching dispatch function */
1644 switch(IoStack->MajorFunction)
1645 {
1646 case IRP_MJ_CLOSE:
1647 Dispatch = ObjectHeader->DispatchTable.Close;
1648 break;
1649 case IRP_MJ_DEVICE_CONTROL:
1650 Dispatch = ObjectHeader->DispatchTable.DeviceIoControl;
1651 break;
1652 case IRP_MJ_READ:
1653 Dispatch = ObjectHeader->DispatchTable.Read;
1654 break;
1655 case IRP_MJ_WRITE:
1656 Dispatch = ObjectHeader->DispatchTable.Write;
1657 break;
1658 case IRP_MJ_FLUSH_BUFFERS :
1659 Dispatch = ObjectHeader->DispatchTable.Flush;
1660 break;
1661 case IRP_MJ_QUERY_SECURITY:
1662 Dispatch = ObjectHeader->DispatchTable.QuerySecurity;
1663 break;
1664 case IRP_MJ_SET_SECURITY:
1665 Dispatch = ObjectHeader->DispatchTable.SetSecurity;
1666 break;
1667 case IRP_MJ_PNP:
1668 Dispatch = KsDefaultDispatchPnp;
1669 default:
1670 Dispatch = NULL;
1671 }
1672
1673 /* is the request supported */
1674 if (Dispatch)
1675 {
1676 /* now call the dispatch function */
1677 Status = Dispatch(DeviceObject, Irp);
1678 }
1679 else
1680 {
1681 /* not supported request */
1682 Status = KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1683 }
1684
1685 /* done */
1686 return Status;
1687 }
1688
1689 /*
1690 @implemented
1691 */
1692 KSDDKAPI
1693 NTSTATUS
1694 NTAPI
1695 KsSetMajorFunctionHandler(
1696 IN PDRIVER_OBJECT DriverObject,
1697 IN ULONG MajorFunction)
1698 {
1699 switch ( MajorFunction )
1700 {
1701 case IRP_MJ_CREATE:
1702 DriverObject->MajorFunction[MajorFunction] = KspCreate;
1703 break;
1704 break;
1705 case IRP_MJ_DEVICE_CONTROL:
1706 DriverObject->MajorFunction[MajorFunction] = KspDeviceControl;
1707 break;
1708 case IRP_MJ_CLOSE:
1709 case IRP_MJ_READ:
1710 case IRP_MJ_WRITE:
1711 case IRP_MJ_FLUSH_BUFFERS :
1712 case IRP_MJ_QUERY_SECURITY:
1713 case IRP_MJ_SET_SECURITY:
1714 DriverObject->MajorFunction[MajorFunction] = KspDispatchIrp;
1715 break;
1716 default:
1717 return STATUS_INVALID_PARAMETER;
1718 };
1719
1720 return STATUS_SUCCESS;
1721 }
1722
1723 /*
1724 @implemented
1725 */
1726 KSDDKAPI
1727 NTSTATUS
1728 NTAPI
1729 KsDispatchIrp(
1730 IN PDEVICE_OBJECT DeviceObject,
1731 IN PIRP Irp)
1732 {
1733 PIO_STACK_LOCATION IoStack;
1734 PKSIDEVICE_HEADER DeviceHeader;
1735 PDEVICE_EXTENSION DeviceExtension;
1736
1737 /* get device extension */
1738 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1739 /* get device header */
1740 DeviceHeader = DeviceExtension->DeviceHeader;
1741
1742
1743 /* get current irp stack */
1744 IoStack = IoGetCurrentIrpStackLocation(Irp);
1745
1746 if (IoStack->MajorFunction <= IRP_MJ_DEVICE_CONTROL)
1747 {
1748 if (IoStack->MajorFunction == IRP_MJ_CREATE)
1749 {
1750 /* check internal type */
1751 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1752 {
1753 /* AVStream client */
1754 return IKsDevice_Create(DeviceObject, Irp);
1755 }
1756 else
1757 {
1758 /* external client (portcls) */
1759 return KspCreate(DeviceObject, Irp);
1760 }
1761 }
1762
1763 if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1764 {
1765 /* handle device requests */
1766 return KspDeviceControl(DeviceObject, Irp);
1767 }
1768
1769 switch (IoStack->MajorFunction)
1770 {
1771 case IRP_MJ_CLOSE:
1772 case IRP_MJ_READ:
1773 case IRP_MJ_WRITE:
1774 case IRP_MJ_FLUSH_BUFFERS:
1775 case IRP_MJ_QUERY_SECURITY:
1776 case IRP_MJ_SET_SECURITY:
1777 case IRP_MJ_PNP:
1778 return KspDispatchIrp(DeviceObject, Irp);
1779 default:
1780 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1781 }
1782 }
1783
1784 /* dispatch power */
1785 if (IoStack->MajorFunction == IRP_MJ_POWER)
1786 {
1787 /* check internal type */
1788 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1789 {
1790 /* AVStream client */
1791 return IKsDevice_Power(DeviceObject, Irp);
1792 }
1793 else
1794 {
1795 /* external client (portcls) */
1796 return KsDefaultDispatchPower(DeviceObject, Irp);
1797 }
1798 }
1799 else if (IoStack->MajorFunction == IRP_MJ_PNP) /* dispatch pnp */
1800 {
1801 /* check internal type */
1802 if (DeviceHeader->lpVtblIKsDevice) /* FIXME improve check */
1803 {
1804 /* AVStream client */
1805 return IKsDevice_Pnp(DeviceObject, Irp);
1806 }
1807 else
1808 {
1809 /* external client (portcls) */
1810 return KsDefaultDispatchPnp(DeviceObject, Irp);
1811 }
1812 }
1813 else if (IoStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL)
1814 {
1815 /* forward irp */
1816 return KsDefaultForwardIrp(DeviceObject, Irp);
1817 }
1818 else
1819 {
1820 /* not supported */
1821 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1822 }
1823 }
1824
1825 /*
1826 @unimplemented
1827 */
1828 KSDDKAPI
1829 ULONG
1830 NTAPI
1831 KsGetNodeIdFromIrp(
1832 IN PIRP Irp)
1833 {
1834 UNIMPLEMENTED
1835 return (ULONG)-1;
1836 }
1837