Как правильно работать с API функциями Win32 Spooler

Данный набор 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;
}

 

 
« Предыдущая статья   Следующая статья »