none
Reading a unicode string from the driver context with IOCTL RRS feed

  • Question

  • Hej,

    my customer wants to be able to query the driver version ( as obtained from ntverp/stampinf) through an IOCTL. Since I found no way of reading the Version resource stored in the driver file through the framework, my driver queries the registry when the driver and first device instance is loaded and stores the version ID in a string.

    in Driver.c

    DECLARE_CONST_UNICODE_STRING(DriverVersion, L"Unknown");
    . . . . .
       mStatusX = WdfStringCreate(&DriverVersion,
                                  &mObjAttribs,
                                  &pDrvCtx->mDrvVerString); 
    . . . . .

    and in Device.c

       DECLARE_CONST_UNICODE_STRING(DriverVersion, L"DriverVersion");
     . . . . . . . 
                mStatusX = WdfRegistryQueryString(mKey,
                                                 &DriverVersion,
                                                 TsevGetDriverContext(pDevCtx->mDriverObj)->mDrvVerString);
    . . . . .

    Later in the IOCTL, then

       WdfStringGetUnicodeString(TsevGetDriverContext(pDevCtx->mDriverObj)->mDrvVerString, &mOutString);

       mStatus = WdfRequestRetrieveOutputBuffer(Request,
                                               (mOutString.Length + 1) * sizeof(WCHAR),                 // Min. Buffer Size
                                               (PULONG*)&mReqOutBuf,
                                               &mReqOutBufSz);   

       RtlZeroMemory((PVOID)mReqOutBuf, mReqOutBufSz);
       RtlCopyMemory((PVOID)mReqOutBuf, (PVOID)mOutString.Buffer, mOutString.Length * sizeof(WCHAR));

    This solution has been working fine since Jan 2020 but today I got a mini-dump, presumably because the string is stored at a paged location.

    nt!KiPageFault+0x247
    rec_4xg!memcpy+0x20 [minkernel\crts\crtw32\string\amd64\memcpy.asm @ 156] 
    rec_4xg!TsevOpGetDriverVersion+0x126 [p:\projects\sag_impact_vc709\driver\win\common_4xg\ioctl_ops.c @ 377] 
    rec_4xg!TsevProcessOutRequest+0x99 [p:\projects\sag_impact_vc709\driver\win\common_4xg\ioctl_ops.c @ 742] 
    rec_4xg!TsevIoCtl+0x125 [p:\projects\sag_impact_vc709\driver\win\common_4xg\ioctl_ops.c @ 81] 
    Wdf01000!FxIoQueue::DispatchRequestToDriver+0x1b7 [d:\rs1\minkernel\wdf\framework\shared\irphandlers\io\fxioqueue.cpp @ 3322]
    Wdf01000!FxIoQueue::DispatchEvents+0x3aa [d:\rs1\minkernel\wdf\framework\shared\irphandlers\io\fxioqueue.cpp @ 3122] 
    Wdf01000!FxPkgIo::DispatchStep1+0x52c [d:\rs1\minkernel\wdf\framework\shared\irphandlers\io\fxpkgio.cpp @ 324] 
    Wdf01000!FxDevice::DispatchWithLock+0x6fb [d:\rs1\minkernel\wdf\framework\shared\core\fxdevice.cpp @ 1430] 


    So what would be the solution? Should I for instance use

    WdfMemoryCreate() to create a memory object in the IOCTL function
    WdfMemoryCopyFromBuffer() to copy from the (possibly paged out) string buffer to the memory object
    WdfMemoryCopyToBuffer() to copy from the memory object into the IRP Output Buffer

    Or will this solution risk failure too if the string storage has been swapped out? Any better solutions of course appreciated.

    Thanks,




    • Edited by cfgardiner Tuesday, June 30, 2020 12:18 AM
    Tuesday, June 30, 2020 12:09 AM

Answers

  • The multiplying of mOutString.Length by sizeof(WCHAR) is wrong.  mOutString.Length is the length in bytes of the string, so you are running off the end of the string.  

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

    • Marked as answer by cfgardiner Tuesday, June 30, 2020 8:04 AM
    Tuesday, June 30, 2020 12:45 AM

All replies

  • The multiplying of mOutString.Length by sizeof(WCHAR) is wrong.  mOutString.Length is the length in bytes of the string, so you are running off the end of the string.  

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

    • Marked as answer by cfgardiner Tuesday, June 30, 2020 8:04 AM
    Tuesday, June 30, 2020 12:45 AM
  • Surely it would be easier to just open the file and use GetFileVersionInfo and VerQueryValue.  No kernel requirements at all.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Tuesday, June 30, 2020 4:30 AM
  • Thanks for pointing that out.

    I just rechecked the docu for WdfStringGetUnicodeString / UNICODE_STRING and that is indeed what it says (length is bytes). Looks like I had a bad day sometime in Jan. ... ;)

    Tuesday, June 30, 2020 8:07 AM
  • Well probably, yes.

    I did try to motivate the customer in this direction but he kept coming back with "surely the driver knows what version it is, why can't I query it?". Customer wants, customer gets .....

    What he gets from me is a driver and a user-space C++ wrapper class around SetupDiEnumDeviceInterfaces et al. In other words he just talks to the driver through a file handle and doesn't have to do the footwork of finding the driver associated with the device, finding the file associated with the driver etc. from his application. He just queries a file handle with the IOCTL I provided and gets the version.

    But maybe I'll add an extra member function to my C++ wrapper which calls GetFileVersionInfo() and VerQueryValue() as an alternative for future use.

    Thanks.

    Tuesday, June 30, 2020 8:20 AM