Difficult to Understand Certain Return Statements Under Certain Circumstances

Here you can discuss ReactOS related topics.

Moderator: Moderator Team

Post Reply
Posts: 10
Joined: Sun Sep 01, 2019 12:59 am

Difficult to Understand Certain Return Statements Under Certain Circumstances

Post by berylliumquestion » Fri Dec 20, 2019 9:18 am

So I've been looking around at where the OS goes when calling a function or returning a value. Except that sometimes when I try to figure out where it is going to go next, I get stumped, and this time it's really confusing me. It is because I look at the logs with extra DPRINT1 statements sprinkled in here and there to gain more information and it seems sometimes the return statement doesn't behave as I expect it to. I've always been under the assumption that return gets you out of a function and returns a value back to the place it was called. However, sometimes it just goes right back to the beginning of a function.

Here is where I'm getting confused. It starts out like this. I've added some DPRINT1 statements:

The beginning file I'm looking at looks like this.
ntoskrnl/io/iomgr/file.c, IopParseDevice:

Code: Select all

        DPRINT1("Before IoCallDriver\n", DeviceObject);
        Status = IoCallDriver(DeviceObject, Irp);
        DPRINT1("After IoCallDriver\n", DeviceObject);
ntoskrnl/io/irp.c, IofCallDriver:

Code: Select all

    DPRINT1("DeviceObject: %p\n", DeviceObject);
    DPRINT1("Irp: %p\n", Irp);
    DPRINT1("DriverObject->MajorFunction: %x\n", DriverObject->MajorFunction);
    DPRINT1("StackPtr->MajorFunction: %x\n", StackPtr->MajorFunction);
    return DriverObject->MajorFunction[StackPtr->MajorFunction](DeviceObject,
The next one I'm looking at is this one
drivers/storage/port/scsiport/scsiport.c, ScsiPortDispatchScsi:

Code: Select all

ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
		     IN PIRP Irp)
    KIRQL Irql;
    PIRP NextIrp, IrpList;

    DPRINT1("ScsiPortDispatchScsi(DeviceObject %p  Irp %p)\n",
        DeviceObject, Irp);
    DPRINT1("0 DeviceObject->Flags: %I64x\n", DeviceObject->Flags);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    DPRINT1("1 DeviceObject->Flags: %I64x\n", DeviceObject->Flags);

Now here is the log which I can't seem to comprehend:

Code: Select all

(ntoskrnl/io/iomgr/irp.c:1295) DeviceObject: B02A2A70
(ntoskrnl/io/iomgr/irp.c:1296) Irp: B029E620
(ntoskrnl/io/iomgr/irp.c:1297) DriverObject->MajorFunction: b02b58a8
(ntoskrnl/io/iomgr/irp.c:1298) StackPtr->MajorFunction: f
(drivers/storage/port/scsiport/scsiport.c:2572) ScsiPortDispatchScsi(DeviceObject B02A2A70  Irp B029E620)
(drivers/storage/port/scsiport/scsiport.c:2574) 0 DeviceObject->Flags: b029e62000000050
(drivers/storage/port/scsiport/scsiport.c:2825) 1 DeviceObject->Flags: b029e62000000050
(ntoskrnl/io/iomgr/irp.c:1270) irp.c DeviceObject->Flags: b029c0c000000150
(ntoskrnl/io/iomgr/irp.c:1295) DeviceObject: B02169F0
So, beforehand, irp.c to scsiport.c seems completely reasonable to me. What doesn't seem reasonable is when return(Status); is reached and instead of going back to irp.c's return statement then going back to file.c where this process was first set off, but instead moves straight back to the beginning of iofcall in irp.c .

What's going on with that?

Posts: 285
Joined: Sun Jul 11, 2010 11:39 am

Re: Difficult to Understand Certain Return Statements Under Certain Circumstances

Post by ThFabba » Fri Dec 20, 2019 6:02 pm

Io(f)CallDriver is a function that's called a lot during normal OS operations, often multiple times per I/O operation.
There are several reasons why you might see another call right away:
  • There may be multiple threads active at the same time, processing multiple IRPs at the same time. IoCallDriver will be called for each of them.
  • The function is often called recursively. In a PNP driver stack, the dispatch function for one driver will forward the IRP to the next driver by making another call to IoCallDriver, and only the final driver (bus driver) at the bottom of the stack will call IoCompleteRequest to complete the operation.
  • IRPs are asynchronous in nature and sometimes they're processed in less-than-obvious ways. For example it's possible for the owner of an IRP to set a completion routine that re-uses the same structure for a completely different operation. In a case like this you may see an initial call to IoCallDriver followed by request completion via IoCompleteRequest -- which then calls the completion routine and initiates another operation by calling IoCallDriver again.
In your particular example, you can see that the DeviceObject pointer is different between the two calls, so you may simply be witnessing two completely independent I/O operations, either on the same thread, one after the other, or on two different threads.

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests