BOOL ListJobsForPrinter( LPTSTR szPrinterName )
   {   HANDLE         hPrinter;
   DWORD          dwNeeded, dwReturned, i;
   JOB_INFO_1     *pJobInfo;   // You need a printer handle, open the printer
   if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
     return FALSE;   // First you call EnumJobs() to find out how much memory you need
   if( ! EnumJobs( hPrinter, 0, 0xFFFFFFFF, 1, NULL, 0, &dwNeeded,
                   &dwReturned ) )
   {
     // It should have failed, but if it failed for any reason other
     // than "not enough memory", you should bail out
     if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
     {
       ClosePrinter( hPrinter );
       return FALSE;
     }
   }
   // Allocate enough memory for the JOB_INFO_1 structures plus
   // the extra data - dwNeeded from the previous call tells you
   // the total size needed
   if( (pJobInfo = (JOB_INFO_1 *)malloc( dwNeeded )) == NULL )
   {
     ClosePrinter( hPrinter );
     return FALSE;
   }
   // Call EnumJobs() again and let it fill out our structures
   if( ! EnumJobs( hPrinter, 0, 0xFFFFFFFF, 1, (LPBYTE)pJobInfo,
                   dwNeeded, &dwNeeded, &dwReturned ) )
   {
     ClosePrinter( hPrinter );
     free( pJobInfo );
     return FALSE;
   }
   // You're done with the printer handle, close it
   ClosePrinter( hPrinter );   // dwReturned tells how many jobs there are
   // Here, you'll simply display the number of jobs found
   printf( "%d jobs\n", dwReturned );
   // It's easy to loop through the jobs and access each one
   for(i=0;i<dwReturned;i++)
   {
     // pJobInfo[i] is a JOB_INFO_1 struct for that job
     // so here you could do whatever you want for each job
     printf( "[%d] [%s]\n", pJobInfo[i].JobId, pJobInfo[i].pDocument );
   }   // Clean up
   free( pJobInfo );
   return TRUE;
 }