Search code examples
c++cwindows-7comlan

Controlling & Logging Printer Activities in Windows Operating System


We have few printers connected in the network (LAN) setup with no domain controller. The printers are given specific IP addresses. I wish to log all the printer activities to a database (or file-system). Also I want to control the printers, for example, if any user (from a IP address) wishes to print in landscape but one my printers is configured only for printing in portrait, the printer should reject the print. Another example is that if a user has exceeded the print limit (number of pages), the printer should not print the next page.

I have no idea of achieving this. Kindly give your valuable suggestions. Code snippets, ideas are most welcome.


Solution

  • Please check out the Print Spooler API Functions over at MSDN: http://msdn.microsoft.com/en-us/library/dd162861(v=VS.85).aspx

    How To Call Win32 Spooler Enumeration APIs Properly: http://support.microsoft.com/kb/158828

    How to get the status of a printer and a print job: http://support.microsoft.com/kb/160129

    Sample Code:

     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))
               {
                   free( pJobs );
                   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))
                       {
                           free( pJobs );
                           return TRUE;
                       }
                   }
               }
    
               /*
                *  No error condition.
                */ 
               free( pJobs );
               return FALSE;
    
           }