Участник
|
WinAPI. Ссылка (POINT) третьего уровня вложенности
AXAPTA 2.5 SP3
Заранее извиняюсь, за слишком длинный код, но все-равно в результате пришлось бы его привести.
Цель приведенного ниже кода - это получить список очереди на печать и определить, есть ли в этой очереди документ с заранее известным именем.
Проблема в следующем.
Очередь на печать я получаю при помощи API-функции enumJobs. Результат работы этой функции - это массив структур. Сами структуры, в свою очередь, имеют внутри себя ссылки на текстовые строки.
Т.е., получаю конструкцию, с 3 уровнями вложенности ссылок.
Уже целый день угробил, но никак не могу получить значение по этим сслкам на текстовые данные. Сами ссылки на область памяти, где они храняться, получаю, а как получить значения?
PHP код:
static void PrintSpooler(Args _args)
{
#WinAPI
#define.MAX_PATH(260)
#define.StructSizeINFO_1(64)
// Чтение win.ini или реестра
Dll kernel32 = new Dll("kernel32.dll");
DllFunction getProfileString = new DllFunction(kernel32, "GetProfileStringA"); // Чтение win.ini или реестра
Binary appName = new Binary(#MAX_PATH),
keyName = new Binary(#MAX_PATH),
defaultValue = new Binary(#MAX_PATH),
returnedString = new Binary(#MAX_PATH);
int hr;
str strValue;
TextBuffer textBuffer = new TextBuffer();
// Работа со спуллером принтера
Dll winspool = new Dll("winspool.drv");
DllFunction openPrinter = new DllFunction(winspool, "OpenPrinterA"), // открытие принтера
enumJobs = new DllFunction(winspool, "EnumJobsA"), // чтение заданий принтера
getProcessHeap = new DllFunction(kernel32, "GetProcessHeap"),
heapAlloc = new DllFunction(kernel32, "HeapAlloc"),
rtlMoveMemory = new DllFunction(kernel32, "RtlMoveMemory");
Binary printerName = new Binary(#MAX_PATH),
printerHWNDPointer = new Binary(#MAX_PATH),
printerDefault = new Binary(#MAX_PATH),
pJob = new Binary(4),
pcbNeeded = new Binary(4),
pcReturned = new Binary(4),
strINFO;
int printerHandle,
printerJobSize,
processHeap,
printerJob,
numJob,
nextJob,
nextOFF_SET;
;
//---------------------------------------------------------------------------------- Имя принтера по умолчанию
getProfileString.returns(ExtTypes::DWORD);
getProfileString.arg(ExtTypes::POINTER, // lpAppName, // address of section name
ExtTypes::POINTER, // LPCTSTR lpKeyName, // address of key name
ExtTypes::POINTER, // LPCTSTR lpDefault, // address of default string
ExtTypes::POINTER, // LPTSTR lpReturnedString, // address of destination buffer
ExtTypes::DWORD); // DWORD nSize // size of destination buffer
appName.string(0,"Windows");
keyName.string(0,"Device");
defaultValue.string(0,",,,");
hr = getProfileString.call(appName, keyName, defaultValue, returnedString, #MAX_PATH);
if (hr == 0)
{
print WinApi::getLastError();
}
else
{
strValue = returnedString.string(0);
// print strValue; // то, что реально прочитали из реестра
// Собственно имя принтера - это строка до первой запятой
textBuffer.setText(strValue);
textBuffer.nextToken(false, ",");
strValue = textBuffer.token();
print strValue;
}
//--------------------------------------------------------------------------------- Открытие контекста принтера
openPrinter.returns(ExtTypes::DWORD);
openPrinter.arg(ExtTypes::POINTER, // LPTSTR pPrinterName, // pointer to printer or server name
ExtTypes::POINTER, // LPHANDLE phPrinter, // pointer to printer or server handle
ExtTypes::POINTER); // LPPRINTER_DEFAULTS pDefault // pointer to printer defaults structure
printerName.string(0,strValue);
printerDefault.string(0,"");
printerHWNDPointer.dWord(0);
hr = openPrinter.call(printerName, printerHWNDPointer, printerDefault);
printerHandle = printerHWNDPointer.dWord(0);
print "hr= ",hr, " printerHandle= ",printerHandle;
//--------------------------------------------------------------------------------------------------- Очередь на печать
enumJobs.returns(ExtTypes::DWORD);
enumJobs.arg(ExtTypes::DWORD, // HANDLE hPrinter, // handle to printer object
ExtTypes::DWORD, // DWORD FirstJob, // location of first job in print queue to enumerate
ExtTypes::DWORD, // DWORD NoJobs, // number of jobs to enumerate
ExtTypes::DWORD, // DWORD Level, // structure level
ExtTypes::POINTER, // LPBYTE pJob, // pointer to structure array
ExtTypes::DWORD, // DWORD cbBuf, // size of array, in bytes
ExtTypes::POINTER, // LPDWORD pcbNeeded, // addr. of variable with no. of bytes copied
// (or required)
ExtTypes::POINTER); // LPDWORD pcReturned // addr. of variable with no. of job info. structures copied
//------------------------------------------------------ Сначала получаю ссылку на количество байт в результате работы функции
pJob.dWord(0);
pcbNeeded.dWord(0);
pcReturned.dWord(0);
// Вычисляю размер данных
hr = enumJobs.call(printerHandle,0,127,1,pJob,0,pcbNeeded,pcReturned);
printerJobSize = pcbNeeded.dWord(0);
print "hr= ",hr, " printerJobSize= ",printerJobSize;
if (! hr)
{
// Будет ошибка 122 (не хватает места) - это нормально
print WinAPI::getLastError(), " (должно быть 122)";
}
if (! printerJobSize)
{
// В очереди нет заданий на печать
print 'no print';
pause;
// Закрытие контекста принтера
WinApi::closeHandle(printerHandle);
return;
}
//--------------------------------------------------------------------------------- Собственно получение очереди на печать
/*
// Непонятно как и куда приткнуть эту структуру. И надо ли?
job_INFO_1 = new Binary(printerJobSize);
job_INFO_1.dWord(0,0); // DWORD JobId;
job_INFO_1.binary(4,pPrinterName); // LPTSTR pPrinterName;
job_INFO_1.binary(8,pMachineName); // LPTSTR pMachineName;
job_INFO_1.binary(12,pUserName); // LPTSTR pUserName;
job_INFO_1.binary(16,pDocument); // LPTSTR pDocument;
job_INFO_1.binary(20,pDatatype); // LPTSTR pDatatype;
job_INFO_1.binary(24,pStatus); // LPTSTR pStatus;
job_INFO_1.dWord(28,0); // DWORD Status;
job_INFO_1.dWord(32,0); // DWORD Priority;
job_INFO_1.dWord(36,0); // DWORD Position;
job_INFO_1.dWord(40,0); // DWORD TotalPages;
job_INFO_1.dWord(44,0); // DWORD PagesPrinted;
job_INFO_1.binary(48,systemTime); // SYSTEMTIME Submitted;
*/
pJob = new Binary(printerJobSize);
pcReturned.dWord(0);
pcbNeeded.dWord(0);
hr = enumJobs.call(printerHandle,0,127,1,pJob,printerJobSize,pcbNeeded,pcReturned);
numJob = pcReturned.dWord(0);
for (nextJob = 1; nextJob <= numJob; nextJob++)
{
nextOFF_SET = (nextJob - 1)*#StructSizeINFO_1;
print " pJob=", pJob.dWord(nextOFF_SET),
" totalPages=",pJob.dWord(nextOFF_SET+40),
" принтер=",pJob.dWord(nextOFF_SET+4), // ссылка на область памяти, где хранится имя принтера
" документ=",pJob.dWord(nextOFF_SET+16); // ссылка на область памяти, где хранится имя документа
}
if (! hr)
{
print WinAPI::getLastError();
}
//--------------------------------------------------------------------------------------------- Закрытие контекста принтера
WinApi::closeHandle(printerHandle);
pause;
return;
}
AXAPTA 2.5 SP3
|