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

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

getting HANDLE from FILE_OBJECT

Patrick_KlingPatrick_Kling Member Posts: 6

Inside Windows driver routine which handles a DeviceIoControl call from client, I'd like to call many other DeviceIoControl routines using the same HANDLE as the client application. The initial DeviceIoControl routine runs only at the passive level in the driver. The calls to the many other DeviceIoControl routines are not restricted to the passive level. I have a working driver for a PCIe device. The initial call allocates memory on the device. The routines called from within the driver would initiate DMA IN to initialize the memory. Today, the allocation routine works and the DMA IN routines work. I've seen ZwDeviceIoControl, but it needs a HANDLE. Unfortunately, inside the driver, I only have the FILE_OBJECT. Is there a way to get a HANDLE from the FILE_OBJECT? It would need to be the same HANDLE or a duplicate HANDLE since the driver and PCIe device enforce memory protection. Only the PCI device's memory that is allocated to the FILE_OBJECT can be written by the DMA IN.

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,022
    via Email
    On Apr 3, 2019, at 8:24 PM, Patrick_Kling wrote:
    >
    > Inside Windows driver routine which handles a DeviceIoControl call from client, I'd like to call many other DeviceIoControl routines using the same HANDLE as the client application.

    You need to explain your concept a bit more. Any ioctls you issue on that same handle are going to end up right back in your driver. Why don't you just call the appropriate functions directly? What do you think you're going to gain by going through the I/O process again?


    > I have a working driver for a PCIe device. The initial call allocates memory on the device. The routines called from within the driver would initiate DMA IN to initialize the memory. Today, the allocation routine works and the DMA IN routines work. I've seen ZwDeviceIoControl, but it needs a HANDLE. Unfortunately, inside the driver, I only have the FILE_OBJECT.

    Why not just call those routines? What's the point of going through ZwDeviceIoControl to get right back to your own driver? Are you trying to send ioctls to the drivers below you? You can do that just by creating your own IRP and calling IoCallDriver.


    > Is there a way to get a HANDLE from the FILE_OBJECT?

    The FILE_OBJECT is the kernel instantiation of the user-mode HANDLE. It doesn't make sense to go back the other way.


    > It would need to be the same HANDLE or a duplicate HANDLE since the driver and PCIe device enforce memory protection. Only the PCI device's memory that is allocated to the FILE_OBJECT can be written by the DMA IN.

    That makes no sense. DMA doesn't care about memory "ownership". Please describe your situation in more detail.

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

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

  • Patrick_KlingPatrick_Kling Member Posts: 6

    Inside Windows driver routine which handles a DeviceIoControl call from client, I'd >like to call many other DeviceIoControl routines using the same HANDLE as the client >application.

    You need to explain your concept a bit more. Any ioctls you issue on that same handle >are going to end up right back in your driver. Why don't you just call the appropriate >functions directly? What do you think you're going to gain by going through the I/O >process again?

    Today, the allocate memory ioctl is a single call which stays at the passive level. The DMA IN ioctl does not stay at the passive level. It does all the typical things that a PCIe driver does like, pin the MDL of the source memory, queue the transfer with the board (if board HW has room), setup interrupt for when DMA completes, then exits with status PENDING. Anything which doesn't fit on board remains queued in the driver. The device itself protects regions of its own memory based on the client (effectively the FILE_OBJECT) to guarantee no cross contamination between clients (regulated industry - requirement). Anyway, the DMA is limited to a certain max transfer size per request. To clear all the memory, many such DMAs must be scheduled. Some will be given to the board, but some will have to be queued in driver until board has room.

    I was hoping to avoid complexity by reusing existing functionality. If ZwDeviceIoControl is not the best way to do that, what would be the best way to handle the situation. The memory allocation ioctl shouldn't complete until the memory is cleared.

  • rstruempfrstruempf Member Posts: 103

    I may be totally misreading this, but it sounds like you want to call ZwDeviceIoControl to do PASSIVE_LEVEL memory allocation, from higher IRQL code? If so, it doesn't work that way. If I misunderstood, feel free to ignore me.

    _Ron

  • Patrick_KlingPatrick_Kling Member Posts: 6

    Hi -- I clearly have done a poor job explaining my question. Maybe I can try again. The current situation is that I have a working PCIe board WDM driver. Two of the working DeviceIoControl calls 1) allocate board memory 2) DMA from PC to board memory. The #1 allocate function is implemented completely at the passive level. It does allocates some of the boards memory, then writes a few PCIe registers to tell the board about the allocated range. It never blocks. The #2 DMA IN function is a typical WDM DMA. At the passive level, it checks to see if board DMA HW is available, if so, it submits the DMA and sets an interrupt mask to get alerted when the DMA completes. If the board DMA HW is not available, it queues the work inside the driver. The DPC level started by receiving the interrupt will submit the DMA to the board HW when the HW is available.

    The DMA is limited to 256 MB. The amount of allocated memory could be much much larger than that.

    Anyway, all that works well.

    I'd like to know the simplest way to add the following functionality: The #1 allocate function should DMA IN zeros to the board memory before returning to the user -- I hope I can reuse the existing functionality.

  • anton_bassovanton_bassov Member Posts: 5,023

    iThe #1 allocate function should DMA IN zeros to the board memory before returning to the user --
    I hope I can reuse the existing functionality.

    Well, it seems to be more of a question of your hardware, rather than of a driver, don't you think. Unless your hardware supports zeroing memory upon the allocation/initialisation, the only option available to you seems to be extending IOCTL 1, i.e making it allocate memory + DMA zeroed memory to the device. Once, according to you, the amount of memory that you allocate may well exceed your DMA limitations, you would have to make multiple DMA transfers before completing the IOCTL. To be honest, I don't see any other available options here

    Anton Bassov

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,345

    Allocate a single page of non-pages pool, zero it, and create a Scatter Gather List (SGL) that references this page as many times in a row as necessary to zero your device memory.

    If you need to, you could presumably hand-build an MDL that was of whatever length you needed, using the same page over and over again.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • anton_bassovanton_bassov Member Posts: 5,023

    create a Scatter Gather List (SGL) that references this page as many times in a row as necessary to zero your device memory.

    According to the OP, due to the specifics of his board, the maximum length of such SGL is 256 * 256 entires (i.e. 256MB * 256 entries per MB), but the amount of memory on the target device may well exceed this limitation. Therefore, no matter how you look at it, he would have to do this operation multiple times before completing his IOCTL

    Anton Bassov

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,345

    due to the specifics of his board, the maximum length of such SGL is 256 * 256 entires

    Then rinse and repeat as usual. Takes longer to talk about than to code.

    I wonder what his question really is?

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Patrick_KlingPatrick_Kling Member Posts: 6

    is there any way to call the existing DeviceIoControl for DMA IN from within the driver so that all the issues (like multiple calls) you all mentioned are handled easily. For example, I saw a function ZwDeviceIoControl that can call a driver, but it needs a HANDLE. Is there any way to create the HANDLE from within the driver from the FileObject I already have?

  • Patrick_KlingPatrick_Kling Member Posts: 6

    there might be DMAs from other clients running as well on the same HW so reuse of the existing DeviceIoControl would be very convenient since that call already manages the multiple clients according to an appropriate priority scheme.

  • Jamey_KirbyJamey_Kirby Member - All Emails Posts: 433

    To answer the question asked:
    ObOpenObjectByPointer(...) will create a handle to an object.
    A previous OSR thread on getting a handle from a file object is here (from a long time ago):
    https://community.osr.com/discussion/81432

  • rstruempfrstruempf Member Posts: 103

    I have never worked with this before, so I could absolutely be wrong here; I will watch to see the outcome of this thread, but I still read this the same as I originally did. Your DMA IN code, queued or "immediate", driven by the hardware ISR, is at DIRQL. The PASSIVE_LEVEL portion of #2 is just posting a request and waiting for it to complete. You want to reuse PASSIVE_LEVEL memory management code of #1. But you cannot call PASSIVE_LEVEL code from DIRQL to achieve PASSIVE_LEVEL execution. It is only PASSIVE_LEVEL because it is called from user mode. If called from higher IRQLs, it would execute at the higher IRQL, and would likely be a violation of the calling conventions of the function.

    OTOH, if you want to call the IOCTL of #1 from the PASSIVE_LEVEL portion of #2, then you should either be able to call the allocation function directly, or roll an IRP to do the allocation, before handing off to the HW.

  • Patrick_KlingPatrick_Kling Member Posts: 6

    Thank you all (especially Jamey Kirby) for your help.

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,142

    If you already have a File Object you can just build a new IRP, stuff the File Object pointer in it, and send it to yourself.

    -scott
    OSR

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,022
    via Email
    Scott_Noone_(OSR) wrote:
    > If you already have a File Object you can just build a new IRP, stuff the File Object pointer in it, and send it to yourself.

    This is certainly true, but I have a hard time imagining a situation
    where this is the Right Answer.    If you're already processing within
    your driver, why wouldn't you just queue up whatever activity would be
    done in response to that ioctl?  Why involve the kernel?  Although I
    regularly talk to myself, I don't call up my wife to have her relate my
    inner conversation back and forth.  "Hey, tell Tim he's a good and
    valuable member of society.  Tell Tim I appreciate that."

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

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,142

    My wife is always reminding me that I don't need to share my inner converstations with her, so a bad example for me :)

    But, I say it depends...Say I need to reset my device and already have an IOCTL_RESET_DEVICE handler that asychronously resets and completes the IRP when it's done. I could plumb another path that lets me asynchronously reset and signal me when I'm done, or I can just send myself an IRP with a completion routine.

    I've been doing this more frequently in my WDF drivers by opening an I/O Target to myself and sending requests. Not only does it avoid me creating more special case code but it also honors my Queue topology (dispatch type, IRQL constraint, etc.). It's not always the right answer, but it's an option.

    -scott
    OSR

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!

Upcoming OSR Seminars
Developing Minifilters 29 July 2019 OSR Seminar Space
Writing WDF Drivers 23 Sept 2019 OSR Seminar Space
Kernel Debugging 21 Oct 2019 OSR Seminar Space
Internals & Software Drivers 18 Nov 2019 Dulles, VA