?
Solved

Win95 Printer status polling

Posted on 1999-11-12
11
Medium Priority
?
434 Views
Last Modified: 2011-09-20
I am looking for a true "C" Wizard to answer, with(hopefully) source code examples.

I am looking for a "C"(NO MFC Stuff)  programming that polls a printer that Windows 9x has connected to it and it is its defaulted printer.  The polling routines should do:
   1) polling for printer status
   2) Number of print jobs that are awaiting to be printed.
   3) And cancel any awaiting print jobs.

These routines should work thru the Windows 9x evironment and be device driver independent.   I was supposely told that it could be done via MS's DDK package - which I know nothing about.

 Can this be done?  And help me out please.

  Thanks!!!

  Midnight Express

  RSVP Please
0
Comment
Question by:midnightexpress
  • 6
  • 4
11 Comments
 
LVL 14

Expert Comment

by:mcrider
ID: 2269113
midnightexpress,

Please go to http://www.experts-exchange.com/jsp/qShow.jsp?ta=commspt&qid=10243332 
as soon as you read this...


Cheers!
0
 

Author Comment

by:midnightexpress
ID: 2274049
doing as linda and ryanvs has recommeded.
0
 
LVL 2

Expert Comment

by:ryanvs
ID: 2274112
I'm a little busy at the moment, but I will post my file later tonight.  I'm glad we can finally solve this mishap!  Thanks!
0
SMB Security Just Got a Layer Stronger

WatchGuard acquires Percipient Networks to extend protection to the DNS layer, further increasing the value of Total Security Suite.  Learn more about what this means for you and how you can improve your security with WatchGuard today!

 

Author Comment

by:midnightexpress
ID: 2274646
Yes, Thanks, Till then.

 Midnightexpress
0
 

Author Comment

by:midnightexpress
ID: 2292859
Hey RYANVS,
                        Dec 18th, 1999

It's been a Long time, and haven't heard a word from you in a while.  What is the status?  Is it lookin' good?

 Midnightexpress

0
 
LVL 2

Expert Comment

by:ryanvs
ID: 2296578
Hi Midnightexpress,

I apologize for not writing sooner, but it has been extremely busy at work.  I do have a solution that works as far as I can tell.  You can get the printer status, the job count, and delete individual jobs on 95/98/NT.  I tested the delete all jobs on NT and it said permission denied even though I had full admin rights, so that was strange but apart from that it looks good.  So I was documenting the file and adding more comments, except I had to stop to try and meet a deadline for work.

Unfortunately, I had to rush and try to get everything ready for vacation (which I'm on right now!) and I was so busy that I never got a chance to post the file.  And since I don't have the file with me I can't post it until Jan. 3 or 4.  Sorry!

Well I hope you have a good time during the holidays and I will post the file when I get back.  Thanks!
0
 

Author Comment

by:midnightexpress
ID: 2296772
Okay,  
  I understand that you have a life of your own and that I will have to be patience and mind my manners.  So when you get back from your well deserved vacation,  drop me an email when you are ready - and we'll work things out then.  As for me, I will be working(it seems like working is an occupational hazard).

 Midnightexpress.
0
 

Author Comment

by:midnightexpress
ID: 2336719
Hello, Ryanvs:

 How was the Vacaction? Kinda of relaxing? Hope all went well.

  Thanks,

  Midnightexpress
0
 
LVL 2

Accepted Solution

by:
ryanvs earned 800 total points
ID: 2343701
Hi Midnightexpress,

Thank you for your patience!  Vacation was nice, but as usual not long enough. :)

I have the files working as far as I can tell, but I want to debug them a little more tomorrow.  In the meantime, here is what I have so that you can start using them.

// -----------------------------------------------------------------------
// File         : PrinterPoll.h
// Description  : Declaration of print poll functions, including getting
//              : the default printer, getting the print job count,
//              : deleting a print job, deleting all print jobs, and more.
// Author       : Ryan Van Slooten
// -----------------------------------------------------------------------


#if !defined(PRINTERPOLL_H__INCLUDED_)
#define PRINTERPOLL_H__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <winspool.h>
#include <tchar.h>


typedef struct tagSTATUSLOOKUP
{
  DWORD           dwStatus;       // Status Identifier
  LPTSTR          szName;         // Name of Status Identifier
  LPTSTR          szStatus;       // Status Message
  LPTSTR          szDesc;         // Status Description
} STATUSLOOKUP;


typedef struct tagPRINTERPOLL
{
  HANDLE          hPrinter;       // Handle to Printer
  TCHAR          *szName;         // Printer Name
  TCHAR          *szDevice;       // Printer Device
  TCHAR          *szPort;         // Printer Port
  PRINTER_INFO_2 *pPrintInfo2;    // Printer Information, Level 2
  DWORD           dwPI2Bytes;     // Number of Bytes for Printer Info 2
  JOB_INFO_1     *pJobInfo1;      // Print Job Information, Level 1
  DWORD           dwJI1Bytes;     // Number of Bytes for Job Info 1
  DWORD           dwJobCount;     // Count of Print Jobs
} PRINTERPOLL, *LPPRINTERPOLL;


// Function prototypes
BOOL IsWindowsNT();
BOOL GetDefaultPrinterName(LPPRINTERPOLL pPrinterPoll);
BOOL GetPrinterStatus(LPPRINTERPOLL pPrinterPoll);
int  GetPrintJobCount(LPPRINTERPOLL pPrinterPoll);
BOOL GetPrintJobInfo(LPPRINTERPOLL pPrinterPoll, DWORD JobId);
BOOL GetPrintAllJobsInfo(LPPRINTERPOLL pPrinterPoll);
BOOL DeletePrintJob(LPPRINTERPOLL pPrinterPoll, DWORD JobId);
BOOL DeleteAllPrintJobs(LPPRINTERPOLL pPrinterPoll);
void CleanupPrinterPoll(LPPRINTERPOLL pPrinterPoll);


#endif // !defined(PRINTERPOLL_H__INCLUDED_)




// -----------------------------------------------------------------------
// File         : PrinterPoll.c
// Description  : Definition/implementation of print poll functions,
//              : including getting the default printer, getting the print
//              : job count, deleting a print job, deleting all print jobs,
//              : and more.
// Author       : Ryan Van Slooten
// -----------------------------------------------------------------------

#include "Main.h"
#include <winspool.h>
#include "PrinterPoll.h"


// =======================================================================
// Variable       : slPrinterStatusCodes
// Description    : Lookup codes for PRINTER_INFO_2.Status
// =======================================================================
static STATUSLOOKUP slPrinterStatusCodes[] = {
    PRINTER_STATUS_BUSY             , _T("PRINTER_STATUS_BUSY")             , _T("Printer Busy")              , _T("The printer is busy.")
   ,PRINTER_STATUS_DOOR_OPEN        , _T("PRINTER_STATUS_DOOR_OPEN")        , _T("Printer Door Open")         , _T("The printer door is open.")
   ,PRINTER_STATUS_ERROR            , _T("PRINTER_STATUS_ERROR")            , _T("Printer Error")             , _T("The printer is in an error state.")
   ,PRINTER_STATUS_INITIALIZING     , _T("PRINTER_STATUS_INITIALIZING")     , _T("Printer Initializing")      , _T("The printer is initializing.")
   ,PRINTER_STATUS_IO_ACTIVE        , _T("PRINTER_STATUS_IO_ACTIVE")        , _T("Printer I/O Active")        , _T("The printer is in an active input/output state.")
   ,PRINTER_STATUS_MANUAL_FEED      , _T("PRINTER_STATUS_MANUAL_FEED")      , _T("Printer Manual Feed")       , _T("The printer is in a manual feed state.")
   ,PRINTER_STATUS_NO_TONER         , _T("PRINTER_STATUS_NO_TONER")         , _T("Printer No Toner")          , _T("The printer is out of toner.")
   ,PRINTER_STATUS_NOT_AVAILABLE    , _T("PRINTER_STATUS_NOT_AVAILABLE")    , _T("Printer Not Available")     , _T("The printer is not available for printing.")
   ,PRINTER_STATUS_OFFLINE          , _T("PRINTER_STATUS_OFFLINE")          , _T("Printer Offline")           , _T("The printer is offline.")
   ,PRINTER_STATUS_OUT_OF_MEMORY    , _T("PRINTER_STATUS_OUT_OF_MEMORY")    , _T("Printer Out of Memory")     , _T("The printer has run out of memory.")
   ,PRINTER_STATUS_OUTPUT_BIN_FULL  , _T("PRINTER_STATUS_OUTPUT_BIN_FULL")  , _T("Printer Output Bin Full")   , _T("The printer's output bin is full.")
   ,PRINTER_STATUS_PAGE_PUNT        , _T("PRINTER_STATUS_PAGE_PUNT")        , _T("Printer Page Punt")         , _T("The printer cannot print the current page.\n\n"
                                                                                                                   "Windows 95: Indicates the page is being \"punted\" "
                                                                                                                   "(that is, not printed) because it is too complex for "
                                                                                                                   "the printer to print.")
   ,PRINTER_STATUS_PAPER_JAM        , _T("PRINTER_STATUS_PAPER_JAM")        , _T("Printer Paper Jam")         , _T("Paper is jammed in the printer.")
   ,PRINTER_STATUS_PAPER_OUT        , _T("PRINTER_STATUS_PAPER_OUT")        , _T("Printer Paper Out")         , _T("The printer is out of paper.")
   ,PRINTER_STATUS_PAPER_PROBLEM    , _T("PRINTER_STATUS_PAPER_PROBLEM")    , _T("Printer Paper Problem")     , _T("The printer has a paper problem.")
   ,PRINTER_STATUS_PAUSED           , _T("PRINTER_STATUS_PAUSED")           , _T("Printer Paused")            , _T("The printer is paused.")
   ,PRINTER_STATUS_PENDING_DELETION , _T("PRINTER_STATUS_PENDING_DELETION") , _T("Printer Pending Deletion")  , _T("The printer is deleting a print job.")
   ,PRINTER_STATUS_POWER_SAVE       , _T("PRINTER_STATUS_POWER_SAVE")       , _T("Printer Power Save")        , _T("The printer is in power-save mode.")
   ,PRINTER_STATUS_PRINTING         , _T("PRINTER_STATUS_PRINTING")         , _T("Printer Printing")          , _T("The printer is printing.")
   ,PRINTER_STATUS_PROCESSING       , _T("PRINTER_STATUS_PROCESSING")       , _T("Printer Processing")        , _T("The printer is processing a print job.")
   ,PRINTER_STATUS_SERVER_UNKNOWN   , _T("PRINTER_STATUS_SERVER_UNKNOWN")   , _T("Printer Server Unknown")    , _T("The printer server status is unknown.")  
   ,PRINTER_STATUS_TONER_LOW        , _T("PRINTER_STATUS_TONER_LOW")        , _T("Printer Toner Low")         , _T("The printer is low on toner.")
   ,PRINTER_STATUS_USER_INTERVENTION, _T("PRINTER_STATUS_USER_INTERVENTION"), _T("Printer User Intervention") , _T("The user needs to do something to the printer.")
   ,PRINTER_STATUS_WAITING          , _T("PRINTER_STATUS_WAITING")          , _T("Printer Waiting")           , _T("The printer is waiting.")
   ,PRINTER_STATUS_WARMING_UP       , _T("PRINTER_STATUS_WARMING_UP")       , _T("Printer Warming Up")        , _T("The printer is warming up.")
};
#define PRINTERSTATUSLOOKUP_SIZE    (sizeof(slPrinterStatusCodes) / sizeof(slPrinterStatusCodes[0]))


// =======================================================================
// Variable       : slJobStatusCodes
// Description    : Lookup codes for JOB_INFO_1.Status
// =======================================================================
static STATUSLOOKUP slJobStatusCodes[] = {
    JOB_STATUS_DELETING           , _T("JOB_STATUS_DELETING")         , _T("Job Deleting")          , _T("The print job is being deleted.")
   ,JOB_STATUS_ERROR              , _T("JOB_STATUS_ERROR")            , _T("Job Error")             , _T("The print job has an error status.")
   ,JOB_STATUS_OFFLINE            , _T("JOB_STATUS_OFFLINE")          , _T("Job Offline")           , _T("The print job is offline.")
   ,JOB_STATUS_PAPEROUT           , _T("JOB_STATUS_PAPEROUT")         , _T("Job Paper Out")         , _T("The printer is out of paper.")
   ,JOB_STATUS_PAUSED             , _T("JOB_STATUS_PAUSED")           , _T("Job Paused")            , _T("The print job is paused.")
   ,JOB_STATUS_PRINTED            , _T("JOB_STATUS_PRINTED")          , _T("Job Printed")           , _T("The print job has been printed.")
   ,JOB_STATUS_PRINTING           , _T("JOB_STATUS_PRINTING")         , _T("Job Printing")          , _T("The print job is printing.")
   ,JOB_STATUS_SPOOLING           , _T("JOB_STATUS_SPOOLING")         , _T("Job Spooling")          , _T("The print job is being spooled.")
   ,JOB_STATUS_DELETED            , _T("JOB_STATUS_DELETED")          , _T("Job Deleted")           , _T("The print job has been deleted.")
   ,JOB_STATUS_BLOCKED_DEVQ       , _T("JOB_STATUS_BLOCKED_DEVQ")     , _T("Job Blocked")           , _T("The print job is blocked by the queue.")
   ,JOB_STATUS_USER_INTERVENTION  , _T("JOB_STATUS_USER_INTERVENTION"), _T("Job User Intervention") , _T("The print job requires user intervention.")
   ,JOB_STATUS_RESTART            , _T("JOB_STATUS_RESTART")          , _T("Job Restart")           , _T("The print job is being restarted.")

};
#define JOBSTATUSLOOKUP_SIZE    (sizeof(slJobStatusCodes) / sizeof(slJobStatusCodes[0]))


// =======================================================================
// Function name  : MsgBoxLastError
// Description    : Displays a message box with the formatted windows
//                : error message
// Return type    : void
// Parameters     : HWND hwnd               [in] Handle to Parent Window
// =======================================================================
void MsgBoxLastError(HWND hwnd)
{
  TCHAR szBuffer[256];
  DWORD dwError;
  int   nLen;

  dwError = GetLastError();
  if ( dwError )
  {
    nLen = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM
                        | FORMAT_MESSAGE_IGNORE_INSERTS,  // source and processing options
                        NULL,                             // pointer to  message source
                        dwError,                          // requested message identifier
                        0,                                // language identifier for requested message
                        szBuffer,                         // pointer to message buffer
                        256,                              // maximum size of message buffer
                        NULL                              // pointer to array of message inserts
    );

    MessageBox(hwnd, szBuffer, NULL, MB_OK);
  }
}

// =======================================================================
// Function name  : IsWindowsNT
// Description    : Check system version information for Windows NT
// Return type    : BOOL
// Parameters     : void
// =======================================================================
BOOL IsWindowsNT()
{
  OSVERSIONINFO osvi;
  ZeroMemory(&osvi, sizeof(osvi));
  osvi.dwOSVersionInfoSize = sizeof(osvi);
  if ( GetVersionEx(&osvi) )
  {
    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
      return TRUE;
  }
  return FALSE;
}


// =======================================================================
// Function name  : GetDefaultPrinterName
// Description    : Retrieves the default printer from Windows.  If the
//                : computer is not running NT, then it uses EnumPrinters
//                : to find the default printer.  If that function fails,
//                : or the computer is NT, then it checks the registry
//                : for the default printer
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
BOOL GetDefaultPrinterName(LPPRINTERPOLL pPrinterPoll)
{
  TCHAR   szName[256];
  TCHAR  *szDevice,
         *szDriver,
         *szOutput;
  DWORD   dwBytes;

  // Variables for EnumPrinters
  LPPRINTER_INFO_5 ppinfo5;           // Default printer struct memory
  DWORD   dwNeeded,                   // Needed bytes for ppinfo5
          dwReturned;                 // Number of printers enumerated
  BOOL    bResult = FALSE;

  // Windows 95/98: Use EnumPrinters
  if ( !IsWindowsNT() )
  {
    // Get needed size of printer information memory
    EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, NULL, 0, &dwNeeded, &dwReturned);

    // Allocate memory for default printer
    ppinfo5 = (LPPRINTER_INFO_5) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);

    // Fill the default printer information
    if ( ppinfo5 )
      bResult = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, (LPBYTE) ppinfo5, dwNeeded, &dwNeeded, &dwReturned);

    bResult = bResult && (dwReturned > 0);
    if ( bResult
      && ppinfo5->pPrinterName
      && ppinfo5->pPortName )
    {
      // Copy Printer Name
      dwBytes = _tcsclen(ppinfo5->pPrinterName) + sizeof(TCHAR);
      pPrinterPoll->szName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
      if ( !pPrinterPoll->szName ) return FALSE;
      _tcscpy(pPrinterPoll->szName, ppinfo5->pPrinterName);

      // Copy Port Name
      dwBytes = _tcsclen(ppinfo5->pPortName) + sizeof(TCHAR);
      pPrinterPoll->szPort = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
      if ( !pPrinterPoll->szPort ) return FALSE;
      _tcscpy(pPrinterPoll->szPort, ppinfo5->pPortName);
    }

    if ( ppinfo5 )
      HeapFree(GetProcessHeap(), 0, ppinfo5);
  }

  if ( !bResult )
  {
    // Read Default Printer from Registry/.INI File
    ZeroMemory(szName, sizeof(szName));
    GetProfileString(_T("windows"),  // Section Name,
                     _T("device"),   // Key Name,
                     _T(""),         // Returned: Default Printer
                     szName,         // Default Value
                     256);

    // The returned string contains the name of the
    // default printer, the name of the printer
    // DRV file, and the port to which the
    // printer is attached.

    // Use standard C runtime function: strtok
    // to parse the string.
    if ( NULL != (szDevice = _tcstok(szName, _T(",")))
      && NULL != (szDriver = _tcstok(NULL,   _T(",")))
      && NULL != (szOutput = _tcstok(NULL,   _T(","))))
    {
      // Copy Printer Name
      dwBytes = _tcsclen(szDevice) + sizeof(TCHAR);
      pPrinterPoll->szName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
      if ( !pPrinterPoll->szName ) return FALSE;
      _tcscpy(pPrinterPoll->szName, szDevice);

      // Copy Driver Name
      dwBytes = _tcsclen(szDriver) + sizeof(TCHAR);
      pPrinterPoll->szDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
      if ( !pPrinterPoll->szDevice) return FALSE;
      _tcscpy(pPrinterPoll->szDevice, szDriver);

      // Copy Port Name
      dwBytes = _tcsclen(szOutput) + sizeof(TCHAR);
      pPrinterPoll->szPort = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
      if ( !pPrinterPoll->szPort ) return FALSE;
      _tcscpy(pPrinterPoll->szPort, szOutput);

      bResult = TRUE;
    }
    else
      bResult = FALSE;
  }

  return bResult;
}


// =======================================================================
// Function name  : GetPrinterStatus
// Description    : Refreshes current print jobs.  If the printer is not
//                : already open, it initializes and opens the printer
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
BOOL GetPrinterStatus(LPPRINTERPOLL pPrinterPoll)
{
  LPBYTE          pbyBuffer = NULL;
  DWORD           dwNeeded,
                  dwBuffer;
  BOOL            bResult;

  // Check for valid Print Struct and Memory
  if ( !pPrinterPoll || !pPrinterPoll->szName)
    return FALSE;

  // Open Default Printer, if it isn't already open
  if ( !pPrinterPoll->hPrinter )
  {
    bResult = OpenPrinter(pPrinterPoll->szName, &pPrinterPoll->hPrinter, NULL);
    if ( !bResult || pPrinterPoll->hPrinter == NULL)
      return FALSE;
  }

  // Get Required Bytes for Printer Status Info
  bResult = GetPrinter(pPrinterPoll->hPrinter, // Printer Handle
                    2,                      // Level Info
                    NULL,                   // Printer Info
                    0,                      // Buffer Size
                   &dwNeeded);              // Bytes Needed

  if (dwNeeded == 0)
    return FALSE;

  // Check if Buffer Size has already been allocated and if it is large enough
  if (pPrinterPoll->dwPI2Bytes < dwNeeded)
  {
    // Free Buffer Memory
    if ( pPrinterPoll->pPrintInfo2 )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->pPrintInfo2);
      pPrinterPoll->pPrintInfo2 = NULL;
      pPrinterPoll->dwPI2Bytes = 0;
    }

    // Allocate Buffer Memory
    pbyBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
    if (pbyBuffer == NULL)
      return FALSE;

    // Save Buffer and Byte Count
    dwBuffer = dwNeeded;
    pPrinterPoll->dwPI2Bytes  = dwNeeded;
    pPrinterPoll->pPrintInfo2 = (PRINTER_INFO_2 *) pbyBuffer;
  }
  else
  {
    pbyBuffer = (LPBYTE) pPrinterPoll->pPrintInfo2;
    dwBuffer  = pPrinterPoll->dwPI2Bytes;
  }

  // Get Default Printer Status
  bResult = GetPrinter(pPrinterPoll->hPrinter, // Printer Handle
                    2,                      // Level Info
                    pbyBuffer,              // Printer Info Buffer
                    dwBuffer,               // Buffer Size
                   &dwNeeded);              // Bytes Needed

  // Printer Status Info is in pi2
  //   pi2.Status   -- Printer Status
  //   pi2.cJobs    -- Count of Jobs
  if ( bResult )
  {
    // Do something on success here...
    pPrinterPoll->dwJobCount = pPrinterPoll->pPrintInfo2->cJobs;
  }

  return bResult;
}

// =======================================================================
// Function name  : GetPrintJobCount
// Description    : Returns the number of print jobs.  This refreshes the
//                : printer status each time the function is called.
// Return type    : int                                    Job Count
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
int  GetPrintJobCount(LPPRINTERPOLL pPrinterPoll)
{
  int nResult;

  nResult = GetPrinterStatus(pPrinterPoll);
  if (nResult != 0)
  {
    pPrinterPoll->dwJobCount = pPrinterPoll->pPrintInfo2->cJobs;
    return pPrinterPoll->pPrintInfo2->cJobs;
  }

  // Call Failed
  return 0;
}

// =======================================================================
// Function name  : GetPrintJobInfo
// Description    : Retrieves the job information for a single print
//                : document.
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
//                : DWORD         JobId          [in]     Print Job Id
// =======================================================================
BOOL GetPrintJobInfo(LPPRINTERPOLL pPrinterPoll, DWORD JobId)
{
  LPBYTE pbyBuffer;
  DWORD  dwNeeded,
         dwBuffer;
  BOOL   bResult;

  // Query required byte size
  bResult = GetJob(
    pPrinterPoll->hPrinter,   // handle to printer
    JobId,                    // job identifier
    1,                        // information level
    NULL,                     // array of jobs
    0,                        // bytes in array
    &dwNeeded                 // bytes received or required
  );

  // Check required byte size
  if (pPrinterPoll->dwJI1Bytes < dwNeeded)
  {
    // Deallocate Buffer Memory
    if ( pPrinterPoll->pJobInfo1 )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->pJobInfo1);
      pPrinterPoll->pJobInfo1 = NULL;
      pPrinterPoll->dwJI1Bytes = 0;
    }

    // Allocate Buffer Memory
    pbyBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
    if (pbyBuffer == NULL)
      return FALSE;

    pPrinterPoll->dwJI1Bytes = dwBuffer = dwNeeded;
    pPrinterPoll->pJobInfo1 = (JOB_INFO_1 *) pbyBuffer;
  }
  else
  {
    pbyBuffer = (LPBYTE) pPrinterPoll->pJobInfo1;
    dwBuffer  = pPrinterPoll->dwJI1Bytes;
  }

  // Get Print Job Information
  bResult = GetJob(
    pPrinterPoll->hPrinter,   // handle to printer
    JobId,                    // job identifier
    1,                        // information level
    pbyBuffer,                // array of jobs
    dwBuffer,                 // bytes in array
    &dwNeeded                 // bytes received or required
  );

  return bResult;
}

// =======================================================================
// Function name  : GetPrintAllJobsInfo
// Description    : Retrieves the job information for all print
//                : documents for a specific printer.
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
BOOL GetPrintAllJobsInfo(LPPRINTERPOLL pPrinterPoll)
{
  LPBYTE pbyBuffer;
  DWORD  dwNeeded,
         dwBuffer,
         dwJobCount;
  BOOL   bResult;
  int    cJobs;

  // Printer Must be Open first, or call GetDefaultPrinter() and GetPrinterStatus;
  if ( !pPrinterPoll->hPrinter )
    return FALSE;

  cJobs = GetPrintJobCount(pPrinterPoll);

  // Get Required Byte Usage for All Jobs for Current Printer
  bResult = EnumJobs(
    pPrinterPoll->hPrinter,     // handle to printer object
    0,                          // index of first job
    cJobs,                      // number of jobs to enumerate
    1,                          // information level
    NULL,                       // job information buffer
    0,                          // size of job information buffer
    &dwNeeded,                  // bytes received or required
    &dwJobCount                 // number of jobs received
  );

  // Error:  No jobs/bytes needed
  if (dwNeeded == 0)
    return FALSE;

  if (pPrinterPoll->dwJI1Bytes < dwNeeded)
  {
    if ( pPrinterPoll->pJobInfo1 )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->pJobInfo1);
      pPrinterPoll->pJobInfo1 = NULL;
      pPrinterPoll->dwJI1Bytes = 0;
    }

    // Allocate Buffer Memory
    pbyBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
    if (pbyBuffer == NULL)
      return FALSE;

    pPrinterPoll->dwJI1Bytes = dwBuffer = dwNeeded;
    pPrinterPoll->pJobInfo1 = (JOB_INFO_1 *) pbyBuffer;
  }
  else
  {
    pbyBuffer = (LPBYTE) pPrinterPoll->pJobInfo1;
    dwBuffer  = pPrinterPoll->dwJI1Bytes;
  }

  // Get Required Byte Usage for All Jobs for Current Printer
  bResult = EnumJobs(
    pPrinterPoll->hPrinter,     // handle to printer object
    0,                          // index of first job
    cJobs,                      // number of jobs to enumerate
    1,                          // information level
    pbyBuffer,                  // job information buffer
    dwBuffer,                   // size of job information buffer
    &dwNeeded,                  // bytes received or required
    &dwJobCount                 // number of jobs received
  );

  // Update count of jobs enumerated
  pPrinterPoll->dwJobCount = dwJobCount;

  return bResult;
}


// =======================================================================
// Function name  : DeletePrintJob
// Description    : Deletes a specific print job from a printer.
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
//                : DWORD         JobId          [in]     Print Job Id
// =======================================================================
BOOL DeletePrintJob(LPPRINTERPOLL pPrinterPoll, DWORD JobId)
{
  DWORD dwCommand;
  BOOL bResult;

  // Notice:
  //    In WindowsNT, you must have permission to delete print jobs.
  //    If you don't have permission, this function will have no effect.
  if ( IsWindowsNT() )
    dwCommand = JOB_CONTROL_DELETE;
  else
    dwCommand = JOB_CONTROL_CANCEL;

  bResult = SetJob(
    pPrinterPoll->hPrinter,   // handle to printer object
    JobId,                    // print job identifier
    0,                        // information level
    NULL,                     // job information buffer
    dwCommand                 // job command value
  );

  if (!bResult)
    MsgBoxLastError(NULL);

  return bResult;
}

// =======================================================================
// Function name  : DeleteAllPrintJobs
// Description    : Attempts to delete all print jobs.  If the mass delete
//                : code (PRINTER_CONTROL_PURGE) fails, the function
//                : attempts to delete the print jobs individually.
// Return type    : BOOL (0 = Failure, Non-Zero = Success)
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
BOOL DeleteAllPrintJobs(LPPRINTERPOLL pPrinterPoll)
{
  BOOL bResult = FALSE;
  int i;

  // Printer Must be Open first, or call GetDefaultPrinter() and GetPrinterStatus;
  if (pPrinterPoll->hPrinter)
  {
    // Level   :  0
    // pPrinter:  NULL
    // Command :  PRINTER_CONTROL_PURGE  (Deletes all print jobs in the printer.)

    bResult = SetPrinter(
      pPrinterPoll->hPrinter,   // handle to printer object
      0,                        // information level
      NULL,                     // printer data buffer
      PRINTER_CONTROL_PURGE     // printer-state command
    );

    // Option 1:  Show message box with error
    //if (!bResult)
    //  MsgBoxLastError(NULL);

    // Option 2:  Delete each job individually
    for (i = 0; i < (int) pPrinterPoll->dwJobCount; ++i)
    {
      bResult = DeletePrintJob(pPrinterPoll, pPrinterPoll->pJobInfo1[i].JobId);

      // Option 1:  Show message box with error
      //if (!bResult)
      //  MsgBoxLastError(NULL);

      // Option 2:  Ignore error and continue processing
    }
  }

  return bResult;
}

// =======================================================================
// Function name  : CleanupPrinterPoll
// Description    : Deallocates memory associated with PRINTERPOLL variable
// Return type    : void
// Parameters     : LPPRINTERPOLL pPrinterPoll   [in/out]
// =======================================================================
void CleanupPrinterPoll(LPPRINTERPOLL pPrinterPoll)
{
  if ( pPrinterPoll )
  {
    if ( pPrinterPoll->hPrinter )
    {
      ClosePrinter(pPrinterPoll->hPrinter);
      pPrinterPoll->hPrinter = NULL;
    }

    if ( pPrinterPoll->szName )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->szName);
      pPrinterPoll->szName = NULL;
    }
    if ( pPrinterPoll->szDevice )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->szDevice);
      pPrinterPoll->szDevice = NULL;
    }
    if ( pPrinterPoll->szPort )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->szPort);
      pPrinterPoll->szPort = NULL;
    }
    if ( pPrinterPoll->pPrintInfo2 )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->pPrintInfo2);
      pPrinterPoll->pPrintInfo2 = NULL;
      pPrinterPoll->dwPI2Bytes = 0;
    }
    if ( pPrinterPoll->pJobInfo1 )
    {
      HeapFree(GetProcessHeap(), 0, pPrinterPoll->pJobInfo1);
      pPrinterPoll->pJobInfo1 = NULL;
      pPrinterPoll->dwJI1Bytes = 0;
    }
  }
}

// =======================================================================
// Function name  : GetPrinterStatusString
// Description    : Returns a string containing the printer status code
// Return type    : LPCTSTR                         Status Code String
// Parameters     : DWORD   dwStatus          [in]  Printer Status Code
// =======================================================================
LPCTSTR GetPrinterStatusString(DWORD dwStatus)
{
  int i;

  for (i = 0; i < PRINTERSTATUSLOOKUP_SIZE; ++i)
  {
    if (slPrinterStatusCodes[i].dwStatus == dwStatus)
      return slPrinterStatusCodes[i].szStatus;
  }

  return NULL;
}

// =======================================================================
// Function name  : GetPrintJobStatusString
// Description    : Returns a string containing the job status code
// Return type    : LPCTSTR                         Status Code String
// Parameters     : DWORD   dwStatus          [in]  Job Status Code
// =======================================================================
LPCTSTR GetPrintJobStatusString(DWORD dwStatus)
{
  int i;

  for (i = 0; i < JOBSTATUSLOOKUP_SIZE; ++i)
  {
    if (slJobStatusCodes[i].dwStatus == dwStatus)
      return slJobStatusCodes[i].szStatus;
  }

  return NULL;
}

0
 
LVL 2

Expert Comment

by:ryanvs
ID: 2343717
Here are some of the files I used in a project to test the program.

The project includes the following files:
  Header Files
    Main.h
    PrinterPoll.h
  Source Files
    Main.c
    PrinterPoll.c
  Resouce Files
    PrinterPoll.rc

And it had a menu that looked like this:
  Printer
    "Select &Printer", IDM_SELECTPRINTER
    --
    "&Delete Job", IDM_DELETEJOB
    "Purge &All Jobs", IDM_PURGEPRINTER
    --
    "&Refresh", IDM_REFRESHPRINTER
    --
    "E&xit", IDM_EXIT

You need to link to the following libraries:
  kernel32.lib
  user32.lib
  gdi32.lib
  shell32.lib
  winspool.lib   Print Library
  comctl32.lib   used ListView
  comdlg32.lib   Intended to use, but never finished

Good Luck!


// Main.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(MAIN_H__INCLUDED_)
#define MAIN_H__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN            // Exclude rarely-used stuff from Windows headers

#include <windows.h>
#include <tchar.h>


#endif // !defined(MAIN_H__INCLUDED_)




This is the resource file: PrinterPoll.rc

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_PRINTMENU MENU DISCARDABLE
BEGIN
    POPUP "Printer"
    BEGIN
        MENUITEM "Select &Printer",             IDM_SELECTPRINTER
        MENUITEM SEPARATOR
        MENUITEM "&Delete Job",                 IDM_DELETEJOB
        MENUITEM "Purge &All Jobs",             IDM_PURGEPRINTER
        MENUITEM SEPARATOR
        MENUITEM "&Refresh",                    IDM_REFRESHPRINTER
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDM_EXIT
    END
END


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED







// Main.c: Defines the entry point for the application.
//

#include "Main.h"
#include "Resource.h"
#include "PrinterPoll.h"
#include <commctrl.h>
#include <commdlg.h>


// Timer for periodically refreshing printer status
#define ID_TIMER    1


// Window Procedure Prototype
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL             CreatePrintView(HWND, HINSTANCE );
void             RefreshPrintItems();


// Global Variables
static PRINTERPOLL g_prntpoll;
static HWND        g_hwndPrintView;
static HINSTANCE   g_hInstance;


// Main Function
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
  static char           szAppName[] = "PrinterPoll";
  static char           szTitle[]   = "Printer Poll App";
  HWND                  hwnd;
  MSG                   msg;
  WNDCLASSEX            wndclass;
  INITCOMMONCONTROLSEX  iccex;

  // Initialize Printer List View
  g_hwndPrintView = NULL;

  // Initialize Common Controls: ListView
  iccex.dwSize  = sizeof(iccex);
  iccex.dwICC   = ICC_LISTVIEW_CLASSES;
  InitCommonControlsEx(&iccex);

  // Initialize Window Class
  ZeroMemory(&wndclass, sizeof(wndclass));
  wndclass.cbSize         = sizeof(wndclass);
  wndclass.style          = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc    = WndProc;
  wndclass.cbClsExtra     = 0;
  wndclass.cbWndExtra     = 0;
  wndclass.hInstance      = hInstance;
  wndclass.hIcon          = NULL;
  wndclass.hIconSm        = NULL;
  wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
  wndclass.lpszMenuName   = MAKEINTRESOURCE(IDR_PRINTMENU);
  wndclass.lpszClassName  = szAppName;

  // Save Global Instance
  g_hInstance = hInstance;

  // Create Window
  RegisterClassEx( &wndclass );
  hwnd = CreateWindow(szAppName,
                      szTitle,
                      WS_OVERLAPPEDWINDOW,
                      CW_USEDEFAULT, CW_USEDEFAULT,
                      CW_USEDEFAULT, CW_USEDEFAULT,
                      NULL,
                      NULL,
                      hInstance,
                      NULL
  );

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

// Window Procedure Function
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
  static BOOL bTryPrinter = FALSE;
  static int  nRetries    = 0;
  static int  cx, cy;

  static PRINTDLG pd;
  LPDEVNAMES  hDevNames;
  LPDEVMODE   hDevMode;
  DWORD       dwBytes;
  TCHAR      *szName;

  PAINTSTRUCT ps;
  HDC         hdc;


  HMENU       hMenu;
  LVITEM      lvi;
  int         nIndex;
  int         i;

  switch (iMsg)
  {
  case WM_COMMAND:
    hMenu = GetMenu(hwnd);
    switch ( LOWORD(wParam) )
    {
    case IDM_SELECTPRINTER:
      MessageBox(hwnd, _T("This does not work yet..."), _T("Printer Poll App"), MB_OK);
      break;

      ZeroMemory(&pd, sizeof(pd));
      pd.lStructSize = sizeof(pd);
      pd.hwndOwner   = hwnd;
      pd.Flags       = PD_PRINTSETUP;

      // Show Print Setup Dialog
      if ( PrintDlg(&pd) )
      {
        // Close current printer
        CleanupPrinterPoll(&g_prntpoll);

        // Copy Printer Name
        if ( !pd.hDevNames )
          return 0;

        hDevMode = (LPDEVMODE) pd.hDevMode;
        hDevNames = (LPDEVNAMES) pd.hDevNames;
        szName = (TCHAR *) (hDevNames + hDevNames->wDriverOffset);
        dwBytes = _tcsclen(szName) + sizeof(TCHAR);
        g_prntpoll.szName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytes);
        if ( !g_prntpoll.szName ) return FALSE;
        _tcscpy(g_prntpoll.szName, szName);

        GetPrinterStatus(&g_prntpoll);
        GetPrintAllJobsInfo(&g_prntpoll);
      }

      break;

    case IDM_DELETEJOB:
      // Delete Selected Print Job
      nIndex = ListView_GetNextItem(g_hwndPrintView, -1, LVNI_SELECTED);
      if (nIndex >= 0)
      {
        lvi.mask = LVIF_PARAM;
        lvi.iItem = nIndex;
        lvi.iSubItem = 0;
        ListView_GetItem(g_hwndPrintView, &lvi);
        for (i = 0; i < (int) g_prntpoll.dwJobCount; ++i)
        {
          if ((DWORD) lvi.lParam == g_prntpoll.pJobInfo1[i].JobId)
          {
            DeletePrintJob(&g_prntpoll, lvi.lParam);
            return 0;
          }
        }
      }
      return 0;

    case IDM_PURGEPRINTER:
      // Delete All Print Jobs
      DeleteAllPrintJobs(&g_prntpoll);
      return 0;

    case IDM_REFRESHPRINTER:
      ListView_DeleteAllItems(g_hwndPrintView);
      RefreshPrintItems();
      return 0;

    case IDM_EXIT:
      SendMessage(hwnd, WM_CLOSE, 0, 0L);
      return 0;
    }
    break;

  case WM_CREATE:
    CreatePrintView(hwnd, g_hInstance);

    ZeroMemory(&g_prntpoll, sizeof(g_prntpoll));
    GetDefaultPrinterName(&g_prntpoll);

    SetTimer(hwnd, ID_TIMER, 1000, NULL);
    return 0;

  case WM_PAINT:
    hdc = BeginPaint(hwnd, &ps);
    EndPaint(hwnd, &ps);
    return 0;

  case WM_SIZE:
    cx = LOWORD(lParam);
    cy = HIWORD(lParam);
    MoveWindow(g_hwndPrintView, 0, 0, cx, cy, TRUE);
    return 0;

  case WM_TIMER:
    if ( !bTryPrinter )
    {
      bTryPrinter = TRUE;
      GetPrinterStatus(&g_prntpoll);
      GetPrintAllJobsInfo(&g_prntpoll);
      RefreshPrintItems();
      bTryPrinter = FALSE;
    }
    return 0;

  case WM_DESTROY:
    KillTimer(hwnd, ID_TIMER);
    CleanupPrinterPoll(&g_prntpoll);
    PostQuitMessage(0);
    return 0;
  }

  return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

BOOL CreatePrintView(HWND hwndParent, HINSTANCE hInstance)
{
  TCHAR    szDoc[]    = _T("Document");
  TCHAR    szStatus[] = _T("Status");
  LVCOLUMN lvc;
  int      nResult;

  g_hwndPrintView = CreateWindowEx(
      WS_EX_CLIENTEDGE,
      WC_LISTVIEW,
      NULL,
      LVS_REPORT |
      WS_CHILD   |
      WS_VISIBLE |
      WS_CLIPSIBLINGS,
      0, 0, 0, 0,
      hwndParent,
      NULL,
      hInstance,
      NULL
  );

  if (g_hwndPrintView == NULL)
    return FALSE;

  lvc.mask = LVCF_TEXT | LVCF_WIDTH;
  lvc.cx = 120;

  // Column 0
  lvc.pszText = szDoc;
  lvc.cchTextMax = lstrlen(szDoc) + 1;
  nResult = ListView_InsertColumn(g_hwndPrintView, 0, &lvc);

  // Column 1
  lvc.pszText = szStatus;
  lvc.cchTextMax = lstrlen(szStatus) + 1;
  nResult = ListView_InsertColumn(g_hwndPrintView, 1, &lvc);

  return TRUE;
}

void RefreshPrintItems()
{
  LVITEM lvi;
  BOOL bFound;
  int nResult,
      i, j;

  // Check number of print jobs
  if (g_prntpoll.dwJobCount == 0)
  {
    // Delete all visible print jobs in ListView
    i = ListView_GetItemCount(g_hwndPrintView);
    if (i > 0)
      ListView_DeleteAllItems(g_hwndPrintView);
  }
  else
  {
    lvi.pszText    = NULL;
    lvi.cchTextMax = 0;

    // Add Job Information to ListView
    for (i = 0; i < (int) g_prntpoll.dwJobCount; ++i)
    {
      lvi.mask = LVIF_PARAM;
      bFound = ListView_GetItem(g_hwndPrintView, &lvi);
      if (bFound && (DWORD) lvi.lParam == g_prntpoll.pJobInfo1[i].JobId)
      {
        // Update Document, Status, etc.
      }
      else
      {
        // Add/Insert Document, Status, etc.
        lvi.mask = LVIF_TEXT | LVIF_PARAM;
        lvi.iItem = i;
        lvi.iSubItem = 0;
        lvi.pszText = g_prntpoll.pJobInfo1[i].pDocument;
        lvi.cchTextMax = lstrlen(lvi.pszText);
        lvi.lParam = g_prntpoll.pJobInfo1[i].JobId;
        nResult = ListView_InsertItem(g_hwndPrintView, &lvi);
      }
    }

    // Delete any documents beyond the stopping point on the ListView
    nResult = ListView_GetItemCount(g_hwndPrintView);
    for (j = i; j < nResult; ++j)
      ListView_DeleteItem(g_hwndPrintView, j);
  }

}

0
 

Author Comment

by:midnightexpress
ID: 2347638

Thanks RYANVS:   1/12/Y2K

Wow!, It's my turn now.

Midnightexpress... T.T.

I'll RSVP if need be.

0

Featured Post

Will You Be GDPR Compliant by 5/28/2018?

GDPR? That's a regulation for the European Union. But, if you collect data from customers or employees within the EU, then you need to know about GDPR and make sure your organization is compliant by May 2018. Check out our preparation checklist to make sure you're on track today!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For years I have put up with a wireless mouse that consistently disappears or is non-responsive.  This is the story of how I discovered it wasn't really the mouse!
Want to create a VM?  Here's how you do it.
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
How to fix display issue, screen flickering issue when I plug in power cord to the machine. Before I start explaining the solution lets check out once the issue how it looks like after I connect the power cord. most of you also have faced this…

599 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question