Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Printing Architecture

0.00/5 (No votes)
30 Nov 2004 1  
This article explains about the components of printing architecture.

Introduction

The Printing Architecture is one of the major components from Windows architecture. It consists of a print spooler and a set of printer drivers. The applications can create print jobs and send them to the printers by calling device-independent Win32 printing and GDI functions. Printer drivers include a user interface component that allows users to control a printer's selectable options (Paper Size, Number of copies, Coloration, Pages per sheet, etc.).

An application's calls to Win32 GDI functions are passed to the GDI graphics engine, which either spools the drawing instructions as an enhanced metafile (EMF) file or, in conjunction with a printer driver, renders a printable image that can be sent to the spooler. Spooler components interpret EMF files, and they can insert page layout information and job control instructions into the data stream. The spooler then sends the data stream to the serial, parallel, or network port driver associated with the target printer's I/O port. Spooler and driver components are designed to be replaceable. Support for a new printer usually requires only the creation of new data files for use with one of the Microsoft-supplied printer drivers.

Most of the device drivers work at kernel mode. Some of the device drivers or part of the device drivers work at user mode and kernel mode. Printer drivers work at both modes.

Printing Process

The printing process is divided into three groups of steps:

  • Client processes
  • Spooler processes
  • Printer processes

Each process performs some operations and passes the print job to another process. For example, user fires a print document from an application, the client process starts the creation of print job by calling the GDI, and after completing the creation of print job, it sends to the spooler. The spooler will perform some operations on that print job and sends to the printer process. The printer processes receive the print job from the spooler process and translate the print language into a bitmap, and then it prints.

Client Processes

A user sends a print job from an application. The application calls the Graphics Device Interface (GDI). If print output is produced in RAW format, the GDI is not used. The GDI calls the printer driver for information, which the GDI uses to create a job in printer language. The GDI delivers the job to the spooler.

Spooler Processes

  • The client side of the spooler (Winspool.drv) makes an RPC call to the server side spooler (Spoolsv.exe).
  • Spoolsv.exe calls the print router (Spoolss.dll).
  • The router (Spoolsv.dll) sends the print job to the Local Print Provider (LPP) or remote print server if the job is being sent to a network printer.
  • The LPP polls print processors to find one that can handle the data type of the job.
  • The LPP sends the job to the print processor, which modifies the job as required to make it print properly.
  • The print processor sends the job to the page separator. A separator page is added, as required.
  • The job is sent to the appropriate port print monitor. If print is bidirectional, the job is first sent to the language monitor such as the Printer Job Language (PJL) monitor, and then sent on to the port monitor. If the job is unidirectional, the job is sent directly to the port monitor.

Printer Processes

  • The printer receives the print job from the print spooler.
  • The printer translates the print language into a bitmap, which it then prints.

Print Spooler Architecture

Introduction to Print Spooler

Print spooling is configured by users. Jobs can be sent to the spooler, or sent directly to the printer. If jobs are sent to the spooler, they can be configured to start printing as soon as possible or after the final page in a job has been sent to the spooler. When you send a print job directly to the printer, your computer renders the entire job and then transfers it directly to the printer. When you send a print job to a spooler, your computer creates the job, including meta-information about how the job must be processed, and then sends the job to the spooler. The spooler then renders the job and sends it to the printer.

Sending a print job directly to the printer is good because you remove a potential point of failure in printing documents, and all print job rendering is done on your computer, affording you more control, and you don’t have to wait for other jobs to complete, as you might if you were printing to a queue on a print server that was being used by many users. Conversely, rendering a print job on your computer consumes computing resources, so you might experience reduced performance or have to wait until the print job has completed before doing anything.

Sending a print job to a spooler is good because your computer does not have to render the print job, meaning your computer’s resources are more completely and immediately available. Conversely, sending a print job to a spooler fails if the print server with the spooler is unavailable, and you might have to wait for other jobs to finish spooling before your job is processed.

The primary component of the printing interface is the print spooler. The print spooler is an executable file that manages the printing process. Management of printing involves retrieving the location of the correct printer driver, loading that driver, spooling high-level function calls into a print job, scheduling the print job for printing, and so on. The spooler is loaded at system startup and continues to run until the operating system is shut down. Applications that print create a printer device context (DC). When an application creates a printer DC, the spooler performs necessary tasks such as determining the location of the required printer driver and then loading the appropriate printer driver. It also determines the data type used to record the print job.

The supported data types include enhanced metafiles (EMF), ASCII text, and raw data (all printer specific data types such as PostScript and PCL). Custom data types can be added to the spooler when additional printer drivers and print processors are installed. A print job is a document stored internally (by using one of the supported data types) that may contain one or more pages of output. It may consist of multiple forms; for example, a job may consist of one envelope and three pages of A4 paper. A print job is defined (or bracketed) by the StartDoc and EndDoc functions.

The default data type for a print job is the enhanced metafile. An EMF record is a compact structure used to store text output commands, raster graphics commands, and so on. When an application calls StartDoc, the spooler creates a spool file and a data file and begins storing EMF records in the spool file. The spool and data files are created in an operating system directory. The spooler uses the spool file to store EMF records, and uses the data file to record the type of form, the data type for the print job, the target printer, and so on. The spooler deletes these files when the job has successfully printed.

The Microsoft Windows print spooler is made up of a set of Microsoft-supplied and optional vendor-supplied components, with responsibilities that include:

  • Determining whether a print job should be handled locally or across a network
  • Accepting a data stream created by GDI, in conjunction with a printer driver, for output on a particular type of printer
  • Spooling the data to a file (if spooling is enabled)
  • Selecting the first available physical printer in a logical printer queue
  • Converting a data stream from a spooled format (such as enhanced metafile (EMF)) to a format that can be sent to printer hardware (such as printer control language (PCL))
  • Sending a data stream to printer hardware
  • Maintaining a registry-based database for spooler components and printer forms

Windows print spooler support for Directory Services consists of:

  • Publishing print queues
  • Maintaining three registry keys
  • Allowing access to spooler-maintained registry keys
  • Returning a print queue's publication state

Spooler Components

The primary components of the Microsoft Windows print spooler are illustrated in the following diagram. The print spooler consists of a group of components that include the print router, the local and remote print provider, the print processor, and the language and port monitors.

  • Application: The print application creates a print job by calling GDI functions.
  • GDI: The Graphics Device Interface (GDI) includes both user-mode and kernel-mode components. The user-mode component, Win32 GDI, is used by Win32 applications that require graphics support. The kernel-mode component, the graphics engine (or graphics rendering engine), exports services and functions that graphics device drivers can use.
  • Winspool.drv: Winspool.drv is the client interface into the spooler. It exports the functions that make up the spooler's Win32 API, and provides RPC stubs for accessing the server. (GDI is the primary client, but applications also call some of its Win32 functions.)
  • Spoolsv.exe: Spoolsv.exe is the spooler's API server. It is implemented as a Windows 2000 (or later) service that is started when the operating system is started. This module exports an RPC interface to the server side of the spooler's Win32 API. Clients of spoolsv.exe include winspool.drv (locally) and Win32spl.dll (remotely). The module implements some API functions, but most function calls are passed to a print provider by means of the router (spoolss.dll).
  • Router: The router, spoolss.dll, determines which print provider to call, based on a printer name or handle supplied with each function call, and passes the function call to the correct provider.
  • Print Provider: The print provider that supports the specified print device.
  • Print Monitor: Windows XP supports two types of print monitors: language monitors, and port monitors.

If printer hardware is local to the system on which the application is running, the "client" and "server" are the same system (although this is not evident in the diagram).

Note: All spooler components execute in user mode.

Print Providers

This section provides the following topics:

Introduction to Print Providers

Print providers are responsible for directing print jobs to local or remote print devices. They are also responsible for print queue management operations, such as starting, stopping, and enumerating a server's print queues. Print providers define a high-level, machine-independent, Operating System-independent view of a print server. All print providers implement a common set of print provider capabilities. These capabilities are defined by a set of API functions, which are called by the spooler's router (spoolss.dll).

Print Provider Flow Paths

When viewing the diagram, you should consider the following points:

  • If the printer is managed by the client system, the print job is handled by the local print provider (localspl.dll). Printers managed by localspl.dll do not have to be physically local to the client; they can be directly connected to network cards.
  • If the printer is located on a NT-based-operating system server, the network provider (win32spl.dll) uses RPC to redirect calls from the client's router to the server's spoolsv.exe process. Because the printer is local to the server, the server's local print provider will handle the print job.
  • If the printer is located on some other type of server, it can be accessed by either the local print provider or by a network print provider that supports that server type, using data formats and network protocols supported by the server.
  • For the local print provider to access a remote printer, it must contain a port monitor that can use network protocols recognized by the remote printer or server.

Print Provider Capabilities

By supporting predefined sets of API functions, Windows print providers can supply the following capabilities:

  • Print Queue Management: Adding, deleting, opening, closing, enumerating, and setting parameters for print queues. Also, providing notification of changes to a print queue's state.
  • Printer Driver Management: Adding, deleting, enumerating, and specifying a directory for printer drivers.
  • Print Job Creation: Starting and ending a document, starting and ending a document page, writing the job's data stream to a port, reading printer status information.
  • Print Job Scheduling: Scheduling, enumerating, and setting parameters for a print job.
  • Forms Management: Adding, deleting, enumerating, and setting parameters for print forms.
  • Print Processor Management: Adding, deleting, enumerating, specifying a directory for and the data types supported by print processors.
  • Print Monitor Management: Adding, deleting, and enumerating print monitors.
  • Port Management: Adding, deleting, configuring, enumerating, and setting parameters for printer ports.
  • Registry Management: Creating, deleting, and enumerating registry keys and values associated with a print provider.
  • Other Capabilities: Displaying a message box, shutting down the print provider, reading a memory mapped spool file, providing a communication path between port monitor UI DLLs and port monitor server DLLs.

These capabilities are implemented as a set of functions defined by print providers. There are many functions supported to define a print provider. Functions are divided into the following groups:

  • Initialization Functions
  • Print Queue Management Functions
  • Printer Driver Management Functions
  • Print Job Creation Functions
  • Print Job Scheduling Functions
  • Forms Management Functions
  • Print Processor Management Functions
  • Print Monitor Management Functions
  • Port Management Functions
  • Registry Management Functions
  • Other Functions

Local Print Provider

The local print provider for Windows provides job control and printer management capabilities for all printers that are accessed through the local print provider's port monitors. (A client administrator sets up access to such printers by selecting the Local Printer option when using the Add Printer Wizard.) Such printers include those connected to the local system's serial and parallel ports. They can also include devices connected to other I/O channels, such as SCSI ports, along with printers connected to remote non-NT-based-operating system servers.

Control Flow in Local Printer Provider

As the diagram shows, an application creates a print job by calling the Graphics Driver Interface (GDI). Regardless of whether the print job's initial output format is EMF, the local print provider's job creation API creates a spool file. Later, when the job is scheduled, the spool file is read and, if the format is EMF, the EMF print processor sends the job back to GDI for conversion to RAW format, with the help of a printer graphics DLL. The converted data stream can then be sent back through the local print provider to the printer (without being re-spooled).

Printer Driver

Printer drivers contain information that is specific to the printer that is used. Printer drivers reside on user’s computers and are used by the GDI to render print jobs. A printer driver is a software program that understands how to communicate with printers and plotters. Printer drivers translate the information a user sends from the computer into commands that the printer understands. Various drivers must be installed on the print server to support different hardware and operating systems. For example, an administrator running Windows 2000 Server who shares a printer with clients running Windows 95 and Windows 98 might want to install the appropriate drivers so the users won't be prompted to install the missing drivers. The printer driver sends the printer-setting information, including the specifications needed to produce each character of the document, to the GDI. It also transmits helper services or utilities required to make the output print correctly.

Printer drivers are composed of three separate files:

  1. A printer graphics driver (for example, PSCRIPT.DLL, RASDD.DLL, or PLOTTER.DLL). Graphics drivers are responsible for print rendering (converting GDI commands from the graphics engine into printer commands that a printer can understand). Each graphics driver handles different printer languages. For example:
    • PSCRIPT.DLL: deals with the PostScript printer language.
    • PLOTTER.DLL: deals with the HPGL/2 language used by many plotters.
    • RASDD.DLL: deals with printer languages based on raster (bitmap) images, including PCL and most dot matrix printer languages.
  2. A printer interface driver (for example, PSCRPTUI.DLL, RASDDUI.DLL, or PLOTUI.DLL). This dynamic-link library (DLL) includes the user interface you see when you configure a printer in Print Manager. It is called by the client side of the router (WINSPOOL.DRV).
  3. Characterization files: Characterization data files provide model-specific information about print devices.

Printer Driver Components

All Windows printer drivers consist of the following components:

  • A printer graphics DLL that assists GDI in rendering a print job, and sends the rendered data stream to the print spooler.
  • A printer interface DLL that provides both a user interface to the driver's configuration parameters, and an interface the spooler can call to notify the driver of print-related system events.

Print Processors

The print processor is a dynamic-link library (DLL) which calls the printer driver. An application has tried to use a print processor which has not been installed on your computer. The spooler monitors the current print jobs and the target printer to determine an appropriate time to print a job. Once the spooler determines that a job should be printed, it calls the print processor. The print processor works together with the printer driver to move the spooled print jobs from the hard disk.

Introduction to Print Processors

Print processors are user-mode DLLs that are responsible for converting a print job's spooled data into a format that can be sent to a print monitor. They are also responsible for handling application requests to pause, resume and cancel print jobs.

The print job's spooled data is contained in a spool file. The print processor reads the file, performs conversion operations on the data stream, and writes the converted data to the spooler. The spooler then sends the data stream to the appropriate print monitor.

Microsoft Windows 2000 and later includes the print processors listed in the following table.

Print Processor Input Data Types Output Data Types
localspl.dll *
  • EMF
  • RAW
  • TEXT
RAW
sfmpsprt.dll PSCRIPT1 RAW

* Beginning with Windows 2000, localmon.dll and winprint.dll are included in localspl.dll.

For information about the data types, see the following topics:

  • EMF Data Type
  • RAW Data Type
  • TEXT Data Type
  • PSCRIPT1 Data Type

You can create a customized print processor to support a data type that is not supported by Windows 2000 or later operating system versions. You can also provide a customized print processor that supports one or more of the supported data types, thus allowing you to modify the capabilities provided by the supplied print processors. Print processors are associated with printer drivers during driver installation, so multiple print processors supporting the same data type can coexist.

EMF Data Type

Enhanced Metafile (EMF) data consists of instructions to call GDI functions. The print processor must call the GDI functions to render printable images. The GDI functions make calls to the printer driver's printer graphics DLL, which renders the image and sends it to the spooler as RAW data (by calling EngWritePrinter). NT-based operating system clients send EMF data to NT-based operating system print servers. EMF data is device independent and can be sent to a server more quickly than RAW data. A print job is also spooled as EMF data when the requesting application is local to the server, allowing a quick return to the application while the EMF data is subsequently rendered by a background spooler thread.

EMF (Enhanced MetaFile) is a spool file format used in printing by the Windows operating system. When a print job is sent to the printer, if it is already printing another file, the computer reads the new file and stores it, usually on the hard disk or in memory, for printing at a later time. Spooling allows multiple print jobs to be given to the printer at one time.

The EMF format is the 32-bit version of the original Windows metafile (WMF) format. The EMF format was created to solve the deficiencies of the WMF format in printing graphics from sophisticated graphics programs. The EMF format is device-independent. This means that the dimensions of a graphic are maintained on the printed copy regardless of the resolution in dots per inch of the printer. In a network, the smaller file size of the EMF format reduces network traffic. EMF is the spool file used by the Windows operating system.

RAW Data Type

RAW data can be sent to a print monitor without further processing. The print processor just sends this data back to the spooler (by calling WritePrinter, described in the Platform SDK documentation), sometimes inserting form feeds. An example of a RAW data file is one consisting of printer control language (PCL) commands. Print jobs are sent from client to server in RAW format if either the client or the server does not support NT-based-operating system EMF, or if a server administrator has disabled EMF support. In such cases, image rendering is performed on the client before the job is sent to the server. Postscript commands can be considered RAW data if the target printer supports Postscript. On the other hand, the sfmpsprt.dll print processor takes Postscript input and interprets it for non-Postscript printers, so in that case, the Postscript is not RAW data.

A RAW spool file is a one that is sent to the Windows spooler unprocessed (which is why it's called "RAW"). The raw file is used to send Postscript commands to a Postscript printer. The Postscript commands are understood by the printer, but are just plain data to the Windows spooler. The RAW format is device-dependent and slower. If printing problems occur while using the EMF format, they can sometimes be fixed by simply changing the format to "RAW" in the printer Properties.

Difference Between EMF and RAW Data Formats?

RAW is data formatted exactly how the printer needs it. Depending on the printer concerned, it could be fully rendered to a dot-by-dot page image or, on more sophisticated printers, incorporate vector elements. A PostScript printer, for example, expects a page to be described by a set of PostScript commands. This is essentially a vector format and that's what the RAW data would contain. EMF (Enhanced Metafile) describes the page in a vector format specific to Windows. EMF is actually a capture of the GDI (Graphics Device Interface) commands that programs use to tell Windows how to draw what you see on the output device, normally the screen. Because EMF is Windows' native image description language, capturing the commands into a spool file is a relatively quick and simple process. Immediately converting data to RAW format involves more processing and may produce a larger quantity of data than the equivalent EMF. Therefore, when printing from an application, EMF gets the immediate business of generating the print job over as soon as possible before returning control to the user.

When the print spooler is ready to send a buffered page to the printer, RAW data can be passed straight through whereas EMF commands must first be rendered into RAW format. This is done as a background process which means you can continue working. On a well-specified PC and/or printer, the effect on overall performance of this background processing may not be noticeable.

That's the theory, but it doesn't always hold true. And you would think print quality should be the same in either case, but I have avoided describing a lot of behind-the-scenes complications. Odd problems can sometimes be solved by switching from EMF to RAW, or occasionally vice-versa. In fact, RAW is the manufacturer's preferred format for some printers. There isn't much you can do about the speed, but make sure the computer has enough memory to avoid excessive use of the swap file and ensure the disk is defragmented. You might also try the spool setting 'Print directly to the printer'. This is not an option when a printer is shared over a network. Your application will take longer to return control to you, but printing time may be reduced, because the job is not being spooled to disk.

TEXT Data Type

TEXT data consists solely of ANSI text. The print processor calls GDI to draw characters using the print device's default font, and sends the resulting RAW-formatted output to the spooler (by calling WritePrinter, described in the Platform SDK documentation). The process is equivalent to opening the input file with Notepad and then printing the file. (This format is used for printers that do not print text characters.)

Processing a Print Job

When the spooler is ready to send a print job to a print processor, it calls the print processor's OpenPrintProcessor function. This function performs initialization activities and returns a handle. The spooler can then call PrintDocumentOnPrintProcessor, which is the print processor function that converts the data stream from the input format to the output format and returns the converted stream to the spooler. If the input format is NT-based-operating system EMF, the PrintDocumentOnPrintProcessor function can control the playback of the EMF records by using the functions listed in Using GDI Functions in Print Processors. These functions provide an interface between the print processor and the printer driver. This interface allows print processors to control the physical layout of printer pages, and thus facilitates implementing such features as printing multiple document pages per physical page ("N-up" printing), printing pages in reverse order, and printing multiple copies of each page.

A print processor's output data stream must be returned to the spooler. Typically, if the data conversion requires interaction with the printer driver's printer graphics DLL (as is the case for EMF input data), the graphics DLL returns the stream to the spooler by calling EngWritePrinter. On the other hand, if the conversion does not call the printer graphics DLL (as is the case for RAW input data), then the print processor calls WritePrinter. The PrintDocumentOnPrintProcessor function can be interrupted by asynchronous calls from the spooler to the print processor's ControlPrintProcessor function. This function implements an application's ability to pause, resume, or cancel a print job. After PrintDocumentOnPrintProcessor finishes converting the data stream and returns, the spooler calls the print processor's ClosePrintProcessor function.

Installing a Print Processor

To install a print processor, an installation application must call the spooler's AddPrintProcessor function. To associate a print processor with a print queue, list its file name in an INF file in a PrintProcessor entry. This entry must be included for every print queue to which the print processor is to be associated. For more information, see Printer INF Files. When an installation application calls the spooler's AddPrinter function, using a PRINTER_INFO_2 structure as an input argument, it specifies the print processor name (obtained from the INF file) as a structure member.

Associating a Print Processor with a PnP-installed Print Queue

If the PnP manager detects and installs a print queue on a system running either Windows 2000 or Windows XP, and if the INF file used to install the print queue contains a PrintProcessor entry other than the default Windows print processor, WinPrint, the print processor will not be associated with the print queue. However, the print processor will be installed. (Note that if you install the print queue using the Add Printer wizard, the print processor is correctly associated with the print queue. Note also that the PnP manager in Microsoft Windows Server™ 2003 and later correctly associates a print processor with the print queue.)

To associate the print processor with the print queue for Plug and Play installations on Windows 2000 and Windows XP, include a PRINTER_EVENT_INITIALIZE case in the printer interface DLL's DrvPrinterEvent function. For Microsoft Windows Server™ 2003 and later, it is not necessary to add a PRINTER_EVENT_INITIALIZE case in the DrvPrinterEvent function.

Print Monitor

Print monitors are responsible for directing a print data stream from the print spooler to an appropriate port driver. Two types of print monitors are defined — language monitors and port monitors.

Language Monitors

Language monitors are user-mode DLLs that serve two purposes:

  • They provide a full duplex communications path between the print spooler and bidirectional printers that are capable of providing software-accessible status information.
  • They add printer control information, such as commands defined by a printer job language, to the data stream.

Microsoft provides a language monitor, pjlmon.dll, which supports printer job language (PJL), and provides bidirectional communication for PJL printers. This monitor is included in the DDK as the sample language monitor.

Customized language monitors can be written to support other job control languages, for unidirectional or bidirectional printers.

Language monitors are optional and only associated with a particular printer type if included in the printer's INF file, as described in Installing a Print Monitor.

If a language monitor is associated with a printer, the language monitor receives the printer's data stream from the print processor, modifies it, and passes it to the printer's port monitor.

Port Monitors

Port monitors consist of user-mode DLLs. They are responsible for providing a communications path between the user-mode print spooler and the kernel-mode port drivers that access I/O port hardware. A port monitor typically uses the CreateFile, WriteFile, ReadFile, and DeviceIOControl functions, described in the Platform SDK documentation, to communicate with kernel-mode port drivers. Port monitors are also responsible for management and configuration of a server's printer ports, as described in Managing a Port.

An NT-based-operating system user's view of a "printer" is really a print queue, to which one or more physical printer devices can be connected. A port is the physical connection between the print queue and a single printer device. Each port monitor supports one or more instances of one or more types of ports. For example, localmon.dll, the sample port monitor, can support all of a server's local COM and LPT ports. (The print folder assigns ports to port monitors by calling the Platform SDK documentation's AddPrinter function.)

For print queues representing multiple printer devices (through multiple ports), the spooler sends each print job to the first available port. If the port monitor indicates that a specified port is busy or has encountered an error, the spooler resubmits the job to the queue, specifying another port supported by the port monitor.

Besides localmon.dll, Windows 2000 and later operating system versions provide several additional port monitors. The Windows 2000 Server Resource Kit describes each of these port monitors. Customized port monitors can be written to support additional types of I/O port hardware.

For Windows 2000 and later, each port monitor is divided into two DLLs:

  • Port Monitor UI DLL: A port monitor's user interface DLL contains user interface functionality and executes on print client systems. This DLL must reside in the client system's System32 subdirectory.
  • Port Monitor Server DLL: A port monitor's server DLL contains port communications functionality and executes on print servers. It must not display a user interface.

Initializing a Print Monitor

When the spooler calls LoadLibrary to load a print monitor DLL, the system immediately calls the DLL's DllEntryPoint function. It is generally a good idea for the entry point function to call DisableThreadLibraryCalls, described in the Platform SDK documentation, so the DLL is not unnecessarily notified when threads are created and deleted.

Each DLL exports an initialization function, which the spooler calls after calling LoadLibrary. Language monitor DLLs and port monitor server DLLs export an InitializePrintMonitor2 function. Port monitor UI DLLs export an InitializePrintMonitorUI function.

These two initialization functions are responsible for returning pointers to the rest of the functions defined by print monitors, so the spooler can call them. The initialization functions can also perform load-time initialization operations. The monitor's InitializePrintMonitor2 function returns a monitor instance handle. The monitor should allocate local memory to store instance-specific information, and use the monitor handle as an identifier for the allocated memory.

When the spooler is first started, it loads all of the monitor DLLs that have been installed. After calling all monitor initialization functions, the spooler calls each port monitor's EnumPorts function, which enumerates the ports supported by the monitor. (A monitor supports a port if the port has been added to the monitor's database, as described in Adding a Port.) Each supported port is then opened, as described in Opening and Closing a Port.

Opening and Closing a Port

After a port has been added, as described in Adding a Port, the spooler can open it by calling the appropriate language monitor's OpenPortEx function.

The language monitor uses the OpenPortEx function to create and return a port handle. Typically, a language monitor calls its associated port monitor's OpenPort function, and the language monitor just returns the handle obtained from the port monitor's OpenPort.

If a language monitor is not associated with a port, the spooler calls the port monitor's OpenPort function directly.

The spooler does not allow more than one path to a port to be enabled at one time. Thus, after it has called OpenPortEx (or OpenPort) in a particular monitor, it does not attempt to open the same port again before closing it.

After a port has been opened, the spooler can call additional functions to print a job, as described in Printing a Print Job, using the port handle as an input argument. A monitor should be written so that, after a port has been opened, the spooler can send multiple print jobs before closing the port.

The spooler closes a port if a job must be sent through a different language monitor, if no print queues are associated with a port, or when the system shuts down. To close a port, the spooler calls a language monitor's ClosePort function. The function invalidates the handle that was created when the port was opened. A language monitor typically calls the ClosePort function defined by its associated port monitor.

If a language monitor is not associated with a port, the spooler calls the port monitor's ClosePort function directly.

Printing a Print Job

After a port has been opened, as described in Opening and Closing a Port, the spooler can send print jobs to the port.

Each print job is delimited by spooler calls to a language or port monitor's StartDocPort and EndDocPort functions. The spooler calls these functions when a print processor calls the spooler's StartDocPrinter and EndDocPrinter functions, which are described in the Platform SDK documentation. Within the scope of a set of StartDocPort and EndDocPort functions, unlimited spooler calls to a monitor's WritePort, ReadPort, and GetPrinterDataFromPort functions can occur.

Each of these functions requires the port handle returned by OpenPortEx (or OpenPort) to be specified as an input argument. Typically, a language monitor implements each of the functions by calling the like-named function in its associated port monitor.

When the spooler calls a language monitor's WritePort function to send a data stream to the port, the function generally adds language-specific information, such as PJL commands, to the received data stream before passing it to the associated port monitor's WritePort function.

The ReadPort function is used for obtaining status information from bidirectional printer hardware, which a language monitor might send to the spooler by calling SetPort, described in the Platform SDK documentation. The spooler does not call the ReadPort function.

If printing hardware is bidirectional, both its language monitor and its port monitor should support a GetPrinterDataFromPort function. A language monitor's GetPrinterDataFromPort function should accept a registry value name as input, obtain a value for that name (generally by calling associated port monitor's WritePort and ReadPort functions), and return the value to the caller. A port monitor's GetPrinterDataFromPort function should accept an I/O control code as input, call DeviceIoControl (described in the Platform SDK documentation) to pass the control code to the port driver, and return the result.

Installing a Print Monitor

This section describes the methods that can be used to install print monitors. (You can install a print monitor with the same INF file that you use to install your printer. For more information about INF files, see Plug and Play and Power Management.)

Installing a Language Monitor: To install a language monitor, you must list its file name in an INF file by using a LanguageMonitor entry. This entry must be included for every printer driver that controls a printer requiring the use of the language monitor. For more information, see Printer INF Files. The Add Driver wizard or the Add Printer wizard reads this INF file and installs language monitors associated with printer drivers. Alternatively, custom installation applications can install language monitors by calling the spooler's AddMonitor function, to explicitly install only a specific monitor DLL.

Installing a Port Monitor: To install a port monitor, your installation medium must include a printer INF file (that is, an INF file for which Class = Printer) that contains a PortMonitors section. The single entry in this section points to an install section containing two entries: an INF CopyFiles directive that lists all of the files that make up the port monitor, and a PortMonitorDll entry that specifies which DLL in the previous list implements the port monitor interface. The following example code illustrates these points. The PortMonitors section points to an install section named SamplePortMon. In that section, an INF CopyFiles directive copies three files that make up the port monitor. Following that, a PortMonitorDll entry identifies the DLL that implements the port monitor interface.

[PortMonitors]
"Sample Port Monitor" = SamplePortMon

[SamplePortMon]
CopyFiles = @file1.dll, @file2.dll, @file3.hlp
PortMonitorDll = file1.dll

To install a port monitor, open the Printers folder in Control Panel. On the Printers folder's File menu, select Server Properties. On the File Server Properties dialog, click the Ports tab, and then click the Add Port... button. On the Printer Ports dialog, click the New Port Type... button. Type the path to the INF file in the text input box, and then click OK.

Alternatively, a custom installation application can install the port monitor DLL by a call to the AddMonitor function.

Bidirectional Communication

The spooler provides support for bidirectional ("BiDi") communication between an application or driver and a printer. This support enables the application or driver to send one or more requests to the printer, and the printer to respond to these requests.

Bidirectional Support Architecture

The bidi communication support involves two parts: the bidi communication schema and the bidi spooler APIs. The schema describes the requests that an application can make to a device and the format for the requests. The spooler APIs send the requests to the device and also send and receive the bidi data. An application can also send a request to a network print provider for a network printer or a printer that is connected to a remote printer server.

To send a single request to the printer, an application or printer driver must first compose the request, and then call the IBidiSpl::SendRecv method. To send multiple requests, the application or driver composes a list of requests, and then calls the IBidiSpl::MultiSendRecv method. After receiving the request, the client-side portion of the spooler (winspool.drv) passes it on to the server-side spooler (spoolsv.exe). The server-side spooler can be on the local computer, or on a remote network print server. When the server-side spooler receives the request, it parses the data in the request. The server-side spooler converts the data to a form suitable for use by the application or driver, and passes it back to the client-side spooler, and finally back to the originator of the request.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here