How to Determine Whether a Printer Supports Color

Introduction

A recent project required me to determine whether a printer supported printing in color. This seemed like the kind of task that others before me must have faced. I searched CodeGuru and other forums and found some approaches to this problem. However, none were too convincing or complete. Each article I found pointed out some flaw in the approach. With a little bit of research, I was able to develop my own approach to the problem.

Printer Drivers Reveal All

I always had a gut feeling that the information I needed was at a very basic low level. With some research, I stumbled across the DrvDeviceCapabilities() function. This function comes from the Microsoft DDK (Driver Development Kit). Microsoft recommends each hadrware vendor export this function from their drivers to provide requested information about a printer's capabilities. By using this function, it's pretty easy to determine color capabilities.

The Code

The first step in determining color capabilities is to open the printer. This is accomplished by the following:

BOOL rc = OpenPrinter(printer.GetBuffer(0), &hPrinter, NULL);

Once this is done, you'll need to get the printer and driver structures:

// get printer info.
rc     = GetPrinter(hPrinter, 2, NULL, NULL, &dwBytesNeeded);
pinfo2 = (PRINTER_INFO_2*) LocalAlloc(LPTR, dwBytesNeeded);
rc     = GetPrinter(hPrinter, 2, (LPBYTE)pinfo2, dwBytesNeeded,
         &dwBytesNeeded);
// get driver info.
rc     = GetPrinterDriver(hPrinter, NULL, 2, NULL, NULL,
         &dwBytesNeeded);
dinfo2 = (DRIVER_INFO_2*) LocalAlloc(LPTR, dwBytesNeeded);
rc     = GetPrinterDriver(hPrinter, NULL, 2, (LPBYTE)dinfo2,
                          dwBytesNeeded, &dwBytesNeeded);

The function we're interested in resides in the driver configuration file. Once we have it, we can call the function:

// get handle to printer driver config module
HMODULE hmod = LoadLibrary(dinfo2->pConfigFile);
if (hmod)
{
  DWORD (WINAPI* DriverCaps)(HANDLE, LPWSTR, WORD, VOID*, PDEVMODE);
  // get pointer to exported function.
  DriverCaps = (DWORD (WINAPI*) (HANDLE, LPWSTR, WORD, VOID*,
                PDEVMODE))
  GetProcAddress(hmod, "DrvDeviceCapabilities");
  if (DriverCaps)
  {
    WCHAR wszPrinter[256] = {0};
    MultiByteToWideChar(CP_ACP, 0, printer, -1, wszPrinter, 256);
    // call exported function.
    dwColor = (*DriverCaps)(hPrinter, wszPrinter,
                            32 /*DC_COLORDEVICE*/,
                            (VOID*)NULL, pinfo2->pDevMode);
  }
  FreeLibrary(hmod);
}

In the preceding code snippet, the DC_COLORDEVICE flag tells "DrvDeviceCapabillites" to return a 1 if the printer supports color, or a 0 if it does not.

To Use

Download the .zip file. It contains the following function:

int CheckForColorPrinter(CString printer)

Include the function in your code and pass it the name of the printer. (You can obtain the name of the printer from CPrintDialog.) If the printer supports color, the function returns "1". If color is NOT supported, it returns "0".



Downloads

Comments

  • Mr

    Posted by Chris Mackay on 01/06/2014 01:42pm

    It is my opinion that dmColor is for telling the print handler how to handle the output and its value is never meant to distinguish a real B&W from a color printer. The HP LaserJet P2015, for example is a black toner only printer, but can handle color if it is converted to a grayscale; dmColor set to DMCOLOR_COLOR comes back as DMCOLOR_COLOR!!! Can anyone tell how to identify a Printer as providing only MonoChrome output (including GRAYSCALE) as opposed to one that can provide both MonoChromer AND Color? The information must be in the system somewhere, especially since it can be seen in Windows 7 Devices and Printers page when a device (such as Samsung CLX-3300) is selected. WMI Scripting might have the answer but it is hiding from me!

    Reply
  • Not recommended

    Posted by einman on 08/29/2004 01:37am

    There are a variety of problems with this:

    1. You should use the Win32 function DeviceCapabilities, not hack directly into the driver entry point. This breaks Win9x compatibility, which you might not care about, but it also may break future OS compatibility, which is a bad idea.

    This is a nice demonstration of how one could hack into a printer driver (and in fact we do things like this to test our own drivers), but it it completely unnecessary, since there is an OS function to do it.

    2. DC_COLORDEVICE is only supported in Windows 2000 and later, and because of that, drivers designed for NT4 or 9x won't return it. Worse yet, some color drivers don't fill it in correctly.

    The right way(s) to do it:

    DC_COLORDEVICE was intended for this purpose, but it wasn't added until Windows 2000, and isn't required for a color driver to function correctly, so some drivers don't implement it.

    You can find out if a driver is set to print color by calling GetDeviceCaps() on a printer DC and looking at PLANES and BITSPIXEL. Unless they're both 1, the device is color. This is the official way to do it. However, this will really tell you if the driver is currently set to print color. A color printer set to monochrome mode would appear like a monochrome printer. If that's fine, OK.

    If not, try checking DC_COLORDEVICE as well. Lastly, you could try calling DocumentProperties (DM_COPY) to get a DEVMODE, change dmColor to DMCOLOR_COLOR, and pass it back in for validation (DM_COPY|DM_MODIFY), and unless it comes back DMCOLOR_MONOCHROME, the printer is probably color.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • It's time high-level executives and IT compliance officers recognize and acknowledge the danger of malicious insiders, an increased attack surface and the potential for breaches caused by employee error or negligence. See why there is extra emphasis on insider threats.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds