none
SetFilePointer doesn't react to IoRead or IoWrite RRS feed

  • Question

  • One part of the driver gives access to a configuration data block that the user can read and write.

    In the driver, this is implemented as a "file". One can seek to a position and read/write there using regular OS calls. Implementing read/write/seek properly allows existing code to be reused.

    In the IoRead/IoWrite callbacks, the driver can retrieve the file position using "WdfRequestGetParameters" and then fetch the offset as "Parameters.Parameters.Write.DeviceOffset". This reports whatever was passed to the last SetFilePointer call.

    The only problem with this is that the file pointer does not move with a read or write operation. Not what one would normally expect. If you first read 4 bytes of data, and then read another 4 bytes, you get the same 4 bytes again instead of the next set of bytes.

    How can I properly "move" the file pointer from within the read/write methods? (And related, how to make SEEK_END work?)

    Monday, July 18, 2016 12:43 PM

Answers

  • SetFilePosition works just fine. The only thing different between Posix and Windows for the driver is that a read or write will not move the file pointer on Windows. It's something I can live with, if the user wants code to be portable it must always do a seek (or SetFilePosition) before any read or write operation on this part.

    It's only this small portion of the driver interface that needs this, usually used to send parameters to filters and such (e.g. FIR coefficients or video kernel data). Speed isn't relevant, it's even using memory-mapped IO through PCIe to read/write the data which is horrendously slow. The actual data transfers are always "streaming" data that don't use positioning.

    Wednesday, July 20, 2016 5:55 AM

All replies

  • file offset is maintained in the file object by the driver. using file io semantics with an offset for interacting with a non FS driver is a bit dicey and a slippery slope of what you need to support beyond normal IO operations. I would recommend sticking to IOCTLs and reads/writes without offsets

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, July 18, 2016 4:25 PM
  • I'm not afraid of slippery slopes, bring it on.

    What do I have to do to make the filepointer move?

    Tuesday, July 19, 2016 5:13 AM
  • You are going to have to maintain the file offset yourself in the driver.  Go find the sources to the FAT file system and then start looking for all the references to CurrentByteOffset in the source.   You are looking at a very large amount of work, to make a device act in a way that is alien to how most devices work in Windows, before proceeding really ask yourself why?


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Tuesday, July 19, 2016 10:57 AM
  • The why is simple:

    WriteFile(hDev, buffer1, bytes1, &bytesWritten ...);
    SetFilePointer(hDev, bytesWritten, NULL, FILE_SET);
    WriteFile(hDev, buffer2, bytes2, &bytesWritten ...);
    

    That extra required "SetFilePointer" in between the WriteFile calls to set the file pointer to where you'd already expect it to be will confuse users and lead to all kinds of weird unexpected behaviour.

    So enlighten me, how would an interface to what behaves like a small block of memory in "most devices in Windows" look like? (I don't want to map it, because it can only be accessed in 32-bit words on 32-bit aligned addresses and reading or writing it may have side effects)

    Tuesday, July 19, 2016 1:08 PM
  • Well part of this is to take a look at your CreateFile, I suspect you are opening the device for asynchronous I/O.  If you look at https://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx  you will see:

    "File pointer position for a synchronous handle is maintained by the system as data is read or written and can also be updated  using the SetFilePointer or SetFilePointerEx function." 

    Unfortunately, most of us would for a "small block of memory" map it, since you can't I would use an IOCTL interface. As it is what are you going to do with the file pointer if gets passed 0x4321?


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Tuesday, July 19, 2016 1:22 PM
  • I thought of that too, but I'm not passing FILE_FLAG_OVERLAPPED to the CreateFile, so I'd expect access to be synchronous, and that the file pointer would update on read/write calls.

    If the position is out of range, I return an EOF error.

    If the position is misaligned, I currently return an error, since no application so far ever attempted it. I could resolve it using read-modify-write in the driver.

    This is memory-mapped register space on the PCIe bus. Mapping it to userspace is a recipe for headaches on any OS. (If mapping DMA buffers to userspace isn't working reliably, chances of this mapping ever working are less than me winning the lottery.)

    Tuesday, July 19, 2016 2:02 PM
  • the point is that the "Beaten path" way of doing this is to use an IOCTL and then the caller specifies an offset in the input buffer. you control who your users are and what they see, very few if any win32 developers expect to access a non FS device driver with FS semantics. While unix makes this easy and expects this, Windows does not.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, July 19, 2016 3:39 PM
  • As I stated earlier if you really want to do this you need to go look at the FAT file system sources see https://github.com/Microsoft/Windows-driver-samples/tree/master/filesys/fastfat

    Of course these are huge and complex (which is what all file systems are in Windows), but it will give you the data.

    This is why we have been pushing that you do something simple like an IOCTL that passes the offset in one input buffer and the data in a second for a write, and a similar model for a read.   This is simple, easy, and if you start looking at many of the Microsoft supplied IOCTL's it exactly meets their model, i.e. a buffer with some input parameters, and a data buffer for either in or out.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Tuesday, July 19, 2016 4:46 PM
  • @Mike: you probably miss pread and pwrite Posix syscalls in Windows. Windows still is not Linux. Not yet. A Win32 analog of these is perhaps WriteFileEx/ReadFileEx, it allows to pass the offset in the OVERLAPPED. But these are asynchronous, so you get dependency on how you open the handle... and there be slippery slopes.

    Instead Windows ioctls provide the 2nd buffer, which can contain any kind of input data for the ioctl.

    -- pa

    Tuesday, July 19, 2016 7:00 PM
  • SetFilePosition works just fine. The only thing different between Posix and Windows for the driver is that a read or write will not move the file pointer on Windows. It's something I can live with, if the user wants code to be portable it must always do a seek (or SetFilePosition) before any read or write operation on this part.

    It's only this small portion of the driver interface that needs this, usually used to send parameters to filters and such (e.g. FIR coefficients or video kernel data). Speed isn't relevant, it's even using memory-mapped IO through PCIe to read/write the data which is horrendously slow. The actual data transfers are always "streaming" data that don't use positioning.

    Wednesday, July 20, 2016 5:55 AM