How can I obtain the IFIMETRICS from FONTOBJ in a Microsoft Universal Printer Driver?

sorn 1 Reputation point
2022-06-09T07:46:10.427+00:00

I'm writting a Microsoft Universal Printer Driver for our printer (User Mode Driver).

When implementing the OEMTextOut() hook, we need to get the font information from the FONTOBJ, but seems there no way to do that, below are what I have tried:

  1. Try to get IFIMETRICS by FONTOBJ_pifi() which come from win32k library, but the driver just simple crash if we link to win32k.lib
  2. Call DRVENABLEDATA->pdrvfn[INDEX_DrvQueryFont] which comes from IPrintOemUni2::EnablePDEV, not working, that function just reports "OEMTextOut failed with error 87: " (argument error) I take a research on it's argument dhpdev: The PDEVOEM which we generated in the EnablePDEV()
    iFile: 0ll
    iFace: 1l
  3. Search on the network, does not find any related information

I take weeks to try to get a way out, but seems no luck. Could someone give me a hand? Thanks!

Sample Code:

typedef struct _OEMPDEV {  
    // The full driver function table table  
    PFN     drvfn[INDEX_LAST + 1];  
} OEMPDEV, * POEMPDEV;      
  
HRESULT __stdcall OemUni::EnablePDEV(  
    PDEVOBJ         pdevobj,  
    _In_ PWSTR      pPrinterName,  
    ULONG           cPatterns,  
    HSURF* phsurfPatterns,  
    ULONG           cjGdiInfo,  
    GDIINFO* pGdiInfo,  
    ULONG           cjDevInfo,  
    DEVINFO* pDevInfo,  
    DRVENABLEDATA* pded,  
    OUT PDEVOEM* pDevOem)  
{  
    POEMPDEV    poempdev;  
    INT         i;  
    PDRVFN      pdrvfn;  
  
    //  
    // Allocate the OEMDev  
    //  
    poempdev = new OEMPDEV;  
    if (NULL == poempdev)  
    {  
        return NULL;  
    }  
  
    //  
    // Fill in OEMDEV  
    //  
  
    memset(poempdev->drvfn, 0, sizeof(poempdev->drvfn));  
  
    for (i = 0; i < (INT)pded->c; ++i)  
    {  
        if (i >= _countof(poempdev->drvfn))  
        {  
            break;  
        }  
  
        pdrvfn = &pded->pdrvfn[i];  
        poempdev->drvfn[pdrvfn->iFunc] = pdrvfn->pfn;  
    }  
  
    *pDevOem = (POEMPDEV)poempdev;  
  
    return (NULL != *pDevOem ? S_OK : E_FAIL);  
}  
  
  
BOOL APIENTRY  
OEMTextOut(  
    SURFOBJ* pso,  
    STROBJ* pstro,  
    FONTOBJ* pfo,  
    CLIPOBJ* pco,  
    RECTL* prclExtra,  
    RECTL* prclOpaque,  
    BRUSHOBJ* pboFore,  
    BRUSHOBJ* pboOpaque,  
    POINTL* pptlOrg,  
    MIX         mix  
)  
{   
    ULONG_PTR _pid = 0;  
    PDEVOBJ pdevobj;  
    POEMPDEV    poempdev;  
  
    pdevobj = (PDEVOBJ)pso->dhpdev;  
    poempdev = (POEMPDEV)pdevobj->pdevOEM;  
  
    // Pass DHPDEV which output from EnablePDEV, failed return error 87, with NULL result  
    PIFIMETRICS metrics = ((PFN_DrvQueryFont)poempdev->drvfn[INDEX_DrvQueryFont])((DHPDEV)poempdev, pfo->iFile, pfo->iFace, &_pid);  
  
    // Driver crash, not allowed  
    metrics = FONTOBJ_pifi(pfo);  
  
    // Try pass the dhpdev of SURFOBJ, but still failed return error 87, with NULL result  
    metrics = ((PFN_DrvQueryFont)(poempdev->drvfn[INDEX_DrvQueryFont]))(pso->dhpdev, pfo->iFile, pfo->iFace, &_pid);  
  
    return (((PFN_DrvTextOut)(poempdev->drvfn[INDEX_DrvTextOut])) (  
        pso,  
        pstro,  
        pfo,  
        pco,  
        prclExtra,  
        prclOpaque,  
        pboFore,  
        pboOpaque,  
        pptlOrg,  
        mix));  
}  
Microsoft Graph Print API
Windows Server Printing
Windows Server Printing
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.Printing: Printer centralized deployment and management, scan and fax resources management, and document services
499 questions
Windows Hardware Performance
Windows Hardware Performance
Windows: A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.Hardware Performance: Delivering / providing hardware or hardware systems or adjusting / adapting hardware or hardware systems.
1,246 questions
No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Limitless Technology 37,351 Reputation points
    2022-06-13T07:30:24.553+00:00

    Hi there,

    The IFIMETRICS structure defines information for a given typeface that GDI can use. Generally, the DrvQueryFont function is used by GDI to get the IFIMETRICS structure. The FONTOBJ_pifi function retrieves the pointer to the IFIMETRICS structure associated with a specified font.

    See if changing the IFIMETRICS structure to the PRINTIFI32 structure stops the crash.

    The IFIMETRICS structure's Align member causes it to be larger for x64 machines than for x32 machines, which has ramifications for binary font format files formatted according to this structure. Starting with Windows Server 2003 SP1, an additional, fixed-size structure has been added to Prntfont.h: PRINTIFI32. The PRINTIFI32 structure is identical to the IFIMETRICS structure, except that it does not contain an Align member.

    -------------------------------------------------------------------------------------------------------------------------------------------------

    --If the reply is helpful, please Upvote and Accept it as an answer–


  2. sorn 1 Reputation point
    2022-06-14T01:38:41.807+00:00

    @Limitless Technology

    Thanks for your response, but I'm not clearly understand how to get a PRINTIFI32 from a FONTOBJ.

    First of all, I was compile the driver as x64 mode, it's a x64 driver.

    Then, the FONTOBJ_pifi() just freeze inside itself without return.

    And seems DrvQueryFont() not be allowed to call inside a printer driver ? It just returned NULL.

    I checked the document about PRINTIFI32, but how can I get it from a FONTOBJ?

    No comments

  3. sorn 1 Reputation point
    2022-06-14T01:44:22.287+00:00

    The situation could be reappearance in the bitmap sample (Windows-driver-samples\print\OEM Printer Customization Plug-in Samples\C++\bitmap\, https://github.com/Microsoft/Windows-driver-samples)

    Just simply added OEMTextOut() hook, then you will see that happen.

    No comments

  4. sorn 1 Reputation point
    2022-07-07T11:49:26.857+00:00

    I found the problem! Just link to umpdddi.lib not win32k.lib !

    win32k.lib provided for kernel mode driver, but umpdddi.lib provide for user mode driver!

    After linked to umpdddi.lib and remove the win32k.lib, I got a valid result from FONTOBJ_pifi(pfo)!

    Hope this information will be useful for someone blocking here.

    No comments