Microsoft KB Archive/158828

{|
 * width="100%"|

HOWTO: Call Win32 Spooler Enumeration APIs Properly

 * }

Q158828

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), used with:
 * Microsoft Windows NT Server version 4.0
 * Microsoft Windows NT Workstation version 4.0
 * Microsoft Windows 95
 * Microsoft Windows 2000 Advanced Server
 * Microsoft Windows 2000 Server
 * Microsoft Windows 2000 Professional

-

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 : kbOSWinNT400 kbOSWin2000 kbSDKWin32 kbOSWin95 kbDSupport kbGDIFAQ

Issue type : kbhowto

Technology : kbAudDeveloper kbWin32API