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