BOOL bGetForms( HANDLE hPrinter, PRASDDUIINFO pRasdduiInfo /* Global Data Access */ ) { DWORD cbNeeded; /* Number of bytes needed */ DWORD cReturned; /* Number of forms returned */ FORM_INFO_1 *pForm; /* Scanning through returned data */ FORM_DATA *pFDTmp; /* Filling in FORM_DATA stuff */ /* * Standard technique: call first to determine how much storage * is required, allocate the storage and then call again. */ if( !EnumForms( hPrinter, 1, NULL, 0, &cbNeeded, &cReturned ) ) { if( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { if( pFIBase = (FORM_INFO_1 *)HEAPALLOC( pRasdduiInfo, 0, cbNeeded ) ) { if( EnumForms( hPrinter, 1, (LPBYTE)pFIBase, cbNeeded, &cbNeeded, &cReturned ) ) { /* * Allocate the number + 1 of structures needed to make * the FORM_DATA array. This is used elsewhere. */ cbNeeded = (cReturned + 1) * sizeof( FORM_DATA ); if( !(pFD = (FORM_DATA *)HEAPALLOC( pRasdduiInfo, 0, cbNeeded )) ) { vEndForms(pRasdduiInfo); /* Does the clean up */ return FALSE; } ZeroMemory( pFD, cbNeeded ); pForm = pFIBase; pFDTmp = pFD; pRasdduiInfo->cForms = cReturned; /* For setting defaults etc */ while( cReturned-- ) { /* * Have our structure point to the forms data, * and also convert the forms data base into * master units. */ XTOMASTER( pForm->Size.cx ); YTOMASTER( pForm->Size.cy ); pFDTmp->pFI = pForm++; ++pFDTmp; } } //If EnumForms fails, return false. else { RIP("Rasddui!bGetForms:2nd call to EnumForms Failed\n"); vEndForms(pRasdduiInfo); /* Does the clean up */ return FALSE; } return TRUE; /* AOK */ } } //If EnumForms fails, return false. else { RIP("Rasddui!bGetForms:EnumForms returns error other than ERROR_INSUFFICIENT_BUFFER\n"); vEndForms(pRasdduiInfo); /* Does the clean up */ return FALSE; } } RIP("Rasddui!bGetForms:1st call to EnumForms Failed\n"); /* * If we reach here, one of the above if(..) statements failed, * and that is NOT good. */ return FALSE; /* SHOULD NEVER HAPPEN */ }
BOOL PrepareFeatureData( PDEVDATA pdev ) /*++ Routine Description: Prepare data for handling printer specific feature Arguments: pdev - Pointer to our DEVDATA structure Return Value: TRUE if successful, FALSE otherwise --*/ { PPACKEDORDERDEP pOrderDep; PFEATUREDATA pFeatureData; BYTE options[MAX_PRINTER_OPTIONS]; WORD index, cOptions; HPPD hppd; ASSERT(pdev->cSelectedFeature == 0 && pdev->pFeatureData == NULL); // Allocate memory to hold printer specific feature data memset(options, OPTION_INDEX_ANY, sizeof(options)); hppd = pdev->hppd; cOptions = hppd->cDocumentStickyFeatures + hppd->cPrinterStickyFeatures; ASSERT(cOptions <= MAX_PRINTER_OPTIONS) if (hppd->cDocumentStickyFeatures != pdev->dm.dmPrivate.wOptionCount && hppd->cPrinterStickyFeatures != pdev->pPrinterData->wOptionCount) { DBGMSG(DBG_LEVEL_ERROR, "Invalid option count.\n"); } memcpy(options, pdev->dm.dmPrivate.options, hppd->cDocumentStickyFeatures); memcpy(&options[hppd->cDocumentStickyFeatures], pdev->pPrinterData->options, hppd->cPrinterStickyFeatures); pdev->pFeatureData = HEAPALLOC(pdev->hheap, cOptions * sizeof(FEATUREDATA)); if (pdev->pFeatureData == NULL) { DBGERRMSG("MEMALLOC"); return FALSE; } // Collect printer specific feature data pFeatureData = pdev->pFeatureData; for (index=0; index < cOptions; index++) { if (options[index] != OPTION_INDEX_ANY) { pOrderDep = PpdFindOrderDep(hppd, index, options[index]); if (pOrderDep != NULL && (pOrderDep->section & (ODS_PROLOG | ODS_EXITSERVER))) { // Prolog and ExitServer are treated the same as DocSetup DBGMSG(DBG_LEVEL_WARNING, "Prolog and ExitServer section encountered.\n"); pFeatureData->section = ODS_DOCSETUP; pFeatureData->order = pOrderDep->order; } else if (pOrderDep == NULL) { // If a feature has no corresponding OrderDependency entry, // assume it goes to the end of DocumentSetup section. pFeatureData->section = ODS_DOCSETUP; pFeatureData->order = MAXPSREAL; } else { pFeatureData->section = pOrderDep->section; pFeatureData->order = pOrderDep->order; } pFeatureData->feature = index; pFeatureData->option = options[index]; pFeatureData++; } } // Sort printer specific feature data using OrderDependency. // Since the number of features is very small (usually less // than a handful), we don't have to be too concerned with // sorting speed here. if (pdev->cSelectedFeature = (WORD) (pFeatureData - pdev->pFeatureData)) { cOptions = pdev->cSelectedFeature; pFeatureData = pdev->pFeatureData; for (index=0; index < cOptions-1; index++) { WORD n, m = index; for (n=index+1; n < cOptions; n++) { if (pFeatureData[n].order < pFeatureData[m].order) m = n; } if (m != index) { FEATUREDATA featureData; featureData = pFeatureData[index]; pFeatureData[index] = pFeatureData[m]; pFeatureData[m] = featureData; } } } return TRUE; }