/*++ Copyright (c) 1996 Microsoft Corporation Module Name: unilib.c Abstract: This file handles the shared KM and UM code for Unidrv Environment: Win32 subsystem, Unidrv driver Revision History: 02/04/97 -davidx- Devmode changes to support OEM plugins. 10/17/96 -amandan- Created it. --*/ #include "precomp.h" #ifndef KERNEL_MODE #include #endif #include #include "oemutil.h" #include "gpd.h" // // Internal data structure // typedef union { WORD w; BYTE b[2]; } UW; typedef union { DWORD dw; BYTE b[4]; } UDW; #if !defined(DEVSTUDIO) // MDS doesn't need these // // Information about UniDriver private devmode // CONST DRIVER_DEVMODE_INFO gDriverDMInfo = { UNIDRIVER_VERSION, sizeof(UNIDRVEXTRA), UNIDRIVER_VERSION_500, sizeof(UNIDRVEXTRA500), UNIDRIVER_VERSION_400, sizeof(UNIDRVEXTRA400), UNIDRIVER_VERSION_351, sizeof(UNIDRVEXTRA351), }; CONST DWORD gdwDriverDMSignature = UNIDEVMODE_SIGNATURE; CONST WORD gwDriverVersion = UNIDRIVER_VERSION; // // Functions // BOOL BInitDriverDefaultDevmode( OUT PDEVMODE pdm, IN LPCTSTR pDeviceName, IN PUIINFO pUIInfo, IN PRAWBINARYDATA pRawData, IN BOOL bMetric ) /*++ Routine Description: This function intializes the devmode with the UNIDRV default devmode Arguments: pdm pointer to Unidrv DEVMODE pDeviceName pointer to device name pUIInfo pointer to UIINFO pRawData pointer to RAWBINARYDATA bMetric indicates whether system is running in a metric country Return Value: TRUE if successful, FALSE if there is an error Note: This function should initialize both public devmode fields and driver private devmode fields. It's also assumed that output buffer has already been zero initialized by the caller. --*/ { PDEVMODE pdmPublic; PUNIDRVEXTRA pdmPrivate; PWSTR pwstrFormName; PFEATURE pFeature; PGPDDRIVERINFO pDriverInfo; pDriverInfo = GET_DRIVER_INFO_FROM_INFOHEADER(pUIInfo->pInfoHeader); pdmPublic = pdm; /*********************/ /* PUBLIC DEVMODE */ /*********************/ if (pDeviceName) CopyStringW(pdmPublic->dmDeviceName, pDeviceName, CCHDEVICENAME); pdmPublic->dmDriverVersion = UNIDRIVER_VERSION; pdmPublic->dmSpecVersion = DM_SPECVERSION; pdmPublic->dmSize = sizeof(DEVMODE); pdmPublic->dmDriverExtra = sizeof(UNIDRVEXTRA); pdmPublic->dmFields = DM_COPIES | DM_ORIENTATION | DM_PAPERSIZE | DM_COLLATE | DM_DITHERTYPE | DM_COLOR | DM_FORMNAME | DM_TTOPTION | DM_DEFAULTSOURCE | #ifndef WINNT_40 DM_NUP | #endif DM_PRINTQUALITY; pdmPublic->dmOrientation = DMORIENT_PORTRAIT; pdmPublic->dmDuplex = DMDUP_SIMPLEX; pdmPublic->dmCollate = DMCOLLATE_TRUE; pdmPublic->dmMediaType = DMMEDIA_STANDARD; pdmPublic->dmTTOption = DMTT_SUBDEV; pdmPublic->dmColor = DMCOLOR_MONOCHROME; pdmPublic->dmDefaultSource = DMBIN_FORMSOURCE; pdmPublic->dmScale = 100; pdmPublic->dmCopies = 1; #ifndef WINNT_40 pdmPublic->dmNup = DMNUP_SYSTEM; #endif // // We always set ICM off. The spooler will turn it on at install time // if there are color profiles installed with this printer // pdmPublic->dmICMMethod = DMICMMETHOD_NONE; pdmPublic->dmICMIntent = DMICM_CONTRAST; pdmPublic->dmDitherType = pUIInfo->defaultQuality + QUALITY_MACRO_START; if (pUIInfo->liBestQualitySettings == END_OF_LIST && pUIInfo->liBetterQualitySettings == END_OF_LIST && pUIInfo->liDraftQualitySettings == END_OF_LIST) pdmPublic->dmDitherType = QUALITY_MACRO_CUSTOM; #ifndef WINNT_40 pdmPublic->dmFields |= (DM_ICMMETHOD | DM_ICMINTENT); #endif if (pDriverInfo && pDriverInfo->Globals.bTTFSEnabled == FALSE) pdmPublic->dmTTOption = DMTT_DOWNLOAD; if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION)) { PRESOLUTION pRes; // // Use the default resolution specified in the PPD file // if (pRes = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) { pdmPublic->dmPrintQuality = (short)pRes->iXdpi; pdmPublic->dmYResolution = (short)pRes->iYdpi; } } if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX)) { PDUPLEX pDuplex; // // Use the default duplex option specified in the GPD file // pdmPublic->dmFields |= DM_DUPLEX; if (pDuplex = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) pdmPublic->dmDuplex = (SHORT) pDuplex->dwDuplexID; } // // Always set DM_COLLATE flag since we can simulate it if the // device cannot. // if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE)) { PMEDIATYPE pMediaType; // // Use the default media type specified in the PPD file // pdmPublic->dmFields |= DM_MEDIATYPE; if (pMediaType = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) pdmPublic->dmMediaType = (SHORT)pMediaType->dwMediaTypeID; } if (pUIInfo->dwFlags & FLAG_COLOR_DEVICE) { if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_COLORMODE)) { POPTION pColorMode; PCOLORMODEEX pColorModeEx; if ((pColorMode = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) && (pColorModeEx = OFFSET_TO_POINTER(pUIInfo->pInfoHeader, pColorMode->loRenderOffset)) && (pColorModeEx->bColor)) { pdmPublic->dmColor = DMCOLOR_COLOR; } } pdmPublic->dmFields |= DM_COLOR; } // // Initialize form-related fields // VDefaultDevmodeFormFields(pUIInfo, pdmPublic, bMetric); /*********************/ /* PRIVATE DEVMODE */ /*********************/ // // Fill in the private portion of devmode // pdmPrivate = (PUNIDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm); pdmPrivate->wVer = UNIDRVEXTRA_VERSION ; pdmPrivate->wSize = sizeof(UNIDRVEXTRA); pdmPrivate->wOEMExtra = 0; ZeroMemory(pdmPrivate->wReserved, sizeof(pdmPrivate->wReserved)); pdmPrivate->iLayout = ONE_UP; pdmPrivate->bReversePrint = FALSE; pdmPrivate->iQuality = pUIInfo->defaultQuality; // // Initialize default sFlags // if (pUIInfo->dwFlags & FLAG_FONT_DOWNLOADABLE) pdmPrivate->dwFlags &= DXF_DOWNLOADTT; pdmPrivate->dwSignature = UNIDEVMODE_SIGNATURE; pdmPrivate->dwChecksum32 = pRawData->dwChecksum32; pdmPrivate->dwOptions = pRawData->dwDocumentFeatures; InitDefaultOptions(pRawData, pdmPrivate->aOptions, MAX_PRINTER_OPTIONS, MODE_DOCUMENT_STICKY); return TRUE; } VOID VMergePublicDevmodeFields ( PDEVMODE pdmSrc, PDEVMODE pdmDest, PUIINFO pUIInfo, PRAWBINARYDATA pRawData ) /*++ Routine Description: This function merges the public devmode fields from SRC to DEST It is assumed that the devmode has been converted to the current version before this function is called Arguments: pdmSrc pointer to src DEVMODE pdmDest pointer to destination DEVMODE pUIInfo pointer to UIINFO pRawData pointer to raw binary printer description data Return Value: None Note: --*/ { PFEATURE pFeature; #ifndef WINNT_40 if ( (pdmSrc->dmFields & DM_NUP) && (pdmSrc->dmNup == DMNUP_SYSTEM || pdmSrc->dmNup == DMNUP_ONEUP)) { pdmDest->dmNup = pdmSrc->dmNup; pdmDest->dmFields |= DM_NUP; } #endif // // Copy dmDefaultSource field // if ( pdmSrc->dmFields & DM_DEFAULTSOURCE && ((pdmSrc->dmDefaultSource >= DMBIN_FIRST && pdmSrc->dmDefaultSource <= DMBIN_LAST) || pdmSrc->dmDefaultSource >= DMBIN_USER)) { pdmDest->dmDefaultSource = pdmSrc->dmDefaultSource; pdmDest->dmFields |= DM_DEFAULTSOURCE; } // // Copy the dmDitherType field // if ((pdmSrc->dmFields & DM_DITHERTYPE) && ((pdmSrc->dmDitherType >= QUALITY_MACRO_START && pdmSrc->dmDitherType < QUALITY_MACRO_END) || (pdmSrc->dmDitherType <= HT_PATSIZE_MAX_INDEX))) { pdmDest->dmFields |= DM_DITHERTYPE; pdmDest->dmDitherType = pdmSrc->dmDitherType; } // // Copy dmOrientation field // if ((pdmSrc->dmFields & DM_ORIENTATION) && (pdmSrc->dmOrientation == DMORIENT_PORTRAIT || pdmSrc->dmOrientation == DMORIENT_LANDSCAPE)) { pdmDest->dmFields |= DM_ORIENTATION; pdmDest->dmOrientation = pdmSrc->dmOrientation; } // // If both DM_PAPERLENGTH and DM_PAPERWIDTH are set, copy // dmPaperLength and dmPaperWidth fields. If DM_PAPERSIZE // is set, copy dmPaperSize field. Otherwise, if DM_FORMNAME // is set, copy dmFormName field. // // // If both DM_PAPERLENGTH and DM_PAPERWIDTH are set, copy // dmPaperLength and dmPaperWidth fields. If DM_PAPERSIZE // is set, copy dmPaperSize field. Otherwise, if DM_FORMNAME // is set, copy dmFormName field. // if ((pdmSrc->dmFields & DM_PAPERWIDTH) && (pdmSrc->dmFields & DM_PAPERLENGTH) && (pdmSrc->dmPaperWidth > 0) && (pdmSrc->dmPaperLength > 0)) { pdmDest->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH); pdmDest->dmFields &= ~(DM_PAPERSIZE | DM_FORMNAME); pdmDest->dmPaperWidth = pdmSrc->dmPaperWidth; pdmDest->dmPaperLength = pdmSrc->dmPaperLength; } else if (pdmSrc->dmFields & DM_PAPERSIZE) { pdmDest->dmFields |= DM_PAPERSIZE; pdmDest->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_FORMNAME); pdmDest->dmPaperSize = pdmSrc->dmPaperSize; } else if (pdmSrc->dmFields & DM_FORMNAME) { pdmDest->dmFields |= DM_FORMNAME; pdmDest->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_PAPERSIZE); CopyString(pdmDest->dmFormName, pdmSrc->dmFormName, CCHFORMNAME); } // // Copy dmScale field // if ((pdmSrc->dmFields & DM_SCALE) && (pdmSrc->dmScale >= MIN_SCALE) && (pdmSrc->dmScale <= MAX_SCALE)) { // // Unidrv can't have DM_SCALE flag set for app compat reasons. That is // the same behavior we saw when testing other OEM PCL drivers. // (See bug #35241 for details.) // // pdmDest->dmFields |= DM_SCALE; // pdmDest->dmScale = pdmSrc->dmScale; } // // Copy dmCopies field // if ((pdmSrc->dmFields & DM_COPIES) && (pdmSrc->dmCopies >= 1) && (pdmSrc->dmCopies <= max(MAX_COPIES, (SHORT)pUIInfo->dwMaxCopies))) { pdmDest->dmFields |= DM_COPIES; pdmDest->dmCopies = pdmSrc->dmCopies; } if ((pdmSrc->dmFields & DM_COLOR) && (pdmSrc->dmColor == DMCOLOR_COLOR || pdmSrc->dmColor == DMCOLOR_MONOCHROME)) { pdmDest->dmFields |= DM_COLOR; pdmDest->dmColor = pdmSrc->dmColor; } if ((pdmSrc->dmFields & DM_DUPLEX) && (GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX) != NULL) && (pdmSrc->dmDuplex == DMDUP_SIMPLEX || pdmSrc->dmDuplex == DMDUP_HORIZONTAL || pdmSrc->dmDuplex == DMDUP_VERTICAL)) { pdmDest->dmFields |= DM_DUPLEX; pdmDest->dmDuplex = pdmSrc->dmDuplex; } if ((pdmSrc->dmFields & DM_COLLATE) && (pdmSrc->dmCollate == DMCOLLATE_TRUE || pdmSrc->dmCollate == DMCOLLATE_FALSE)) { pdmDest->dmFields |= DM_COLLATE; pdmDest->dmCollate = pdmSrc->dmCollate; } // // Copy dmTTOption field // if (pdmSrc->dmFields & DM_TTOPTION && (pdmSrc->dmTTOption == DMTT_BITMAP || pdmSrc->dmTTOption == DMTT_DOWNLOAD || pdmSrc->dmTTOption == DMTT_SUBDEV) ) { pdmDest->dmTTOption = pdmSrc->dmTTOption; pdmDest->dmFields |= DM_TTOPTION; } if ((pdmSrc->dmFields & DM_ICMMETHOD) && (pdmSrc->dmICMMethod == DMICMMETHOD_NONE || pdmSrc->dmICMMethod == DMICMMETHOD_SYSTEM || pdmSrc->dmICMMethod == DMICMMETHOD_DRIVER || pdmSrc->dmICMMethod == DMICMMETHOD_DEVICE)) { pdmDest->dmFields |= DM_ICMMETHOD; pdmDest->dmICMMethod = pdmSrc->dmICMMethod; } if ((pdmSrc->dmFields & DM_ICMINTENT) && (pdmSrc->dmICMIntent == DMICM_SATURATE || #ifndef WINNT_40 pdmSrc->dmICMIntent == DMICM_COLORIMETRIC || pdmSrc->dmICMIntent == DMICM_ABS_COLORIMETRIC || #endif pdmSrc->dmICMIntent == DMICM_CONTRAST )) { pdmDest->dmFields |= DM_ICMINTENT; pdmDest->dmICMIntent = pdmSrc->dmICMIntent; } // // Resolution // if ((pdmSrc->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION)) && (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION))) { PRESOLUTION pRes; DWORD dwIndex; INT iXdpi, iYdpi; switch (pdmSrc->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION)) { case DM_PRINTQUALITY: iXdpi = iYdpi = pdmSrc->dmPrintQuality; break; case DM_YRESOLUTION: iXdpi = iYdpi = pdmSrc->dmYResolution; break; default: iXdpi = pdmSrc->dmPrintQuality; iYdpi = pdmSrc->dmYResolution; break; } dwIndex = MapToDeviceOptIndex(pUIInfo->pInfoHeader, GID_RESOLUTION, iXdpi, iYdpi, NULL); if (pRes = PGetIndexedOption(pUIInfo, pFeature, dwIndex)) { pdmDest->dmFields |= (DM_PRINTQUALITY|DM_YRESOLUTION); pdmDest->dmPrintQuality = GETQUALITY_X(pRes); pdmDest->dmYResolution = GETQUALITY_Y(pRes); } } // // Media type // if ((pdmSrc->dmFields & DM_MEDIATYPE) && (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE)) && (pdmSrc->dmMediaType == DMMEDIA_STANDARD || pdmSrc->dmMediaType == DMMEDIA_TRANSPARENCY || pdmSrc->dmMediaType == DMMEDIA_GLOSSY || pdmSrc->dmMediaType >= DMMEDIA_USER) ) { pdmDest->dmFields |= DM_MEDIATYPE; pdmDest->dmMediaType = pdmSrc->dmMediaType; } } BOOL BMergeDriverDevmode( IN OUT PDEVMODE pdmDest, IN PUIINFO pUIInfo, IN PRAWBINARYDATA pRawData, IN PDEVMODE pdmSrc ) /*++ Routine Description: This function validates the source devmode and merge it with the destination devmode for UNIDRV Arguments: pdmDest pointer to destination Unidrv DEVMODE pUIInfo pointer to UIINFO pRawData pointer to RAWBINARYDATA pdmSrc pointer to src DEVMODE Return Value: TRUE if successful, FALSE if there is a fatal error Note: This function should take care of both public devmode fields and driver private devmode fields. It can assume the input devmode has already been convert to the current size. --*/ { PUNIDRVEXTRA pPrivDest, pPrivSrc; ASSERT(pdmDest != NULL && pdmDest->dmSize == sizeof(DEVMODE) && pdmDest->dmDriverExtra >= sizeof(UNIDRVEXTRA) && pdmSrc != NULL && pdmSrc->dmSize == sizeof(DEVMODE) && pdmSrc->dmDriverExtra >= sizeof(UNIDRVEXTRA)); /**********************************/ /* TRANSFER PUBLIC DEVMODE FIELDS */ /**********************************/ VMergePublicDevmodeFields(pdmSrc, pdmDest, pUIInfo, pRawData); /***************************/ /* GET PRIVATE DEVMODE */ /***************************/ // // If the source devmode has a private portion, then check // to see if belongs to us. Copy the private portion to // the destination devmode if it does. // pPrivSrc = (PUNIDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmSrc); pPrivDest = (PUNIDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmDest); // // Validate private portion of input devmode // If it's not our private devmode, then return the default already in // privDest // if (pPrivSrc->dwSignature == UNIDEVMODE_SIGNATURE) { memcpy(pPrivDest, pPrivSrc, sizeof(UNIDRVEXTRA)); if (pPrivDest->dwChecksum32 != pRawData->dwChecksum32) { WARNING(( "UNIDRV: Devmode checksum mismatch.\n")); pPrivDest->dwChecksum32 = pRawData->dwChecksum32; pPrivDest->dwOptions = pRawData->dwDocumentFeatures; InitDefaultOptions(pRawData, pPrivDest->aOptions, MAX_PRINTER_OPTIONS, MODE_DOCUMENT_STICKY); } } return TRUE; } #endif // !defined(DEVSTUDIO) // // Alignment functions // WORD DwAlign2( IN PBYTE pubData) /*++ Routine Description: Converts a non-aligned, big endian (e.g. 80386) value and returns it as an integer, with the correct byte alignment. Arguments: pubData - a pointer to a data buffer to convert Return Value: The converted value. --*/ { static INT iType = 0; UW Uw; if( iType == 0 ) { // // Need to determine byte/word relationships // Uw.b[ 0 ] = 0x01; Uw.b[ 1 ] = 0x02; iType = Uw.w == 0x0102 ? 1 : 2; } if( iType == 2 ) { Uw.b[ 0 ] = *pubData++; Uw.b[ 1 ] = *pubData; } else { Uw.b[ 1 ] = *pubData++; Uw.b[ 0 ] = *pubData; } return Uw.w; } DWORD DwAlign4( IN PBYTE pubData) { static INT iType = 0; UDW Udw; if( iType == 0 ) { // // Need to determine byte/word relationships // Udw.b[ 0 ] = 0x01; Udw.b[ 1 ] = 0x02; Udw.b[ 2 ] = 0x03; Udw.b[ 3 ] = 0x04; iType = Udw.dw == 0x01020304 ? 1 : 2; } if( iType == 2 ) { Udw.b[ 0 ] = *pubData++; Udw.b[ 1 ] = *pubData++; Udw.b[ 2 ] = *pubData++; Udw.b[ 3 ] = *pubData; } else { Udw.b[ 3 ] = *pubData++; Udw.b[ 2 ] = *pubData++; Udw.b[ 1 ] = *pubData++; Udw.b[ 0 ] = *pubData; } return Udw.dw; } #if !defined(DEVSTUDIO) // Not necessary for MDS BOOL BGetDevmodeSettingForOEM( IN PDEVMODE pdm, IN DWORD dwIndex, OUT PVOID pOutput, IN DWORD cbSize, OUT PDWORD pcbNeeded ) /*++ Routine Description: Function to provide OEM plugins access to driver private devmode settings Arguments: pdm - Points to the devmode to be access dwIndex - Predefined index to specify which devmode the caller is interested in pOutput - Points to output buffer cbSize - Size of output buffer pcbNeeded - Returns the expected size of output buffer Return Value: TRUE if successful, FALSE if there is an error --*/ #define MAPPSDEVMODEFIELD(index, field) \ { index, offsetof(UNIDRVEXTRA, field), sizeof(pdmPrivate->field) } { PUNIDRVEXTRA pdmPrivate; INT i; static const struct { DWORD dwIndex; DWORD dwOffset; DWORD dwSize; } aIndexMap[] = { MAPPSDEVMODEFIELD(OEMGDS_UNIDM_GPDVER, wVer), MAPPSDEVMODEFIELD(OEMGDS_UNIDM_FLAGS, dwFlags), { 0, 0, 0 } }; pdmPrivate = (PUNIDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm); i = 0; while (aIndexMap[i].dwSize != 0) { if (aIndexMap[i].dwIndex == dwIndex) { *pcbNeeded = aIndexMap[i].dwSize; if (cbSize < aIndexMap[i].dwSize || pOutput == NULL) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } CopyMemory(pOutput, (PBYTE) pdmPrivate + aIndexMap[i].dwOffset, aIndexMap[i].dwSize); return TRUE; } i++; } WARNING(("Unknown unidrv devmode index: %d\n", dwIndex)); SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } BOOL BConvertPrinterPropertiesData( IN HANDLE hPrinter, IN PRAWBINARYDATA pRawData, OUT PPRINTERDATA pPrinterData, IN PVOID pvSrcData, IN DWORD dwSrcSize ) /*++ Routine Description: Convert an older or newer version PRINTERDATA structure to current version Arguments: hPrinter - Handle to the current printer pRawData - Points to raw printer description data pPrinterData - Points to destination buffer pvSrcData - Points to source data to be converted dwSrcSize - Size of the source data in bytes Return Value: TRUE if conversion was successful, FALSE otherwise Note: This function is called after the library function has already done a generic conversion. --*/ { return TRUE; } VOID VUpdatePrivatePrinterData( IN HANDLE hPrinter, IN OUT PPRINTERDATA pPrinterData, IN DWORD dwMode, IN PUIINFO pUIInfo, IN POPTSELECT pCombinedOptions ) /*++ Routine Description: Update the registry with the keywords Arguments: hPrinter - Handle to the current printer pPrinterData - Points to PRINTERDATA dwMode - MODE_READ/MODE_WRITE Return Value: None TRUE if conversion was successful, FALSE otherwise --*/ { // // UniDriver read/write registry steps for point and print to NT4 drivers // 1. Writes ModelName to registry if necessary // 2. Upgrade PageProtection // 3. Upgrade FreeMem // PTSTR ptstrModelName = NULL; PPAGEPROTECT pPageProtect = NULL; PMEMOPTION pMemOption = NULL; PFEATURE pPPFeature, pMemFeature; DWORD dwFeatureIndex,dwSelection,dwIndex,dwError; DWORD dwFlag, dwType, cbNeeded; if (!pUIInfo || !pCombinedOptions) return; if (pPPFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGEPROTECTION)) pPageProtect = PGetIndexedOption(pUIInfo, pPPFeature, 0); if (pMemFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEMOPTION)) pMemOption = PGetIndexedOption(pUIInfo, pMemFeature, 0); dwType = REG_BINARY; if (pPageProtect) { dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pPPFeature); dwError = GetPrinterData(hPrinter, REGVAL_PAGE_PROTECTION, &dwType, (BYTE *)&dwFlag, sizeof(dwFlag), &cbNeeded); if (dwMode == MODE_READ ) { if (dwError == ERROR_SUCCESS) { if (dwFlag & DXF_PAGEPROT) dwSelection = PAGEPRO_ON; else dwSelection = PAGEPRO_OFF; for (dwIndex = 0; dwIndex < pPPFeature->Options.dwCount; dwIndex++, pPageProtect++) { if (dwSelection == pPageProtect->dwPageProtectID) break; } if (dwIndex == pPPFeature->Options.dwCount) dwIndex = pPPFeature->dwDefaultOptIndex; pCombinedOptions[dwFeatureIndex].ubCurOptIndex = (BYTE)dwIndex; } } else // MODE_WRITE { #ifndef KERNEL_MODE SHORT sRasddFlag; if (dwError != ERROR_SUCCESS) sRasddFlag = 0; else sRasddFlag = (SHORT)dwFlag; pPageProtect = PGetIndexedOption(pUIInfo, pPPFeature, pCombinedOptions[dwFeatureIndex].ubCurOptIndex); if (pPageProtect && pPageProtect->dwPageProtectID == PAGEPRO_ON) sRasddFlag |= DXF_PAGEPROT; else sRasddFlag &= ~DXF_PAGEPROT; SetPrinterData(hPrinter, REGVAL_PAGE_PROTECTION, REG_BINARY, (BYTE *)&sRasddFlag, sizeof(sRasddFlag)); #endif } } if ( pMemOption) { dwFeatureIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pMemFeature); dwError = GetPrinterData(hPrinter, REGVAL_RASDD_FREEMEM, &dwType, (BYTE *)&dwFlag, sizeof(dwFlag), &cbNeeded); if (dwMode == MODE_READ ) { if (dwError == ERROR_SUCCESS) { for (dwIndex = 0; dwIndex < pMemFeature->Options.dwCount; dwIndex++, pMemOption++) { if (dwFlag == (pMemOption->dwInstalledMem/KBYTES)) break; } if (dwIndex == pMemFeature->Options.dwCount) dwIndex = pMemFeature->dwDefaultOptIndex; pCombinedOptions[dwFeatureIndex].ubCurOptIndex = (BYTE)dwIndex; } } else // MODE_WRITE { #ifndef KERNEL_MODE pMemOption = PGetIndexedOption(pUIInfo, pMemFeature, pCombinedOptions[dwFeatureIndex].ubCurOptIndex); if (pMemOption) dwFlag = (pMemOption->dwInstalledMem/KBYTES); SetPrinterData(hPrinter, REGVAL_RASDD_FREEMEM, REG_BINARY, (BYTE *)&dwFlag, sizeof(dwFlag)); #endif } } // // Rasdd requires ModelName, so check if it's there and write it if it's not. // if (!(ptstrModelName = PtstrGetPrinterDataString(hPrinter, REGVAL_MODELNAME, &dwFlag))) { #ifndef KERNEL_MODE PGPDDRIVERINFO pDriverInfo; pDriverInfo = OFFSET_TO_POINTER(pUIInfo->pInfoHeader, pUIInfo->pInfoHeader->loDriverOffset); BSetPrinterDataString(hPrinter, REGVAL_MODELNAME, pDriverInfo->Globals.pwstrModelName, REG_SZ); #endif } if (ptstrModelName) MemFree(ptstrModelName); return; } VOID VDefaultDevmodeFormFields( PUIINFO pUIInfo, PDEVMODE pDevmode, BOOL bMetric ) /*++ Routine Description: Initialized the form-related devmode fields with their default values Arguments: pUIInfo - Points for UIINFO pDevmode - Points to the DEVMODE whose form-related fields are to be initialized bMetric - Specifies whether the system is running in metric mode Return Value: NONE --*/ { PFEATURE pFeature; PPAGESIZE pPageSize; if (bMetric && (pUIInfo->dwFlags & FLAG_A4_SIZE_EXISTS)) { CopyString(pDevmode->dmFormName, A4_FORMNAME, CCHFORMNAME); pDevmode->dmPaperSize = DMPAPER_A4; pDevmode->dmPaperWidth = 2100; // 210mm measured in 0.1mm units pDevmode->dmPaperLength = 2970; // 297mm } else if (!bMetric && (pUIInfo->dwFlags & FLAG_LETTER_SIZE_EXISTS)) { CopyString(pDevmode->dmFormName, LETTER_FORMNAME, CCHFORMNAME); pDevmode->dmPaperSize = DMPAPER_LETTER; pDevmode->dmPaperWidth = 2159; // 8.5" pDevmode->dmPaperLength = 2794; // 11" } else { if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)) { // // Skip writing the dmFormName here because // ValidateDevmodeFormField will take care of it. // pPageSize = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex); if (pPageSize) { pDevmode->dmPaperSize = (SHORT)pPageSize->dwPaperSizeID; pDevmode->dmPaperWidth = (SHORT)(MASTER_UNIT_TO_MICRON(pPageSize->szPaperSize.cx, pUIInfo->ptMasterUnits.x) / DEVMODE_PAPER_UNIT); pDevmode->dmPaperLength = (SHORT)(MASTER_UNIT_TO_MICRON(pPageSize->szPaperSize.cy, pUIInfo->ptMasterUnits.y) / DEVMODE_PAPER_UNIT); pDevmode->dmFields |= (DM_PAPERWIDTH | DM_PAPERLENGTH | DM_PAPERSIZE); pDevmode->dmFields &= ~DM_FORMNAME; return; } } } pDevmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH); pDevmode->dmFields |= (DM_PAPERSIZE | DM_FORMNAME); } #endif // !defined(DEVSTUDIO)