irp! in an IRP structure stackcount--irp! currentlocation--irp! Currentstacklocation Three fields are intricately related, only in this article have been made memo.
The IRP structure is followed by a io_stack_location array typedef struct _IRP {CSHORT Type; USHORT Size; struct _MDL *mdladdress; ULONG Flags; Union {struct _IRP *masterirp; Volatile LONG Irpcount; PVOID SystemBuffer; } associatedirp; List_entry Threadlistentry; return value Io_status_block iostatus; Kprocessor_mode Requestormode; BOOLEAN pendingreturned; The stack depth from top to bottom of the entire device stack (length of the io_stack_location array) CHAR Stackcount; Current device stack depth, counting from 1 */* In addition, a section of code in the IofCallDriver function: irp->currentlocation--; if (irp->currentlocation <= 0) {KeBugCheckEx (no_more_irp_stack_locations, (ulong_ptr) Irp, 0, 0, 0); Before invoking the next layer of equipment, first irp->currentlocation minus one, if Irp->currentlocation==0 is bugcheck, from here can be determined, currentlocation is counted from 1 Currentlocation is like the concept of the second layer (array element 1) of the first layer (corresponding to array element 0) in everyday spoken language */CHAR currentlocation; boolean cancel; kirql cancelirql; cchar apcenvironment; UCHAR allocationflags; pio_status_block useriosb; //Sync object Pkevent userevent; Union { struct { PIO_APC_ROUTINE userapcroutine; pvoid userapccontext; } asynchronousparameters; large_integer allocationsize; } Overlay; volatile pdriver_cancel cancelroutine; pvoid userbuffer; Union { struct { _anonymous_union UNION { kdevice_queue_entry devicequeueentry; _anonymous_struct STRUCT { pvoid drivercontext[4]; } dummystructname; } dummyunionname; //The thread that issued the IRP pethread thread; pchar auxiliarybuffer; _anonymous_struct STRUCT { list_entry ListEntry; _anonymous_union UNION { //the stack array element pointer currently in use /* The relationship between stackcount/currentlocation/currentstacklocation is still to be established from IOSIZEOFIRP and IOINITIALIZEIRP. */ struct _io_stack_location *currentstacklocation; ulong packettype; } dummyunionname; dummystructname; //Device object associated file object struct _file_object * originalfileobject; } overlay; //The APC object used when the entire IRP is returned asynchronously &NBSP;&NBSP;&NBSp kapc apc; pvoid completionkey; } Tail;} IRP;
As the note says,
The relationship between the stackcount/currentlocation/currentstacklocation and the three is still to be established from IOSIZEOFIRP and IOINITIALIZEIRP.
Next, take a look at the actions of IOSIZEOFIRP and ioinitializeirp on these fields in the IRP
Voidntapiioinitializeirp (in Pirp Irp, in USHORT packetsize, in CChar StackSize) {/* Clear It */Iotrace (Io_irp_debug, "%s-initializing irp%p\n", __function__, IRP); RtlZeroMemory (IRP, packetsize); /* Set the Header and other data */Irp->type = IO_TYPE_IRP; Irp->size = PacketSize; Irp->stackcount = stacksize;//The initial state when the current stack depth is actual depth (StackSize) +1//because the IRP at this time has not yet entered the device object stack irp->currentlocation = StackSize + 1; Irp->apcenvironment = Kegetcurrentthread ()->apcstateindex;//io_stack_location array followed by the IRP, with only stacksize elements in the array ,//subscript from 0 to StackSize-1, so the pointer has crossed an element. Most importantly, the call to IoCallDriver will be called once iogetnextirpstacklocation, the array//pointer to the correct position, and then pass the IRP down/* or the old device stacksize=1 for example: irp- >currentlocation=2, the second device in the device stack (unfortunately there are only 1 devices on the stack), Irp->tail.overlay.currentstacklocation=&io_stack_ LOCATION[1]. The array has only element 0, so it is still out of bounds. When IofCallDriver is called, the Iosetnextirpstacklocation (IRP) is irp->currentlocation= 1, meaning to take the first element in the stack, Irp->tail.overlay.currentstacklocation--stack pointer to &io_stack_location[0], take stack element 0*/irp->tail.overlay.currentstacklocation = (PIO _stack_location) (IRP + 1) + StackSize; /* Initialize the Thread List */Initializelisthead (&irp->threadlistentry);}
/* StackSize is the number of devices from the top level to the bottom of the device stack, with older devices as an example stacksize=1. So this macro will get the sizeof (IRP) and only an array of io_stack_location elements in the pool, subscript 0 */#define IOSIZEOFIRP (_stacksize) ( (USHORT) (sizeof ( IRP) + ((_stacksize) * (sizeof (io_stack_location))))
Association of IRP and Io_stack_location structures