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 ****************************************************************/
19 /* PRIVATE FUNCTIONS ********************************************************/
23 IopFreeIrpKernelApc(IN PKAPC Apc
,
24 IN PKNORMAL_ROUTINE
*NormalRoutine
,
25 IN PVOID
*NormalContext
,
26 IN PVOID
*SystemArgument1
,
27 IN PVOID
*SystemArgument2
)
30 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
35 IopAbortIrpKernelApc(IN PKAPC Apc
)
38 IoFreeIrp(CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
));
43 IopCleanupFailedIrp(IN PFILE_OBJECT FileObject
,
44 IN PKEVENT EventObject OPTIONAL
,
45 IN PVOID Buffer OPTIONAL
)
49 /* Dereference the event */
50 if (EventObject
) ObDereferenceObject(EventObject
);
52 /* Free a buffer, if any */
53 if (Buffer
) ExFreePool(Buffer
);
55 /* If this was a file opened for synch I/O, then unlock it */
56 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
) IopUnlockFileObject(FileObject
);
58 /* Now dereference it and return */
59 ObDereferenceObject(FileObject
);
60 return STATUS_INSUFFICIENT_RESOURCES
;
65 IopAbortInterruptedIrp(IN PKEVENT EventObject
,
73 /* Raise IRQL to APC */
74 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
76 /* Check if nobody completed it yet */
77 if (!KeReadStateEvent(EventObject
))
79 /* First, cancel it */
80 CancelResult
= IoCancelIrp(Irp
);
83 /* Check if we cancelled it */
86 /* Wait for the IRP to be cancelled */
87 Wait
.QuadPart
= -100000;
88 while (!KeReadStateEvent(EventObject
))
90 /* Delay indefintely */
91 KeDelayExecutionThread(KernelMode
, FALSE
, &Wait
);
96 /* No cancellation done, so wait for the I/O system to kill it */
97 KeWaitForSingleObject(EventObject
,
106 /* We got preempted, so give up */
107 KeLowerIrql(OldIrql
);
113 IopDisassociateThreadIrp(VOID
)
115 KIRQL OldIrql
, LockIrql
;
117 PLIST_ENTRY IrpEntry
;
118 PIO_ERROR_LOG_PACKET ErrorLogEntry
;
119 PDEVICE_OBJECT DeviceObject
= NULL
;
120 PIO_STACK_LOCATION IoStackLocation
;
122 /* First, raise to APC to protect IrpList */
123 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
125 /* Get the Thread and check the list */
126 IrpThread
= PsGetCurrentThread();
127 if (IsListEmpty(&IrpThread
->IrpList
))
129 /* It got completed now, so quit */
130 KeLowerIrql(OldIrql
);
134 /* Ensure no one will come disturb */
135 LockIrql
= KeAcquireQueuedSpinLock(LockQueueIoCompletionLock
);
137 /* Get the misbehaving IRP */
138 IrpEntry
= IrpThread
->IrpList
.Flink
;
139 IopDeadIrp
= 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 (IopDeadIrp
->CurrentLocation
== (IopDeadIrp
->StackCount
+ 2))
150 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock
, LockIrql
);
151 KeLowerIrql(OldIrql
);
155 /* Disown the IRP! */
156 IopDeadIrp
->Tail
.Overlay
.Thread
= NULL
;
157 RemoveHeadList(&IrpThread
->IrpList
);
158 InitializeListHead(&IopDeadIrp
->ThreadListEntry
);
160 /* Get the stack location and check if it's valid */
161 IoStackLocation
= IoGetCurrentIrpStackLocation(IopDeadIrp
);
162 if (IopDeadIrp
->CurrentLocation
<= IopDeadIrp
->StackCount
)
164 /* Get the device object */
165 DeviceObject
= IoStackLocation
->DeviceObject
;
168 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock
, LockIrql
);
169 /* Lower IRQL now, since we have the pointers we need */
170 KeLowerIrql(OldIrql
);
172 /* Check if we can send an Error Log Entry*/
175 /* Allocate an entry */
176 ErrorLogEntry
= IoAllocateErrorLogEntry(DeviceObject
,
177 sizeof(IO_ERROR_LOG_PACKET
));
180 /* Write the entry */
181 ErrorLogEntry
->ErrorCode
= IO_DRIVER_CANCEL_TIMEOUT
;
182 IoWriteErrorLogEntry(ErrorLogEntry
);
189 IopCleanupIrp(IN PIRP Irp
,
190 IN PFILE_OBJECT FileObject
)
193 IOTRACE(IO_IRP_DEBUG
,
194 "%s - Cleaning IRP %p for %p\n",
199 /* Check if there's an MDL */
200 while ((Mdl
= Irp
->MdlAddress
))
202 /* Clear all of them */
203 Irp
->MdlAddress
= Mdl
->Next
;
207 /* Check if the IRP has system buffer */
208 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
210 /* Free the buffer */
211 ExFreePoolWithTag(Irp
->AssociatedIrp
.SystemBuffer
, TAG_SYS_BUF
);
214 /* Check if this IRP has a user event, a file object, and is async */
215 if ((Irp
->UserEvent
) &&
216 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
) &&
219 /* Dereference the User Event */
220 ObDereferenceObject(Irp
->UserEvent
);
223 /* Check if we have a file object and this isn't a create operation */
224 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
226 /* Dereference the file object */
227 ObDereferenceObject(FileObject
);
236 IopCompleteRequest(IN PKAPC Apc
,
237 IN PKNORMAL_ROUTINE
* NormalRoutine
,
238 IN PVOID
* NormalContext
,
239 IN PVOID
* SystemArgument1
,
240 IN PVOID
* SystemArgument2
)
242 PFILE_OBJECT FileObject
;
245 PVOID Port
= NULL
, Key
= NULL
;
246 BOOLEAN SignaledCreateRequest
= FALSE
;
248 /* Get data from the APC */
249 FileObject
= (PFILE_OBJECT
)*SystemArgument1
;
250 Irp
= CONTAINING_RECORD(Apc
, IRP
, Tail
.Apc
);
251 IOTRACE(IO_IRP_DEBUG
,
252 "%s - Completing IRP %p for %p\n",
258 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
260 /* Check if we have a file object */
261 if (*SystemArgument2
)
263 /* Check if we're reparsing */
264 if ((Irp
->IoStatus
.Status
== STATUS_REPARSE
) &&
265 (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
))
267 PREPARSE_DATA_BUFFER ReparseData
;
269 ReparseData
= (PREPARSE_DATA_BUFFER
)*SystemArgument2
;
271 ASSERT(ReparseData
->ReparseTag
== IO_REPARSE_TAG_MOUNT_POINT
);
272 ASSERT(ReparseData
->ReparseDataLength
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
273 ASSERT(ReparseData
->Reserved
< MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
275 IopDoNameTransmogrify(Irp
, FileObject
, ReparseData
);
279 /* Handle Buffered case first */
280 if (Irp
->Flags
& IRP_BUFFERED_IO
)
282 /* Check if we have an input buffer and if we succeeded */
283 if ((Irp
->Flags
& IRP_INPUT_OPERATION
) &&
284 (Irp
->IoStatus
.Status
!= STATUS_VERIFY_REQUIRED
) &&
285 !(NT_ERROR(Irp
->IoStatus
.Status
)))
289 /* Copy the buffer back to the user */
290 RtlCopyMemory(Irp
->UserBuffer
,
291 Irp
->AssociatedIrp
.SystemBuffer
,
292 Irp
->IoStatus
.Information
);
294 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
297 Irp
->IoStatus
.Status
= _SEH2_GetExceptionCode();
302 /* Also check if we should de-allocate it */
303 if (Irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
306 ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
310 /* Now we got rid of these two... */
311 Irp
->Flags
&= ~(IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
);
313 /* Check if there's an MDL */
314 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
322 Irp
->MdlAddress
= NULL
;
325 * Check if either the request was completed without any errors
326 * (but warnings are OK!), or if it was completed with an error, but
327 * did return from a pending I/O Operation and is not synchronous.
329 if (!NT_ERROR(Irp
->IoStatus
.Status
) ||
330 (Irp
->PendingReturned
&&
331 !IsIrpSynchronous(Irp
, FileObject
)))
333 /* Get any information we need from the FO before we kill it */
334 if ((FileObject
) && (FileObject
->CompletionContext
))
336 /* Save Completion Data */
337 Port
= FileObject
->CompletionContext
->Port
;
338 Key
= FileObject
->CompletionContext
->Key
;
341 /* Check for UserIos */
342 if (Irp
->UserIosb
!= NULL
)
344 /* Use SEH to make sure we don't write somewhere invalid */
347 /* Save the IOSB Information */
348 *Irp
->UserIosb
= Irp
->IoStatus
;
350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
352 /* Ignore any error */
357 /* Check if we have an event or a file object */
360 /* At the very least, this is a PKEVENT, so signal it always */
361 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
363 /* Check if we also have a File Object */
366 /* Check if this is an Asynch API */
367 if (!(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
369 /* Dereference the event */
370 ObDereferenceObject(Irp
->UserEvent
);
374 * Now, if this is a Synch I/O File Object, then this event is
375 * NOT an actual Executive Event, so we won't dereference it,
376 * and instead, we will signal the File Object
378 if ((FileObject
->Flags
& FO_SYNCHRONOUS_IO
) &&
379 !(Irp
->Flags
& IRP_OB_QUERY_NAME
))
381 /* Signal the file object and set the status */
382 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
383 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
387 * This could also be a create operation, in which case we want
388 * to make sure there's no APC fired.
390 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
392 /* Clear the APC Routine and remember this */
393 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
394 SignaledCreateRequest
= TRUE
;
400 /* Signal the file object and set the status */
401 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
402 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
405 * This could also be a create operation, in which case we want
406 * to make sure there's no APC fired.
408 if (Irp
->Flags
& IRP_CREATE_OPERATION
)
410 /* Clear the APC Routine and remember this */
411 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
412 SignaledCreateRequest
= TRUE
;
416 /* Update transfer count for everything but create operation */
417 if (!(Irp
->Flags
& IRP_CREATE_OPERATION
))
419 if (Irp
->Flags
& IRP_WRITE_OPERATION
)
421 /* Update write transfer count */
422 IopUpdateTransferCount(IopWriteTransfer
,
423 (ULONG
)Irp
->IoStatus
.Information
);
425 else if (Irp
->Flags
& IRP_READ_OPERATION
)
427 /* Update read transfer count */
428 IopUpdateTransferCount(IopReadTransfer
,
429 (ULONG
)Irp
->IoStatus
.Information
);
433 /* Update other transfer count */
434 IopUpdateTransferCount(IopOtherTransfer
,
435 (ULONG
)Irp
->IoStatus
.Information
);
439 /* Now that we've signaled the events, de-associate the IRP */
440 IopUnQueueIrpFromThread(Irp
);
442 /* Now check if a User APC Routine was requested */
443 if (Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
)
446 KeInitializeApc(&Irp
->Tail
.Apc
,
447 KeGetCurrentThread(),
448 CurrentApcEnvironment
,
450 IopAbortIrpKernelApc
,
451 (PKNORMAL_ROUTINE
)Irp
->
452 Overlay
.AsynchronousParameters
.UserApcRoutine
,
455 Overlay
.AsynchronousParameters
.UserApcContext
);
458 KeInsertQueueApc(&Irp
->Tail
.Apc
, Irp
->UserIosb
, NULL
, 2);
461 (Irp
->Overlay
.AsynchronousParameters
.UserApcContext
))
463 /* We have an I/O Completion setup... create the special Overlay */
464 Irp
->Tail
.CompletionKey
= Key
;
465 Irp
->Tail
.Overlay
.PacketType
= IopCompletionPacketIrp
;
466 KeInsertQueue(Port
, &Irp
->Tail
.Overlay
.ListEntry
);
470 /* Free the IRP since we don't need it anymore */
474 /* Check if we have a file object that wasn't part of a create */
475 if ((FileObject
) && !(SignaledCreateRequest
))
477 /* Dereference it, since it's not needed anymore either */
478 ObDereferenceObjectDeferDelete(FileObject
);
484 * Either we didn't return from the request, or we did return but this
485 * request was synchronous.
487 if ((Irp
->PendingReturned
) && (FileObject
))
489 /* So we did return with a synch operation, was it the IRP? */
490 if (Irp
->Flags
& IRP_SYNCHRONOUS_API
)
492 /* Yes, this IRP was synchronous, so return the I/O Status */
493 *Irp
->UserIosb
= Irp
->IoStatus
;
495 /* Now check if the user gave an event */
499 KeSetEvent(Irp
->UserEvent
, 0, FALSE
);
503 /* No event was given, so signal the FO instead */
504 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
510 * It's not the IRP that was synchronous, it was the FO
511 * that was opened this way. Signal its event.
513 FileObject
->FinalStatus
= Irp
->IoStatus
.Status
;
514 KeSetEvent(&FileObject
->Event
, 0, FALSE
);
518 /* Now that we got here, we do this for incomplete I/Os as well */
519 if ((FileObject
) && !(Irp
->Flags
& IRP_CREATE_OPERATION
))
521 /* Dereference the File Object unless this was a create */
522 ObDereferenceObjectDeferDelete(FileObject
);
526 * Check if this was an Executive Event (remember that we know this
527 * by checking if the IRP is synchronous)
529 if ((Irp
->UserEvent
) &&
531 !(Irp
->Flags
& IRP_SYNCHRONOUS_API
))
533 /* This isn't a PKEVENT, so dereference it */
534 ObDereferenceObject(Irp
->UserEvent
);
537 /* Now that we've signaled the events, de-associate the IRP */
538 IopUnQueueIrpFromThread(Irp
);
540 /* Free the IRP as well */
545 /* FUNCTIONS *****************************************************************/
552 IoAllocateIrp(IN CCHAR StackSize
,
553 IN BOOLEAN ChargeQuota
)
556 USHORT Size
= IoSizeOfIrp(StackSize
);
559 PNPAGED_LOOKASIDE_LIST List
= NULL
;
560 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
562 /* Set Charge Quota Flag */
563 if (ChargeQuota
) Flags
|= IRP_QUOTA_CHARGED
;
566 Prcb
= KeGetCurrentPrcb();
568 /* Figure out which Lookaside List to use */
569 if ((StackSize
<= 8) && (ChargeQuota
== FALSE
|| Prcb
->LookasideIrpFloat
> 0))
571 /* Set Fixed Size Flag */
572 Flags
|= IRP_ALLOCATED_FIXED_SIZE
;
574 /* See if we should use big list */
577 Size
= IoSizeOfIrp(8);
578 ListType
= LookasideLargeIrpList
;
581 /* Get the P List First */
582 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
584 /* Attempt allocation */
585 List
->L
.TotalAllocates
++;
586 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
588 /* Check if the P List failed */
591 /* Let the balancer know */
592 List
->L
.AllocateMisses
++;
595 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
596 List
->L
.TotalAllocates
++;
597 Irp
= (PIRP
)InterlockedPopEntrySList(&List
->L
.ListHead
);
601 /* Check if we have to use the pool */
604 /* Did we try lookaside and fail? */
605 if (Flags
& IRP_ALLOCATED_FIXED_SIZE
) List
->L
.AllocateMisses
++;
607 /* Check if we should charge quota */
610 Irp
= ExAllocatePoolWithQuotaTag(NonPagedPool
| POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
,
616 /* Allocate the IRP with no quota charge */
617 Irp
= ExAllocatePoolWithTag(NonPagedPool
, Size
, TAG_IRP
);
620 /* Make sure it was sucessful */
621 if (!Irp
) return NULL
;
623 else if (Flags
& IRP_QUOTA_CHARGED
)
625 /* Decrement lookaside float */
626 InterlockedDecrement(&Prcb
->LookasideIrpFloat
);
627 Flags
|= IRP_LOOKASIDE_ALLOCATION
;
629 /* In this case there is no charge quota */
630 Flags
&= ~IRP_QUOTA_CHARGED
;
633 /* Now Initialize it */
634 IoInitializeIrp(Irp
, Size
, StackSize
);
636 /* Set the Allocation Flags */
637 Irp
->AllocationFlags
= Flags
;
640 IOTRACE(IO_IRP_DEBUG
,
641 "%s - Allocated IRP %p with allocation flags %lx\n",
653 IopAllocateIrpMustSucceed(IN CCHAR StackSize
)
659 /* Try to get an IRP */
660 Irp
= IoAllocateIrp(StackSize
, FALSE
);
664 /* If we fail, start looping till we may get one */
669 /* First, sleep for 10ms */
670 Sleep
.QuadPart
= -10 * 1000 * 10;
671 KeDelayExecutionThread(KernelMode
, FALSE
, &Sleep
);
673 /* Then, retry allocation */
674 Irp
= IoAllocateIrp(StackSize
, FALSE
);
687 IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction
,
688 IN PDEVICE_OBJECT DeviceObject
,
691 IN PLARGE_INTEGER StartingOffset
,
692 IN PIO_STATUS_BLOCK IoStatusBlock
)
695 PIO_STACK_LOCATION StackPtr
;
698 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
699 if (!Irp
) return NULL
;
702 StackPtr
= IoGetNextIrpStackLocation(Irp
);
704 /* Write the Major function and then deal with it */
705 StackPtr
->MajorFunction
= (UCHAR
)MajorFunction
;
707 /* Do not handle the following here */
708 if ((MajorFunction
!= IRP_MJ_FLUSH_BUFFERS
) &&
709 (MajorFunction
!= IRP_MJ_SHUTDOWN
) &&
710 (MajorFunction
!= IRP_MJ_PNP
) &&
711 (MajorFunction
!= IRP_MJ_POWER
))
713 /* Check if this is Buffered IO */
714 if (DeviceObject
->Flags
& DO_BUFFERED_IO
)
716 /* Allocate the System Buffer */
717 Irp
->AssociatedIrp
.SystemBuffer
=
718 ExAllocatePoolWithTag(NonPagedPool
, Length
, TAG_SYS_BUF
);
719 if (!Irp
->AssociatedIrp
.SystemBuffer
)
721 /* Free the IRP and fail */
727 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
729 /* Handle special IRP_MJ_WRITE Case */
730 if (MajorFunction
== IRP_MJ_WRITE
)
732 /* Copy the buffer data */
733 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Buffer
, Length
);
737 /* Set the Input Operation flag and set this as a User Buffer */
738 Irp
->Flags
|= IRP_INPUT_OPERATION
;
739 Irp
->UserBuffer
= Buffer
;
742 else if (DeviceObject
->Flags
& DO_DIRECT_IO
)
744 /* Use an MDL for Direct I/O */
745 Irp
->MdlAddress
= IoAllocateMdl(Buffer
,
750 if (!Irp
->MdlAddress
)
752 /* Free the IRP and fail */
761 MmProbeAndLockPages(Irp
->MdlAddress
,
763 MajorFunction
== IRP_MJ_READ
?
764 IoWriteAccess
: IoReadAccess
);
766 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
768 /* Free the IRP and its MDL */
769 IoFreeMdl(Irp
->MdlAddress
);
773 _SEH2_YIELD(return NULL
);
779 /* Neither, use the buffer */
780 Irp
->UserBuffer
= Buffer
;
783 /* Check if this is a read */
784 if (MajorFunction
== IRP_MJ_READ
)
786 /* Set the parameters for a read */
787 StackPtr
->Parameters
.Read
.Length
= Length
;
788 StackPtr
->Parameters
.Read
.ByteOffset
= *StartingOffset
;
790 else if (MajorFunction
== IRP_MJ_WRITE
)
792 /* Otherwise, set write parameters */
793 StackPtr
->Parameters
.Write
.Length
= Length
;
794 StackPtr
->Parameters
.Write
.ByteOffset
= *StartingOffset
;
798 /* Set the Current Thread and IOSB */
799 Irp
->UserIosb
= IoStatusBlock
;
800 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
803 IOTRACE(IO_IRP_DEBUG
,
804 "%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
818 IoBuildDeviceIoControlRequest(IN ULONG IoControlCode
,
819 IN PDEVICE_OBJECT DeviceObject
,
820 IN PVOID InputBuffer
,
821 IN ULONG InputBufferLength
,
822 IN PVOID OutputBuffer
,
823 IN ULONG OutputBufferLength
,
824 IN BOOLEAN InternalDeviceIoControl
,
826 IN PIO_STATUS_BLOCK IoStatusBlock
)
829 PIO_STACK_LOCATION StackPtr
;
833 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
834 if (!Irp
) return NULL
;
837 StackPtr
= IoGetNextIrpStackLocation(Irp
);
839 /* Set the DevCtl Type */
840 StackPtr
->MajorFunction
= InternalDeviceIoControl
?
841 IRP_MJ_INTERNAL_DEVICE_CONTROL
:
842 IRP_MJ_DEVICE_CONTROL
;
844 /* Set the IOCTL Data */
845 StackPtr
->Parameters
.DeviceIoControl
.IoControlCode
= IoControlCode
;
846 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
847 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
=
850 /* Handle the Methods */
851 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode
))
854 case METHOD_BUFFERED
:
856 /* Select the right Buffer Length */
857 BufferLength
= InputBufferLength
> OutputBufferLength
?
858 InputBufferLength
: OutputBufferLength
;
860 /* Make sure there is one */
863 /* Allocate the System Buffer */
864 Irp
->AssociatedIrp
.SystemBuffer
=
865 ExAllocatePoolWithTag(NonPagedPool
,
868 if (!Irp
->AssociatedIrp
.SystemBuffer
)
870 /* Free the IRP and fail */
875 /* Check if we got a buffer */
878 /* Copy into the System Buffer */
879 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
884 /* Write the flags */
885 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
886 if (OutputBuffer
) Irp
->Flags
|= IRP_INPUT_OPERATION
;
888 /* Save the Buffer */
889 Irp
->UserBuffer
= OutputBuffer
;
893 /* Clear the Flags and Buffer */
895 Irp
->UserBuffer
= NULL
;
900 case METHOD_IN_DIRECT
:
901 case METHOD_OUT_DIRECT
:
903 /* Check if we got an input buffer */
906 /* Allocate the System Buffer */
907 Irp
->AssociatedIrp
.SystemBuffer
=
908 ExAllocatePoolWithTag(NonPagedPool
,
911 if (!Irp
->AssociatedIrp
.SystemBuffer
)
913 /* Free the IRP and fail */
918 /* Copy into the System Buffer */
919 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
,
923 /* Write the flags */
924 Irp
->Flags
= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
;
928 /* Clear the flags */
932 /* Check if we got an output buffer */
935 /* Allocate the System Buffer */
936 Irp
->MdlAddress
= IoAllocateMdl(OutputBuffer
,
941 if (!Irp
->MdlAddress
)
943 /* Free the IRP and fail */
952 MmProbeAndLockPages(Irp
->MdlAddress
,
954 IO_METHOD_FROM_CTL_CODE(IoControlCode
) ==
956 IoReadAccess
: IoWriteAccess
);
958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
961 IoFreeMdl(Irp
->MdlAddress
);
963 /* Free the input buffer and IRP */
964 if (InputBuffer
) ExFreePool(Irp
->AssociatedIrp
.SystemBuffer
);
968 _SEH2_YIELD(return NULL
);
976 /* Just save the Buffer */
977 Irp
->UserBuffer
= OutputBuffer
;
978 StackPtr
->Parameters
.DeviceIoControl
.Type3InputBuffer
= InputBuffer
;
981 /* Now write the Event and IoSB */
982 Irp
->UserIosb
= IoStatusBlock
;
983 Irp
->UserEvent
= Event
;
985 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
986 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
987 IoQueueThreadIrp(Irp
);
990 IOTRACE(IO_IRP_DEBUG
,
991 "%s - Built IRP %p with IOCTL, Buffers, DO %lx %p %p %p\n",
1006 IoBuildSynchronousFsdRequest(IN ULONG MajorFunction
,
1007 IN PDEVICE_OBJECT DeviceObject
,
1010 IN PLARGE_INTEGER StartingOffset
,
1012 IN PIO_STATUS_BLOCK IoStatusBlock
)
1016 /* Do the big work to set up the IRP */
1017 Irp
= IoBuildAsynchronousFsdRequest(MajorFunction
,
1023 if (!Irp
) return NULL
;
1025 /* Set the Event which makes it Syncronous */
1026 Irp
->UserEvent
= Event
;
1028 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
1029 IoQueueThreadIrp(Irp
);
1038 IoCancelIrp(IN PIRP Irp
)
1041 PDRIVER_CANCEL CancelRoutine
;
1042 IOTRACE(IO_IRP_DEBUG
,
1043 "%s - Canceling IRP %p\n",
1046 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1048 /* Acquire the cancel lock and cancel the IRP */
1049 IoAcquireCancelSpinLock(&OldIrql
);
1052 /* Clear the cancel routine and get the old one */
1053 CancelRoutine
= (PVOID
)IoSetCancelRoutine(Irp
, NULL
);
1056 /* We had a routine, make sure the IRP isn't completed */
1057 if (Irp
->CurrentLocation
> (Irp
->StackCount
+ 1))
1059 /* It is, bugcheck */
1060 KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP
,
1062 (ULONG_PTR
)CancelRoutine
,
1067 /* Set the cancel IRQL And call the routine */
1068 Irp
->CancelIrql
= OldIrql
;
1069 CancelRoutine(IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
, Irp
);
1073 /* Otherwise, release the cancel lock and fail */
1074 IoReleaseCancelSpinLock(OldIrql
);
1083 IoCancelThreadIo(IN PETHREAD Thread
)
1086 ULONG Retries
= 3000;
1087 LARGE_INTEGER Interval
;
1088 PLIST_ENTRY ListHead
, NextEntry
;
1092 /* Windows isn't using given thread, but using current. */
1093 Thread
= PsGetCurrentThread();
1095 IOTRACE(IO_IRP_DEBUG
,
1096 "%s - Canceling IRPs for Thread %p\n",
1100 /* Raise to APC to protect the IrpList */
1101 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1103 /* Start by cancelling all the IRPs in the current thread queue. */
1104 ListHead
= &Thread
->IrpList
;
1105 NextEntry
= ListHead
->Flink
;
1106 while (ListHead
!= NextEntry
)
1109 Irp
= CONTAINING_RECORD(NextEntry
, IRP
, ThreadListEntry
);
1114 /* Move to the next entry */
1115 NextEntry
= NextEntry
->Flink
;
1118 /* Wait 100 milliseconds */
1119 Interval
.QuadPart
= -1000000;
1121 /* Wait till all the IRPs are completed or cancelled. */
1122 while (!IsListEmpty(&Thread
->IrpList
))
1124 /* Now we can lower */
1125 KeLowerIrql(OldIrql
);
1127 /* Wait a short while and then look if all our IRPs were completed. */
1128 KeDelayExecutionThread(KernelMode
, FALSE
, &Interval
);
1131 * Don't stay here forever if some broken driver doesn't complete
1136 /* Print out a message and remove the IRP */
1137 DPRINT1("Broken driver did not complete!\n");
1138 IopDisassociateThreadIrp();
1141 /* Raise the IRQL Again */
1142 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1145 /* We're done, lower the IRQL */
1146 KeLowerIrql(OldIrql
);
1155 IoCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1159 return IofCallDriver(DeviceObject
, Irp
);
1162 #define IoCallDriver IofCallDriver
1167 #undef IoCompleteRequest
1170 IoCompleteRequest(IN PIRP Irp
,
1171 IN CCHAR PriorityBoost
)
1173 /* Call the fastcall */
1174 IofCompleteRequest(Irp
, PriorityBoost
);
1177 #define IoCompleteRequest IofCompleteRequest
1184 IoEnqueueIrp(IN PIRP Irp
)
1186 /* This is the same as calling IoQueueThreadIrp */
1187 IoQueueThreadIrp(Irp
);
1195 IofCallDriver(IN PDEVICE_OBJECT DeviceObject
,
1198 PDRIVER_OBJECT DriverObject
;
1199 PIO_STACK_LOCATION StackPtr
;
1201 /* Make sure this is a valid IRP */
1202 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1204 /* Get the Driver Object */
1205 DriverObject
= DeviceObject
->DriverObject
;
1207 /* Decrease the current location and check if */
1208 Irp
->CurrentLocation
--;
1209 if (Irp
->CurrentLocation
<= 0)
1211 /* This IRP ran out of stack, bugcheck */
1212 KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1215 /* Now update the stack location */
1216 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1217 Irp
->Tail
.Overlay
.CurrentStackLocation
= StackPtr
;
1219 /* Get the Device Object */
1220 StackPtr
->DeviceObject
= DeviceObject
;
1223 return DriverObject
->MajorFunction
[StackPtr
->MajorFunction
](DeviceObject
,
1229 IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation
)
1231 IoStackLocation
->MinorFunction
= 0;
1232 IoStackLocation
->Flags
= 0;
1233 IoStackLocation
->Control
&= SL_ERROR_RETURNED
;
1234 IoStackLocation
->Parameters
.Others
.Argument1
= 0;
1235 IoStackLocation
->Parameters
.Others
.Argument2
= 0;
1236 IoStackLocation
->Parameters
.Others
.Argument3
= 0;
1237 IoStackLocation
->FileObject
= NULL
;
1245 IofCompleteRequest(IN PIRP Irp
,
1246 IN CCHAR PriorityBoost
)
1248 PIO_STACK_LOCATION StackPtr
, LastStackPtr
;
1249 PDEVICE_OBJECT DeviceObject
;
1250 PFILE_OBJECT FileObject
;
1257 NTSTATUS ErrorCode
= STATUS_SUCCESS
;
1258 PREPARSE_DATA_BUFFER DataBuffer
= NULL
;
1259 IOTRACE(IO_IRP_DEBUG
,
1260 "%s - Completing IRP %p\n",
1264 /* Make sure this IRP isn't getting completed twice or is invalid */
1265 if ((Irp
->CurrentLocation
) > (Irp
->StackCount
+ 1))
1268 KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS
, (ULONG_PTR
)Irp
, 0, 0, 0);
1271 /* Some sanity checks */
1272 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1273 ASSERT(!Irp
->CancelRoutine
);
1274 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1275 ASSERT(Irp
->IoStatus
.Status
!= (NTSTATUS
)0xFFFFFFFF);
1277 /* Get the last stack */
1278 LastStackPtr
= (PIO_STACK_LOCATION
)(Irp
+ 1);
1279 if (LastStackPtr
->Control
& SL_ERROR_RETURNED
)
1281 /* Get the error code */
1282 ErrorCode
= PtrToUlong(LastStackPtr
->Parameters
.Others
.Argument4
);
1286 * Start the loop with the current stack and point the IRP to the next stack
1287 * and then keep incrementing the stack as we loop through. The IRP should
1288 * always point to the next stack location w.r.t the one currently being
1289 * analyzed, so completion routine code will see the appropriate value.
1290 * Because of this, we must loop until the current stack location is +1 of
1291 * the stack count, because when StackPtr is at the end, CurrentLocation is +1.
1293 for (StackPtr
= IoGetCurrentIrpStackLocation(Irp
),
1294 Irp
->CurrentLocation
++,
1295 Irp
->Tail
.Overlay
.CurrentStackLocation
++;
1296 Irp
->CurrentLocation
<= (Irp
->StackCount
+ 1);
1298 Irp
->CurrentLocation
++,
1299 Irp
->Tail
.Overlay
.CurrentStackLocation
++)
1301 /* Set Pending Returned */
1302 Irp
->PendingReturned
= StackPtr
->Control
& SL_PENDING_RETURNED
;
1304 /* Check if we failed */
1305 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1307 /* Check if it was changed by a completion routine */
1308 if (Irp
->IoStatus
.Status
!= ErrorCode
)
1310 /* Update the error for the current stack */
1311 ErrorCode
= Irp
->IoStatus
.Status
;
1312 StackPtr
->Control
|= SL_ERROR_RETURNED
;
1313 LastStackPtr
->Parameters
.Others
.Argument4
= UlongToPtr(ErrorCode
);
1314 LastStackPtr
->Control
|= SL_ERROR_RETURNED
;
1318 /* Check if there is a Completion Routine to Call */
1319 if ((NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1320 (StackPtr
->Control
& SL_INVOKE_ON_SUCCESS
)) ||
1321 (!NT_SUCCESS(Irp
->IoStatus
.Status
) &&
1322 (StackPtr
->Control
& SL_INVOKE_ON_ERROR
)) ||
1324 (StackPtr
->Control
& SL_INVOKE_ON_CANCEL
)))
1326 /* Clear the stack location */
1327 IopClearStackLocation(StackPtr
);
1329 /* Check for highest-level device completion routines */
1330 if (Irp
->CurrentLocation
== (Irp
->StackCount
+ 1))
1332 /* Clear the DO, since the current stack location is invalid */
1333 DeviceObject
= NULL
;
1337 /* Otherwise, return the real one */
1338 DeviceObject
= IoGetCurrentIrpStackLocation(Irp
)->DeviceObject
;
1341 /* Call the completion routine */
1342 Status
= StackPtr
->CompletionRoutine(DeviceObject
,
1346 /* Don't touch the Packet in this case, since it might be gone! */
1347 if (Status
== STATUS_MORE_PROCESSING_REQUIRED
) return;
1351 /* Otherwise, check if this is a completed IRP */
1352 if ((Irp
->CurrentLocation
<= Irp
->StackCount
) &&
1353 (Irp
->PendingReturned
))
1355 /* Mark it as pending */
1356 IoMarkIrpPending(Irp
);
1359 /* Clear the stack location */
1360 IopClearStackLocation(StackPtr
);
1364 /* Check if the IRP is an associated IRP */
1365 if (Irp
->Flags
& IRP_ASSOCIATED_IRP
)
1367 /* Get the master IRP and count */
1368 MasterIrp
= Irp
->AssociatedIrp
.MasterIrp
;
1369 MasterCount
= InterlockedDecrement(&MasterIrp
->AssociatedIrp
.IrpCount
);
1372 for (Mdl
= Irp
->MdlAddress
; Mdl
; Mdl
= NextMdl
)
1374 /* Go to the next one */
1375 NextMdl
= Mdl
->Next
;
1379 /* Free the IRP itself */
1382 /* Complete the Master IRP */
1383 if (!MasterCount
) IofCompleteRequest(MasterIrp
, PriorityBoost
);
1387 /* Check whether we have to reparse */
1388 if (Irp
->IoStatus
.Status
== STATUS_REPARSE
)
1390 if (Irp
->IoStatus
.Information
> IO_REMOUNT
)
1392 /* If that's a reparse tag we understand, save the buffer from deletion */
1393 if (Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1395 ASSERT(Irp
->Tail
.Overlay
.AuxiliaryBuffer
!= NULL
);
1396 DataBuffer
= (PREPARSE_DATA_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
1397 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
1401 Irp
->IoStatus
.Status
= STATUS_IO_REPARSE_TAG_NOT_HANDLED
;
1406 /* Check if we have an auxiliary buffer */
1407 if (Irp
->Tail
.Overlay
.AuxiliaryBuffer
)
1410 ExFreePool(Irp
->Tail
.Overlay
.AuxiliaryBuffer
);
1411 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
1414 /* Check if this is a Paging I/O or Close Operation */
1415 if (Irp
->Flags
& (IRP_PAGING_IO
| IRP_CLOSE_OPERATION
))
1417 /* Handle a Close Operation or Sync Paging I/O */
1418 if (Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_CLOSE_OPERATION
))
1420 /* Set the I/O Status and Signal the Event */
1421 Flags
= Irp
->Flags
& (IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
);
1422 *Irp
->UserIosb
= Irp
->IoStatus
;
1423 KeSetEvent(Irp
->UserEvent
, PriorityBoost
, FALSE
);
1425 /* Free the IRP for a Paging I/O Only, Close is handled by us */
1426 if (Flags
) IoFreeIrp(Irp
);
1432 KeInitializeApc(&Irp
->Tail
.Apc
1433 &Irp
->Tail
.Overlay
.Thread
->Tcb
,
1434 Irp
->ApcEnvironment
,
1435 IopCompletePageWrite
,
1440 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1445 /* Not implemented yet. */
1446 UNIMPLEMENTED_DBGBREAK("Not supported!\n");
1450 /* Get out of here */
1454 /* Unlock MDL Pages, page 167. */
1455 Mdl
= Irp
->MdlAddress
;
1462 /* Check if we should exit because of a Deferred I/O (page 168) */
1463 if ((Irp
->Flags
& IRP_DEFER_IO_COMPLETION
) && !(Irp
->PendingReturned
))
1465 /* Restore the saved reparse buffer for the caller */
1466 if (Irp
->IoStatus
.Status
== STATUS_REPARSE
&&
1467 Irp
->IoStatus
.Information
== IO_REPARSE_TAG_MOUNT_POINT
)
1469 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PCHAR
)DataBuffer
;
1473 * Return without queuing the completion APC, since the caller will
1474 * take care of doing its own optimized completion at PASSIVE_LEVEL.
1479 /* Get the thread and file object */
1480 Thread
= Irp
->Tail
.Overlay
.Thread
;
1481 FileObject
= Irp
->Tail
.Overlay
.OriginalFileObject
;
1483 /* Make sure the IRP isn't canceled */
1486 /* Initialize the APC */
1487 KeInitializeApc(&Irp
->Tail
.Apc
,
1489 Irp
->ApcEnvironment
,
1497 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1504 /* The IRP just got canceled... does a thread still own it? */
1507 /* Yes! There is still hope! Initialize the APC */
1508 KeInitializeApc(&Irp
->Tail
.Apc
,
1510 Irp
->ApcEnvironment
,
1518 KeInsertQueueApc(&Irp
->Tail
.Apc
,
1525 /* Nothing left for us to do, kill it */
1526 ASSERT(Irp
->Cancel
);
1527 IopCleanupIrp(Irp
, FileObject
);
1534 IopSynchronousCompletion(IN PDEVICE_OBJECT DeviceObject
,
1538 if (Irp
->PendingReturned
)
1539 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1540 return STATUS_MORE_PROCESSING_REQUIRED
;
1548 IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject
,
1554 /* Check if next stack location is available */
1555 if (Irp
->CurrentLocation
< Irp
->StackCount
)
1557 /* No more stack location */
1561 /* Initialize event */
1562 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1564 /* Copy stack location for next driver */
1565 IoCopyCurrentIrpStackLocationToNext(Irp
);
1567 /* Set a completion routine, which will signal the event */
1568 IoSetCompletionRoutine(Irp
, IopSynchronousCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
1570 /* Call next driver */
1571 Status
= IoCallDriver(DeviceObject
, Irp
);
1573 /* Check if irp is pending */
1574 if (Status
== STATUS_PENDING
)
1576 /* Yes, wait for its completion */
1577 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
1580 /* Return success */
1589 IoFreeIrp(IN PIRP Irp
)
1591 PNPAGED_LOOKASIDE_LIST List
;
1592 PP_NPAGED_LOOKASIDE_NUMBER ListType
= LookasideSmallIrpList
;
1594 IOTRACE(IO_IRP_DEBUG
,
1595 "%s - Freeing IRPs %p\n",
1599 /* Make sure the Thread IRP list is empty and that it OK to free it */
1600 ASSERT(Irp
->Type
== IO_TYPE_IRP
);
1601 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1602 ASSERT(Irp
->CurrentLocation
>= Irp
->StackCount
);
1605 Prcb
= KeGetCurrentPrcb();
1607 /* If this was a lookaside alloc, increment lookaside float */
1608 if (Irp
->AllocationFlags
& IRP_LOOKASIDE_ALLOCATION
)
1610 Irp
->AllocationFlags
&= ~IRP_LOOKASIDE_ALLOCATION
;
1611 InterlockedIncrement(&Prcb
->LookasideIrpFloat
);
1614 /* If this was a pool alloc, free it with the pool */
1615 if (!(Irp
->AllocationFlags
& IRP_ALLOCATED_FIXED_SIZE
))
1618 ExFreePoolWithTag(Irp
, TAG_IRP
);
1622 /* Check if this was a Big IRP */
1623 if (Irp
->StackCount
!= 1) ListType
= LookasideLargeIrpList
;
1625 /* Use the P List */
1626 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].P
;
1627 List
->L
.TotalFrees
++;
1629 /* Check if the Free was within the Depth or not */
1630 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1632 /* Let the balancer know */
1633 List
->L
.FreeMisses
++;
1635 /* Use the L List */
1636 List
= (PNPAGED_LOOKASIDE_LIST
)Prcb
->PPLookasideList
[ListType
].L
;
1637 List
->L
.TotalFrees
++;
1639 /* Check if the Free was within the Depth or not */
1640 if (ExQueryDepthSList(&List
->L
.ListHead
) >= List
->L
.Depth
)
1642 /* All lists failed, use the pool */
1643 List
->L
.FreeMisses
++;
1644 ExFreePoolWithTag(Irp
, TAG_IRP
);
1649 /* The free was within the Depth */
1652 InterlockedPushEntrySList(&List
->L
.ListHead
,
1663 IoGetPagingIoPriority(IN PIRP Irp
)
1665 IO_PAGING_PRIORITY Priority
;
1671 /* Check what priority it has */
1672 if (Flags
& IRP_CLASS_CACHE_OPERATION
)
1675 Priority
= IoPagingPriorityHigh
;
1677 else if (Flags
& IRP_PAGING_IO
)
1679 /* Normal priority */
1680 Priority
= IoPagingPriorityNormal
;
1684 /* Invalid -- not a paging IRP */
1685 Priority
= IoPagingPriorityInvalid
;
1688 /* Return the priority */
1697 IoGetRequestorProcess(IN PIRP Irp
)
1699 /* Return the requestor process */
1700 if (Irp
->Tail
.Overlay
.Thread
)
1702 if (Irp
->ApcEnvironment
== OriginalApcEnvironment
)
1704 return Irp
->Tail
.Overlay
.Thread
->ThreadsProcess
;
1706 else if (Irp
->ApcEnvironment
== AttachedApcEnvironment
)
1708 return (PEPROCESS
)Irp
->Tail
.Overlay
.Thread
->Tcb
.ApcState
.Process
;
1720 IoGetRequestorProcessId(IN PIRP Irp
)
1724 /* Return the requestor process' id */
1725 Process
= IoGetRequestorProcess(Irp
);
1726 if (Process
) return PtrToUlong(Process
->UniqueProcessId
);
1736 IoGetRequestorSessionId(IN PIRP Irp
,
1737 OUT PULONG pSessionId
)
1741 /* Return the session */
1742 if (Irp
->Tail
.Overlay
.Thread
)
1744 Process
= Irp
->Tail
.Overlay
.Thread
->ThreadsProcess
;
1745 *pSessionId
= MmGetSessionId(Process
);
1746 return STATUS_SUCCESS
;
1749 *pSessionId
= (ULONG
)-1;
1750 return STATUS_UNSUCCESSFUL
;
1758 IoGetTopLevelIrp(VOID
)
1760 /* Return the IRP */
1761 return (PIRP
)PsGetCurrentThread()->TopLevelIrp
;
1769 IoInitializeIrp(IN PIRP Irp
,
1770 IN USHORT PacketSize
,
1774 IOTRACE(IO_IRP_DEBUG
,
1775 "%s - Initializing IRP %p\n",
1778 RtlZeroMemory(Irp
, PacketSize
);
1780 /* Set the Header and other data */
1781 Irp
->Type
= IO_TYPE_IRP
;
1782 Irp
->Size
= PacketSize
;
1783 Irp
->StackCount
= StackSize
;
1784 Irp
->CurrentLocation
= StackSize
+ 1;
1785 Irp
->ApcEnvironment
= KeGetCurrentThread()->ApcStateIndex
;
1786 Irp
->Tail
.Overlay
.CurrentStackLocation
= (PIO_STACK_LOCATION
)(Irp
+ 1) + StackSize
;
1788 /* Initialize the Thread List */
1789 InitializeListHead(&Irp
->ThreadListEntry
);
1797 IoIsOperationSynchronous(IN PIRP Irp
)
1802 /* If the IRP requests synchronous paging I/O, if the file object was opened
1803 for synchronous I/O, if the IRP_SYNCHRONOUS_API flag is set in the IRP
1804 the operation is synchronous */
1805 SynchIO
= (IoGetCurrentIrpStackLocation(Irp
)->FileObject
->Flags
& FO_SYNCHRONOUS_IO
) ||
1806 (Irp
->Flags
& IRP_SYNCHRONOUS_API
) || (Irp
->Flags
& IRP_SYNCHRONOUS_PAGING_IO
);
1808 /* If the IRP requests asynchronous paging I/O, the operation is asynchronous,
1809 even if one of the above conditions is true */
1810 ForceAsync
= (Irp
->Flags
& IRP_PAGING_IO
) && !(Irp
->Flags
& IRP_SYNCHRONOUS_PAGING_IO
);
1812 /* Check the flags */
1813 if (SynchIO
&& !ForceAsync
)
1815 /* Synch API or Paging I/O is OK, as is Sync File I/O */
1819 /* Otherwise, it is an asynchronous operation. */
1828 IoIsValidNameGraftingBuffer(IN PIRP Irp
,
1829 IN PREPARSE_DATA_BUFFER ReparseBuffer
)
1840 IoMakeAssociatedIrp(IN PIRP Irp
,
1844 IOTRACE(IO_IRP_DEBUG
,
1845 "%s - Associating IRP %p\n",
1849 /* Allocate the IRP */
1850 AssocIrp
= IoAllocateIrp(StackSize
, FALSE
);
1851 if (!AssocIrp
) return NULL
;
1854 AssocIrp
->Flags
|= IRP_ASSOCIATED_IRP
;
1856 /* Set the Thread */
1857 AssocIrp
->Tail
.Overlay
.Thread
= Irp
->Tail
.Overlay
.Thread
;
1859 /* Associate them */
1860 AssocIrp
->AssociatedIrp
.MasterIrp
= Irp
;
1869 IoQueueThreadIrp(IN PIRP Irp
)
1871 IOTRACE(IO_IRP_DEBUG
,
1872 "%s - Queueing IRP %p\n",
1876 /* Use our inlined routine */
1877 IopQueueIrpToThread(Irp
);
1882 * Reference: Chris Cant's "Writing WDM Device Drivers"
1886 IoReuseIrp(IN OUT PIRP Irp
,
1889 UCHAR AllocationFlags
;
1890 IOTRACE(IO_IRP_DEBUG
,
1891 "%s - Reusing IRP %p\n",
1895 /* Make sure it's OK to reuse it */
1896 ASSERT(!Irp
->CancelRoutine
);
1897 ASSERT(IsListEmpty(&Irp
->ThreadListEntry
));
1899 /* Get the old flags */
1900 AllocationFlags
= Irp
->AllocationFlags
;
1902 /* Reinitialize the IRP */
1903 IoInitializeIrp(Irp
, Irp
->Size
, Irp
->StackCount
);
1905 /* Duplicate the data */
1906 Irp
->IoStatus
.Status
= Status
;
1907 Irp
->AllocationFlags
= AllocationFlags
;
1915 IoSetTopLevelIrp(IN PIRP Irp
)
1918 PsGetCurrentThread()->TopLevelIrp
= (ULONG_PTR
)Irp
;
1921 #if defined (_WIN64)
1925 IN PIRP Irp OPTIONAL
)