Example #1
0
os2Printers::os2Printers()
{
DBGNX();
  mQueueCount = 0;

  ULONG  TotalQueues = 0;
  ULONG  MemNeeded = 0;
  SPLERR rc;

  rc = SplEnumQueue(0, 3, 0, 0, &mQueueCount, &TotalQueues,
                    &MemNeeded, 0);

  PRQINFO3* pPQI3Buf = (PRQINFO3*)malloc(MemNeeded);
  rc = SplEnumQueue(0, 3, pPQI3Buf, MemNeeded, &mQueueCount, &TotalQueues,
                    &MemNeeded, 0);

  if (mQueueCount > MAX_PRINT_QUEUES)
    mQueueCount = MAX_PRINT_QUEUES;

  ULONG defaultQueue = 0;
  for (ULONG cnt = 0; cnt < mQueueCount; cnt++) {
    if (pPQI3Buf[cnt].fsType & PRQ3_TYPE_APPDEFAULT)
      defaultQueue = cnt;
    mPQBuf[cnt] = new os2PrintQ(&pPQI3Buf[cnt]);
  }

  // move the entry for the default printer to index 0 (if necessary)
  if (defaultQueue > 0) {
    os2PrintQ* temp = mPQBuf[0];
    mPQBuf[0] = mPQBuf[defaultQueue];
    mPQBuf[defaultQueue] = temp;
  }

  free(pPQI3Buf);
}
Example #2
0
BOOL PrnCreatePrinterList(PPRN pprn)

{
PCHAR	  pch;			   /* String Character Pointer		*/
PPRQINFO3 pQueueInfo;		   /* Queue Information			*/
ULONG	  aulVersion[2];	   /* Version Number Holder		*/
ULONG	  cReturned;		   /* Returned Queue Count		*/
ULONG	  cTotal;		   /* Total Count			*/
ULONG	  cbNeeded;		   /* Buffer Size			*/
register INT i;			   /* Loop Counter			*/
register UINT n;		   /* Loop Counter			*/

DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_REVISION, aulVersion,
		2UL * sizeof(ULONG));

		       /* Determine the	amount of memory required for	*/
		       /* queue	information				*/

SplEnumQueue((PSZ)NULL,	3UL, (PVOID)NULL, 0UL, &cReturned, &cTotal,
	     &cbNeeded,	NULL);

		       /* Check	to see if any printers were detected	*/
		       /* and if none were found, return with the no	*/
		       /* no queue list	retrieved flag			*/
if ( cTotal == 0L )
   {
   pprn->hAB	 = 0UL;
   pprn->cQueues = 0;
   return(FALSE);
   }
		       /* Allocate memory for the queue	list		*/

if ( DosAllocMem((PPVOID)(PVOID)&pQueueInfo, cbNeeded, PAG_READ	| PAG_WRITE | PAG_COMMIT) )
   {
   pprn->hAB	 = 0UL;
   pprn->cQueues = 0;
   return(FALSE);
   }
		       /* Retrieve the queue list from the system	*/

SplEnumQueue((PSZ)NULL,	3UL, (PVOID)pQueueInfo,	cbNeeded, &cReturned,
	     &cTotal, &cbNeeded, NULL);

pprn->pquei = (PQUEINFO)malloc(sizeof(QUEINFO) * cTotal);

		       /* Scan the queue list looking for the entry	*/
		       /* that contains	the default queue and when	*/
		       /* found, save the queue	index entry		*/

for ( i	= 0; i < cReturned; i++	)
   {
   if (	pQueueInfo[i].pszName )
       {
       pprn->pquei[i].pszName =	(PSZ)malloc((n = strlen(pQueueInfo[i].pszName) + 1));
       memcpy(pprn->pquei[i].pszName, pQueueInfo[i].pszName, n);
       }
   else
       pprn->pquei[i].pszName =	NULL;

   if (	pQueueInfo[i].pszDriverName )
       {
       pprn->pquei[i].pszDriverName = (PSZ)malloc((n = strlen(pQueueInfo[i].pszDriverName) + 1));
       memcpy(pprn->pquei[i].pszDriverName, pQueueInfo[i].pszDriverName, n);
       }
   else
       pprn->pquei[i].pszDriverName = NULL;

   if (	pQueueInfo[i].pszPrinters )
       {
       pprn->pquei[i].pszPrinters = (PSZ)malloc((n = strlen(pQueueInfo[i].pszPrinters) + 1));
       memcpy(pprn->pquei[i].pszPrinters, pQueueInfo[i].pszPrinters, n);
       }
   else
       pprn->pquei[i].pszPrinters = NULL;

   pprn->pquei[i].pDriverData =	(PSZ)malloc((ULONG)pQueueInfo[i].pDriverData->cb);
   memcpy(pprn->pquei[i].pDriverData, pQueueInfo[i].pDriverData, (ULONG)pQueueInfo[i].pDriverData->cb);

		       /* Check	for the	default	queue			*/

   if (	((aulVersion[0]	== 20UL) && (aulVersion[1] >= 10UL)) ||	(aulVersion[0] > 20UL) )
       if ( pQueueInfo[i].fsType & PRQ3_TYPE_APPDEFAULT	)
	   pprn->iQueue	= i;
   }

if ( (aulVersion[0] == 20UL) &&	(aulVersion[1] < 10UL) )
   {
		       /* Get the default queue	to use			*/

   if (	PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "QUEUE", NULL,
			      pprn->szQueue, 256UL) )
       {
		       /* Truncate the semicolon delimiter in the queue	*/
		       /* name						*/

       pch = strchr(pprn->szQueue, ';');
       *pch = (CHAR)0;
       }
   else
		       /* No default queue name	found, use the first	*/
		       /* printer from the list				*/

       strcpy(pprn->szQueue, pQueueInfo->pszName);

		       /* Scan the queue list looking for the entry	*/
		       /* that contains	the default queue and when	*/
		       /* found, save the queue	index entry		*/

   for ( i = 0;	i < cReturned; i++ )
       if ( !strcmp(pprn->szQueue, pQueueInfo[i].pszName) )
	   {
	   pprn->iQueue	= i;
	   break;
	   }
   }
		       /* Save the queue information within the	printer	*/
		       /* information structure	and save the number of	*/
		       /* queues found within the system as well and	*/
		       /* return the queues found flag			*/

pprn->cQueues =	(INT)cReturned;

DosFreeMem((PVOID)pQueueInfo);

return(TRUE);
}
Example #3
0
void os2Printers::RefreshPrintQueue()
{
DBGX();
  ULONG  newQueueCount = 0;
  ULONG  TotalQueues = 0;
  ULONG  MemNeeded = 0;
  SPLERR rc;

  rc = SplEnumQueue(0, 3, 0, 0, &newQueueCount, &TotalQueues,
                    &MemNeeded, 0);
  PRQINFO3* pPQI3Buf = (PRQINFO3*)malloc(MemNeeded);

  rc = SplEnumQueue(0, 3, pPQI3Buf, MemNeeded, &newQueueCount, &TotalQueues,
                    &MemNeeded, 0);
  if (newQueueCount > MAX_PRINT_QUEUES)
    newQueueCount = MAX_PRINT_QUEUES;

  os2PrintQ* tmpBuf[MAX_PRINT_QUEUES];

  ULONG defaultQueue = 0;
  for (ULONG cnt = 0; cnt < newQueueCount; cnt++) {
    if (pPQI3Buf[cnt].fsType & PRQ3_TYPE_APPDEFAULT)
      defaultQueue = cnt;

    BOOL found = FALSE;
    for (ULONG index = 0; index < mQueueCount && !found; index++) {
       // Compare printer from requeried list with what's already in
       // Mozilla's printer list(mPQBuf).  If printer is already there,
       // use current properties; otherwise create a new printer in list.
       if (mPQBuf[index] != 0) {
         if (!strcmp(pPQI3Buf[cnt].pszPrinters, mPQBuf[index]->PrinterName()) &&
             !strcmp(pPQI3Buf[cnt].pszDriverName, mPQBuf[index]->FullName())) {
           found = TRUE;
           tmpBuf[cnt] = mPQBuf[index];
           mPQBuf[index] = 0;
         }
       }
    }
    if (!found)
       tmpBuf[cnt] = new os2PrintQ(&pPQI3Buf[cnt]);
  }

  for (ULONG index = 0; index < newQueueCount; index++) {
    if (mPQBuf[index] != 0)
      delete(mPQBuf[index]);
    mPQBuf[index] = tmpBuf[index];
  }

  if (mQueueCount > newQueueCount)
    for (ULONG index = newQueueCount; index < mQueueCount; index++)
       if (mPQBuf[index] != 0)
         delete(mPQBuf[index]);

  mQueueCount = newQueueCount;

  // move the entry for the default printer to index 0 (if necessary)
  if (defaultQueue > 0) {
    os2PrintQ* temp = mPQBuf[0];
    mPQBuf[0] = mPQBuf[defaultQueue];
    mPQBuf[defaultQueue] = temp;
  }

  free(pPQI3Buf);
}
Example #4
0
/* returns 0 if OK, non-zero for error */
int
pm_find_queue(char *queue_name, char *driver_name)
{
    SPLERR splerr;
    USHORT jobCount;
    ULONG cbBuf;
    ULONG cTotal;
    ULONG cReturned;
    ULONG cbNeeded;
    ULONG ulLevel;
    ULONG i;
    PSZ pszComputerName;
    PBYTE pBuf;
    PPRQINFO3 prq;

    ulLevel = 3L;
    pszComputerName = (PSZ) NULL;
    splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, 0L,	/* cbBuf */
			  &cReturned, &cTotal,
			  &cbNeeded, NULL);
    if (splerr == ERROR_MORE_DATA || splerr == NERR_BufTooSmall) {
	if (!DosAllocMem((PVOID) & pBuf, cbNeeded,
			 PAG_READ | PAG_WRITE | PAG_COMMIT)) {
	    cbBuf = cbNeeded;
	    splerr = SplEnumQueue(pszComputerName, ulLevel, pBuf, cbBuf,
				  &cReturned, &cTotal,
				  &cbNeeded, NULL);
	    if (splerr == NO_ERROR) {
		/* Set pointer to point to the beginning of the buffer.           */
		prq = (PPRQINFO3) pBuf;

		/* cReturned has the count of the number of PRQINFO3 structures.  */
		for (i = 0; i < cReturned; i++) {
		    if (queue_name) {
			/* find queue name and return driver name */
			if (strlen(queue_name) == 0) {	/* use default queue */
			    if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
				strcpy(queue_name, prq->pszName);
			}
			if (strcmp(prq->pszName, queue_name) == 0) {
			    char *p;

			    for (p = prq->pszDriverName; *p && (*p != '.'); p++)
				/* do nothing */ ;
			    *p = '\0';	/* truncate at '.' */
			    if (driver_name != NULL)
				strcpy(driver_name, prq->pszDriverName);
			    DosFreeMem((PVOID) pBuf);
			    return 0;
			}
		    } else {
			/* list queue details */
			if (prq->fsType & PRQ3_TYPE_APPDEFAULT)
			    eprintf1("  \042%s\042  (DEFAULT)\n", prq->pszName);
			else
			    eprintf1("  \042%s\042\n", prq->pszName);
		    }
		    prq++;
		}		/*endfor cReturned */
	    }
	    DosFreeMem((PVOID) pBuf);
	}
    }
    /* end if Q level given */ 
    else {
	/* If we are here we had a bad error code. Print it and some other info. */
	eprintf4("SplEnumQueue Error=%ld, Total=%ld, Returned=%ld, Needed=%ld\n",
		splerr, cTotal, cReturned, cbNeeded);
    }
    if (splerr)
	return splerr;
    if (queue_name)
	return -1;
    return 0;
}
/*--------------------------------------------------------------------------------------*\
 * This function updates the spooler container, and the structures related to the       *
 * queues and jobs on this local machine, according to the current real time spooler    *
 * contents.                                                                            *
 * Req:                                                                                 *
 * Returns:                                                                             *
 *      NO_ERROR ...... If called sucessfully                                           *
 *      ulErrorCode ... If called unsucessfully                                         *
\*--------------------------------------------------------------------------------------*/
ULONG           RefreshSpooler(void)
{
    ULONG           ulQueueCountReturned;   /* Number of queues returned in SplEnumQueue() */
    ULONG           ulQueueCountNeeded;     /* Number of queues available */
    ULONG           ulQueueSize;            /* Size of information returned */
    PRQINFO3        *pQueueInfo;            /* Points to all information returned */
    PRQINFO3        *pCurrentQueue;         /* Points to current queue within all queues available */
    PRQINFO3        *pLastQueue;            /* Points to the queue current job is inserted */
    ULONG           ulCurrentQueue;
    PRJINFO2        *pCurrentJob;           /* Points to current job within one queue */
    ULONG           ulCurrentJob;
    ULONG           ulJobCount;             /* Number of jobs within current queue */
    RECORDINSERT    RecordInsert;           /* RECORDINSERT structure to control record insertion */
    SPOOLERRECORD   *pSpoolerRecord;        /* Pointer to new SPOOLERRECORD created, when a new entry
                                           was found in the queue */
    SPOOLEROBJECT   *pCurrentSpoolerObject; /* Pointer to current SPOOLEROBJECT added to list, when a new
                                           entry was found in the queue */
    SPOOLEROBJECT   *pAppendSpoolerObject;  /* Pointer to the last element in the SPOOLEROBJECT list,
                                           where the current queue entry is appended */

    if(pHP->ulDebug>=DEBUG_ENTRY)
        printf("Spooler: Refresh()\n");
    /*                                                                                      *\
     * Fill RECORDINSERT structure, which will be used for inserting records.               *
    \*                                                                                      */
    /* Initialize RECORDINSERT structure */
    RecordInsert.cb=sizeof(RecordInsert);
    /* Insert record at end of existing records */
    RecordInsert.pRecordOrder=(PRECORDCORE)CMA_END;
    RecordInsert.pRecordParent=NULL;        /* There is no parent */
    RecordInsert.fInvalidateRecord=TRUE;    /* Update during insertation */
    RecordInsert.zOrder=CMA_TOP;            /* Insert at top of Z-Order */
    RecordInsert.cRecordsInsert=1;          /* Insert 1 record */
    /*                                                                                      *\
     * Get first record from container, free SPOOLERRECORD structure and the corresponding  *
     * SPOOLEROBJECT structure, and then remove record from container until all records are *
     * removed from the spooler container.                                                  *
    \*                                                                                      */
    /* Prevent unnecessary container drawing */
    WinEnableWindowUpdate(pHP->hwndSpoolerContainer, FALSE);
    /* Get first container record to delete them sequentially */
    pSpoolerRecord=(SPOOLERRECORD *)WinSendMsg(pHP->hwndSpoolerContainer, CM_QUERYRECORD,
                   NULL, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
    while(pSpoolerRecord)
    {   /* Delete and free records */
        free(pSpoolerRecord->pszQueue);
        free(pSpoolerRecord->pszQueueStatus);
        free(pSpoolerRecord->pszQueueComment);
        free(pSpoolerRecord->pszQueueDriver);
        free(pSpoolerRecord->pszJob);
        free(pSpoolerRecord->pszJobNumber);
        free(pSpoolerRecord->pszJobStatus);
        free(pSpoolerRecord->pszJobComment);
        free(pSpoolerRecord->pSpoolerObject);
        /* Delete record in container. Warning! as this function
           expects an array, but we only delete one record, we
           have to get the address of the pointer to the record. */
        WinSendMsg(pHP->hwndSpoolerContainer, CM_REMOVERECORD,
                   MPFROMP(&pSpoolerRecord), MPFROM2SHORT(1, CMA_FREE|CMA_INVALIDATE));
        /* Get next container record to delete them sequentially */
        pSpoolerRecord=(SPOOLERRECORD *)WinSendMsg(pHP->hwndSpoolerContainer, CM_QUERYRECORD,
                       NULL, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
    }
    /* We have deleted all container object */
    pHP->pSpoolerObjectRoot=pAppendSpoolerObject=NULL;
    /*                                                                                      *\
     * Now enumerate the printer queue of the local machine, and create container records   *
     * for each queue and its jobs, even if the queue currently doesn't have any print job  *
     * (the queue is inserted in this case to allow queue manipulation).                    *
    \*                                                                                      */
    SplEnumQueue(                           /* Get printer queue count of local machine */
        NULL,                               /* Local machine */
        4,                                  /* Detail level */
        NULL,                               /* Output buffer */
        0,                                  /* Output buffer size */
        &ulQueueCountReturned,              /* Number of entries returned */
        &ulQueueCountNeeded,                /* Number of entries available */
        &ulQueueSize,                       /* Size of available information */
        NULL);                              /* Reserved */
    /* If no queue available return error */
    if(ulQueueCountNeeded==0) return(ERROR_INVALID_DATA);
    /* Get all local printer queues */
    pQueueInfo=malloc(ulQueueSize);
    SplEnumQueue(NULL, 4, pQueueInfo, ulQueueSize,
                 &ulQueueCountReturned, &ulQueueCountNeeded, &ulQueueSize, NULL);
    pCurrentQueue=pQueueInfo;               /* Begin with first queue. For each queue a PRQINFO3
                                           structure is available immediately followed by a
                                           PRJINFO2 structure for each job in the queue. */
    for(ulCurrentQueue=0; ulCurrentQueue<ulQueueCountReturned; ulCurrentQueue++)
    {
        UCHAR   ucCurrentJob[256];
        UCHAR   ucCurrentQueueStatus[256];
        UCHAR   ucBuffer[256];

        /* Print queue status bitmask */
        switch(pCurrentQueue->fsStatus & PRQ_STATUS_MASK)
        {
        case PRQ_ACTIVE:
            strcpy(ucCurrentQueueStatus, "Active");
            break;

        case PRQ_PAUSED:
            strcpy(ucCurrentQueueStatus, "Paused");
            break;

        case PRQ_ERROR:
            strcpy(ucCurrentQueueStatus, "Error");
            break;

        case PRQ_PENDING:
            strcpy(ucCurrentQueueStatus, "Pending");
            break;
        }
        ulJobCount=pCurrentQueue->cJobs;    /* Get number of jobs in current queue */
        pLastQueue=pCurrentQueue;           /* Save the queue for the case it contains at least 1 job */
        pCurrentQueue++;                    /* Point to next PRQINFO3 structure if current queue
                                           has no jobs, or to a PRJINFO2 structure for a job */
        /* Get all jobs within current queue */
        for(ulCurrentJob=0, pCurrentJob=(PRJINFO2 *)pCurrentQueue; ulCurrentJob<ulJobCount;
                ulCurrentJob++, pCurrentJob++)
        {
            ucCurrentJob[0]='\0';           /* Clear to get sure, but it would be a surprise if this
                                           empty string doesn't get overwritten */
            switch(pCurrentJob->fsStatus & PRJ_QSTATUS)
            {
            case PRJ_QS_QUEUED:
                strcpy(ucCurrentJob, "Queued");
                break;

            case PRJ_QS_PAUSED:
                strcpy(ucCurrentJob, "Paused");
                break;

            case PRJ_QS_SPOOLING:
                strcpy(ucCurrentJob, "Spooling");
                break;

            case PRJ_QS_PRINTING:
                strcpy(ucCurrentJob, "Printing");
                break;

            default:
                strcpy(ucCurrentJob, "Unknown");
                break;
            }
            if(!(pCurrentJob->fsStatus & PRJ_DEVSTATUS))
            {
                strcat(ucCurrentJob, ", Normal");
            }
            else
            {
                if(pCurrentJob->fsStatus & PRJ_COMPLETE)
                {
                    strcat(ucCurrentJob, ", Complete");
                }
                if(pCurrentJob->fsStatus & PRJ_INTERV)
                {
                    strcat(ucCurrentJob, ", Intervention required");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTOFFLINE)
                {
                    strcat(ucCurrentJob, ", Destination offline");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTPAUSED)
                {
                    strcat(ucCurrentJob, ", Destination paused");
                }
                if(pCurrentJob->fsStatus & PRJ_NOTIFY)
                {
                    strcat(ucCurrentJob, ", Alert raised");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTNOPAPER)
                {
                    strcat(ucCurrentJob, ", Out of paper");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTFORMCHG)
                {
                    strcat(ucCurrentJob, ", Form change");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTCRTCHG)
                {
                    strcat(ucCurrentJob, ", Cartridge change");
                }
                if(pCurrentJob->fsStatus & PRJ_DESTPENCHG)
                {
                    strcat(ucCurrentJob, ", Pen change");
                }
            }
            /*                                                                                      *\
             * Because we have found at least one job for the current queue, add one record to the  *
             * container for each job.                                                              *
            \*                                                                                      */
            /* Because we found a job, get queue data of current queue */
            /* Allocate, setup and chain in a SPOOLEROBJECT structure */
            pCurrentSpoolerObject=malloc(sizeof(SPOOLEROBJECT));
            memset(pCurrentSpoolerObject, '\0', sizeof(SPOOLEROBJECT));
            pCurrentSpoolerObject->pSpoolerObjectNext=NULL;
            pCurrentSpoolerObject->pSpoolerObjectBack=pAppendSpoolerObject;
            pCurrentSpoolerObject->bInQueue=TRUE;
            if(pAppendSpoolerObject!=NULL)
                /* Advance pointer to current record */
                pAppendSpoolerObject->pSpoolerObjectNext=pCurrentSpoolerObject;
            else
                pAppendSpoolerObject=pCurrentSpoolerObject;
            /* Save pointer to first record */
            if(pHP->pSpoolerObjectRoot!=NULL) pHP->pSpoolerObjectRoot=pCurrentSpoolerObject;
            /* Allocate one record to insert into container */
            pSpoolerRecord=(SPOOLERRECORD *)WinSendMsg(pHP->hwndSpoolerContainer, CM_ALLOCRECORD,
                           MPFROMLONG(sizeof(SPOOLERRECORD)-sizeof(MINIRECORDCORE)), MPFROMLONG(1));
            /* Chain SPOOLERRECORD and corresponding SPOOLEROBJECT together */
            pSpoolerRecord->pSpoolerObject=pCurrentSpoolerObject;
            pCurrentSpoolerObject->pSpoolerRecord=pSpoolerRecord;
            /* Fill record */
            pSpoolerRecord->pszQueue=strdup(pLastQueue->pszName);
            pSpoolerRecord->pszQueueStatus=strdup(ucCurrentQueueStatus);
            pSpoolerRecord->pszQueueComment=strdup(pLastQueue->pszComment);
            pSpoolerRecord->pszQueueDriver=strdup(pLastQueue->pszDriverName);
            pSpoolerRecord->pszJob=strdup(pCurrentJob->pszDocument);
            sprintf(ucBuffer, "%4d", pCurrentJob->uJobId);
            pSpoolerRecord->pszJobNumber=strdup(ucBuffer);
            pSpoolerRecord->pszJobStatus=strdup(ucCurrentJob);
            pSpoolerRecord->pszJobComment=strdup(pCurrentJob->pszComment);
            pSpoolerRecord->ulJob=pCurrentJob->uJobId;
            /* Insert record into container */
            WinSendMsg(pHP->hwndSpoolerContainer, CM_INSERTRECORD,
                       MPFROMP(pSpoolerRecord), MPFROMP(&RecordInsert));
        }
        if(ulJobCount==0)
        {
            /*                                                                                      *\
             * Because the current queue doesn't have at least on job, create a container record    *
             * anyway, even when there is no job data.                                              *
            \*                                                                                      */
            /* Allocate, setup and chain in a SPOOLEROBJECT structure */
            pCurrentSpoolerObject=malloc(sizeof(SPOOLEROBJECT));
            memset(pCurrentSpoolerObject, '\0', sizeof(SPOOLEROBJECT));
            pCurrentSpoolerObject->pSpoolerObjectNext=NULL;
            pCurrentSpoolerObject->pSpoolerObjectBack=pAppendSpoolerObject;
            pCurrentSpoolerObject->bInQueue=TRUE;
            if(pAppendSpoolerObject!=NULL)
                /* Advance pointer to current record */
                pAppendSpoolerObject->pSpoolerObjectNext=pCurrentSpoolerObject;
            else
                pAppendSpoolerObject=pCurrentSpoolerObject;
            /* Save pointer to first record */
            if(pHP->pSpoolerObjectRoot!=NULL) pHP->pSpoolerObjectRoot=pCurrentSpoolerObject;
            /* Allocate one record in container */
            pSpoolerRecord=(SPOOLERRECORD *)WinSendMsg(pHP->hwndSpoolerContainer, CM_ALLOCRECORD,
                           MPFROMLONG(sizeof(SPOOLERRECORD)-sizeof(MINIRECORDCORE)), MPFROMLONG(1));
            /* Chain SPOOLERRECORD and corresponding SPOOLEROBJECT together */
            pSpoolerRecord->pSpoolerObject=pCurrentSpoolerObject;
            pCurrentSpoolerObject->pSpoolerRecord=pSpoolerRecord;
            /* Fill record */
            pSpoolerRecord->pszQueue=strdup(pLastQueue->pszName);
            pSpoolerRecord->pszQueueStatus=strdup(ucCurrentQueueStatus);
            pSpoolerRecord->pszQueueComment=strdup(pLastQueue->pszComment);
            pSpoolerRecord->pszQueueDriver=strdup(pLastQueue->pszDriverName);
            pSpoolerRecord->pszJob=strdup("");
            pSpoolerRecord->pszJobNumber=strdup("");
            pSpoolerRecord->pszJobStatus=strdup("");
            pSpoolerRecord->pszJobComment=strdup("");
            pSpoolerRecord->ulJob=0;
            /* Insert record into container */
            WinSendMsg(pHP->hwndSpoolerContainer, CM_INSERTRECORD,
                       MPFROMP(pSpoolerRecord), MPFROMP(&RecordInsert));
        }
        /* Last job of current queue reached, so current job
           points to next queue */
        pCurrentQueue=(PRQINFO3 *)pCurrentJob;
    }
    free(pQueueInfo);
    /* Now draw changes in container window */
    WinEnableWindowUpdate(pHP->hwndSpoolerContainer, TRUE);
    return(NO_ERROR);
}
/*@ XPrinterDevice::SetupPrinter(char *title, XFrameWindow * owner, XString * queueName, XString * fileName)
@remarks Let the user select the printer-queue in a dialog. The dialog is loaded from OOLRES.DLL which must be installed.
@parameters
<t 'ø' c=2>
øchar *title            øthe title of the dialog
øXFrameWindow * owner   øowner window. If NULL, the dialog for the printer-setup is not opened
                         and the  queue given in parameter 3 is initialized directly
øXString * queueName      ødefault queue-name (can be null)
øXString * fileName      øbuffer for a fileName if the user wants to print to a file (if NULL no fiflename is stored)
</t>
@returns BOOL success
*/
BOOL XPrinterDevice::SetupPrinter(const char *title, const XFrameWindow * owner, XString * queueName, XString * fileName)
{
   BOOL fOK;
   CHAR szDefaultQueue[196];
   CHAR szSavedQueue[196];
   CHAR szWork[196];
   PCHAR pch;
   PPRQINFO3 pqi;
   SIZEL sizel;
   ULONG cReturned;
   ULONG cTotal;
   ULONG cbNeeded;
   ULONG ul;
   ULONG ulrc;

   // Caller must set these items before calling.
   if (!pSetup->hab || !pSetup->lWorldCoordinates)
      return FALSE;

   // no good unless I can open a PS
   pSetup->pDevOpenData = NULL;

   // Close the info DC's and PS's from any previous call.
   if (pSetup->hpsPrinterInfo)
   {
      GpiAssociate(pSetup->hpsPrinterInfo, (HDC) 0);
      GpiDestroyPS(pSetup->hpsPrinterInfo);
      pSetup->hpsPrinterInfo = (HPS) 0;
   }

   if (pSetup->hdcPrinterInfo)
   {
      DevCloseDC(pSetup->hdcPrinterInfo);
      pSetup->hdcPrinterInfo = (HDC) 0;
   }

   if (pSetup->pQueueInfo)
   {
      // Free the array of PRQINFO3 from previous call.
      free(pSetup->pQueueInfo);
      pSetup->pQueueInfo = NULL;
   }

   // Query how many queues exist on this computer and the
   // number of bytes needed to hold the array.
   ul = SplEnumQueue(NULL, 3, NULL, 0, &cReturned, &cTotal, &cbNeeded, NULL);
   if (cTotal == 0)
   {
      // There are no queues on this computer!
      pSetup->cQueues = 0;
      return FALSE;
   }

   // Allocate memory to store the newly enumerated queue information.
   pSetup->pQueueInfo = (PRQINFO3 *) malloc(cbNeeded);
   if (!pSetup->pQueueInfo)
      return FALSE;

   // Call system again to get the array of PRQINFO3 structures.
   ul = SplEnumQueue(NULL, 3, pSetup->pQueueInfo, cbNeeded, &cReturned, &cTotal, &cbNeeded, NULL);
   if (ul != 0 ||
      cReturned != cTotal)
      return FALSE;
   pSetup->cQueues = cReturned;

   // Establish a default queue -- might need it.
   // Profiled queue name ends with a semicolon.
   ul = PrfQueryProfileString(HINI_PROFILE, (PSZ) "PM_SPOOLER", (PSZ) "QUEUE", NULL, szDefaultQueue, 196);
   if (ul > 1)
   {
      // Trim off semicolon.
      pch = strchr(szDefaultQueue, ';');
      *pch = 0;
   }
   else
   {
      // Hmmmm. Use the first one queue from the enumeration.
      strcpy(szDefaultQueue, (char*) pSetup->pQueueInfo->pszName);
   }
   if (!strlen(szDefaultQueue))
      return FALSE;

   if (0 == strlen(pSetup->szPreferredQueue))
   {
      // No queue preference; use default.
      strcpy(pSetup->szPreferredQueue, szDefaultQueue);

      // Don't expect to see DRIVDATA without queue name.
      // if(! pSetup->pDriverData ) return FALSE;
   }

   if (queueName)
   {
      if (!queueName->IsEmpty())
      {
         pSetup->fToFile = FALSE;
         strcpy(pSetup->szPreferredQueue, (char *) *queueName);
      }
      if (fileName)
      {
         if (!fileName->IsEmpty())
         {
            pSetup->fToFile = TRUE;
            strcpy(pSetup->szFileName, (char *) *fileName);
         }
      }
   }

   pqi = FindQueue(pSetup);
   if (!pqi)
   {
      strcpy(pSetup->szPreferredQueue, szDefaultQueue);
      if (pSetup->pDriverData)
      {
         free(pSetup->pDriverData);
         pSetup->pDriverData = NULL;
      }
   }
   else
   {
      fOK = TRUE;

      if (pSetup->pDriverData)
      {
         fOK = fOK && (pqi->pDriverData->cb == pSetup->pDriverData->cb);
         fOK = fOK && (0 == strcmp(pqi->pDriverData->szDeviceName, pSetup->pDriverData->szDeviceName));
      }

      if (!fOK)
      {
         free(pSetup->pDriverData);
         pSetup->pDriverData = NULL;
      }
   }

   pqi = FindQueue(pSetup);

   if (!pSetup->pDriverData)
   {
      pSetup->pDriverData = (DRIVDATA *) malloc(pqi->pDriverData->cb);
      if (!pSetup->pDriverData)
      {
         ulrc = FALSE;
         return ulrc;
      }
      memcpy(pSetup->pDriverData, pqi->pDriverData, pqi->pDriverData->cb);
   }

   if (!pSetup->pDriverData || pSetup->pDriverData->cb <= 0 || pSetup->pDriverData->cb != pqi->pDriverData->cb || strcmp(pqi->pDriverData->szDeviceName, pSetup->pDriverData->szDeviceName))
      return FALSE;

   memcpy(pqi->pDriverData, pSetup->pDriverData, pSetup->pDriverData->cb);

   strcpy(szSavedQueue, pSetup->szPreferredQueue);

   if (owner)
   {
      XCountryInfo info;
      XResourceLibrary lib( "oolres");
      LONG dlgID;

      switch (info.GetCountry())
      {
      case 39:            // italy
         dlgID = IDD_SELPRINT_ITA;
         break;
      case 2:             // can francais
      case 33:            // france
      case 32:            // belgien
         dlgID = IDD_SELPRINT_FRA;
         break;
      case 49:            // german
         dlgID = IDD_SELPRINT_GER;
         break;
      default:            // english
         dlgID = IDD_SELPRINT_ENG;
      }
      XResource res(dlgID, &lib);

      PrinterDialog *printerDialog = new PrinterDialog(owner, pSetup, &res);
//      printerDialog->SetText((char*) title);
      LONG result = printerDialog->Start();
      if (result == DID_CANCEL)
         return FALSE;
   }
   else
   {
      if (queueName)
      {
         pSetup->fToFile = FALSE;
         strcpy(pSetup->szPreferredQueue, (char *) *queueName);

         if (fileName)
         {
            pSetup->fToFile = TRUE;
            strcpy(pSetup->szFileName, (char *) *fileName);
         }
      }
   }

   *queueName = "";
   *fileName = "";

   pqi = FindQueue(pSetup);
   if (!pqi)
      return FALSE;

   if (0 != strcmp(szSavedQueue, pSetup->szPreferredQueue))
   {
      if (!pSetup->pDriverData)
         return FALSE;
      free(pSetup->pDriverData);

      pSetup->pDriverData = (DRIVDATA *) malloc(pqi->pDriverData->cb);
      if (!pSetup->pDriverData)
      {
         ulrc = FALSE;
         return ulrc;
      }
      pSetup->pDriverData->cb = pqi->pDriverData->cb;
   }

   if (!pSetup->pDriverData || !pSetup->pDriverData->cb == pqi->pDriverData->cb)
      return FALSE;
   memcpy(pSetup->pDriverData, pqi->pDriverData, pqi->pDriverData->cb);

   if (pSetup->fToFile)
   {
      pSetup->lDCType = OD_DIRECT;
      pSetup->devopenstruc.pszLogAddress = (PSZ) pSetup->szFileName;
   }
   else
   {
      pSetup->lDCType = OD_QUEUED;
      pSetup->devopenstruc.pszLogAddress = (PSZ) pSetup->szPreferredQueue;
   }

   strcpy(szWork, (char*) pqi->pszDriverName);
   pch = strchr(szWork, '.');
   if (pch)
      *pch = 0;

   if (pSetup->devopenstruc.pszDriverName)
      free(pSetup->devopenstruc.pszDriverName);

   pSetup->devopenstruc.pszDriverName = (PSZ) malloc(1 + strlen(szWork));
   if (!pSetup->devopenstruc.pszDriverName)
      return FALSE;

   strcpy( (char*) pSetup->devopenstruc.pszDriverName, szWork);

   pSetup->devopenstruc.pdriv = pSetup->pDriverData;
   pSetup->devopenstruc.pszDataType = (PSZ) "PM_Q_STD";

   pSetup->hdcPrinterInfo = DevOpenDC(pSetup->hab, OD_INFO, (PSZ) "*", 4, (PDEVOPENDATA) & pSetup->devopenstruc, (HDC) 0);
   if (!pSetup->hdcPrinterInfo)
      return FALSE;

   sizel.cx = 0;
   sizel.cy = 0;
   pSetup->hpsPrinterInfo = GpiCreatePS(pSetup->hab, pSetup->hdcPrinterInfo, &sizel, pSetup->lWorldCoordinates | GPIA_ASSOC);

   if (GPI_ERROR == pSetup->hpsPrinterInfo)
   {
      DevCloseDC(pSetup->hdcPrinterInfo);
      pSetup->hdcPrinterInfo = (HDC) 0;
      pSetup->hpsPrinterInfo = (HPS) 0;
      return FALSE;
   }

   pSetup->pDevOpenData = (PDEVOPENDATA) & pSetup->devopenstruc;

   *queueName = pSetup->szPreferredQueue;
   if (pSetup->fToFile)
      *fileName = pSetup->szFileName;
   return TRUE;
}