Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

DeviceIoControl error code 1

Michael_RolleMichael_Rolle Member - All Emails Posts: 69
Hi,

Can you tell me what are possible causes of this error code from calling this function, or at least what may be relevant to my particular case?

I've been doing a bit of rewriting of a kernel driver I wrote, and now the user side gets error code 1 (incorrect function) from DeviceIoControl. It used to work before.

The IOCTL control code on the user side and the driver side is identical, in fact, from the same source file. The driver's creation of the device calls
s2 = IoCreateDevice (pDriverObject, sizeof (DeviceExt), &internalName, FILE_DEVICE_UNKNOWN, 0, false, &pDeviceObject);
So the device is created with shared access.
On the user side, the file handle is successfully created with
HANDLE handle = CreateFile (deviceName.c_str (), GENERIC_READ + GENERIC_WRITE,
exclusive ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
The 'exclusive' parameter is either true or false, with the same result.

The driver's DeviceControl routine handles an unknown IOCTL code (or any incorrect parameters for the correct IOCTL code) by setting the IRP with a STATUS_INVALID_DEVICE_REQUEST, or C0000010h. So I suspect that DeviceControl is not even getting called.

I haven't found anything useful searching online.

Comments

  • Michael_RolleMichael_Rolle Member - All Emails Posts: 69
    I just added a new IOCTL code, and used it with DeviceIoControl, in this case with some input data and no output data. I haven't yet changed the driver to recognize this new code.
    Result is still code 1 (incorrect function). This further indicates that the driver's MJ_CONTROL routine isn't getting called.

    Also, ... I have a second driver with similar code, and I can perform DeviceIoControl OK with that driver. This is encouraging, because I can compare the user and kernel side code between the two and hopefully see what I changed recently in the former that broke it. If I find something, I'll post it.
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,667
    On Feb 9, 2018, at 10:43 PM, xxxxx@rolle.name <xxxxx@lists.osr.com> wrote:
    >
    > Can you tell me what are possible causes of this error code from calling this function, or at least what may be relevant to my particular case?

    Either STATUS_NOT_IMPLEMENTED or STATUS_INVALID_DEVICE_REQUEST will map to ERROR_INVALID_FUNCTION in user mode.


    > The driver's DeviceControl routine handles an unknown IOCTL code (or any incorrect parameters for the correct IOCTL code) by setting the IRP with a STATUS_INVALID_DEVICE_REQUEST, or C0000010h. So I suspect that DeviceControl is not even getting called.

    Oh, I suspect it is. STATUS_INVALID_DEVICE_REQUEST will bubble up as ERROR_INVALID_FUNCTION.

    How much validation do you do? One common problem is to have a 32-bit app calling a 64-bit driver, where one of the fields in the buffer structure has a different size or causes it to have different padding.

    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Michael_RolleMichael_Rolle Member - All Emails Posts: 69
    Problem solved!

    Hi again, Tim,

    I just figured that out. I called the second driver with an unknown control code, to which it responds by posting STATUS_INVALID_DEVICE_REQUEST to the IRP and also returning the same. And sure enough, on the user side I saw ERROR_INVALID_FUNCTION, just like you said.

    Pity that this behavior is not documented by Microsoft. It would have saved me from going down the rabbit hole.

    By the way, what's the difference between the return value from my DispatchControl and the value I store in pIrp->IoStatus.Status? I'm planning to use a DPC to complete the DispatchControl in some cases, so the pIrp->IoStatus.Status value presumably won't be used until later when the DPC calls IoCompleteRequest (). What is DispatchControl supposed to return in this case?

    Thanks.
  • Michael_RolleMichael_Rolle Member - All Emails Posts: 69
    I just read the Microsoft docs article "Completing the IRP". My reading of this is:
    1. If the dispatch routine does complete the IRP, either successfully or otherwise, then it stores the status in the IRP _and_ returns the same status value.
    2. If the dispatch routine does not complete the IRP, then it returns STATUS_PENDING.

    This seems simple enough. Is my understanding correct?

    I'm curious about a possible race condition. If I queue a DPC to complete the IRP, is it possible that the DPC will start running immediately and will call IoCompleteRequest before the dispatch routine returns with STATUS_PENDING. I suppose this is not a problem, either because the kernel won't run any new DPCs until the dispatch routine returns, or because the kernel realizes the IRP has already been completed and does the right thing. Can you confirm this?

    Thanks.
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,667
    On Feb 10, 2018, at 12:03 AM, xxxxx@rolle.name <xxxxx@lists.osr.com> wrote:
    >
    > I just figured that out. I called the second driver with an unknown control code, to which it responds by posting STATUS_INVALID_DEVICE_REQUEST to the IRP and also returning the same. And sure enough, on the user side I saw ERROR_INVALID_FUNCTION, just like you said.
    >
    > Pity that this behavior is not documented by Microsoft. It would have saved me from going down the rabbit hole.

    It IS documented. Or at least it was. There is an MSDN page somewhere that documents the mapping from NTSTATUS codes to Win32 error codes.


    > By the way, what's the difference between the return value from my DispatchControl and the value I store in pIrp->IoStatus.Status?

    The driver is required by contract to return the same value you put in the IoStatus, except for IRPs you pend. That's why KMDF doesn't give you the chance to get that wrong.


    > I'm planning to use a DPC to complete the DispatchControl in some cases, so the pIrp->IoStatus.Status value presumably won't be used until later when the DPC calls IoCompleteRequest (). What is DispatchControl supposed to return in this case?

    STATUS_PENDING. You'll need to call IoMarkIrpPending in that case as well.

    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,667
    On Feb 10, 2018, at 12:28 AM, xxxxx@rolle.name <xxxxx@lists.osr.com> wrote:
    >
    > I just read the Microsoft docs article "Completing the IRP". My reading of this is:
    > 1. If the dispatch routine does complete the IRP, either successfully or otherwise, then it stores the status in the IRP _and_ returns the same status value.
    > 2. If the dispatch routine does not complete the IRP, then it returns STATUS_PENDING.
    >
    > This seems simple enough. Is my understanding correct?

    Yep, with the additional requirement that you call IoMarkIrpPending in the 2nd case.


    > I'm curious about a possible race condition. If I queue a DPC to complete the IRP, is it possible that the DPC will start running immediately and will call IoCompleteRequest before the dispatch routine returns with STATUS_PENDING. I suppose this is not a problem, either because the kernel won't run any new DPCs until the dispatch routine returns, or because the kernel realizes the IRP has already been completed and does the right thing. Can you confirm this?

    Yes, as long as you have marked the IRP as pending. I assume you wouldn't just be queuing a DPC; that would be silly, because you could just complete the IRP in the dispatch routine. I assume you're waiting for a timer or some piece of hardware, which will then cause the DPC to be queued.

    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Justin_SchoenwaldJustin_Schoenwald Member - All Emails Posts: 25
    > Either STATUS_NOT_IMPLEMENTED or STATUS_INVALID_DEVICE_REQUEST will map to ERROR_INVALID_FUNCTION in user mode.
    I get NON-ZERO return from DeviceIoControl() using
    IOCTL_STORAGE_QUERY_PROPERTY, QueryType = PropertyExistsQuery (which I
    take to mean that said property is available)

    but then get ERROR_INVALID_FUNCTION with PropertyStandardQuery.

    The semantics of "STATUS_NOT_IMPLEMENTED" and
    "STATUS_INVALID_DEVICE_REQUEST" suggest that information is lost in
    mapping both to the same error code.
    If it's NOT_IMPLEMENTED then the positive result from the initial query
    seems to be in error (standard Windows 10 disk drivers).
    If it's INVALID_DEVICE_REQUEST then perhaps I'm doing something wrong
    with this particular device?

    Which seems more likely, given that with other devices I get consistent
    results?
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!