HOWTO: How To Call Win32 Spooler Enumeration APIs Properly

ID: Q158828

4.00 WINDOWS NT kbprint kbhowto
The information in this article applies to:


SUMMARY

Proper use of the Win32 Spooler Enumeration APIs requires two calls to the desired function. These APIs generally fill out an array of structures. However, the structures usually include pointers to strings or to other data. This extraneous data must also be stored in the return memory, so the strings and other data are appended to the array. Therefore, simply declaring an array of such structures on the stack would not set aside enough memory to hold all of the information the API returns.


MORE INFORMATION

The Enumeration APIs that behave this way include: EnumForms(), EnumJobs(), EnumMonitors(), EnumPorts(), EnumPrinterDrivers(), EnumPrinters(), and EnumPrintProcessors(). Also, GetJob(), GetPrinter(), and DocumentProperties() require the same treatment. In each case, proper usage requires an initial call to the function to determine the necessary buffer size, and a subsequent call that passes in a pointer to a dynamically-allocated buffer of sufficient size. The code below, from a console application, demonstrates this approach using the EnumJobs() API:


   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;
 } 

Additional query words: 4.00 kbdsd


Keywords          : kbNTOS400 kbSDKWin32 kbWinOS95 kbDSupport 
Version           : winnt:4.0
Platform          : winnt 
Issue type        : kbhowto 

Last Reviewed: July 1, 1999