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