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