Printer drivers and GDI RAW

Hello all,

I have developed a unidrv-based printer driver which uses the winprint processor (default data type is set to EMF) and works as expected in most cases. “Works as expected”, in these cases means “when my test application prints, I can see a spooled file that contains correct data”. Anything that happens after the spooled file is generated is out of scope of this question since the problem shows up at that stage (more on this later).

  • The RAW printing APIs (WriteFile() etc) produce the correct output. An application based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/dd162959(v=vs.85).aspx works without a hitch.

  • GDI printing using EMF also works. Using CreateDC(), StartDoc(), StartPage(), ExtTextOut() etc produces the expected output. In StartDoc()'s DOCINFO I use NULL or “emf” as the data type.

  • GDI printing using RAW doesn’t work. My port monitor gets garbage data (just a large number of 0xFF and NUL values, for a simple string it may get 39KB of this) with the job. The spool file also shows this complete garbage in this situation, but in the other cases the data is completely fine.

I suspect I am missing some huge block somewhere and the most reasonable guess is that the printer graphics DLL is supposed to do some processing of the RAW data to a format that my printer will understand, which data will then be saved to the spooler file by unidrv. This suspicion is based on https://msdn.microsoft.com/en-us/library/windows/hardware/ff551757(v=vs.85).aspx.

But when this DLL is not present, I think that GDI and/or unidrv do not understand what to and just write out some uninitialized buffers or random data. Am I on the right track? I am asking mainly to avoid a situation where I would spend time understanding and implementing the printing graphics DLL and end up with the same incorrect results.

As a test case I did try to use the printer graphics DLL that comes with the WDK (OEMUNI) with my printer and I have been able to gather the following information:

COemUni2::FilterGraphics() does get called with the garbage data (I get the expected DEVOBJ and DEVMODE but the buffer is just a large stream of 0xFF and NUL). The function gets called multiple times (with around 400byte chunks each time). This data is the same data that I can see in the spool file for the job.

OEMTextOut() hook also gets called. In this call I can see the string that my test application is writing in pstro->pwszOrg but since the sample doesn’t really do anything other than passthrough my results are the same.

Would implementing the graphics DLL fix my issues or would this be a waste of time? I would like to support GDI RAW printing.

You are probably seeing the default output of Unidrv - a monochrome, device-independent bitmap. You’ll want to make changes to your GPD file(s) to decorate this output with PDL commands for your device. If you come across a requirement that can’t be fulfilled through the GPD, then you’ll need to provide customization to Unidrv via a configuration or printer graphics plug-in.

Configuration Plug-in (UNIDRV) - https://msdn.microsoft.com/en-us/library/windows/hardware/ff563612(v=vs.85).aspx
Rendering Plug-in (UNIDRV) - https://msdn.microsoft.com/en-us/library/windows/hardware/ff561948(v=vs.85).aspx