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