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.
OpenPortEx
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.
StartDocPort
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.
WritePort
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.
EndDocPort
called only after all job data has been successfully sent via 1 or more WritePort calls
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.