Данный набор API функций Win32 спулера занимается в основном заполнением массива структур. Однако, структуры обычно включают в себя указатели на строки либо на другие данные. Эти посторонние данные также должны быть сохранены в возвращаемой памяти, соответственно они добавляются в конец массива. Поэтому, простого объявления массива таких структур в стеке будет недостаточно, чтобы хранить всю информацию, которую возвращают данные API функции. Итак, речь идёт о функциях: EnumForms(), EnumJobs(), EnumMonitors(), EnumPorts(), EnumPrinterDrivers(), EnumPrinters(), и EnumPrintProcessors(). Кстати, функции GetJob(), GetPrinter(), и DocumentProperties() требуют идентичной обработки. Каждую функцию необходимо вызывать дважды. Первый вызов предназначен для определения необходимого размера буфера, а последующий вызов необходим для передачи указателя на динамически распределённый буфер достаточного размера. Код, представленный ниже, является консольным приложением, и демонстрирует использование функции EnumJobs(): BOOL ListJobsForPrinter( LPTSTR szPrinterName ) {
HANDLE hPrinter; DWORD dwNeeded, dwReturned, i; JOB_INFO_1 *pJobInfo;
// Нам понадобится дескриптор принтера, поэтому откроем его if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) ) return FALSE;
// Сперва вызовем EnumJobs() чтобы определить, сколько нам потребуется // памяти if( ! EnumJobs( hPrinter, 0, 0xFFFFFFFF, 1, NULL, 0, &dwNeeded, &dwReturned ) ) { // В любом случае надо обработать ошибку нехватки памяти if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) { ClosePrinter( hPrinter ); return FALSE; } } // Распределяем достаточное количество памяти для структуры JOB_INFO_1 // плюс дополнительные данные - dwNeeded из предыдущего вызова // говорит нам, какой объём необходим if( (pJobInfo = (JOB_INFO_1 *)malloc( dwNeeded )) == NULL ) { ClosePrinter( hPrinter ); return FALSE; } // Вызываем EnumJobs() снова, заполняя тем самым структуры if( ! EnumJobs( hPrinter, 0, 0xFFFFFFFF, 1, (LPBYTE)pJobInfo, dwNeeded, &dwNeeded, &dwReturned ) ) { ClosePrinter( hPrinter ); free( pJobInfo ); return FALSE; } // Больше дескриптор принтера нам не нужен, поэтому закрываем его ClosePrinter( hPrinter );
// dwReturned говорит нам, сколько текущих заданий // Просто отображаем количество найденных заданий printf( "%d jobs\n", dwReturned ); // Проще сделать это в цикле и пройтись по каждому заданию for(i=0;i<dwReturned;i++) { // pJobInfo[i] это структура JOB_INFO_1 для данного задания printf( "[%d] [%s]\n", pJobInfo[i].JobId, pJobInfo[i].pDocument ); }
// Очищаем free( pJobInfo ); return TRUE; } |