| Участник | 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
		 |