The Windows Universal Printer Driver

Abstract
The purpose of this white paper is to provide an introduction to Windows printer drivers in general, and to the Universal Printer Driver - UNIDRV - in particular. UNIDRV runs is available on all versions of Microsoft Windows since Windows NT 4.0 (Service Pack 6), including Windows 7.x, Windows 8.x, Windows 10.x and Windows 11.x

Outline

  • The Role of Printer Drivers
  • Types of Printer Drivers
  • The Universal Printer Driver
  • UNDRIV Plug-Ins

    The Role of Printer Drivers
    A Windows printer driver is an installable component that converts graphic drawing calls made by applications into device-specific drawing instructions. When applications send any graphical output to a printer, they call a portion of the Windows 32-Bit (Win32) Application Programming Interface known as the Graphics Device Interface or GDI. GDI - or more specifically GDI32.DLL - loads printer drivers, and calls a printer driver to convert individual drawing calls into a printer-specific graphic language.


    GDI Drawing Support
    The primary graphical library in the Windows API is GDI. So when a typical application wants to draw - either on the display screen or to a printer - it calls GDI. A device driver is required for both display devices and printers/plotters, and in fact the driver interface for both types of devices is very similar.
    There are three basic categories of GDI drawing functions: text, raster, and vector. These same distinctions exist at the device driver level. To a great extent, understanding the operation of the API will help in implementing device-driver level graphics functions. One printer driver developer described how his GDI programming experience was helpful in building printer drivers in this way: "It was like going through the looking glass - instead of just calling functions, in the printer driver you were implementing them."


    Text Drawing
    Text, of course, has to do with the display of readable letters and numbers. The means of controlling the appearance of text - letter styles, letter height, whether bold or italic - is through a font. Much of the work of text drawing in a device driver involves identifying available fonts, describing all the details of available fonts, and working to make those fonts available to an application when it requests the use of a particular font.
    Windows has built-in support for Truetype, a flexible font scaling technology that helps minimize the differences between fonts that are available for different devices. In addition to Truetype fonts, some printers support their own, built-in fonts. In such cases, it is the job of the device driver to notify GDI that device-specific fonts are available, to provide GDI a detailed description of these fonts, and to make those fonts appear on the device when an application requests them.


    Raster Drawing
    Rasters mean arrays of pixels, and in many cases when people say "raster graphics" they mean off-screen bitmaps. GDI provides applications with quite a number of calls for drawing raster graphics. For example, a rectangular area can be filled with a solid color - a key capability in a display device driver. Most of the interesting raster drawing calls operate on bitmaps, and bitmaps can be stretched, shrunk, rotated, or skewed.
    GDI provides support for Device Independent Bitmaps (DIBs). This is a standard for storing arrays of pixels in a way that the bitmaps can be moved from one device to another with a minimum loss of information. This standard started out (in Windows 3.1) as a standard format for storing bitmaps in files, and that is the format used by painting programs like PBRUSH and MSPAINT. Starting with Windows NT 4.0, DIBs became an important in-memory format for bitmaps, and since then device drivers have included support for DIBs. There is, for example, a Win32 function for creating a DIB - CreateDIBSection. This is an important function because it introduced to Windows the ability to have a dual-ported bitmap, meaning that applications could directly access the memory of the bitmap while also drawing into the same bitmap using regular GDI drawing calls.
    There are several standard formats for DIBs, including those shown here:

    Description
    Bits Per Pixel
    Planes
    Possible Colors

    Color Table?

    Monochrome
    1
    1
    2
    Y
    VGA Color
    4
    1
    16
    Y
    1 Byte/Pixel
    8
    1
    256
    Y
    2 Bytes/Pixel
    16
    1
    64K
    N
    3 Bytes/Pixel
    24
    1
    16 Million
    N
    4 Bytes/ Pixel
    32
    1
    4 Billion
    N
    JPEG
    24
    1
    16 Million
    N

    PNG

    8
    1
    256
    Y

    It is important to note that support for the last two DIB formats, JPEG and PNG, are optional formats that are available starting in Windows 2000 and later. If a printer driver (or a display driver) does not support these formats, it is up to the application to convert a JPEG (or a PNG) image to another, supported DIB format. The presence of support for JPEG opens the possibility that high-end printers could have built-in support for decompression of high-quality photographic images - a potential market advantage owing to the potential for improved throughput on such a device.


    Vector Drawing
    Vector drawing means polygonal objects provided by GDI drawing functions like Rectangle, Pie, Polygon, and Polyline. With some printers, UNIDRV support vector drawing by rendering vector objects onto off-screen bitmaps and then sending these bitmaps to the printer using the printer's raster drawing commands.
    Starting with Windows XP, UNIDRV supports both HP/GL as well as the vector drawing of PCL/XL. What this means is that a UNDRIV-based printing solution can now provide a faster, more memory efficient support for vector-intensive applications. This support is available through the *Personality keyword in the GPD file.
    A UNIDRV-based printer driver can hook out the vector drawing DDI calls (DrvStrokePath, DrvFillPath, and DrvStrokeAndFillPath) to support any device-specific vector drawing languages. Support for this involves writing some code and deploying it in a UNDRV rendering plug-in.


    Windows Printing System Architecture
    A printer driver is a dynamic link library (DLL), which is an executable module that can be loaded into the address space of any process. Printer drivers are typically loaded into the address space of two different processes: (1) an application that is printing, and (2) the spooler. The name of the UNIDRV printer driver component is UNIDRV.DLL. Figure 1 shows the relationship of UNIDRV.DLL to other system elements when printing from NOTEPAD.
    The accompanying figure shows spooling of the print job as an EMF (Enhanced Metafile) spool file. EMF is a standard format for storing GDI drawing calls. A key benefit that EMF spooling provides is fast return-to-application time. The EMF file is created when the application calls GDI functions to draw. This same file gets played back by the print processor (LOCALSPL.DLL in Windows 2000 and later, WINPRINT.DLL in Windows NT 4.0) and the appropriate GDI functions are called, which in turn are used to call into the rendering driver, UNIDRV.DLL.
    Figure 1 - UNIDRV.DLL in the System.

    Figure 2 - UNIDRVUI.DLL in the system.

    In addition to its graphical output, a printer driver solution will also provide a user-interface - in the form of dialog boxes and property sheets - by which a user can control how output appears on the printed page. In previous versions of Windows, graphical output support and user-interface support were merged in a single DLL. On all versions of Windows NT, the two elements were split into separate DLLs. The name of the UNIDRV user-interface support library is UNIDRVUI.DLL. This DLL can be loaded into any of three different processes: (1) an application that is printing, (2) the spooler, and (3) the Explorer process.
    Figure 2 shows the relationship of UNIDRVUI.DLL to other system elements when printing from NOTEPAD. This diagram is much simpler than that shown in figure 1, since it leaves out the spooler entirely.
    Figure 1 also places the rendering driver - UNIDRV.DLL - in the address space of the printing application. For the sake of accuracy, I must point out that this only occurs when sending output to a file and not to a port. While this is different from figure 1, it accurately represents the behavior of the system. More to the point, what the two figures have in common - and what is central to the architecture of Windows printing - is the fact that it is exclusively the job of GDI32.DLL to call a printer driver.


    Types of Printer Drivers
    When a new printer is developed, a printer driver team has two basic choices: write an entire driver from scratch - sometimes known as a "monolithic printer driver", or to use a table-driven driver framework such as UNIDRV.


    A Monolithic Printer Drivers
    The term "Monolithic Printer Driver" basically means that the printer driver development team builds all the code - typically C or C++ - needed to enable printing. The first printer drivers that were created - back in the Windows 1.x days - were by necessity monolithic.
    One benefit of monolithic printer drivers is that the development team has total control over all the source code. There is nothing you cannot do. Unfortunately, there are a lot of things that you must do to account for application bugs, and there is just plain a lot of code that goes into a printer driver. One alternative that has been created is the table-driver printer driver framework.


    Table-Driven Printer Driver Frameworks
    Over time, as more and more drivers were created, it became obvious that a lot of the code in different printer drivers was the same. In part, this was because new drivers were often created by porting the code of an existing driver. But more to the point, common code was present because different printers often work the same way or at least in a similar fashion. For example, many PCL printers - PCL 3, PCL 4, and PCL 5 - d issue a Form-Feed (0x0C) to eject a page. But on non-PCL printers, like the Canon Bubble-Jet BJC-240, the page eject command is different - it is accomplished with a seven-byte sequence of characters. While the commands might be different on different printers, there are a common set of operations that must be accomplished for all print operations.
    A printer driver framework - like UNIDRV - provides a mechanism for defining the data needed to drive the creation of printed output. In theory, at least, this is a simple thing to do. In an ideal world, someone could simply refer to the technical specifications for a printer, fill in some tables, and the printer driver framework would do everything with no coding required at all.
    In fact, there is almost always a need for some kind of custom coding. How much depends on the amount of fine-tuning a driver team wants to provide to tweak the output created by the framework. UNIDRV is the third major printer driver framework that Microsoft has created (and third-parties built other frameworks). As each successive framework was made available, each has provided more and more support for adding code to supplement the table-driven approach. In UNIDRV, that mechanism is known as the "plug-in".


    The Universal Printer Driver
    The Universal Printer Driver - UNIDRV.DLL - is a table-driver printer driver solution. It provides support for printers that are driven by PCL and PCL-like printer display languages (PDLs). While UNIDRV supports PCL 3, 4, 5, and PCL-XL, it does not support Postscript.
    A very basic UNIDRV solution can be implemented without writing any code. Instead all that is needed is a GPD - Generic Printer Description - file. A GPD file is a text file that contains details about what printer command to start a print job, eject a page, and end a print job, along with all the other steps needed to draw text, raster, and vector objects.


    GPD Files
    The role of GPD files is essentially to fill in a table of capabilities that a printer can support, and to provide the specific command sequences needed to create graphical output. GPD files are text files, which mean - aside from a text editor - no special tool is needed to edit them. Microsoft provides a tool in the DDK to edit GPD files. Figure 3 shows a screen shot of this tool - the Minidriver Development Tool, or Print MDT for short - which, in addition to editing, has some other nice features. For example, it provides rudimentary syntax checking, a color-coded display of a GPD files, editing of some of the binary files that accompany a printer driver (font files and character mapping files), and it also create an install (.INF) file for a driver.
    Figure 3 - The Print MDT Tool

    UNIDRV Plug-Ins
    Strictly speaking, no code is necessary to create a UNIDRV-based printer driver. However, there are some situations that require coding. For such cases, you create a UNIDRV plug-in. There are two basic types of UNIDRV plug-ins - one for each of the two core UNIDRV modules:
    1. Rendering plug-in - which fine-tunes output from UNIDRV.DLL.
    2. User-interface plug-in - which fine-tunes the user-interface on UNIDRVUI.DLL.
    Both types of plug-ins are implemented as Component Object Model (COM) in-process servers. An in-process server is basically a dynamic link library (DLL) that exports a very specific set of entry points, the most important one being DllGetClassObject. When called, this function returns a pointer to a COM class factory. The job of the class factory component is to manufacture all of the components that a given COM server supports. In the case of a UNIDRV plug-in, that means either the rendering plug-in component or the user-interface plug-in component.


    Rendering Plug-Ins
    A rendering plug-in lets you fine-tune the graphical output of the core UNIDRV rendering engine, UNIDRV.DLL. A rendering plug-in lets you accomplish any of the following:
    1. Download non-standard fonts
    2. Filter the PDL stream (Requires Windows XP, or later).
    3. Modify individual PDL commands based on the setting of custom features.
    4. Intercept driver-entry point calls into UNIDRV.
    5. Change individual scan-lines as they are sent out of UNIDRV.
    6. Perform customized raster compression.
    7. Modify half-tone patterns
    8. Control the downloading of Truetype fonts.
    9. Perform custom or proprietary color management.
    10. Handle vector drawing calls in a custom, proprietary manner.
    This is by no means a complete list. In general the purpose of a rendering plug-in is to allow printer driver developers to take over any drawing, while still allowing UNIDRV to handle the graphic output that it can. UNIDRV provides a good baseline for all kinds of rendering. The choice of what to handle in a rendering plug-in depends entirely on the target market for a specific printer, and the ways that a printer driver team expects to add value. You can change everything - but in doing so you make yourself more like a monolithic printer driver. The UNIDRV team expects you to only change the areas where you can significantly improve on what UNIDRV can already provide, or in areas that highlight specific features of your printer that UNIDRV by itself does not address.


    User-Interface Plug-Ins
    The second type of plug-in, a user-interface plug-in, lets you fine-tune the user-interface elements of the user-interface library UNIDRVUI.DLL. A user-interface plug-in lets you accomplish any of the following:
    1. Install-time actions
    2. Add a property sheet to a printer properties property sheet, or to a document properties property sheet.
    3. Add custom controls to standard property sheets.
    4. Provide a custom font installer dialog box.
    Once again, this is a partial list. Just like a rendering plug-in, a user-interface plug-in will tend to be focused on key areas of major improvements, but the standard UNIDRVUI features provides a fairly rich set of support for all of the things that UNIDRV can do.

    Feedback:
    " To provide feedback about the white paper, please send e-mail to
    Acronyms and Terms
    API Application Programming Interface
    COM Component Object Model
    DDI Device Driver Interface
    DLL Dynamic Link Library
    DDK Device Driver Kit
    EMF Enhanced Metafile
    PDL Printer Description Language
    SDK Software Development Kit

     

    For more technical details on any of our hands-on training sessions,
    Please contact us at the email address at this link:contact information

    (c) Copyright 1990-2024 The Paul Yao Company. All rights reserved.