DEVESC_QUERYSIZE is used to determine the amount of buffer space necessary to query or set single or multiple job properties. Since DEVESC_QUERYSIZE is new, applications will call GreEscape DEVESC_QUERYESCSUPPORT to determine if you support this DevEscape.
This function has a handle to a device context (HDC) that should already have printer property information associated with the HDC. Job property information may change or may be dependent upon the printer property information in the HDC. In that case, if an application passes job properties for a different device or for a different spooler printer name, then misleading information will be returned.
If a property is not supported, DEVESC_QUERYSIZE will allow space to hold the size of a simple DJP_ITEM structure. This space allows the next part of the process to continue without error. The application will be notified by GreEscape DEVESC_QUERYJOBPROPERTIES that the propery is not supported.
Make sure to test the input job properties to make sure that they are valid. This includes passing tests such as whether they contain your driver's signature string, whether the device name is yours, and whether the values are within proper ranges (only landscape or portrait). If these tests fail, then fail the call.
LONG ENGENTRY Escape (HDC hdc, LONG lEscape, LONG cInCount, PBYTE pInData, PLONG pcOutCount, PBYTE pOutData, PDDC pddc, ULONG ulFunction) { switch (lEscape) { case DEVESC_QUERYSIZE: { INT cbQueries = cInCount; PQUERYSIZE pQuerySize = (PQUERYSIZE)pInData; PQUERYTUPLE pTuple = pQuerySize->aTuples; INT cbElmSize = sizeof (QUERYTUPLE); INT iCount; INT iMaxCount; INT iSize; if (GRE_234 > globals.ulGreVersion) { assertstring ("Not supported on pre-DAX engine!\n"); lrc = DEVESC_NOTIMPLEMENTED; break; } pGoodDrivData = ReturnDriverData (pddc->pdb, pdi, pddc->pdb->hmcbHeap, pDrivData, pddc->pdb->pszPrinterName, TRUE, pDevice, pDriver); assertF (pGoodDrivData); /* Is the size of the input driver data is not the same as ** the size of our good data? */ if (pDrivData->cb != pGoodDrivData->cb) lrc = DEV_PROP_BUF_TOO_SMALL; /* Or, if the two don't compare, then fail the call. */ if (0 != memcmp (pDrivData, pGoodDrivData, pGoodDrivData->cb)) lrc = DEV_INV_INP_JOBPROPERTIES; // Take off the header cbQueries -= QUERYSIZE_HEADER_SIZE; // Must be an even multiple assertT (cbQueries % cbElmSize); if (cbQueries % cbElmSize) break; // Initialize the returned size pQuerySize->ulSizeNeeded = 0; while (cbQueries) { switch (pTuple->ulProperty) { case DJP_NONE: iSize = sizeof (((PDJP_ITEM)NULL)->ulValue); iMaxCount = 1; break; case DJP_SJ_ORIENTATION: iSize = sizeof (DJPT_ORIENTATION); iMaxCount = 2; break; case DJP_CJ_RESOLUTION: iSize = sizeof (DJPT_RESOLUTION); iMaxCount = pDevice->usNumRes; break; case DJP_SJ_BITSPERPEL: iSize = sizeof (DJPT_BITSPERPEL); iMaxCount = pDevice->usNumPrintModes; break; case DJP_SJ_COLOR: { PPRINTMODE pPrintMode = pDriver->pPrintModes; ULONG ulNumDefined = pDriver->ulNumPrintModes; PULONG pulPrintModes = pDevice->pulPrintModes; ULONG ulNumDevice = pDevice->usNumPrintModes; BOOL fFoundMono = FALSE, fFoundColor = FALSE; register INT i, j; for (i = 0; i < ulNumDevice; i++) { for (j = 0; j < ulNumDefined; j++) { if (pPrintMode[j].ulPrintModeID == pulPrintModes[i]) { if (1 == pPrintMode[j].usBitsPerPel) fFoundMono = TRUE; else fFoundColor = TRUE; } } } iSize = sizeof (DJPT_COLOR); iMaxCount = 0; if (fFoundMono) iMaxCount++; if (fFoundColor) iMaxCount++; if (!fFoundMono && !fFoundColor ) iMaxCount = 1; break; } case DJP_CJ_FORM: case DJP_SJ_PAPERSIZE: { PUSERCONNECT pUserConn; ULONG ulFormID, ulTrayID, ulMediaID; FORMINFO2 FormInfo; PTRAYINFO pTrayInfo = NULL; LONG lRet; register INT i; iMaxCount = 0; switch (pTuple->ulProperty) { case DJP_CJ_FORM: iSize = sizeof (DJPT_FORM); break; case DJP_SJ_PAPERSIZE: iSize = sizeof (DJPT_PAPERSIZE); break; } for (i = 0; i < pDevice->usNumConnects; i++) { GetIDsFromConnID (pDriver, pDevice, pDevice->pulCONNECTS[i], &ulTrayID, &ulFormID, &ulMediaID); if (DJP_CJ_FORM == pTuple->ulProperty) { iMaxCount++; } else if (DJP_SJ_PAPERSIZE == pTuple->ulProperty) { lRet = GetDefaultFormInfo (pdb, ulFormID, pJobProp->ulDefResID, &FormInfo); if (lRet) lRet = FormInfo.ulDJPid; else lRet = DJP_PSI_NONE; if (DJP_PSI_NONE != lRet) iMaxCount++; } } // get pointer to first user-defined form connection pUserConn = pDevice->pUserDefData->pUserCONNECTS; // as long as we have user-defined form connections while (pUserConn) { if (DJP_CJ_FORM == pTuple->ulProperty) { iMaxCount++; } else if (DJP_SJ_PAPERSIZE == pTuple->ulProperty) { lRet = GetDefaultFormInfo (pdb, ulFormID, pJobProp->ulDefResID, &FormInfo); if (lRet) lRet = FormInfo.ulDJPid; else lRet = DJP_PSI_NONE; if (DJP_PSI_NONE != lRet) iMaxCount++; } // Move to the next connection pUserConn = pUserConn->pNextConnect; } if (0 == iMaxCount) // Make sure its at least 1 iMaxCount = 1; break; } case DJP_SJ_COPIES: iSize = sizeof (DJPT_COPIES); iMaxCount = 1; break; case DJP_SJ_PRINTQUALITY: case DJP_SJ_TRAYTYPE: case DJP_SJ_MEDIA: case DJP_SJ_MEDIA_COLOR: case DJP_CJ_MIXEDFORMS: case DJP_SJ_FONTDOWNLOADING: case DJP_SJ_DUPLEX: case DJP_SJ_COLLATE: case DJP_SJ_FEED: case DJP_SJ_SCALING: case DJP_SJ_FORMFEEDCONTROL: case DJP_SJ_N_UP: default: iSize = sizeof (((PDJP_ITEM)NULL)->ulValue); iMaxCount = 1; DBPRINTF (("Unknow query '%s' = %d!\n", pszProperty (pTuple->ulProperty), pTuple->ulProperty)); break; } DBPRINTF (("Query size '%s'/%d = %d. Max count = %d\n", pszProperty (pTuple->ulProperty), pTuple->ulProperty, iSize, iMaxCount)); if (DJP_NONE == pTuple->ulProperty || DJP_CURRENT == pTuple->lType ) { iCount = 1; } else if (DJP_ALL == pTuple->lType) { iCount = iMaxCount; } else { iCount = 1; assertstring ("Unknown type!\n"); } // Bump up the returned size pQuerySize->ulSizeNeeded += DJP_HEADER_SIZE + iCount * iSize; cbQueries -= cbElmSize; pTuple++; } // good result ulrc = DEV_OK; break; } } return lrc; }