2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/irp.c
5 * PURPOSE: IRP Handling Functions
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Filip Navara (navaraf@reactos.org)
11 /* INCLUDES ****************************************************************/
17 /* Undefine some macros we implement here */
19 #undef IoCompleteRequest
21 /* PRIVATE FUNCTIONS ********************************************************/
25 IopFreeIrpKernelApc(IN PKAPC Apc
,
26 IN PKNORMAL_ROUTINE
*NormalRoutine
,
27 IN PVOID
*NormalContext
,
28 IN PVOID
*SystemArgument1
,
29 IN PVOID
*SystemArgument2
)
32 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
37 IopAbortIrpKernelApc(IN PKAPC Apc
)
40 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
45 IopCleanupFailedIrp(IN PFILE_OBJECT FileObject
,
46 IN PKEVENT EventObject OPTIONAL
,
47 IN PVOID Buffer OPTIONAL
)
51 /* Dereference the event */
52 if (EventObject
) ObDereferenceObject(EventObject
);
54 /* Free a buffer, if any */
55 if (Buffer
) ExFreePool(Buffer
);
57 /* If this was a file opened for synch I/O, then unlock it */
58 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
60 /* Now dereference it and return */
61 ObDereferenceObject(FileObject
);
62 return STATUS_INSUFFICIENT_RESOURCES
;
67 IopAbortInterruptedIrp(IN PKEVENT EventObject
,
75 /* Raise IRQL to APC */
76 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
78 /* Check if nobody completed it yet */
79 if (!KeReadStateEvent(EventObject
))
81 /* First, cancel it */
82 CancelResult
= IoCancelIrp(Irp
);
85 /* Check if we cancelled it */
88 /* Wait for the IRP to be cancelled */
89 Wait
.QuadPart
= -100000;
90 while (!KeReadStateEvent(EventObject
))
92 /* Delay indefintely */
93 KeDelayExecutionThread(KernelMode
, FALSE
, &Wait
);
98 /* No cancellation done, so wait for the I/O system to kill it */
99 KeWaitForSingleObject(EventObject
,
108 /* We got preempted, so give up */
109 KeLowerIrql(OldIrql
);
115 IopRemoveThreadIrp(VOID
)
120 PLIST_ENTRY IrpEntry
;
121 PIO_ERROR_LOG_PACKET ErrorLogEntry
;
122 PDEVICE_OBJECT DeviceObject
= NULL
;
123 PIO_STACK_LOCATION IoStackLocation
;
125 /* First, raise to APC to protect IrpList */
126 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
128 /* Get the Thread and check the list */
129 IrpThread
= PsGetCurrentThread();
130 if (IsListEmpty(&IrpThread
->IrpList
))
132 /* It got completed now, so quit */
133 KeLowerIrql(OldIrql
);
137 /* Get the misbehaving IRP */
138 IrpEntry
= IrpThread
->IrpList
.Flink
;
139 DeadIrp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
140 IOTRACE(IO_IRP_DEBUG
,
141 "%s - Deassociating IRP %p for %p\n",
146 /* Don't cancel the IRP if it's already been completed far */
147 if (DeadIrp
->CurrentLocation
== (DeadIrp
->StackCount
+ 2))
150 KeLowerIrql(OldIrql
);
154 /* Disown the IRP! */
155 DeadIrp
->Tail
.Overlay
.Thread
= NULL
;
156 RemoveHeadList(&IrpThread
->IrpList
);
157 InitializeListHead(&DeadIrp
->ThreadListEntry
);
159 /* Get the stack location and check if it's valid */
160 IoStackLocation
= IoGetCurrentIrpStackLocation(DeadIrp
);
161 if (DeadIrp
->CurrentLocation
<= DeadIrp
->StackCount
)
163 /* Get the device object */
164 DeviceObject
= IoStackLocation
->DeviceObject
;
167 /* Lower IRQL now, since we have the pointers we need */
168 KeLowerIrql(OldIrql
);
170 /* Check if we can send an Error Log Entry*/
173 /* Allocate an entry */
174 ErrorLogEntry
= IoAllocateErrorLogEntry(DeviceObject
,
175 sizeof(IO_ERROR_LOG_PACKET
));
178 /* Write the entry */
179 ErrorLogEntry
->ErrorCode
= 0xBAADF00D; /* FIXME */
180 IoWriteErrorLogEntry(ErrorLogEntry
);
187 IopCleanupIrp(IN PIRP Irp
,
188 IN PFILE_OBJECT FileObject
)
191 IOTRACE(IO_IRP_DEBUG
,
192 "%s - Cleaning IRP %p for %p\n",
197 /* Check if there's an MDL */
198 while ((Mdl
= Irp
->MdlAddress
))
200 /* Clear all of them */
201 Irp
->MdlAddress
= Mdl
->Next
;
205 /* Check if the IRP has system buffer */
206 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
208 /* Free the buffer */
209 ExFreePoolWithTag(Irp
->AssociatedIrp
.SystemBuffer
, TAG_SYS_BUF
);
212 /* Check if this IRP has a user event, a file object, and is async */
213 if ((Irp
->UserEvent
) &&
214 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
) &&
217 /* Dereference the User Event */
218 ObDereferenceObject(Irp
->UserEvent
);
221 /* Check if we have a file object and this isn't a create operation */
222 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
224 /* Dereference the file object */
225 ObDereferenceObject(FileObject
);
234 IopCompleteRequest(IN PKAPC Apc
,
235 IN PKNORMAL_ROUTINE
* NormalRoutine
,
236 IN PVOID
* NormalContext
,
237 IN PVOID
* SystemArgument1
,
238 IN PVOID
* SystemArgument2
)
240 PFILE_OBJECT FileObject
;
243 PVOID Port
= NULL
, Key
= NULL
;
244 BOOLEAN SignaledCreateRequest
= FALSE
;
246 /* Get data from the APC */
247 FileObject
= (PFILE_OBJECT
)*SystemArgument1
;
248 Irp
= CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
);
249 IOTRACE(IO_IRP_DEBUG
,
250 "%s - Completing IRP %p for %p\n",
256 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
258 /* Check if we have a file object */
259 if (*SystemArgument2
)
261 /* Check if we're reparsing */
262 if ((Irp
->IoStatus
.Status
== STATUS_REPARSE
) &&
263 (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
))
265 /* We should never get this yet */
266 DPRINT1("Reparse support not yet present!\n");
271 /* Handle Buffered case first */
272 if (Irp
->Flags
& IRP_BUFFERED_IO
)
274 /* Check if we have an input buffer and if we succeeded */
275 if ((Irp
->Flags
& IRP_INPUT_OPERATION
) &&
276 (Irp
->IoStatus
.Status
!= STATUS_VERIFY_REQUIRED
) &&
277 !(NT_ERROR(Irp
->IoStatus
.Status
)))
279 /* Copy the buffer back to the user */
280 RtlCopyMemory(Irp
->UserBuffer
,
281 Irp
->AssociatedIrp
.SystemBuffer
,
282 Irp
->IoStatus
.Information
);
285 /* Also check if we should de-allocate it */
286 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
289 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
293 /* Now we got rid of these two... */
294 Irp
->Flags
&= ~(IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
296 /* Check if there's an MDL */
297 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
305 Irp
->MdlAddress
= NULL
;
308 * Check if either the request was completed without any errors
309 * (but warnings are OK!), or if it was completed with an error, but
310 * did return from a pending I/O Operation and is not synchronous.
312 if (!(NT_ERROR(Irp
->IoStatus
.Status
)) ||
313 (NT_ERROR(Irp
->IoStatus
.Status
) &&
314 (Irp
->PendingReturned
) &&
315 !(IsIrpSynchronous(Irp
, FileObject
))))
317 /* Get any information we need from the FO before we kill it */
318 if ((FileObject
) && (FileObject
->CompletionContext
))
320 /* Save Completion Data */
321 Port
= FileObject
->CompletionContext
->Port
;
322 Key
= FileObject
->CompletionContext
->Key
;
325 /* Use SEH to make sure we don't write somewhere invalid */
328 /* Save the IOSB Information */
329 *Irp
->UserIosb
= Irp
->IoStatus
;
331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
333 /* Ignore any error */
337 /* Check if we have an event or a file object */
340 /* At the very least, this is a PKEVENT, so signal it always */
341 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
343 /* Check if we also have a File Object */
346 /* Check if this is an Asynch API */
347 if (!(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
349 /* Dereference the event */
350 ObDereferenceObject(Irp
->UserEvent
);
354 * Now, if this is a Synch I/O File Object, then this event is
355 * NOT an actual Executive Event, so we won't dereference it,
356 * and instead, we will signal the File Object
358 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) &&
359 !(Irp
->Flags
& IRP_OB_QUERY_NAME
))
361 /* Signal the file object and set the status */
362 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
363 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
367 * This could also be a create operation, in which case we want
368 * to make sure there's no APC fired.
370 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
372 /* Clear the APC Routine and remember this */
373 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
374 SignaledCreateRequest
= TRUE
;
380 /* Signal the file object and set the status */
381 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
382 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
385 * This could also be a create operation, in which case we want
386 * to make sure there's no APC fired.
388 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
390 /* Clear the APC Routine and remember this */
391 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
392 SignaledCreateRequest
= TRUE
;
396 /* Update transfer count for everything but create operation */
397 if (!(Irp
->Flags
& IRP_CREATE_OPERATION
))
399 if (Irp
->Flags
& IRP_WRITE_OPERATION
)
401 /* Update write transfer count */
402 IopUpdateTransferCount(IopWriteTransfer
,
403 (ULONG
)Irp
->IoStatus
.Information
);
405 else if (Irp
->Flags
& IRP_READ_OPERATION
)
407 /* Update read transfer count */
408 IopUpdateTransferCount(IopReadTransfer
,
409 (ULONG
)Irp
->IoStatus
.Information
);
413 /* Update other transfer count */
414 IopUpdateTransferCount(IopOtherTransfer
,
415 (ULONG
)Irp
->IoStatus
.Information
);
419 /* Now that we've signaled the events, de-associate the IRP */
420 IopUnQueueIrpFromThread(Irp
);
422 /* Now check if a User APC Routine was requested */
423 if (Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
)
426 KeInitializeApc(&Irp
->Tail
.Apc
,
427 KeGetCurrentThread(),
428 CurrentApcEnvironment
,
430 IopAbortIrpKernelApc
,
431 (PKNORMAL_ROUTINE
)Irp
->
432 Overlay
.AsynchronousParameters
.UserApcRoutine
,
435 Overlay
.AsynchronousParameters
.UserApcContext
);
438 KeInsertQueueApc(&Irp
->Tail
.Apc
, Irp
->UserIosb
, NULL
, 2);
441 (Irp
->Overlay
.AsynchronousParameters
.UserApcContext
))
443 /* We have an I/O Completion setup... create the special Overlay */
444 Irp
->Tail
.CompletionKey
= Key
;
445 Irp
->Tail
.Overlay
.PacketType
= IopCompletionPacketIrp
;
446 KeInsertQueue(Port
, &Irp
->Tail
.Overlay
.ListEntry
);
450 /* Free the IRP since we don't need it anymore */
454 /* Check if we have a file object that wasn't part of a create */
455 if ((FileObject
) && !(SignaledCreateRequest
))
457 /* Dereference it, since it's not needed anymore either */
458 ObDereferenceObjectDeferDelete(FileObject
);
463 /* Check if we have an associated user IOSB */
466 /* We do, so let's give them the final status */
469 /* Save the IOSB Information */
470 *Irp
->UserIosb
= Irp
->IoStatus
;
472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
474 /* Ignore any error */
480 * Either we didn't return from the request, or we did return but this
481 * request was synchronous.
483 if ((Irp
->PendingReturned
) && (FileObject
))
485 /* So we did return with a synch operation, was it the IRP? */
486 if (Irp
->Flags
& IRP_SYNCHRONOUS_API
)
488 /* Now check if the user gave an event */
492 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
496 /* No event was given, so signal the FO instead */
497 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
503 * It's not the IRP that was synchronous, it was the FO
504 * that was opened this way. Signal its event.
506 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
507 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
511 /* Now that we got here, we do this for incomplete I/Os as well */
512 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
514 /* Dereference the File Object unless this was a create */
515 ObDereferenceObjectDeferDelete(FileObject
);
519 * Check if this was an Executive Event (remember that we know this
520 * by checking if the IRP is synchronous)
522 if ((Irp
->UserEvent
) &&
524 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
526 /* This isn't a PKEVENT, so dereference it */
527 ObDereferenceObject(Irp
->UserEvent
);
530 /* Now that we've signaled the events, de-associate the IRP */
531 IopUnQueueIrpFromThread(Irp
);
533 /* Free the IRP as well */
538 /* FUNCTIONS *****************************************************************/
545 IoAllocateIrp(IN CCHAR StackSize
,
546 IN BOOLEAN ChargeQuota
)
549 USHORT Size
= IoSizeOfIrp(StackSize
);
552 PNPAGED_LOOKASIDE_LIST List
= NULL
;
553 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
555 /* Set Charge Quota Flag */
556 if (ChargeQuota
) Flags
|= IRP_QUOTA_CHARGED
;
558 /* FIXME: Implement Lookaside Floats */
560 /* Figure out which Lookaside List to use */
561 if ((StackSize
<= 8) && (ChargeQuota
== FALSE
))
563 /* Set Fixed Size Flag */
564 Flags
= IRP_ALLOCATED_FIXED_SIZE
;
566 /* See if we should use big list */
569 Size
= IoSizeOfIrp(8);
570 ListType
= LookasideLargeIrpList
;
574 Prcb
= KeGetCurrentPrcb();
576 /* Get the P List First */
577 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
579 /* Attempt allocation */
580 List
->L
.TotalAllocates
++;
581 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
583 /* Check if the P List failed */
586 /* Let the balancer know */
587 List
->L
.AllocateMisses
++;
590 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
591 List
->L
.TotalAllocates
++;
592 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
596 /* Check if we have to use the pool */
599 /* Did we try lookaside and fail? */
600 if (Flags
& IRP_ALLOCATED_FIXED_SIZE
) List
->L
.AllocateMisses
++;
602 /* Check if we should charge quota */
605 /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
607 Irp
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_IRP
);
611 /* Allocate the IRP With no Quota charge */
612 Irp
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_IRP
);
615 /* Make sure it was sucessful */
616 if (!Irp
) return(NULL
);
620 /* In this case there is no charge quota */
621 Flags
&= ~IRP_QUOTA_CHARGED
;
624 /* Now Initialize it */
625 IoInitializeIrp(Irp
, Size
, StackSize
);
627 /* Set the Allocation Flags */
628 Irp
->AllocationFlags
= Flags
;
631 IOTRACE(IO_IRP_DEBUG
,
632 "%s - Allocated IRP %p with allocation flags %lx\n",
644 IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction
,
645 IN PDEVICE_OBJECT DeviceObject
,
648 IN PLARGE_INTEGER StartingOffset
,
649 IN PIO_STATUS_BLOCK IoStatusBlock
)
652 PIO_STACK_LOCATION StackPtr
;
655 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
656 if (!Irp
) return NULL
;
659 StackPtr
= IoGetNextIrpStackLocation(Irp
);
661 /* Write the Major function and then deal with it */
662 StackPtr
->MajorFunction
= (UCHAR
)MajorFunction
;
664 /* Do not handle the following here */
665 if ((MajorFunction
!= IRP_MJ_FLUSH_BUFFERS
) &&
666 (MajorFunction
!= IRP_MJ_SHUTDOWN
) &&
667 (MajorFunction
!= IRP_MJ_PNP
) &&
668 (MajorFunction
!= IRP_MJ_POWER
))
670 /* Check if this is Buffered IO */
671 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
673 /* Allocate the System Buffer */
674 Irp
->AssociatedIrp
.SystemBuffer
=
675 ExAllocatePoolWithTag(NonPagedPool
, Length
, TAG_SYS_BUF
);
676 if (!Irp
->AssociatedIrp
.SystemBuffer
)
678 /* Free the IRP and fail */
684 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
686 /* Handle special IRP_MJ_WRITE Case */
687 if (MajorFunction
== IRP_MJ_WRITE
)
689 /* Copy the buffer data */
690 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
694 /* Set the Input Operation flag and set this as a User Buffer */
695 Irp
->Flags
|= IRP_INPUT_OPERATION
;
696 Irp
->UserBuffer
= Buffer
;
699 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
701 /* Use an MDL for Direct I/O */
702 Irp
->MdlAddress
= IoAllocateMdl(Buffer
,
707 if (!Irp
->MdlAddress
)
709 /* Free the IRP and fail */
718 MmProbeAndLockPages(Irp
->MdlAddress
,
720 MajorFunction
== IRP_MJ_READ
?
721 IoWriteAccess
: IoReadAccess
);
723 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
725 /* Free the IRP and its MDL */
726 IoFreeMdl(Irp
->MdlAddress
);
730 _SEH2_YIELD(return NULL
);
736 /* Neither, use the buffer */
737 Irp
->UserBuffer
= Buffer
;
740 /* Check if this is a read */
741 if (MajorFunction
== IRP_MJ_READ
)
743 /* Set the parameters for a read */
744 StackPtr
->Parameters
.Read
.Length
= Length
;
745 StackPtr
->Parameters
.Read
.ByteOffset
= *StartingOffset
;
747 else if (MajorFunction
== IRP_MJ_WRITE
)
749 /* Otherwise, set write parameters */
750 StackPtr
->Parameters
.Write
.Length
= Length
;
751 StackPtr
->Parameters
.Write
.ByteOffset
= *StartingOffset
;
755 /* Set the Current Thread and IOSB */
756 Irp
->UserIosb
= IoStatusBlock
;
757 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
760 IOTRACE(IO_IRP_DEBUG
,
761 "%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
775 IoBuildDeviceIoControlRequest(IN ULONG IoControlCode
,
776 IN PDEVICE_OBJECT DeviceObject
,
777 IN PVOID InputBuffer
,
778 IN ULONG InputBufferLength
,
779 IN PVOID OutputBuffer
,
780 IN ULONG OutputBufferLength
,
781 IN BOOLEAN InternalDeviceIoControl
,
783 IN PIO_STATUS_BLOCK IoStatusBlock
)
786 PIO_STACK_LOCATION StackPtr
;
790 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
791 if (!Irp
) return NULL
;
794 StackPtr
= IoGetNextIrpStackLocation(Irp
);
796 /* Set the DevCtl Type */
797 StackPtr
->MajorFunction
= InternalDeviceIoControl
?
798 IRP_MJ_INTERNAL_DEVICE_CONTROL
:
799 IRP_MJ_DEVICE_CONTROL
;
801 /* Set the IOCTL Data */
802 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
803 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
804 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
807 /* Handle the Methods */
808 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode
))
811 case METHOD_BUFFERED
:
813 /* Select the right Buffer Length */
814 BufferLength
= InputBufferLength
> OutputBufferLength
?
815 InputBufferLength
: OutputBufferLength
;
817 /* Make sure there is one */
820 /* Allocate the System Buffer */
821 Irp
->AssociatedIrp
.SystemBuffer
=
822 ExAllocatePoolWithTag(NonPagedPool
,
825 if (!Irp
->AssociatedIrp
.SystemBuffer
)
827 /* Free the IRP and fail */
832 /* Check if we got a buffer */
835 /* Copy into the System Buffer */
836 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
841 /* Write the flags */
842 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
843 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
845 /* Save the Buffer */
846 Irp
->UserBuffer
= OutputBuffer
;
850 /* Clear the Flags and Buffer */
852 Irp
->UserBuffer
= NULL
;
857 case METHOD_IN_DIRECT
:
858 case METHOD_OUT_DIRECT
:
860 /* Check if we got an input buffer */
863 /* Allocate the System Buffer */
864 Irp
->AssociatedIrp
.SystemBuffer
=
865 ExAllocatePoolWithTag(NonPagedPool
,
868 if (!Irp
->AssociatedIrp
.SystemBuffer
)
870 /* Free the IRP and fail */
875 /* Copy into the System Buffer */
876 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
880 /* Write the flags */
881 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
885 /* Clear the flags */
889 /* Check if we got an output buffer */
892 /* Allocate the System Buffer */
893 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
898 if (!Irp
->MdlAddress
)
900 /* Free the IRP and fail */
909 MmProbeAndLockPages(Irp
->MdlAddress
,
911 IO_METHOD_FROM_CTL_CODE(IoControlCode
) ==
913 IoReadAccess
: IoWriteAccess
);
915 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
918 IoFreeMdl(Irp
->MdlAddress
);
920 /* Free the input buffer and IRP */
921 if (InputBuffer
) ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
925 _SEH2_YIELD(return NULL
);
933 /* Just save the Buffer */
934 Irp
->UserBuffer
= OutputBuffer
;
935 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
938 /* Now write the Event and IoSB */
939 Irp
->UserIosb
= IoStatusBlock
;
940 Irp
->UserEvent
= Event
;
942 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
943 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
944 IoQueueThreadIrp(Irp
);
947 IOTRACE(IO_IRP_DEBUG
,
948 "%s - Built IRP %p with IOCTL, Buffers, DO %lx %p %p %p\n",
963 IoBuildSynchronousFsdRequest(IN ULONG MajorFunction
,
964 IN PDEVICE_OBJECT DeviceObject
,
967 IN PLARGE_INTEGER StartingOffset
,
969 IN PIO_STATUS_BLOCK IoStatusBlock
)
973 /* Do the big work to set up the IRP */
974 Irp
= IoBuildAsynchronousFsdRequest(MajorFunction
,
980 if (!Irp
) return NULL
;
982 /* Set the Event which makes it Syncronous */
983 Irp
->UserEvent
= Event
;
985 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
986 IoQueueThreadIrp(Irp
);
995 IoCancelIrp(IN PIRP Irp
)
999 PDRIVER_CANCEL CancelRoutine
;
1000 IOTRACE(IO_IRP_DEBUG
,
1001 "%s - Canceling IRP %p\n",
1004 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1005 IrqlAtEntry
= KeGetCurrentIrql();
1007 /* Acquire the cancel lock and cancel the IRP */
1008 IoAcquireCancelSpinLock(&OldIrql
);
1011 /* Clear the cancel routine and get the old one */
1012 CancelRoutine
= (PVOID
)IoSetCancelRoutine(Irp
, NULL
);
1015 /* We had a routine, make sure the IRP isn't completed */
1016 if (Irp
->CurrentLocation
> (Irp
->StackCount
+ 1))
1018 /* It is, bugcheck */
1019 KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP
,
1026 /* Set the cancel IRQL And call the routine */
1027 Irp
->CancelIrql
= OldIrql
;
1028 CancelRoutine(IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
, Irp
);
1029 ASSERT(IrqlAtEntry
== KeGetCurrentIrql());
1033 /* Otherwise, release the cancel lock and fail */
1034 IoReleaseCancelSpinLock(OldIrql
);
1043 IoCancelThreadIo(IN PETHREAD Thread
)
1046 ULONG Retries
= 3000;
1047 LARGE_INTEGER Interval
;
1048 PLIST_ENTRY ListHead
, NextEntry
;
1050 IOTRACE(IO_IRP_DEBUG
,
1051 "%s - Canceling IRPs for Thread %p\n",
1055 /* Raise to APC to protect the IrpList */
1056 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1058 /* Start by cancelling all the IRPs in the current thread queue. */
1059 ListHead
= &Thread
->IrpList
;
1060 NextEntry
= ListHead
->Flink
;
1061 while (ListHead
!= NextEntry
)
1064 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
1069 /* Move to the next entry */
1070 NextEntry
= NextEntry
->Flink
;
1073 /* Wait 100 milliseconds */
1074 Interval
.QuadPart
= -1000000;
1076 /* Wait till all the IRPs are completed or cancelled. */
1077 while (!IsListEmpty(&Thread
->IrpList
))
1079 /* Now we can lower */
1080 KeLowerIrql(OldIrql
);
1082 /* Wait a short while and then look if all our IRPs were completed. */
1083 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1086 * Don't stay here forever if some broken driver doesn't complete
1091 /* Print out a message and remove the IRP */
1092 DPRINT1("Broken driver did not complete!\n");
1093 IopRemoveThreadIrp();
1096 /* Raise the IRQL Again */
1097 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1100 /* We're done, lower the IRQL */
1101 KeLowerIrql(OldIrql
);
1109 IoCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1113 return IofCallDriver(DeviceObject
, Irp
);
1121 IoCompleteRequest(IN PIRP Irp
,
1122 IN CCHAR PriorityBoost
)
1124 /* Call the fastcall */
1125 IofCompleteRequest(Irp
, PriorityBoost
);
1133 IoEnqueueIrp(IN PIRP Irp
)
1135 /* This is the same as calling IoQueueThreadIrp */
1136 IoQueueThreadIrp(Irp
);
1144 IofCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1147 PDRIVER_OBJECT DriverObject
;
1148 PIO_STACK_LOCATION StackPtr
;
1150 /* Make sure this is a valid IRP */
1151 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1153 /* Get the Driver Object */
1154 DriverObject
= DeviceObject
->DriverObject
;
1156 /* Decrease the current location and check if */
1157 Irp
->CurrentLocation
--;
1158 if (Irp
->CurrentLocation
<= 0)
1160 /* This IRP ran out of stack, bugcheck */
1161 KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1164 /* Now update the stack location */
1165 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1166 Irp
->Tail
.Overlay
.CurrentStackLocation
= StackPtr
;
1168 /* Get the Device Object */
1169 StackPtr
->DeviceObject
= DeviceObject
;
1172 return DriverObject
->MajorFunction
[StackPtr
->MajorFunction
](DeviceObject
,
1178 IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation
)
1180 IoStackLocation
->MinorFunction
= 0;
1181 IoStackLocation
->Flags
= 0;
1182 IoStackLocation
->Control
&= SL_ERROR_RETURNED
;
1183 IoStackLocation
->Parameters
.Others
.Argument1
= 0;
1184 IoStackLocation
->Parameters
.Others
.Argument2
= 0;
1185 IoStackLocation
->Parameters
.Others
.Argument3
= 0;
1186 IoStackLocation
->FileObject
= NULL
;
1194 IofCompleteRequest(IN PIRP Irp
,
1195 IN CCHAR PriorityBoost
)
1197 PIO_STACK_LOCATION StackPtr
, LastStackPtr
;
1198 PDEVICE_OBJECT DeviceObject
;
1199 PFILE_OBJECT FileObject
;
1206 NTSTATUS ErrorCode
= STATUS_SUCCESS
;
1207 IOTRACE(IO_IRP_DEBUG
,
1208 "%s - Completing IRP %p\n",
1212 /* Make sure this IRP isn't getting completed twice or is invalid */
1213 if ((Irp
->CurrentLocation
) > (Irp
->StackCount
+ 1))
1216 KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1219 /* Some sanity checks */
1220 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1221 ASSERT(!Irp
->CancelRoutine
);
1222 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1223 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
1225 /* Get the last stack */
1226 LastStackPtr
= (PIO_STACK_LOCATION
)(Irp
+ 1);
1227 if (LastStackPtr
->Control
& SL_ERROR_RETURNED
)
1229 /* Get the error code */
1230 ErrorCode
= PtrToUlong(LastStackPtr
->Parameters
.Others
.Argument4
);
1233 /* Get the Current Stack */
1234 StackPtr
= IoGetCurrentIrpStackLocation(Irp
);
1236 /* Loop the Stacks and complete the IRPs */
1239 /* Skip current stack location */
1240 IoSkipCurrentIrpStackLocation(Irp
);
1242 /* Set Pending Returned */
1243 Irp
->PendingReturned
= StackPtr
->Control
& SL_PENDING_RETURNED
;
1245 /* Check if we failed */
1246 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1248 /* Check if it was changed by a completion routine */
1249 if (Irp
->IoStatus
.Status
!= ErrorCode
)
1251 /* Update the error for the current stack */
1252 ErrorCode
= Irp
->IoStatus
.Status
;
1253 StackPtr
->Control
|= SL_ERROR_RETURNED
;
1254 LastStackPtr
->Parameters
.Others
.Argument4
= UlongToPtr(ErrorCode
);
1255 LastStackPtr
->Control
|= SL_ERROR_RETURNED
;
1259 /* Check if there is a Completion Routine to Call */
1260 if ((NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1261 (StackPtr
->Control
& SL_INVOKE_ON_SUCCESS
)) ||
1262 (!NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1263 (StackPtr
->Control
& SL_INVOKE_ON_ERROR
)) ||
1265 (StackPtr
->Control
& SL_INVOKE_ON_CANCEL
)))
1267 /* Clear the stack location */
1268 IopClearStackLocation(StackPtr
);
1270 /* Check for highest-level device completion routines */
1271 if (Irp
->CurrentLocation
== (Irp
->StackCount
+ 1))
1273 /* Clear the DO, since the current stack location is invalid */
1274 DeviceObject
= NULL
;
1278 /* Otherwise, return the real one */
1279 DeviceObject
= IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
;
1282 /* Call the completion routine */
1283 Status
= StackPtr
->CompletionRoutine(DeviceObject
,
1287 /* Don't touch the Packet in this case, since it might be gone! */
1288 if (Status
== STATUS_MORE_PROCESSING_REQUIRED
) return;
1292 /* Otherwise, check if this is a completed IRP */
1293 if ((Irp
->CurrentLocation
<= Irp
->StackCount
) &&
1294 (Irp
->PendingReturned
))
1296 /* Mark it as pending */
1297 IoMarkIrpPending(Irp
);
1300 /* Clear the stack location */
1301 IopClearStackLocation(StackPtr
);
1304 /* Move pointer to next stack location */
1306 } while (Irp
->CurrentLocation
<= Irp
->StackCount
);
1308 /* Check if the IRP is an associated IRP */
1309 if (Irp
->Flags
& IRP_ASSOCIATED_IRP
)
1311 /* Get the master IRP and count */
1312 MasterIrp
= Irp
->AssociatedIrp
.MasterIrp
;
1313 MasterCount
= InterlockedDecrement(&MasterIrp
->AssociatedIrp
.IrpCount
);
1316 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
1318 /* Go to the next one */
1319 NextMdl
= Mdl
->Next
;
1323 /* Free the IRP itself */
1326 /* Complete the Master IRP */
1327 if (!MasterCount
) IofCompleteRequest(MasterIrp
, PriorityBoost
);
1331 /* We don't support this yet */
1332 ASSERT(Irp
->IoStatus
.Status
!= STATUS_REPARSE
);
1334 /* Check if we have an auxiliary buffer */
1335 if (Irp
->Tail
.Overlay
.AuxiliaryBuffer
)
1338 ExFreePool(Irp
->Tail
.Overlay
.AuxiliaryBuffer
);
1339 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
1342 /* Check if this is a Paging I/O or Close Operation */
1343 if (Irp
->Flags
& (IRP_PAGING_IO
| IRP_CLOSE_OPERATION
))
1345 /* Handle a Close Operation or Sync Paging I/O */
1346 if (Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_CLOSE_OPERATION
))
1348 /* Set the I/O Status and Signal the Event */
1349 Flags
= Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
);
1350 *Irp
->UserIosb
= Irp
->IoStatus
;
1351 KeSetEvent(Irp
->UserEvent
, PriorityBoost
, FALSE
);
1353 /* Free the IRP for a Paging I/O Only, Close is handled by us */
1354 if (Flags
) IoFreeIrp(Irp
);
1360 KeInitializeApc(&Irp
->Tail
.Apc
1361 &Irp
->Tail
.Overlay
.Thread
->Tcb
,
1362 Irp
->ApcEnvironment
,
1363 IopCompletePageWrite
,
1368 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1373 /* Not implemented yet. */
1374 DPRINT1("Not supported!\n");
1379 /* Get out of here */
1383 /* Unlock MDL Pages, page 167. */
1384 Mdl
= Irp
->MdlAddress
;
1391 /* Check if we should exit because of a Deferred I/O (page 168) */
1392 if ((Irp
->Flags
& IRP_DEFER_IO_COMPLETION
) && !(Irp
->PendingReturned
))
1395 * Return without queuing the completion APC, since the caller will
1396 * take care of doing its own optimized completion at PASSIVE_LEVEL.
1401 /* Get the thread and file object */
1402 Thread
= Irp
->Tail
.Overlay
.Thread
;
1403 FileObject
= Irp
->Tail
.Overlay
.OriginalFileObject
;
1405 /* Make sure the IRP isn't canceled */
1408 /* Initialize the APC */
1409 KeInitializeApc(&Irp
->Tail
.Apc
,
1411 Irp
->ApcEnvironment
,
1419 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1421 NULL
, /* This is used for REPARSE stuff */
1426 /* The IRP just got canceled... does a thread still own it? */
1427 Thread
= Irp
->Tail
.Overlay
.Thread
;
1430 /* Yes! There is still hope! Initialize the APC */
1431 KeInitializeApc(&Irp
->Tail
.Apc
,
1433 Irp
->ApcEnvironment
,
1441 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1443 NULL
, /* This is used for REPARSE stuff */
1448 /* Nothing left for us to do, kill it */
1449 ASSERT(Irp
->Cancel
);
1450 IopCleanupIrp(Irp
, FileObject
);
1457 IopSynchronousCompletion(IN PDEVICE_OBJECT DeviceObject
,
1461 if (Irp
->PendingReturned
)
1462 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1463 return STATUS_MORE_PROCESSING_REQUIRED
;
1471 IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject
,
1477 /* Check if next stack location is available */
1478 if (Irp
->CurrentLocation
< Irp
->StackCount
)
1480 /* No more stack location */
1484 /* Initialize event */
1485 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1487 /* Copy stack location for next driver */
1488 IoCopyCurrentIrpStackLocationToNext(Irp
);
1490 /* Set a completion routine, which will signal the event */
1491 IoSetCompletionRoutine(Irp
, IopSynchronousCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
1493 /* Call next driver */
1494 Status
= IoCallDriver(DeviceObject
, Irp
);
1496 /* Check if irp is pending */
1497 if (Status
== STATUS_PENDING
)
1499 /* Yes, wait for its completion */
1500 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
1503 /* Return success */
1512 IoFreeIrp(IN PIRP Irp
)
1514 PNPAGED_LOOKASIDE_LIST List
;
1515 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
1517 IOTRACE(IO_IRP_DEBUG
,
1518 "%s - Freeing IRPs %p\n",
1522 /* Make sure the Thread IRP list is empty and that it OK to free it */
1523 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1524 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1525 ASSERT(Irp
->CurrentLocation
>= Irp
->StackCount
);
1527 /* If this was a pool alloc, free it with the pool */
1528 if (!(Irp
->AllocationFlags
& IRP_ALLOCATED_FIXED_SIZE
))
1531 ExFreePoolWithTag(Irp
, TAG_IRP
);
1535 /* Check if this was a Big IRP */
1536 if (Irp
->StackCount
!= 1) ListType
= LookasideLargeIrpList
;
1539 Prcb
= KeGetCurrentPrcb();
1541 /* Use the P List */
1542 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
1543 List
->L
.TotalFrees
++;
1545 /* Check if the Free was within the Depth or not */
1546 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1548 /* Let the balancer know */
1549 List
->L
.FreeMisses
++;
1551 /* Use the L List */
1552 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
1553 List
->L
.TotalFrees
++;
1555 /* Check if the Free was within the Depth or not */
1556 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1558 /* All lists failed, use the pool */
1559 List
->L
.FreeMisses
++;
1560 ExFreePoolWithTag(Irp
, TAG_IRP
);
1565 /* The free was within the Depth */
1568 InterlockedPushEntrySList(&List
->L
.ListHead
,
1569 (PSINGLE_LIST_ENTRY
)Irp
);
1579 IoGetPagingIoPriority(IN PIRP Irp
)
1581 IO_PAGING_PRIORITY Priority
;
1587 /* Check what priority it has */
1588 if (Flags
& 0x8000) // FIXME: Undocumented flag
1591 Priority
= IoPagingPriorityHigh
;
1593 else if (Flags
& IRP_PAGING_IO
)
1595 /* Normal priority */
1596 Priority
= IoPagingPriorityNormal
;
1600 /* Invalid -- not a paging IRP */
1601 Priority
= IoPagingPriorityInvalid
;
1604 /* Return the priority */
1613 IoGetRequestorProcess(IN PIRP Irp
)
1615 /* Return the requestor process */
1616 return Irp
->Tail
.Overlay
.Thread
->ThreadsProcess
;
1624 IoGetRequestorProcessId(IN PIRP Irp
)
1626 /* Return the requestor process' id */
1627 return PtrToUlong(IoGetRequestorProcess(Irp
)->UniqueProcessId
);
1635 IoGetRequestorSessionId(IN PIRP Irp
,
1636 OUT PULONG pSessionId
)
1638 /* Return the session */
1639 *pSessionId
= IoGetRequestorProcess(Irp
)->Session
;
1640 return STATUS_SUCCESS
;
1648 IoGetTopLevelIrp(VOID
)
1650 /* Return the IRP */
1651 return (PIRP
)PsGetCurrentThread()->TopLevelIrp
;
1659 IoInitializeIrp(IN PIRP Irp
,
1660 IN USHORT PacketSize
,
1664 IOTRACE(IO_IRP_DEBUG
,
1665 "%s - Initializing IRP %p\n",
1668 RtlZeroMemory(Irp
, PacketSize
);
1670 /* Set the Header and other data */
1671 Irp
->Type
= IO_TYPE_IRP
;
1672 Irp
->Size
= PacketSize
;
1673 Irp
->StackCount
= StackSize
;
1674 Irp
->CurrentLocation
= StackSize
+ 1;
1675 Irp
->ApcEnvironment
= KeGetCurrentThread()->ApcStateIndex
;
1676 Irp
->Tail
.Overlay
.CurrentStackLocation
= (PIO_STACK_LOCATION
)(Irp
+ 1) + StackSize
;
1678 /* Initialize the Thread List */
1679 InitializeListHead(&Irp
->ThreadListEntry
);
1687 IoIsOperationSynchronous(IN PIRP Irp
)
1689 /* Check the flags */
1690 if (!(Irp
->Flags
& (IRP_PAGING_IO
| IRP_SYNCHRONOUS_PAGING_IO
)) &&
1691 ((Irp
->Flags
& IRP_SYNCHRONOUS_PAGING_IO
) ||
1692 (Irp
->Flags
& IRP_SYNCHRONOUS_API
) ||
1693 (IoGetCurrentIrpStackLocation(Irp
)->FileObject
->Flags
&
1694 FO_SYNCHRONOUS_IO
)))
1696 /* Synch API or Paging I/O is OK, as is Sync File I/O */
1700 /* Otherwise, it is an asynchronous operation. */
1709 IoIsValidNameGraftingBuffer(IN PIRP Irp
,
1710 IN PREPARSE_DATA_BUFFER ReparseBuffer
)
1721 IoMakeAssociatedIrp(IN PIRP Irp
,
1725 IOTRACE(IO_IRP_DEBUG
,
1726 "%s - Associating IRP %p\n",
1730 /* Allocate the IRP */
1731 AssocIrp
= IoAllocateIrp(StackSize
, FALSE
);
1732 if (!AssocIrp
) return NULL
;
1735 AssocIrp
->Flags
|= IRP_ASSOCIATED_IRP
;
1737 /* Set the Thread */
1738 AssocIrp
->Tail
.Overlay
.Thread
= Irp
->Tail
.Overlay
.Thread
;
1740 /* Associate them */
1741 AssocIrp
->AssociatedIrp
.MasterIrp
= Irp
;
1750 IoQueueThreadIrp(IN PIRP Irp
)
1752 IOTRACE(IO_IRP_DEBUG
,
1753 "%s - Queueing IRP %p\n",
1757 /* Use our inlined routine */
1758 IopQueueIrpToThread(Irp
);
1763 * Reference: Chris Cant's "Writing WDM Device Drivers"
1767 IoReuseIrp(IN OUT PIRP Irp
,
1770 UCHAR AllocationFlags
;
1771 IOTRACE(IO_IRP_DEBUG
,
1772 "%s - Reusing IRP %p\n",
1776 /* Make sure it's OK to reuse it */
1777 ASSERT(!Irp
->CancelRoutine
);
1778 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1780 /* Get the old flags */
1781 AllocationFlags
= Irp
->AllocationFlags
;
1783 /* Reinitialize the IRP */
1784 IoInitializeIrp(Irp
, Irp
->Size
, Irp
->StackCount
);
1786 /* Duplicate the data */
1787 Irp
->IoStatus
.Status
= Status
;
1788 Irp
->AllocationFlags
= AllocationFlags
;
1796 IoSetTopLevelIrp(IN PIRP Irp
)
1799 PsGetCurrentThread()->TopLevelIrp
= (ULONG_PTR
)Irp
;