HOWTO: Get the Status of a Printer and a Print JobID: Q160129
|
The status of printers and print jobs are updated by the Win32 Spooler during the despool of a print job. At all other times, when that printer is not despooling and reports no state information, the printer is considered to be ready and idle.
As referred to by the Win32 API, a "printer" is comprised of the printer
driver, the print queue, and the input/output path to the physical printer.
The operating system treats a physical printer as merely the destination of
a print job generated by and passed through a system "Printer," referred to
in the rest of this article as a Printer.
The most visible part of a Printer is a print queue. It is managed by the
Print Manager or the Printer folders in the Windows 95-style user
interfaces. The printer driver is the interface to the Printer that is used
by applications to create print jobs via printer DCs. The I/O path for a
Printer consists of several layers of system code culminating with a port
monitor.
The port monitor is the interface to the physical printer at the down-
stream end of a system Printer and is responsible for transferring the data
of a print job across whatever connection exists to the physical printer.
In the case of bi-directional printers, the port monitor would be
responsible for transferring data to and from the physical printer. This
connection, and the physical printer, are where errors occur. It is the job
of the port monitor to report those errors.
The Spooler does not query for the state of a physical printer to which a
Printer is connected. Instead, the state of a physical printer determines
the success of a print job at the time it is despooled over the port
monitor. If some error occurs in this process, the error is reported by the
port monitor and recorded in a print job's status information. The Spooler,
in turn, propagates reasonable error information to the Printer Queue.
Consequently, a system Printer reports no status when the Printer queue is
empty. In this state, the Printer is assumed ready to accept print jobs.
This is a valid assumption even if the physical printer is in an error
state such as off-line. The operating system considers the Printer ready to
accept print jobs even if, for some reason, it cannot complete delivery to
the physical printer. Such a circumstance is considered an error state in
the operating system that must be addressed by the user. It is not
considered an error reportable to the application that is allowed to
complete the spooling of the print job successfully.
BOOL GetJobs(HANDLE hPrinter, /* Handle to the printer. */
JOB_INFO_2 **ppJobInfo, /* Pointer to be filled. */
int *pcJobs, /* Count of jobs filled. */
DWORD *pStatus) /* Print Queue status. */
{
DWORD cByteNeeded,
nReturned,
cByteUsed;
JOB_INFO_2 *pJobStorage = NULL;
PRINTER_INFO_2 *pPrinterInfo = NULL;
/* Get the buffer size needed. */
if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
}
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
if (!(pPrinterInfo))
/* Failure to allocate memory. */
return FALSE;
/* Get the printer information. */
if (!GetPrinter(hPrinter,
2,
(LPSTR)pPrinterInfo,
cByteNeeded,
&cByteUsed))
{
/* Failure to access the printer. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
/* Get job storage space. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
NULL,
0,
(LPDWORD)&cByteNeeded,
(LPDWORD)&nReturned))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
}
pJobStorage = (JOB_INFO_2 *)malloc(cByteNeeded);
if (!pJobStorage)
{
/* Failure to allocate Job storage space. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
ZeroMemory(pJobStorage, cByteNeeded);
/* Get the list of jobs. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
(LPBYTE)pJobStorage,
cByteNeeded,
(LPDWORD)&cByteUsed,
(LPDWORD)&nReturned))
{
free(pPrinterInfo);
free(pJobStorage);
pJobStorage = NULL;
pPrinterInfo = NULL;
return FALSE;
}
/*
* Return the information.
*/
*pcJobs = nReturned;
*pStatus = pPrinterInfo->Status;
*ppJobInfo = pJobStorage;
free(pPrinterInfo);
return TRUE;
}
BOOL IsPrinterError(HANDLE hPrinter)
{
JOB_INFO_2 *pJobs;
int cJobs,
i;
DWORD dwPrinterStatus;
/*
* Get the state information for the Printer Queue and
* the jobs in the Printer Queue.
*/
if (!GetJobs(hPrinter, &pJobs, &cJobs, &dwPrinterStatus))
return FALSE;
/*
* If the Printer reports an error, believe it.
*/
if (dwPrinterStatus &
(PRINTER_STATUS_ERROR |
PRINTER_STATUS_PAPER_JAM |
PRINTER_STATUS_PAPER_OUT |
PRINTER_STATUS_PAPER_PROBLEM |
PRINTER_STATUS_OUTPUT_BIN_FULL |
PRINTER_STATUS_NOT_AVAILABLE |
PRINTER_STATUS_NO_TONER |
PRINTER_STATUS_OUT_OF_MEMORY |
PRINTER_STATUS_OFFLINE |
PRINTER_STATUS_DOOR_OPEN))
{
return TRUE;
}
/*
* Find the Job in the Queue that is printing.
*/
for (i=0; i < cJobs; i++)
{
if (pJobs[i].Status & JOB_STATUS_PRINTING)
{
/*
* If the job is in an error state,
* report an error for the printer.
* Code could be inserted here to
* attempt an interpretation of the
* pStatus member as well.
*/
if (pJobs[i].Status &
(JOB_STATUS_ERROR |
JOB_STATUS_OFFLINE |
JOB_STATUS_PAPEROUT |
JOB_STATUS_BLOCKED_DEVQ))
{
return TRUE;
}
}
}
/*
* No error condition.
*/
return FALSE;
}
For additional information about general instructions on calling Win32 Spooler functions, please see the following article in the Microsoft Knowledge Base:
Q158828 How To Call Win32 Spooler Enumeration APIs Properly
Additional query words: GdiSpool
Keywords : kbNTOS351 kbNTOS400 kbSDKWin32 kbWinOS95 kbDSupport
Version : winnt:3.51,4.0
Platform : winnt
Issue type : kbhowto
Last Reviewed: June 30, 1999