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
23 /* PRIVATE FUNCTIONS ********************************************************/
27 IopFreeIrpKernelApc(IN PKAPC Apc
,
28 IN PKNORMAL_ROUTINE
*NormalRoutine
,
29 IN PVOID
*NormalContext
,
30 IN PVOID
*SystemArgument1
,
31 IN PVOID
*SystemArgument2
)
34 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
39 IopAbortIrpKernelApc(IN PKAPC Apc
)
42 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
47 IopCleanupFailedIrp(IN PFILE_OBJECT FileObject
,
48 IN PKEVENT EventObject OPTIONAL
,
49 IN PVOID Buffer OPTIONAL
)
53 /* Dereference the event */
54 if (EventObject
) ObDereferenceObject(EventObject
);
56 /* Free a buffer, if any */
57 if (Buffer
) ExFreePool(Buffer
);
59 /* If this was a file opened for synch I/O, then unlock it */
60 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
62 /* Now dereference it and return */
63 ObDereferenceObject(FileObject
);
64 return STATUS_INSUFFICIENT_RESOURCES
;
69 IopAbortInterruptedIrp(IN PKEVENT EventObject
,
77 /* Raise IRQL to APC */
78 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
80 /* Check if nobody completed it yet */
81 if (!KeReadStateEvent(EventObject
))
83 /* First, cancel it */
84 CancelResult
= IoCancelIrp(Irp
);
87 /* Check if we cancelled it */
90 /* Wait for the IRP to be cancelled */
91 Wait
.QuadPart
= -100000;
92 while (!KeReadStateEvent(EventObject
))
94 /* Delay indefintely */
95 KeDelayExecutionThread(KernelMode
, FALSE
, &Wait
);
100 /* No cancellation done, so wait for the I/O system to kill it */
101 KeWaitForSingleObject(EventObject
,
110 /* We got preempted, so give up */
111 KeLowerIrql(OldIrql
);
117 IopDisassociateThreadIrp(VOID
)
119 KIRQL OldIrql
, LockIrql
;
121 PLIST_ENTRY IrpEntry
;
122 PIO_ERROR_LOG_PACKET ErrorLogEntry
;
123 PDEVICE_OBJECT DeviceObject
= NULL
;
124 PIO_STACK_LOCATION IoStackLocation
;
126 /* First, raise to APC to protect IrpList */
127 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
129 /* Get the Thread and check the list */
130 IrpThread
= PsGetCurrentThread();
131 if (IsListEmpty(&IrpThread
->IrpList
))
133 /* It got completed now, so quit */
134 KeLowerIrql(OldIrql
);
138 /* Ensure no one will come disturb */
139 LockIrql
= KeAcquireQueuedSpinLock(LockQueueIoCompletionLock
);
141 /* Get the misbehaving IRP */
142 IrpEntry
= IrpThread
->IrpList
.Flink
;
143 IopDeadIrp
= CONTAINING_RECORD(IrpEntry
, IRP
, ThreadListEntry
);
144 IOTRACE(IO_IRP_DEBUG
,
145 "%s - Deassociating IRP %p for %p\n",
150 /* Don't cancel the IRP if it's already been completed far */
151 if (IopDeadIrp
->CurrentLocation
== (IopDeadIrp
->StackCount
+ 2))
154 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock
, LockIrql
);
155 KeLowerIrql(OldIrql
);
159 /* Disown the IRP! */
160 IopDeadIrp
->Tail
.Overlay
.Thread
= NULL
;
161 RemoveHeadList(&IrpThread
->IrpList
);
162 InitializeListHead(&IopDeadIrp
->ThreadListEntry
);
164 /* Get the stack location and check if it's valid */
165 IoStackLocation
= IoGetCurrentIrpStackLocation(IopDeadIrp
);
166 if (IopDeadIrp
->CurrentLocation
<= IopDeadIrp
->StackCount
)
168 /* Get the device object */
169 DeviceObject
= IoStackLocation
->DeviceObject
;
172 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock
, LockIrql
);
173 /* Lower IRQL now, since we have the pointers we need */
174 KeLowerIrql(OldIrql
);
176 /* Check if we can send an Error Log Entry*/
179 /* Allocate an entry */
180 ErrorLogEntry
= IoAllocateErrorLogEntry(DeviceObject
,
181 sizeof(IO_ERROR_LOG_PACKET
));
184 /* Write the entry */
185 ErrorLogEntry
->ErrorCode
= IO_DRIVER_CANCEL_TIMEOUT
;
186 IoWriteErrorLogEntry(ErrorLogEntry
);
193 IopCleanupIrp(IN PIRP Irp
,
194 IN PFILE_OBJECT FileObject
)
197 IOTRACE(IO_IRP_DEBUG
,
198 "%s - Cleaning IRP %p for %p\n",
203 /* Check if there's an MDL */
204 while ((Mdl
= Irp
->MdlAddress
))
206 /* Clear all of them */
207 Irp
->MdlAddress
= Mdl
->Next
;
211 /* Check if the IRP has system buffer */
212 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
214 /* Free the buffer */
215 ExFreePoolWithTag(Irp
->AssociatedIrp
.SystemBuffer
, TAG_SYS_BUF
);
218 /* Check if this IRP has a user event, a file object, and is async */
219 if ((Irp
->UserEvent
) &&
220 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
) &&
223 /* Dereference the User Event */
224 ObDereferenceObject(Irp
->UserEvent
);
227 /* Check if we have a file object and this isn't a create operation */
228 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
230 /* Dereference the file object */
231 ObDereferenceObject(FileObject
);
240 IopCompleteRequest(IN PKAPC Apc
,
241 IN PKNORMAL_ROUTINE
* NormalRoutine
,
242 IN PVOID
* NormalContext
,
243 IN PVOID
* SystemArgument1
,
244 IN PVOID
* SystemArgument2
)
246 PFILE_OBJECT FileObject
;
249 PVOID Port
= NULL
, Key
= NULL
;
250 BOOLEAN SignaledCreateRequest
= FALSE
;
252 /* Get data from the APC */
253 FileObject
= (PFILE_OBJECT
)*SystemArgument1
;
254 Irp
= CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
);
255 IOTRACE(IO_IRP_DEBUG
,
256 "%s - Completing IRP %p for %p\n",
262 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
264 /* Check if we have a file object */
265 if (*SystemArgument2
)
267 /* Check if we're reparsing */
268 if ((Irp
->IoStatus
.Status
== STATUS_REPARSE
) &&
269 (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
))
271 /* We should never get this yet */
272 DPRINT1("Reparse support not yet present!\n");
277 /* Handle Buffered case first */
278 if (Irp
->Flags
& IRP_BUFFERED_IO
)
280 /* Check if we have an input buffer and if we succeeded */
281 if ((Irp
->Flags
& IRP_INPUT_OPERATION
) &&
282 (Irp
->IoStatus
.Status
!= STATUS_VERIFY_REQUIRED
) &&
283 !(NT_ERROR(Irp
->IoStatus
.Status
)))
285 /* Copy the buffer back to the user */
286 RtlCopyMemory(Irp
->UserBuffer
,
287 Irp
->AssociatedIrp
.SystemBuffer
,
288 Irp
->IoStatus
.Information
);
291 /* Also check if we should de-allocate it */
292 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
295 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
299 /* Now we got rid of these two... */
300 Irp
->Flags
&= ~(IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
302 /* Check if there's an MDL */
303 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
311 Irp
->MdlAddress
= NULL
;
314 * Check if either the request was completed without any errors
315 * (but warnings are OK!), or if it was completed with an error, but
316 * did return from a pending I/O Operation and is not synchronous.
318 if (!(NT_ERROR(Irp
->IoStatus
.Status
)) ||
319 (NT_ERROR(Irp
->IoStatus
.Status
) &&
320 (Irp
->PendingReturned
) &&
321 !(IsIrpSynchronous(Irp
, FileObject
))))
323 /* Get any information we need from the FO before we kill it */
324 if ((FileObject
) && (FileObject
->CompletionContext
))
326 /* Save Completion Data */
327 Port
= FileObject
->CompletionContext
->Port
;
328 Key
= FileObject
->CompletionContext
->Key
;
331 /* Use SEH to make sure we don't write somewhere invalid */
334 /* Save the IOSB Information */
335 *Irp
->UserIosb
= Irp
->IoStatus
;
337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
339 /* Ignore any error */
343 /* Check if we have an event or a file object */
346 /* At the very least, this is a PKEVENT, so signal it always */
347 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
349 /* Check if we also have a File Object */
352 /* Check if this is an Asynch API */
353 if (!(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
355 /* Dereference the event */
356 ObDereferenceObject(Irp
->UserEvent
);
360 * Now, if this is a Synch I/O File Object, then this event is
361 * NOT an actual Executive Event, so we won't dereference it,
362 * and instead, we will signal the File Object
364 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) &&
365 !(Irp
->Flags
& IRP_OB_QUERY_NAME
))
367 /* Signal the file object and set the status */
368 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
369 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
373 * This could also be a create operation, in which case we want
374 * to make sure there's no APC fired.
376 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
378 /* Clear the APC Routine and remember this */
379 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
380 SignaledCreateRequest
= TRUE
;
386 /* Signal the file object and set the status */
387 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
388 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
391 * This could also be a create operation, in which case we want
392 * to make sure there's no APC fired.
394 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
396 /* Clear the APC Routine and remember this */
397 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
398 SignaledCreateRequest
= TRUE
;
402 /* Update transfer count for everything but create operation */
403 if (!(Irp
->Flags
& IRP_CREATE_OPERATION
))
405 if (Irp
->Flags
& IRP_WRITE_OPERATION
)
407 /* Update write transfer count */
408 IopUpdateTransferCount(IopWriteTransfer
,
409 (ULONG
)Irp
->IoStatus
.Information
);
411 else if (Irp
->Flags
& IRP_READ_OPERATION
)
413 /* Update read transfer count */
414 IopUpdateTransferCount(IopReadTransfer
,
415 (ULONG
)Irp
->IoStatus
.Information
);
419 /* Update other transfer count */
420 IopUpdateTransferCount(IopOtherTransfer
,
421 (ULONG
)Irp
->IoStatus
.Information
);
425 /* Now that we've signaled the events, de-associate the IRP */
426 IopUnQueueIrpFromThread(Irp
);
428 /* Now check if a User APC Routine was requested */
429 if (Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
)
432 KeInitializeApc(&Irp
->Tail
.Apc
,
433 KeGetCurrentThread(),
434 CurrentApcEnvironment
,
436 IopAbortIrpKernelApc
,
437 (PKNORMAL_ROUTINE
)Irp
->
438 Overlay
.AsynchronousParameters
.UserApcRoutine
,
441 Overlay
.AsynchronousParameters
.UserApcContext
);
444 KeInsertQueueApc(&Irp
->Tail
.Apc
, Irp
->UserIosb
, NULL
, 2);
447 (Irp
->Overlay
.AsynchronousParameters
.UserApcContext
))
449 /* We have an I/O Completion setup... create the special Overlay */
450 Irp
->Tail
.CompletionKey
= Key
;
451 Irp
->Tail
.Overlay
.PacketType
= IopCompletionPacketIrp
;
452 KeInsertQueue(Port
, &Irp
->Tail
.Overlay
.ListEntry
);
456 /* Free the IRP since we don't need it anymore */
460 /* Check if we have a file object that wasn't part of a create */
461 if ((FileObject
) && !(SignaledCreateRequest
))
463 /* Dereference it, since it's not needed anymore either */
464 ObDereferenceObjectDeferDelete(FileObject
);
470 * Either we didn't return from the request, or we did return but this
471 * request was synchronous.
473 if ((Irp
->PendingReturned
) && (FileObject
))
475 /* So we did return with a synch operation, was it the IRP? */
476 if (Irp
->Flags
& IRP_SYNCHRONOUS_API
)
478 /* Yes, this IRP was synchronous, so return the I/O Status */
479 *Irp
->UserIosb
= Irp
->IoStatus
;
481 /* Now check if the user gave an event */
485 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
489 /* No event was given, so signal the FO instead */
490 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
496 * It's not the IRP that was synchronous, it was the FO
497 * that was opened this way. Signal its event.
499 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
500 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
504 /* Now that we got here, we do this for incomplete I/Os as well */
505 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
507 /* Dereference the File Object unless this was a create */
508 ObDereferenceObjectDeferDelete(FileObject
);
512 * Check if this was an Executive Event (remember that we know this
513 * by checking if the IRP is synchronous)
515 if ((Irp
->UserEvent
) &&
517 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
519 /* This isn't a PKEVENT, so dereference it */
520 ObDereferenceObject(Irp
->UserEvent
);
523 /* Now that we've signaled the events, de-associate the IRP */
524 IopUnQueueIrpFromThread(Irp
);
526 /* Free the IRP as well */
531 /* FUNCTIONS *****************************************************************/
538 IoAllocateIrp(IN CCHAR StackSize
,
539 IN BOOLEAN ChargeQuota
)
542 USHORT Size
= IoSizeOfIrp(StackSize
);
545 PNPAGED_LOOKASIDE_LIST List
= NULL
;
546 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
548 /* Set Charge Quota Flag */
549 if (ChargeQuota
) Flags
|= IRP_QUOTA_CHARGED
;
551 /* FIXME: Implement Lookaside Floats */
553 /* Figure out which Lookaside List to use */
554 if ((StackSize
<= 8) && (ChargeQuota
== FALSE
))
556 /* Set Fixed Size Flag */
557 Flags
= IRP_ALLOCATED_FIXED_SIZE
;
559 /* See if we should use big list */
562 Size
= IoSizeOfIrp(8);
563 ListType
= LookasideLargeIrpList
;
567 Prcb
= KeGetCurrentPrcb();
569 /* Get the P List First */
570 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
572 /* Attempt allocation */
573 List
->L
.TotalAllocates
++;
574 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
576 /* Check if the P List failed */
579 /* Let the balancer know */
580 List
->L
.AllocateMisses
++;
583 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
584 List
->L
.TotalAllocates
++;
585 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
589 /* Check if we have to use the pool */
592 /* Did we try lookaside and fail? */
593 if (Flags
& IRP_ALLOCATED_FIXED_SIZE
) List
->L
.AllocateMisses
++;
595 /* Check if we should charge quota */
598 /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
600 Irp
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_IRP
);
604 /* Allocate the IRP With no Quota charge */
605 Irp
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_IRP
);
608 /* Make sure it was sucessful */
609 if (!Irp
) return(NULL
);
613 /* In this case there is no charge quota */
614 Flags
&= ~IRP_QUOTA_CHARGED
;
617 /* Now Initialize it */
618 IoInitializeIrp(Irp
, Size
, StackSize
);
620 /* Set the Allocation Flags */
621 Irp
->AllocationFlags
= Flags
;
624 IOTRACE(IO_IRP_DEBUG
,
625 "%s - Allocated IRP %p with allocation flags %lx\n",
637 IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction
,
638 IN PDEVICE_OBJECT DeviceObject
,
641 IN PLARGE_INTEGER StartingOffset
,
642 IN PIO_STATUS_BLOCK IoStatusBlock
)
645 PIO_STACK_LOCATION StackPtr
;
648 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
649 if (!Irp
) return NULL
;
652 StackPtr
= IoGetNextIrpStackLocation(Irp
);
654 /* Write the Major function and then deal with it */
655 StackPtr
->MajorFunction
= (UCHAR
)MajorFunction
;
657 /* Do not handle the following here */
658 if ((MajorFunction
!= IRP_MJ_FLUSH_BUFFERS
) &&
659 (MajorFunction
!= IRP_MJ_SHUTDOWN
) &&
660 (MajorFunction
!= IRP_MJ_PNP
) &&
661 (MajorFunction
!= IRP_MJ_POWER
))
663 /* Check if this is Buffered IO */
664 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
666 /* Allocate the System Buffer */
667 Irp
->AssociatedIrp
.SystemBuffer
=
668 ExAllocatePoolWithTag(NonPagedPool
, Length
, TAG_SYS_BUF
);
669 if (!Irp
->AssociatedIrp
.SystemBuffer
)
671 /* Free the IRP and fail */
677 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
679 /* Handle special IRP_MJ_WRITE Case */
680 if (MajorFunction
== IRP_MJ_WRITE
)
682 /* Copy the buffer data */
683 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
687 /* Set the Input Operation flag and set this as a User Buffer */
688 Irp
->Flags
|= IRP_INPUT_OPERATION
;
689 Irp
->UserBuffer
= Buffer
;
692 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
694 /* Use an MDL for Direct I/O */
695 Irp
->MdlAddress
= IoAllocateMdl(Buffer
,
700 if (!Irp
->MdlAddress
)
702 /* Free the IRP and fail */
711 MmProbeAndLockPages(Irp
->MdlAddress
,
713 MajorFunction
== IRP_MJ_READ
?
714 IoWriteAccess
: IoReadAccess
);
716 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
718 /* Free the IRP and its MDL */
719 IoFreeMdl(Irp
->MdlAddress
);
723 _SEH2_YIELD(return NULL
);
729 /* Neither, use the buffer */
730 Irp
->UserBuffer
= Buffer
;
733 /* Check if this is a read */
734 if (MajorFunction
== IRP_MJ_READ
)
736 /* Set the parameters for a read */
737 StackPtr
->Parameters
.Read
.Length
= Length
;
738 StackPtr
->Parameters
.Read
.ByteOffset
= *StartingOffset
;
740 else if (MajorFunction
== IRP_MJ_WRITE
)
742 /* Otherwise, set write parameters */
743 StackPtr
->Parameters
.Write
.Length
= Length
;
744 StackPtr
->Parameters
.Write
.ByteOffset
= *StartingOffset
;
748 /* Set the Current Thread and IOSB */
749 Irp
->UserIosb
= IoStatusBlock
;
750 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
753 IOTRACE(IO_IRP_DEBUG
,
754 "%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
768 IoBuildDeviceIoControlRequest(IN ULONG IoControlCode
,
769 IN PDEVICE_OBJECT DeviceObject
,
770 IN PVOID InputBuffer
,
771 IN ULONG InputBufferLength
,
772 IN PVOID OutputBuffer
,
773 IN ULONG OutputBufferLength
,
774 IN BOOLEAN InternalDeviceIoControl
,
776 IN PIO_STATUS_BLOCK IoStatusBlock
)
779 PIO_STACK_LOCATION StackPtr
;
783 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
784 if (!Irp
) return NULL
;
787 StackPtr
= IoGetNextIrpStackLocation(Irp
);
789 /* Set the DevCtl Type */
790 StackPtr
->MajorFunction
= InternalDeviceIoControl
?
791 IRP_MJ_INTERNAL_DEVICE_CONTROL
:
792 IRP_MJ_DEVICE_CONTROL
;
794 /* Set the IOCTL Data */
795 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
796 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
797 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
800 /* Handle the Methods */
801 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode
))
804 case METHOD_BUFFERED
:
806 /* Select the right Buffer Length */
807 BufferLength
= InputBufferLength
> OutputBufferLength
?
808 InputBufferLength
: OutputBufferLength
;
810 /* Make sure there is one */
813 /* Allocate the System Buffer */
814 Irp
->AssociatedIrp
.SystemBuffer
=
815 ExAllocatePoolWithTag(NonPagedPool
,
818 if (!Irp
->AssociatedIrp
.SystemBuffer
)
820 /* Free the IRP and fail */
825 /* Check if we got a buffer */
828 /* Copy into the System Buffer */
829 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
834 /* Write the flags */
835 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
836 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
838 /* Save the Buffer */
839 Irp
->UserBuffer
= OutputBuffer
;
843 /* Clear the Flags and Buffer */
845 Irp
->UserBuffer
= NULL
;
850 case METHOD_IN_DIRECT
:
851 case METHOD_OUT_DIRECT
:
853 /* Check if we got an input buffer */
856 /* Allocate the System Buffer */
857 Irp
->AssociatedIrp
.SystemBuffer
=
858 ExAllocatePoolWithTag(NonPagedPool
,
861 if (!Irp
->AssociatedIrp
.SystemBuffer
)
863 /* Free the IRP and fail */
868 /* Copy into the System Buffer */
869 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
873 /* Write the flags */
874 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
878 /* Clear the flags */
882 /* Check if we got an output buffer */
885 /* Allocate the System Buffer */
886 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
891 if (!Irp
->MdlAddress
)
893 /* Free the IRP and fail */
902 MmProbeAndLockPages(Irp
->MdlAddress
,
904 IO_METHOD_FROM_CTL_CODE(IoControlCode
) ==
906 IoReadAccess
: IoWriteAccess
);
908 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
911 IoFreeMdl(Irp
->MdlAddress
);
913 /* Free the input buffer and IRP */
914 if (InputBuffer
) ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
918 _SEH2_YIELD(return NULL
);
926 /* Just save the Buffer */
927 Irp
->UserBuffer
= OutputBuffer
;
928 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
931 /* Now write the Event and IoSB */
932 Irp
->UserIosb
= IoStatusBlock
;
933 Irp
->UserEvent
= Event
;
935 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
936 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
937 IoQueueThreadIrp(Irp
);
940 IOTRACE(IO_IRP_DEBUG
,
941 "%s - Built IRP %p with IOCTL, Buffers, DO %lx %p %p %p\n",
956 IoBuildSynchronousFsdRequest(IN ULONG MajorFunction
,
957 IN PDEVICE_OBJECT DeviceObject
,
960 IN PLARGE_INTEGER StartingOffset
,
962 IN PIO_STATUS_BLOCK IoStatusBlock
)
966 /* Do the big work to set up the IRP */
967 Irp
= IoBuildAsynchronousFsdRequest(MajorFunction
,
973 if (!Irp
) return NULL
;
975 /* Set the Event which makes it Syncronous */
976 Irp
->UserEvent
= Event
;
978 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
979 IoQueueThreadIrp(Irp
);
988 IoCancelIrp(IN PIRP Irp
)
991 PDRIVER_CANCEL CancelRoutine
;
992 IOTRACE(IO_IRP_DEBUG
,
993 "%s - Canceling IRP %p\n",
996 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
998 /* Acquire the cancel lock and cancel the IRP */
999 IoAcquireCancelSpinLock(&OldIrql
);
1002 /* Clear the cancel routine and get the old one */
1003 CancelRoutine
= (PVOID
)IoSetCancelRoutine(Irp
, NULL
);
1006 /* We had a routine, make sure the IRP isn't completed */
1007 if (Irp
->CurrentLocation
> (Irp
->StackCount
+ 1))
1009 /* It is, bugcheck */
1010 KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP
,
1012 (ULONG_PTR
)CancelRoutine
,
1017 /* Set the cancel IRQL And call the routine */
1018 Irp
->CancelIrql
= OldIrql
;
1019 CancelRoutine(IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
, Irp
);
1023 /* Otherwise, release the cancel lock and fail */
1024 IoReleaseCancelSpinLock(OldIrql
);
1033 IoCancelThreadIo(IN PETHREAD Thread
)
1036 ULONG Retries
= 3000;
1037 LARGE_INTEGER Interval
;
1038 PLIST_ENTRY ListHead
, NextEntry
;
1042 /* Windows isn't using given thread, but using current. */
1043 Thread
= PsGetCurrentThread();
1045 IOTRACE(IO_IRP_DEBUG
,
1046 "%s - Canceling IRPs for Thread %p\n",
1050 /* Raise to APC to protect the IrpList */
1051 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1053 /* Start by cancelling all the IRPs in the current thread queue. */
1054 ListHead
= &Thread
->IrpList
;
1055 NextEntry
= ListHead
->Flink
;
1056 while (ListHead
!= NextEntry
)
1059 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
1064 /* Move to the next entry */
1065 NextEntry
= NextEntry
->Flink
;
1068 /* Wait 100 milliseconds */
1069 Interval
.QuadPart
= -1000000;
1071 /* Wait till all the IRPs are completed or cancelled. */
1072 while (!IsListEmpty(&Thread
->IrpList
))
1074 /* Now we can lower */
1075 KeLowerIrql(OldIrql
);
1077 /* Wait a short while and then look if all our IRPs were completed. */
1078 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1081 * Don't stay here forever if some broken driver doesn't complete
1086 /* Print out a message and remove the IRP */
1087 DPRINT1("Broken driver did not complete!\n");
1088 IopDisassociateThreadIrp();
1091 /* Raise the IRQL Again */
1092 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1095 /* We're done, lower the IRQL */
1096 KeLowerIrql(OldIrql
);
1104 IoCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1108 return IofCallDriver(DeviceObject
, Irp
);
1116 IoCompleteRequest(IN PIRP Irp
,
1117 IN CCHAR PriorityBoost
)
1119 /* Call the fastcall */
1120 IofCompleteRequest(Irp
, PriorityBoost
);
1128 IoEnqueueIrp(IN PIRP Irp
)
1130 /* This is the same as calling IoQueueThreadIrp */
1131 IoQueueThreadIrp(Irp
);
1139 IofCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1142 PDRIVER_OBJECT DriverObject
;
1143 PIO_STACK_LOCATION StackPtr
;
1145 /* Make sure this is a valid IRP */
1146 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1148 /* Get the Driver Object */
1149 DriverObject
= DeviceObject
->DriverObject
;
1151 /* Decrease the current location and check if */
1152 Irp
->CurrentLocation
--;
1153 if (Irp
->CurrentLocation
<= 0)
1155 /* This IRP ran out of stack, bugcheck */
1156 KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1159 /* Now update the stack location */
1160 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1161 Irp
->Tail
.Overlay
.CurrentStackLocation
= StackPtr
;
1163 /* Get the Device Object */
1164 StackPtr
->DeviceObject
= DeviceObject
;
1167 return DriverObject
->MajorFunction
[StackPtr
->MajorFunction
](DeviceObject
,
1173 IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation
)
1175 IoStackLocation
->MinorFunction
= 0;
1176 IoStackLocation
->Flags
= 0;
1177 IoStackLocation
->Control
&= SL_ERROR_RETURNED
;
1178 IoStackLocation
->Parameters
.Others
.Argument1
= 0;
1179 IoStackLocation
->Parameters
.Others
.Argument2
= 0;
1180 IoStackLocation
->Parameters
.Others
.Argument3
= 0;
1181 IoStackLocation
->FileObject
= NULL
;
1189 IofCompleteRequest(IN PIRP Irp
,
1190 IN CCHAR PriorityBoost
)
1192 PIO_STACK_LOCATION StackPtr
, LastStackPtr
;
1193 PDEVICE_OBJECT DeviceObject
;
1194 PFILE_OBJECT FileObject
;
1201 NTSTATUS ErrorCode
= STATUS_SUCCESS
;
1202 IOTRACE(IO_IRP_DEBUG
,
1203 "%s - Completing IRP %p\n",
1207 /* Make sure this IRP isn't getting completed twice or is invalid */
1208 if ((Irp
->CurrentLocation
) > (Irp
->StackCount
+ 1))
1211 KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1214 /* Some sanity checks */
1215 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1216 ASSERT(!Irp
->CancelRoutine
);
1217 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1218 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
1220 /* Get the last stack */
1221 LastStackPtr
= (PIO_STACK_LOCATION
)(Irp
+ 1);
1222 if (LastStackPtr
->Control
& SL_ERROR_RETURNED
)
1224 /* Get the error code */
1225 ErrorCode
= PtrToUlong(LastStackPtr
->Parameters
.Others
.Argument4
);
1229 * Start the loop with the current stack and point the IRP to the next stack
1230 * and then keep incrementing the stack as we loop through. The IRP should
1231 * always point to the next stack location w.r.t the one currently being
1232 * analyzed, so completion routine code will see the appropriate value.
1233 * Because of this, we must loop until the current stack location is +1 of
1234 * the stack count, because when StackPtr is at the end, CurrentLocation is +1.
1236 for (StackPtr
= IoGetCurrentIrpStackLocation(Irp
),
1237 Irp
->CurrentLocation
++,
1238 Irp
->Tail
.Overlay
.CurrentStackLocation
++;
1239 Irp
->CurrentLocation
<= (Irp
->StackCount
+ 1);
1241 Irp
->CurrentLocation
++,
1242 Irp
->Tail
.Overlay
.CurrentStackLocation
++)
1244 /* Set Pending Returned */
1245 Irp
->PendingReturned
= StackPtr
->Control
& SL_PENDING_RETURNED
;
1247 /* Check if we failed */
1248 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1250 /* Check if it was changed by a completion routine */
1251 if (Irp
->IoStatus
.Status
!= ErrorCode
)
1253 /* Update the error for the current stack */
1254 ErrorCode
= Irp
->IoStatus
.Status
;
1255 StackPtr
->Control
|= SL_ERROR_RETURNED
;
1256 LastStackPtr
->Parameters
.Others
.Argument4
= UlongToPtr(ErrorCode
);
1257 LastStackPtr
->Control
|= SL_ERROR_RETURNED
;
1261 /* Check if there is a Completion Routine to Call */
1262 if ((NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1263 (StackPtr
->Control
& SL_INVOKE_ON_SUCCESS
)) ||
1264 (!NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1265 (StackPtr
->Control
& SL_INVOKE_ON_ERROR
)) ||
1267 (StackPtr
->Control
& SL_INVOKE_ON_CANCEL
)))
1269 /* Clear the stack location */
1270 IopClearStackLocation(StackPtr
);
1272 /* Check for highest-level device completion routines */
1273 if (Irp
->CurrentLocation
== (Irp
->StackCount
+ 1))
1275 /* Clear the DO, since the current stack location is invalid */
1276 DeviceObject
= NULL
;
1280 /* Otherwise, return the real one */
1281 DeviceObject
= IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
;
1284 /* Call the completion routine */
1285 Status
= StackPtr
->CompletionRoutine(DeviceObject
,
1289 /* Don't touch the Packet in this case, since it might be gone! */
1290 if (Status
== STATUS_MORE_PROCESSING_REQUIRED
) return;
1294 /* Otherwise, check if this is a completed IRP */
1295 if ((Irp
->CurrentLocation
<= Irp
->StackCount
) &&
1296 (Irp
->PendingReturned
))
1298 /* Mark it as pending */
1299 IoMarkIrpPending(Irp
);
1302 /* Clear the stack location */
1303 IopClearStackLocation(StackPtr
);
1307 /* Check if the IRP is an associated IRP */
1308 if (Irp
->Flags
& IRP_ASSOCIATED_IRP
)
1310 /* Get the master IRP and count */
1311 MasterIrp
= Irp
->AssociatedIrp
.MasterIrp
;
1312 MasterCount
= InterlockedDecrement(&MasterIrp
->AssociatedIrp
.IrpCount
);
1315 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
1317 /* Go to the next one */
1318 NextMdl
= Mdl
->Next
;
1322 /* Free the IRP itself */
1325 /* Complete the Master IRP */
1326 if (!MasterCount
) IofCompleteRequest(MasterIrp
, PriorityBoost
);
1330 /* We don't support this yet */
1331 ASSERT(Irp
->IoStatus
.Status
!= STATUS_REPARSE
);
1333 /* Check if we have an auxiliary buffer */
1334 if (Irp
->Tail
.Overlay
.AuxiliaryBuffer
)
1337 ExFreePool(Irp
->Tail
.Overlay
.AuxiliaryBuffer
);
1338 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
1341 /* Check if this is a Paging I/O or Close Operation */
1342 if (Irp
->Flags
& (IRP_PAGING_IO
| IRP_CLOSE_OPERATION
))
1344 /* Handle a Close Operation or Sync Paging I/O */
1345 if (Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_CLOSE_OPERATION
))
1347 /* Set the I/O Status and Signal the Event */
1348 Flags
= Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
);
1349 *Irp
->UserIosb
= Irp
->IoStatus
;
1350 KeSetEvent(Irp
->UserEvent
, PriorityBoost
, FALSE
);
1352 /* Free the IRP for a Paging I/O Only, Close is handled by us */
1353 if (Flags
) IoFreeIrp(Irp
);
1359 KeInitializeApc(&Irp
->Tail
.Apc
1360 &Irp
->Tail
.Overlay
.Thread
->Tcb
,
1361 Irp
->ApcEnvironment
,
1362 IopCompletePageWrite
,
1367 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1372 /* Not implemented yet. */
1373 DPRINT1("Not supported!\n");
1378 /* Get out of here */
1382 /* Unlock MDL Pages, page 167. */
1383 Mdl
= Irp
->MdlAddress
;
1390 /* Check if we should exit because of a Deferred I/O (page 168) */
1391 if ((Irp
->Flags
& IRP_DEFER_IO_COMPLETION
) && !(Irp
->PendingReturned
))
1394 * Return without queuing the completion APC, since the caller will
1395 * take care of doing its own optimized completion at PASSIVE_LEVEL.
1400 /* Get the thread and file object */
1401 Thread
= Irp
->Tail
.Overlay
.Thread
;
1402 FileObject
= Irp
->Tail
.Overlay
.OriginalFileObject
;
1404 /* Make sure the IRP isn't canceled */
1407 /* Initialize the APC */
1408 KeInitializeApc(&Irp
->Tail
.Apc
,
1410 Irp
->ApcEnvironment
,
1418 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1420 NULL
, /* This is used for REPARSE stuff */
1425 /* The IRP just got canceled... does a thread still own it? */
1428 /* Yes! There is still hope! Initialize the APC */
1429 KeInitializeApc(&Irp
->Tail
.Apc
,
1431 Irp
->ApcEnvironment
,
1439 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1441 NULL
, /* This is used for REPARSE stuff */
1446 /* Nothing left for us to do, kill it */
1447 ASSERT(Irp
->Cancel
);
1448 IopCleanupIrp(Irp
, FileObject
);
1455 IopSynchronousCompletion(IN PDEVICE_OBJECT DeviceObject
,
1459 if (Irp
->PendingReturned
)
1460 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1461 return STATUS_MORE_PROCESSING_REQUIRED
;
1469 IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject
,
1475 /* Check if next stack location is available */
1476 if (Irp
->CurrentLocation
< Irp
->StackCount
)
1478 /* No more stack location */
1482 /* Initialize event */
1483 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1485 /* Copy stack location for next driver */
1486 IoCopyCurrentIrpStackLocationToNext(Irp
);
1488 /* Set a completion routine, which will signal the event */
1489 IoSetCompletionRoutine(Irp
, IopSynchronousCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
1491 /* Call next driver */
1492 Status
= IoCallDriver(DeviceObject
, Irp
);
1494 /* Check if irp is pending */
1495 if (Status
== STATUS_PENDING
)
1497 /* Yes, wait for its completion */
1498 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
1501 /* Return success */
1510 IoFreeIrp(IN PIRP Irp
)
1512 PNPAGED_LOOKASIDE_LIST List
;
1513 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
1515 IOTRACE(IO_IRP_DEBUG
,
1516 "%s - Freeing IRPs %p\n",
1520 /* Make sure the Thread IRP list is empty and that it OK to free it */
1521 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1522 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1523 ASSERT(Irp
->CurrentLocation
>= Irp
->StackCount
);
1525 /* If this was a pool alloc, free it with the pool */
1526 if (!(Irp
->AllocationFlags
& IRP_ALLOCATED_FIXED_SIZE
))
1529 ExFreePoolWithTag(Irp
, TAG_IRP
);
1533 /* Check if this was a Big IRP */
1534 if (Irp
->StackCount
!= 1) ListType
= LookasideLargeIrpList
;
1537 Prcb
= KeGetCurrentPrcb();
1539 /* Use the P List */
1540 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
1541 List
->L
.TotalFrees
++;
1543 /* Check if the Free was within the Depth or not */
1544 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1546 /* Let the balancer know */
1547 List
->L
.FreeMisses
++;
1549 /* Use the L List */
1550 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
1551 List
->L
.TotalFrees
++;
1553 /* Check if the Free was within the Depth or not */
1554 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1556 /* All lists failed, use the pool */
1557 List
->L
.FreeMisses
++;
1558 ExFreePoolWithTag(Irp
, TAG_IRP
);
1563 /* The free was within the Depth */
1566 InterlockedPushEntrySList(&List
->L
.ListHead
,
1577 IoGetPagingIoPriority(IN PIRP Irp
)
1579 IO_PAGING_PRIORITY Priority
;
1585 /* Check what priority it has */
1586 if (Flags
& IRP_CLASS_CACHE_OPERATION
)
1589 Priority
= IoPagingPriorityHigh
;
1591 else if (Flags
& IRP_PAGING_IO
)
1593 /* Normal priority */
1594 Priority
= IoPagingPriorityNormal
;
1598 /* Invalid -- not a paging IRP */
1599 Priority
= IoPagingPriorityInvalid
;
1602 /* Return the priority */
1611 IoGetRequestorProcess(IN PIRP Irp
)
1613 /* Return the requestor process */
1614 if (Irp
->Tail
.Overlay
.Thread
)
1616 return Irp
->Tail
.Overlay
.Thread
->ThreadsProcess
;
1627 IoGetRequestorProcessId(IN PIRP Irp
)
1631 /* Return the requestor process' id */
1632 if ((Process
= IoGetRequestorProcess(Irp
)))
1634 return PtrToUlong(Process
->UniqueProcessId
);
1645 IoGetRequestorSessionId(IN PIRP Irp
,
1646 OUT PULONG pSessionId
)
1650 /* Return the session */
1651 if ((Process
= IoGetRequestorProcess(Irp
)))
1653 *pSessionId
= Process
->Session
;
1654 return STATUS_SUCCESS
;
1657 *pSessionId
= (ULONG
)-1;
1658 return STATUS_UNSUCCESSFUL
;
1666 IoGetTopLevelIrp(VOID
)
1668 /* Return the IRP */
1669 return (PIRP
)PsGetCurrentThread()->TopLevelIrp
;
1677 IoInitializeIrp(IN PIRP Irp
,
1678 IN USHORT PacketSize
,
1682 IOTRACE(IO_IRP_DEBUG
,
1683 "%s - Initializing IRP %p\n",
1686 RtlZeroMemory(Irp
, PacketSize
);
1688 /* Set the Header and other data */
1689 Irp
->Type
= IO_TYPE_IRP
;
1690 Irp
->Size
= PacketSize
;
1691 Irp
->StackCount
= StackSize
;
1692 Irp
->CurrentLocation
= StackSize
+ 1;
1693 Irp
->ApcEnvironment
= KeGetCurrentThread()->ApcStateIndex
;
1694 Irp
->Tail
.Overlay
.CurrentStackLocation
= (PIO_STACK_LOCATION
)(Irp
+ 1) + StackSize
;
1696 /* Initialize the Thread List */
1697 InitializeListHead(&Irp
->ThreadListEntry
);
1705 IoIsOperationSynchronous(IN PIRP Irp
)
1710 /* If the IRP requests synchronous paging I/O, if the file object was opened
1711 for synchronous I/O, if the IRP_SYNCHRONOUS_API flag is set in the IRP
1712 the operation is synchronous */
1713 SynchIO
= (IoGetCurrentIrpStackLocation(Irp
)->FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
1714 (Irp
->Flags
& IRP_SYNCHRONOUS_API
) || (Irp
->Flags
& IRP_SYNCHRONOUS_PAGING_IO
);
1716 /* If the IRP requests asynchronous paging I/O, the operation is asynchronous,
1717 even if one of the above conditions is true */
1718 ForceAsync
= (Irp
->Flags
& IRP_PAGING_IO
) && !(Irp
->Flags
& IRP_SYNCHRONOUS_PAGING_IO
);
1720 /* Check the flags */
1721 if (SynchIO
&& !ForceAsync
)
1723 /* Synch API or Paging I/O is OK, as is Sync File I/O */
1727 /* Otherwise, it is an asynchronous operation. */
1736 IoIsValidNameGraftingBuffer(IN PIRP Irp
,
1737 IN PREPARSE_DATA_BUFFER ReparseBuffer
)
1748 IoMakeAssociatedIrp(IN PIRP Irp
,
1752 IOTRACE(IO_IRP_DEBUG
,
1753 "%s - Associating IRP %p\n",
1757 /* Allocate the IRP */
1758 AssocIrp
= IoAllocateIrp(StackSize
, FALSE
);
1759 if (!AssocIrp
) return NULL
;
1762 AssocIrp
->Flags
|= IRP_ASSOCIATED_IRP
;
1764 /* Set the Thread */
1765 AssocIrp
->Tail
.Overlay
.Thread
= Irp
->Tail
.Overlay
.Thread
;
1767 /* Associate them */
1768 AssocIrp
->AssociatedIrp
.MasterIrp
= Irp
;
1777 IoQueueThreadIrp(IN PIRP Irp
)
1779 IOTRACE(IO_IRP_DEBUG
,
1780 "%s - Queueing IRP %p\n",
1784 /* Use our inlined routine */
1785 IopQueueIrpToThread(Irp
);
1790 * Reference: Chris Cant's "Writing WDM Device Drivers"
1794 IoReuseIrp(IN OUT PIRP Irp
,
1797 UCHAR AllocationFlags
;
1798 IOTRACE(IO_IRP_DEBUG
,
1799 "%s - Reusing IRP %p\n",
1803 /* Make sure it's OK to reuse it */
1804 ASSERT(!Irp
->CancelRoutine
);
1805 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1807 /* Get the old flags */
1808 AllocationFlags
= Irp
->AllocationFlags
;
1810 /* Reinitialize the IRP */
1811 IoInitializeIrp(Irp
, Irp
->Size
, Irp
->StackCount
);
1813 /* Duplicate the data */
1814 Irp
->IoStatus
.Status
= Status
;
1815 Irp
->AllocationFlags
= AllocationFlags
;
1823 IoSetTopLevelIrp(IN PIRP Irp
)
1826 PsGetCurrentThread()->TopLevelIrp
= (ULONG_PTR
)Irp
;
1829 #if defined (_WIN64)
1833 IN PIRP Irp OPTIONAL
)