Как правильно работать с 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;
}
|