User Mode Printer Driver using GDI API functions

Discussion in 'Windows Vista Drivers' started by Zhivko Tabakov, Nov 7, 2005.

  1. Hi all,
    I was under the impression that in user mode printer driver you can use GDI
    functions (like ExtTextOut and SelectClipRgn, not Eng... ones) with
    independent device context (like enhanced metafile).
    My recent experience proved me wrong, so I am curious to find out if it is
    allowed in principle to make such GDI calls or not?

    Thank you for any insides on the subject.

    Zhivko Tabakov
     
    Zhivko Tabakov, Nov 7, 2005
    #1
    1. Advertisements

  2. Zhivko Tabakov

    Vipin[MVP] Guest

    What is your experience or problem? It should be ok to make the calls.
     
    Vipin[MVP], Nov 7, 2005
    #2
    1. Advertisements

  3. It seems like GDI is getting confused and skips or replaces some of the
    client application calls with different ones. It is not crashing, but is not
    working correctly. It is very weird behaviour and it is a bit difficult to
    find out what is causing it.
    I have created simple driver based on MSPlot sample in order to prove the
    behaviour. My changes are fairly simple. They allow me to do ExtTextOut and
    SelectClipRgn from within DrvTextOut agains an enhanced metafile device
    context created in DrvEnableSurface.
    With my changes printing several (12) lines of text from arbitrary client
    application result into just few DrvTextOut calls (for only 4 of the 12
    lines) and on the place of missing lines GDI calls 2 times DrvBitBlt to fill
    some rectangles (and the coordinates of the rectangles are not related to
    the text)?! This is what happens with the test driver, otherwise in my
    driver the result is more like missing whole batches of GDI calls, but it
    happens only with much more complex client application input.
    Interesting is that if I comment out the SelectClipRgn call everything works
    fine - DrvTextOut get called for all characters and no DrvBitBlt calls (same
    thing if I change the ExtTextOut call).
    I can post my changes to MSPlot sample if necessary.
    Thank you for any comments.
     
    Zhivko Tabakov, Nov 7, 2005
    #3
  4. Zhivko Tabakov

    Vipin[MVP] Guest

    I think it may be better to show the code. You can show the snippet and I
    can see if
    there is any problem in the code. you can send me at vprnt at lycos.com
     
    Vipin[MVP], Nov 8, 2005
    #4
  5. Here are the all the modifications that I have done to msplot
    (the essential part is SelectClipRgn and ExtTextOut calls in DrvTextOut, the
    rest of the code is just to enable me to call these 2 APIs). If either is
    omitted DrvTextOut is called correctly for all the text (same if dxes are
    NULL).

    In "TEXTOUT.C"
    ....
    #include <windows.h>
    ....
    //in the beginning of DrvTextOut()
    int *dxes;
    unsigned dxesIdx;
    const wchar_t txt[] = L"Some text printed with some (40pt) character
    spacing.";
    //and after pPDev initialization "if (!(pPDev =...){...}" follows:
    DBGP(("The DrvTextOut Entry (%d chars, first one is:%c)"
    , pstro->cGlyphs, (NULL == pstro->pwszOrg ? ' ' :
    (char)*(pstro->pwszOrg))));
    dxes = (int*)malloc(pstro->cGlyphs * sizeof(int));
    for(dxesIdx = 0; dxesIdx < pstro->cGlyphs; ++dxesIdx)
    dxes[dxesIdx] = 40;
    SelectClipRgn((HDC)pPDev->hMeta, NULL);
    ExtTextOutW((HDC)pPDev->hMeta, 100, 100, 0, NULL, txt,
    sizeof(txt)/sizeof(*txt) - 1, dxes);
    free(dxes);
    return TRUE;
    ....
    In "ENABLE.C"
    ....
    #include "windows.h"
    ....
    //in the beginning of DrvEnableSurface() - create metafile
    RECT someRect = {0, 0, 1000, 1000};
    HDC hdC = CreateCompatibleDC(NULL);
    HDC hdcMeta = CreateEnhMetaFileW(hdC, L"C:\\DelMe.emf", &someRect, NULL);
    DeleteDC(hdC);
    DBGP(("EnableSurface hMeta(%p)", hdcMeta));
    pPDev->hMeta = (HANDLE)hdcMeta;
    ....
    //in the beginning of DrvDisableSurface() - clean up to unlock the file.
    HENHMETAFILE hF = CloseEnhMetaFile((HDC)pPDev->hMeta);
    DeleteEnhMetaFile(hF);
    DBGP(("DrvDisableSurface close hMeta(%p)", pPDev->hMeta));
    ....

    Also in order this to compile the next member need to be added to the
    declaration of PDEV in plotters.h:
    HANDLE hMeta;
    And in order to link Gdi32.lib must be added.

    After building the driver (checked build), the problem can be easy
    replicated (at least on my machine:) by using
    print to file when printing text file from Notepad. The text should be more
    then 15 lines and each line
    should be about 30 characters. The installed driver should be able to print
    text, the last one that I
    used is HP DesignJet 250C (D/A1). At least this is the easiest way for me to
    replicate it.
    In order to check the output the DebugView can be used (I am not familiar
    with MSPLOT output format in
    order to check the actual output file).
    Thank you for the interest.
     
    Zhivko Tabakov, Nov 8, 2005
    #5
  6. Here are the all the modifications that I have done to msplot
    (the essential part is SelectClipRgn and ExtTextOut calls in DrvTextOut, the
    rest of the code is just to enable me to call these 2 APIs). If either is
    omitted DrvTextOut is called correctly for all the text (same if dxes are
    NULL).

    In "TEXTOUT.C"
    ....
    #include <windows.h>
    ....
    //in the beginning of DrvTextOut()
    int *dxes;
    unsigned dxesIdx;
    const wchar_t txt[] = L"Some text printed with some (40pt) character
    spacing.";
    //and after pPDev initialization "if (!(pPDev =...){...}" follows:
    DBGP(("The DrvTextOut Entry (%d chars, first one is:%c)"
    , pstro->cGlyphs, (NULL == pstro->pwszOrg ? ' ' :
    (char)*(pstro->pwszOrg))));
    dxes = (int*)malloc(pstro->cGlyphs * sizeof(int));
    for(dxesIdx = 0; dxesIdx < pstro->cGlyphs; ++dxesIdx)
    dxes[dxesIdx] = 40;
    SelectClipRgn((HDC)pPDev->hMeta, NULL);
    ExtTextOutW((HDC)pPDev->hMeta, 100, 100, 0, NULL, txt,
    sizeof(txt)/sizeof(*txt) - 1, dxes);
    free(dxes);
    return TRUE;
    ....
    In "ENABLE.C"
    ....
    #include "windows.h"
    ....
    //in the beginning of DrvEnableSurface() - create metafile
    RECT someRect = {0, 0, 1000, 1000};
    HDC hdC = CreateCompatibleDC(NULL);
    HDC hdcMeta = CreateEnhMetaFileW(hdC, L"C:\\DelMe.emf", &someRect, NULL);
    DeleteDC(hdC);
    DBGP(("EnableSurface hMeta(%p)", hdcMeta));
    pPDev->hMeta = (HANDLE)hdcMeta;
    ....
    //in the beginning of DrvDisableSurface() - clean up to unlock the file.
    HENHMETAFILE hF = CloseEnhMetaFile((HDC)pPDev->hMeta);
    DeleteEnhMetaFile(hF);
    DBGP(("DrvDisableSurface close hMeta(%p)", pPDev->hMeta));
    ....

    Also in order this to compile the next member need to be added to the
    declaration of PDEV in plotters.h:
    HANDLE hMeta;
    And in order to link Gdi32.lib must be added.

    After building the driver (checked build), the problem can be easy
    replicated (at least on my machine:) by using
    print to file when printing text file from Notepad. The text should be more
    then 15 lines and each line
    should be about 30 characters. The installed driver should be able to print
    text, the last one that I
    used is HP DesignJet 250C (D/A1). At least this is the easiest way for me to
    replicate it.
    In order to check the output the DebugView can be used (I am not familiar
    with MSPLOT output format in
    order to check the actual output file).
    Thank you for the interest.
     
    Zhivko Tabakov, Nov 9, 2005
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.