The following information is provided as is, and the authors take no responsibility for the correctness.

Windows Spooler Print Monitors

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.

Mailing List

  • WinPrnDev - Windows Printer Driver Development
    This list is dedicated to the development of printer drivers and spooler components for the Windows family of operating systems. Looking for Win32 or user-mode peer support? Not here.
    But if you've got a design, implementation or support issue with a Windows printer driver, this is the place to be - Take the opportunity to learn from your peers to get over that particular development hump.

Garbled Port Name Bug

When viewing the details of the ports in the printer UI, the name of the port is garbled.

This is because, when the spooler calls the port monitors it starts by finding out how much memory it requires and allocates it. It then works through each port creating one large block of port info structures in the begining of the allocated memory.

The documentation on EnumPorts is a bit confusing.

To fix this problem do the following:

When you fill the buffer with the port info, fill the port info structures from the begining of the buffer and the strings pointed to in these structures from the end.

SetPort does not use custom status

The documentation of SetPort states, that it is possible to a custom status by specifying a string for PORT_INFO_3.pszStatus.

This does not work. According to Microsoft this is a bug, with no current workaround!

The bug is, according to the Microsoft usenet post, sheduled to be fixed in Longhorn (Windows Vista)

Spooler reactions to MONITOR2 interface function failures

This is an attempt to catalogue the spooler's (undocumented) reactions to a Language Monitor failing (returning FALSE) the various MONITOR2 interface functions (i.e. OpenPortEx). These results have been compiled by attaching a debugger to a minimal Language Monitor implementation and then observing the spooler's call sequences following the forced failure of the various APIs.


  • If OpenPortEx fails when the spooler service first starts, the failure is ignored and the spooler initializes normally.
  • If OpenPortEx fails when the associated print queue's properties window is opened, the failures are ignored and the properties window is displayed as normal (note: the spooler calls OpenPortEx 9 times corresponding to the number of Value Names it would normally try to read via the GetPrinterDataFromPort function).
  • If OpenPortEx fails when a document is printed, the spooler will immediately re-route the document directly to the associated port monitor (i.e. usbmon.dll); this results in the document being sent to the printer, but without any of the behaviours implemented in the Language Monitor being executed. Note that the spooler executes this re-routing only once, and will re-try the Language Monitor's OpenPortEx function for the next job.


called only after OpenPortEx has succeeded

  • If StartDocPort fails when a document is printed, the spooler flags that job as being in error (probably via the SetJob API), waits for a while, and then re-calls StartDocPort to try again. From my testing, it appears that the spooler will continue re-trying the StartDocPort function forever.


called only after StartDocPort has succeeded

  • If WritePort fails when a document is printing, the spooler flags that job as being in error (probably via the SetJob API), waits for a while, and then re-calls WritePort. Any data successfully sent by the Language Monitor prior to returning FALSE (as indicated to the spooler via the pcbWritten out parameter) is not resent (in other words, the data buffer passed to re-calls is offset properly). If the re-try call succeeds, the spooler clears the job error status and continues as normal. From my testing, it appears that the spooler will continue re-trying the WritePort function forever.


called only after all job data has been successfully sent via 1 or more WritePort calls

  • If EndDocPort fails, the spooler flags the job with the “Sent to printer” status, and leaves it in the print queue. Subsequent job submissions to the queue will proceed as normal.

GetPrinterDataFromPort & associated Language Monitor madness

This MONITOR2 function is stated as being optional for both Language Monitors and Print Monitors, but not exporting it results in strange spooler behaviors.

  • If the GetPrinterDataFromPort function is not exported, then whenever a user application calls the GetPrinterData API, the spooler will shutdown your Language Monitor and temporarily link directly with the associated Port Monitor before restoring the normal chain of command.
  • In order to avoid this sort of ridiculous circumvention, you can export a GetPrinterDataFromPort function and always return FALSE. But beware - calling SetLastError(ERROR_INVALID_PARAMETER) before returning is an unwritten requirement.

winspool/print_monitors.txt · Last modified: 2006/12/22 06:43 (external edit)

All text is available under the terms of the GNU Free Documentation License (see Copyrights for details). Disclaimers

Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki