📄 irp.c
字号:
/* Queue it */
KeInsertQueueApc(&Irp->Tail.Apc, Irp->UserIosb, NULL, 2);
}
else if ((Port) &&
(Irp->Overlay.AsynchronousParameters.UserApcContext))
{
/* We have an I/O Completion setup... create the special Overlay */
Irp->Tail.CompletionKey = Key;
Irp->Tail.Overlay.PacketType = IrpCompletionPacket;
KeInsertQueue(Port, &Irp->Tail.Overlay.ListEntry);
}
else
{
/* Free the IRP since we don't need it anymore */
IoFreeIrp(Irp);
}
/* Check if we have a file object that wasn't part of a create */
if ((FileObject) && !(SignaledCreateRequest))
{
/* Dereference it, since it's not needed anymore either */
ObDereferenceObjectDeferDelete(FileObject);
}
}
else
{
/*
* Either we didn't return from the request, or we did return but this
* request was synchronous.
*/
if ((Irp->PendingReturned) && (FileObject))
{
/* So we did return with a synch operation, was it the IRP? */
if (Irp->Flags & IRP_SYNCHRONOUS_API)
{
/* Yes, this IRP was synchronous, so return the I/O Status */
*Irp->UserIosb = Irp->IoStatus;
/* Now check if the user gave an event */
if (Irp->UserEvent)
{
/* Signal it */
KeSetEvent(Irp->UserEvent, 0, FALSE);
}
else
{
/* No event was given, so signal the FO instead */
KeSetEvent(&FileObject->Event, 0, FALSE);
}
}
else
{
/*
* It's not the IRP that was synchronous, it was the FO
* that was opened this way. Signal its event.
*/
FileObject->FinalStatus = Irp->IoStatus.Status;
KeSetEvent(&FileObject->Event, 0, FALSE);
}
}
/* Now that we got here, we do this for incomplete I/Os as well */
if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION))
{
/* Dereference the File Object unless this was a create */
ObDereferenceObjectDeferDelete(FileObject);
}
/*
* Check if this was an Executive Event (remember that we know this
* by checking if the IRP is synchronous)
*/
if ((Irp->UserEvent) &&
(FileObject) &&
!(Irp->Flags & IRP_SYNCHRONOUS_API))
{
/* This isn't a PKEVENT, so dereference it */
ObDereferenceObject(Irp->UserEvent);
}
/* Now that we've signaled the events, de-associate the IRP */
IopUnQueueIrpFromThread(Irp);
/* Free the IRP as well */
IoFreeIrp(Irp);
}
}
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
PIRP
NTAPI
IoAllocateIrp(IN CCHAR StackSize,
IN BOOLEAN ChargeQuota)
{
PIRP Irp = NULL;
USHORT Size = IoSizeOfIrp(StackSize);
PKPRCB Prcb;
UCHAR Flags = 0;
PNPAGED_LOOKASIDE_LIST List = NULL;
PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList;
/* Figure out which Lookaside List to use */
if ((StackSize <= 8) && (ChargeQuota == FALSE))
{
/* Set Fixed Size Flag */
Flags = IRP_ALLOCATED_FIXED_SIZE;
/* See if we should use big list */
if (StackSize != 1)
{
Size = IoSizeOfIrp(8);
ListType = LookasideLargeIrpList;
}
/* Get the PRCB */
Prcb = KeGetCurrentPrcb();
/* Get the P List First */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P;
/* Attempt allocation */
List->L.TotalAllocates++;
Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);
/* Check if the P List failed */
if (!Irp)
{
/* Let the balancer know */
List->L.AllocateMisses++;
/* Try the L List */
List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L;
List->L.TotalAllocates++;
Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);
}
}
/* Check if we have to use the pool */
if (!Irp)
{
/* Did we try lookaside and fail? */
if (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses++;
/* Check if we should charge quota */
if (ChargeQuota)
{
/* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
/* FIXME */
Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
}
else
{
/* Allocate the IRP With no Quota charge */
Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
}
/* Make sure it was sucessful */
if (!Irp) return(NULL);
}
else
{
/* We have an IRP from Lookaside */
Flags |= IRP_LOOKASIDE_ALLOCATION;
}
/* Set Flag */
if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;
/* Now Initialize it */
IoInitializeIrp(Irp, Size, StackSize);
/* Set the Allocation Flags */
Irp->AllocationFlags = Flags;
/* Return it */
IOTRACE(IO_IRP_DEBUG,
"%s - Allocated IRP %p with allocation flags %lx\n",
__FUNCTION__,
Irp,
Flags);
return Irp;
}
/*
* @implemented
*/
PIRP
NTAPI
IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER StartingOffset,
IN PIO_STATUS_BLOCK IoStatusBlock)
{
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
/* Allocate IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp) return Irp;
/* Get the Stack */
StackPtr = IoGetNextIrpStackLocation(Irp);
/* Write the Major function and then deal with it */
StackPtr->MajorFunction = (UCHAR)MajorFunction;
/* Do not handle the following here */
if ((MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
(MajorFunction != IRP_MJ_SHUTDOWN) &&
(MajorFunction != IRP_MJ_PNP) &&
(MajorFunction != IRP_MJ_POWER))
{
/* Check if this is Buffered IO */
if (DeviceObject->Flags & DO_BUFFERED_IO)
{
/* Allocate the System Buffer */
Irp->AssociatedIrp.SystemBuffer =
ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYS_BUF);
if (!Irp->AssociatedIrp.SystemBuffer)
{
/* Free the IRP and fail */
IoFreeIrp(Irp);
return NULL;
}
/* Set flags */
Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
/* Handle special IRP_MJ_WRITE Case */
if (MajorFunction == IRP_MJ_WRITE)
{
/* Copy the buffer data */
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length);
}
else
{
/* Set the Input Operation flag and set this as a User Buffer */
Irp->Flags |= IRP_INPUT_OPERATION;
Irp->UserBuffer = Buffer;
}
}
else if (DeviceObject->Flags & DO_DIRECT_IO)
{
/* Use an MDL for Direct I/O */
Irp->MdlAddress = IoAllocateMdl(Buffer,
Length,
FALSE,
FALSE,
NULL);
if (!Irp->MdlAddress)
{
/* Free the IRP and fail */
IoFreeIrp(Irp);
return NULL;
}
/* Probe and Lock */
_SEH_TRY
{
/* Do the probe */
MmProbeAndLockPages(Irp->MdlAddress,
KernelMode,
MajorFunction == IRP_MJ_READ ?
IoWriteAccess : IoReadAccess);
}
_SEH_HANDLE
{
/* Free the IRP and its MDL */
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
Irp = NULL;
}
_SEH_END;
/* This is how we know if we failed during the probe */
if (!Irp) return NULL;
}
else
{
/* Neither, use the buffer */
Irp->UserBuffer = Buffer;
}
/* Check if this is a read */
if (MajorFunction == IRP_MJ_READ)
{
/* Set the parameters for a read */
StackPtr->Parameters.Read.Length = Length;
StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
}
else if (MajorFunction == IRP_MJ_WRITE)
{
/* Otherwise, set write parameters */
StackPtr->Parameters.Write.Length = Length;
StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
}
}
/* Set the Current Thread and IOSB */
Irp->UserIosb = IoStatusBlock;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
/* Set the Status Block after all is done */
IOTRACE(IO_IRP_DEBUG,
"%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
__FUNCTION__,
Irp,
MajorFunction,
Buffer,
DeviceObject);
return Irp;
}
/*
* @implemented
*/
PIRP
NTAPI
IoBuildDeviceIoControlRequest(IN ULONG IoControlCode,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
IN PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN BOOLEAN InternalDeviceIoControl,
IN PKEVENT Event,
IN PIO_STATUS_BLOCK IoStatusBlock)
{
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
ULONG BufferLength;
/* Allocate IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp) return Irp;
/* Get the Stack */
StackPtr = IoGetNextIrpStackLocation(Irp);
/* Set the DevCtl Type */
StackPtr->MajorFunction = InternalDeviceIoControl ?
IRP_MJ_INTERNAL_DEVICE_CONTROL :
IRP_MJ_DEVICE_CONTROL;
/* Set the IOCTL Data */
StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
StackPtr->Parameters.DeviceIoControl.OutputBufferLength =
OutputBufferLength;
/* Handle the Methods */
switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
{
/* Buffered I/O */
case METHOD_BUFFERED:
/* Select the right Buffer Length */
BufferLength = InputBufferLength > OutputBufferLength ?
InputBufferLength : OutputBufferLength;
/* Make sure there is one */
if (BufferLength)
{
/* Allocate the System Buffer */
Irp->AssociatedIrp.SystemBuffer =
ExAllocatePoolWithTag(NonPagedPool,
BufferLength,
TAG_SYS_BUF);
if (!Irp->AssociatedIrp.SystemBuffer)
{
/* Free the IRP and fail */
IoFreeIrp(Irp);
return NULL;
}
/* Check if we got a buffer */
if (InputBuffer)
{
/* Copy into the System Buffer */
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
InputBuffer,
InputBufferLength);
}
/* Write the flags */
Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION;
/* Save the Buffer */
Irp->UserBuffer = OutputBuffer;
}
else
{
/* Clear the Flags and Buffer */
Irp->Flags = 0;
Irp->UserBuffer = NULL;
}
break;
/* Direct I/O */
case METHOD_IN_DIRECT:
case METHOD_OUT_DIRECT:
/* Check if we got an input buffer */
if (InputBuffer)
{
/* Allocate the System Buffer */
Irp->AssociatedIrp.SystemBuffer =
ExAllocatePoolWithTag(NonPagedPool,
InputBufferLength,
TAG_SYS_BUF);
if (!Irp->AssociatedIrp.SystemBuffer)
{
/* Free the IRP and fail */
IoFreeIrp(Irp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -