/*++ Copyright (c) 1996-1997 Microsoft Corporation Module Name: regdata.c Abstract: Functions for dealing with registry data [Environment:] Windows NT printer drivers Revision History: 02/04/97 -davidx- Use REG_MULTI_SZ type where appropriate. 01/21/97 -davidx- Add functions to manipulate MultiSZ strings. 09/25/96 -davidx- Convert to Hungarian notation. 08/18/96 -davidx- Implement GetPrinterProperties. 08/13/96 -davidx- Created it. --*/ #include "lib.h" BOOL BGetPrinterDataDWord( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, OUT PDWORD pdwValue ) /*++ Routine Description: Get a DWORD value from the registry under PrinerDriverData key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value pdwValue - Returns the requested DWORD value in the registry Return Value: TRUE if successful, FALSE if there is an error --*/ { DWORD dwType, dwByteCount, dwStatus; dwStatus = GetPrinterData(hPrinter, (PTSTR) ptstrRegKey, &dwType, (PBYTE) pdwValue, sizeof(DWORD), &dwByteCount); if (dwStatus != ERROR_SUCCESS) VERBOSE(("GetPrinterData failed: %d\n", dwStatus)); return (dwStatus == ERROR_SUCCESS); } PVOID PvGetPrinterDataBinary( IN HANDLE hPrinter, IN LPCTSTR ptstrSizeKey, IN LPCTSTR ptstrDataKey, OUT PDWORD pdwSize ) /*++ Routine Description: Get binary data from the registry under PrinterDriverData key Arguments: hPrinter - Handle to the printer object ptstrSizeKey - Name of the registry value which contains the binary data size ptstrDataKey - Name of the registry value which contains the binary data itself pdwSize - Points to a variable for receiving the binary data size Return Value: Pointer to the binary printer data read from the registry NULL if there is an error --*/ { DWORD dwType, dwSize, dwByteCount; PVOID pvData = NULL; if (GetPrinterData(hPrinter, (PTSTR) ptstrSizeKey, &dwType, (PBYTE) &dwSize, sizeof(dwSize), &dwByteCount) == ERROR_SUCCESS && dwSize > 0 && (pvData = MemAlloc(dwSize)) && GetPrinterData(hPrinter, (PTSTR) ptstrDataKey, &dwType, pvData, dwSize, &dwByteCount) == ERROR_SUCCESS && dwSize == dwByteCount) { if (pdwSize) *pdwSize = dwSize; return pvData; } VERBOSE(("GetPrinterData failed: %ws/%ws\n", ptstrSizeKey, ptstrDataKey)); MemFree(pvData); return NULL; } PTSTR PtstrGetPrinterDataString( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, OUT LPDWORD pdwSize ) /*++ Routine Description: Get a string value from PrinerDriverData registry key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value pdwSize - Specifies the size Return Value: Pointer to the string value read from the registry NULL if there is an error --*/ { DWORD dwType, dwSize, dwStatus; PVOID pvData = NULL; dwStatus = GetPrinterData(hPrinter, (PTSTR) ptstrRegKey, &dwType, NULL, 0, &dwSize); if ((dwStatus == ERROR_MORE_DATA || dwStatus == ERROR_SUCCESS) && (dwSize > 0) && (dwType == REG_SZ || dwType == REG_MULTI_SZ) && (pvData = MemAlloc(dwSize)) != NULL && (dwStatus = GetPrinterData(hPrinter, (PTSTR) ptstrRegKey, &dwType, pvData, dwSize, &dwSize)) == ERROR_SUCCESS) { if (pdwSize) *pdwSize = dwSize; return pvData; } VERBOSE(("GetPrinterData '%ws' failed: %d\n", ptstrRegKey, dwStatus)); MemFree(pvData); return NULL; } PTSTR PtstrGetPrinterDataMultiSZPair( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, OUT PDWORD pdwSize ) /*++ Routine Description: Get a MULTI_SZ value from PrinerDriverData registry key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value pdwSize - Return the size of MULTI_SZ value in bytes Return Value: Pointer to the MULTI_SZ value read from the registry NULL if there is an error --*/ { DWORD dwType, dwSize, dwStatus; PVOID pvData = NULL; dwStatus = GetPrinterData(hPrinter, (PTSTR) ptstrRegKey, &dwType, NULL, 0, &dwSize); if ((dwStatus == ERROR_MORE_DATA || dwStatus == ERROR_SUCCESS) && (dwSize > 0) && (pvData = MemAlloc(dwSize)) != NULL && (dwStatus = GetPrinterData(hPrinter, (PTSTR) ptstrRegKey, &dwType, pvData, dwSize, &dwSize)) == ERROR_SUCCESS && BVerifyMultiSZPair(pvData, dwSize)) { if (pdwSize) *pdwSize = dwSize; return pvData; } VERBOSE(("GetPrinterData '%ws' failed: %d\n", ptstrRegKey, dwStatus)); MemFree(pvData); return NULL; } BOOL BGetDeviceHalftoneSetup( HANDLE hPrinter, DEVHTINFO *pDevHTInfo ) /*++ Routine Description: Retrieve device halftone setup information from registry Arguments: hprinter - Handle to the printer pDevHTInfo - Pointer to a DEVHTINFO buffer Return Value: TRUE if successful, FALSE otherwise --*/ { DWORD dwType, dwNeeded; return GetPrinterData(hPrinter, REGVAL_CURRENT_DEVHTINFO, &dwType, (PBYTE) pDevHTInfo, sizeof(DEVHTINFO), &dwNeeded) == ERROR_SUCCESS && dwNeeded == sizeof(DEVHTINFO); } #ifndef KERNEL_MODE BOOL BSavePrinterProperties( IN HANDLE hPrinter, IN PRAWBINARYDATA pRawData, IN PPRINTERDATA pPrinterData, IN DWORD dwSize ) /*++ Routine Description: Save Printer Properites to registry Arguments: hPrinter - Specifies a handle to the current printer pRawData - Points to raw binary printer description data pPrinterData - Points to PRINTERDATA dwSize - Specifies the size of PRINTERDATA Return Value: TRUE if successful, FALSE if there is an error --*/ { BOOL bResult = FALSE; DWORD dwKeywordSize, dwFeatureCount = 0; PSTR pstrKeyword; POPTSELECT pCombineOptions; PUIINFO pUIInfo; PARSERINFO ParserInfo; ParserInfo.pRawData = NULL; ParserInfo.pInfoHeader = NULL; if (((pCombineOptions = MemAllocZ(MAX_COMBINED_OPTIONS * sizeof(OPTSELECT))) == NULL) || ((pUIInfo = PGetUIInfo(hPrinter, pRawData, pCombineOptions, pPrinterData->aOptions, &ParserInfo, &dwFeatureCount)) == NULL)) { // // We have to fail the function if out of memory, or PGetUIInfo returns NULL (in which // case pCombinOptions won't have valid option indices). // // Make sure free any allocated memory. // ERR(("pCombinOptions or pUIInfo is NULL\n")); if (pCombineOptions) MemFree(pCombineOptions); return FALSE; } pstrKeyword = PstrConvertIndexToKeyword(hPrinter, pPrinterData->aOptions, &dwKeywordSize, pUIInfo, pCombineOptions, dwFeatureCount); VUpdatePrivatePrinterData(hPrinter, pPrinterData, MODE_WRITE, pUIInfo, pCombineOptions ); if (pstrKeyword) { bResult = BSetPrinterDataBinary(hPrinter, REGVAL_PRINTER_DATA_SIZE, REGVAL_PRINTER_DATA, pPrinterData, dwSize) && BSetPrinterDataBinary(hPrinter, REGVAL_KEYWORD_SIZE, REGVAL_KEYWORD_NAME, pstrKeyword, dwKeywordSize); } if (pstrKeyword) MemFree(pstrKeyword); VFreeParserInfo(&ParserInfo); if (pCombineOptions) MemFree(pCombineOptions); return bResult; } BOOL BSetPrinterDataDWord( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, IN DWORD dwValue ) /*++ Routine Description: Save a DWORD value to the registry under PrinerDriverData key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value dwValue - Specifies the value to be saved Return Value: TRUE if successful, FALSE otherwise --*/ { DWORD dwStatus; dwStatus = SetPrinterData(hPrinter, (PTSTR) ptstrRegKey, REG_DWORD, (PBYTE) &dwValue, sizeof(dwValue)); if (dwStatus != ERROR_SUCCESS) ERR(("Couldn't save printer data '%ws': %d\n", ptstrRegKey, dwStatus)); return (dwStatus == ERROR_SUCCESS); } BOOL BSetPrinterDataBinary( IN HANDLE hPrinter, IN LPCTSTR ptstrSizeKey, IN LPCTSTR ptstrDataKey, IN PVOID pvData, IN DWORD dwSize ) /*++ Routine Description: Save binary data to the registry under PrinterDriverData key Arguments: hPrinter - Handle to the printer object ptstrSizeKey - Name of the registry value which contains the binary data size ptstrDataKey - Name of the registry value which contains the binary data itself pvData - Points to the binary data to be saved dwSize - Specifies the binary data size in bytes Return Value: TRUE if successful, FALSE if there is an error --*/ { if (SetPrinterData(hPrinter, (PTSTR) ptstrSizeKey, REG_DWORD, (PBYTE) &dwSize, sizeof(dwSize)) != ERROR_SUCCESS || SetPrinterData(hPrinter, (PTSTR) ptstrDataKey, REG_BINARY, pvData, dwSize) != ERROR_SUCCESS) { ERR(("Couldn't save printer data '%ws'/'%ws'\n", ptstrSizeKey, ptstrDataKey)); return FALSE; } return TRUE; } BOOL BSetPrinterDataString( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, IN LPCTSTR ptstrValue, IN DWORD dwType ) /*++ Routine Description: Save a string value under PrinerDriverData registry key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value ptstrValue - Points to string value to be saved dwType - Specifies string type: REG_SZ or REG_MULTI_SZ Return Value: TRUE if successful, FALSE if there is an error Note: If ptstrValue parameter is NULL, the specified registry value is deleted. --*/ { DWORD dwStatus, dwSize; if (ptstrValue != NULL) { if (dwType == REG_SZ) dwSize = SIZE_OF_STRING(ptstrValue); else { LPCTSTR p = ptstrValue; while (*p) p += _tcslen(p) + 1; dwSize = ((DWORD)(p - ptstrValue) + 1) * sizeof(TCHAR); } dwStatus = SetPrinterData(hPrinter, (PTSTR) ptstrRegKey, dwType, (PBYTE) ptstrValue, dwSize); if (dwStatus != ERROR_SUCCESS) ERR(("Couldn't save printer data '%ws': %d\n", ptstrRegKey, dwStatus)); } else { dwStatus = DeletePrinterData(hPrinter, (PTSTR) ptstrRegKey); if (dwStatus == ERROR_FILE_NOT_FOUND) dwStatus = ERROR_SUCCESS; if (dwStatus != ERROR_SUCCESS) ERR(("Couldn't delete printer data '%ws': %d\n", ptstrRegKey, dwStatus)); } return (dwStatus == ERROR_SUCCESS); } BOOL BSetPrinterDataMultiSZPair( IN HANDLE hPrinter, IN LPCTSTR ptstrRegKey, IN LPCTSTR ptstrValue, IN DWORD dwSize ) /*++ Routine Description: Save a MULTI_SZ value under PrinerDriverData registry key Arguments: hPrinter - Specifies the printer object ptstrRegKey - Specifies the name of registry value ptstrValue - Points to MULTI_SZ value to be saved dwSize - Specifies the size of the MULTI_SZ value in bytes Return Value: TRUE if successful, FALSE if there is an error --*/ { DWORD dwStatus; ASSERT(BVerifyMultiSZPair(ptstrValue, dwSize)); dwStatus = SetPrinterData(hPrinter, (PTSTR) ptstrRegKey, REG_MULTI_SZ, (PBYTE) ptstrValue, dwSize); if (dwStatus != ERROR_SUCCESS) ERR(("Couldn't save printer data '%ws': %d\n", ptstrRegKey, dwStatus)); return (dwStatus == ERROR_SUCCESS); } BOOL BSaveDeviceHalftoneSetup( HANDLE hPrinter, DEVHTINFO *pDevHTInfo ) /*++ Routine Description: Save device halftone setup information to registry Arguments: hPrinter - Handle to the printer pDevHTInfo - Pointer to device halftone setup information Return Value: TRUE if successful, FALSE otherwise --*/ { return SetPrinterData(hPrinter, REGVAL_CURRENT_DEVHTINFO, REG_BINARY, (PBYTE) pDevHTInfo, sizeof(DEVHTINFO)) == ERROR_SUCCESS; } BOOL BSaveTTSubstTable( IN HANDLE hPrinter, IN TTSUBST_TABLE pTTSubstTable, IN DWORD dwSize ) /*++ Routine Description: Save TrueType font substitution table in registry Arguments: hPrinter - Handle to the current printer pTTSubstTable - Pointer to font substitution table to be saved dwSize - Size of font substitution table, in bytes Return Value: TRUE if successful, FALSE if there is an error Note: Previous version pscript driver used to save font substitution table as two separate keys: one for size and the other for actual data. We only need the data key now. But we should save the size as well to be compatible with old drivers. --*/ { return BSetPrinterDataMultiSZPair(hPrinter, REGVAL_FONT_SUBST_TABLE, pTTSubstTable, dwSize) && BSetPrinterDataDWord(hPrinter, REGVAL_FONT_SUBST_SIZE_PS40, dwSize); } BOOL BSaveFormTrayTable( IN HANDLE hPrinter, IN FORM_TRAY_TABLE pFormTrayTable, IN DWORD dwSize ) /*++ Routine Description: Save form-to-tray assignment table in registry Arguments: hPrinter - Handle to the current printer pFormTrayTable - Pointer to the form-to-tray assignment table to be saved dwSize - Size of the form-to-tray assignment table, in bytes Return Value: TRUE if successful, FALSE if there is an error --*/ { // // Save the table in current format and then call driver-specific // functions to save the information in NT 4.0 format. // return (BSaveAsOldVersionFormTrayTable(hPrinter, pFormTrayTable, dwSize)); } #endif // !KERNEL_MODE FORM_TRAY_TABLE PGetFormTrayTable( IN HANDLE hPrinter, OUT PDWORD pdwSize ) /*++ Routine Description: Retrieve form-to-tray assignment table from registry Arguments: hPrinter - Handle to the printer object pdwSize - Returns the form-to-tray assignment table size Return Value: Pointer to form-to-tray assignment table read from the registry NULL if there is an error --*/ { FORM_TRAY_TABLE pFormTrayTable; DWORD dwSize; // // Call either PSGetFormTrayTable or UniGetFormTrayTable // pFormTrayTable = PGetAndConvertOldVersionFormTrayTable(hPrinter, &dwSize); if (pFormTrayTable != NULL && pdwSize != NULL) *pdwSize = dwSize; return pFormTrayTable; } BOOL BSearchFormTrayTable( IN FORM_TRAY_TABLE pFormTrayTable, IN PTSTR ptstrTrayName, IN PTSTR ptstrFormName, IN OUT PFINDFORMTRAY pFindData ) /*++ Routine Description: Find the specified tray-form pair in a form-to-tray assignment table Arguments: pFormTrayTable - Specifies a form-to-tray assignment table to be searched ptstrTrayName - Specifies the interested tray name ptstrFormName - Specifies the interested form name pFindData - Data structure used to keep information from one call to the next Return Value: TRUE if the specified tray-form pair is found in the table FALSE otherwise NOTE: If either ptstrTrayName or ptstrFormName is NULL, they'll act as wildcard and match any tray name or form name. The caller must call ResetFindFormTray(pFormTrayTable, pFindData) before calling this function for the very first time. --*/ { PTSTR ptstrNextEntry; BOOL bFound = FALSE; // // Make sure pFindData is properly initialized // ASSERT(pFindData->pvSignature == pFindData); ptstrNextEntry = pFindData->ptstrNextEntry; while (*ptstrNextEntry) { PTSTR ptstrTrayField, ptstrFormField, ptstrPrinterFormField; // // Extract information from the current table entry // ptstrTrayField = ptstrNextEntry; ptstrNextEntry += _tcslen(ptstrNextEntry) + 1; ptstrFormField = ptstrNextEntry; ptstrNextEntry += _tcslen(ptstrNextEntry) + 1; // // Check if we found a matching entry // if ((ptstrTrayName == NULL || _tcscmp(ptstrTrayName, ptstrTrayField) == EQUAL_STRING) && (ptstrFormName == NULL || _tcscmp(ptstrFormName, ptstrFormField) == EQUAL_STRING)) { pFindData->ptstrTrayName = ptstrTrayField; pFindData->ptstrFormName = ptstrFormField; bFound = TRUE; break; } } pFindData->ptstrNextEntry = ptstrNextEntry; return bFound; } BOOL BGetPrinterProperties( IN HANDLE hPrinter, IN PRAWBINARYDATA pRawData, OUT PPRINTERDATA pPrinterData ) /*++ Routine Description: Return the current printer-sticky property data Arguments: hPrinter - Specifies a handle to the current printer pRawData - Points to raw binary printer description data pPrinterData - Buffer for storing the retrieved printer property info Return Value: TRUE if successful, FALSE if there is an error --*/ { PVOID pvRegData; PSTR pstrKeyword; DWORD dwRegDataSize, dwKeywordSize, dwFeatureCount, dwVersion; POPTSELECT pCombineOptions; PUIINFO pUIInfo; PARSERINFO ParserInfo; // // Allocate a buffer to hold printer property data and // read the property property data from the registry. // if (pvRegData = PvGetPrinterDataBinary(hPrinter, REGVAL_PRINTER_DATA_SIZE, REGVAL_PRINTER_DATA, &dwRegDataSize)) { // // Convert the printer property data from the registry to current version // ZeroMemory(pPrinterData, sizeof(PRINTERDATA)); CopyMemory(pPrinterData, pvRegData, min(sizeof(PRINTERDATA), dwRegDataSize)); pPrinterData->wDriverVersion = gwDriverVersion; pPrinterData->wSize = sizeof(PRINTERDATA); if (pPrinterData->wReserved2 != 0 || pPrinterData->dwChecksum32 != pRawData->dwChecksum32) { InitDefaultOptions(pRawData, pPrinterData->aOptions, MAX_PRINTER_OPTIONS, MODE_PRINTER_STICKY); pPrinterData->wReserved2 = 0; pPrinterData->dwChecksum32 = pRawData->dwChecksum32; pPrinterData->dwOptions = pRawData->dwPrinterFeatures; pPrinterData->wProtocol = PROTOCOL_ASCII; pPrinterData->dwFlags |= PFLAGS_CTRLD_AFTER; pPrinterData->wMinoutlinePPEM = DEFAULT_MINOUTLINEPPEM; pPrinterData->wMaxbitmapPPEM = DEFAULT_MAXBITMAPPPEM; } // // Call driver-specific conversion to give them a chance to touch up // (VOID) BConvertPrinterPropertiesData(hPrinter, pRawData, pPrinterData, pvRegData, dwRegDataSize); } else { if (!BGetDefaultPrinterProperties(hPrinter, pRawData, pPrinterData)) return FALSE; } // // At this point we should get a valid PrinterData or a // default PrinterData. Propagate Feature.Options to // PrinterData options array if possible // ParserInfo.pRawData = NULL; ParserInfo.pInfoHeader = NULL; if (((pCombineOptions = MemAllocZ(MAX_COMBINED_OPTIONS * sizeof(OPTSELECT))) == NULL) || ((pUIInfo = PGetUIInfo(hPrinter, pRawData, pCombineOptions, pPrinterData->aOptions, &ParserInfo, &dwFeatureCount)) == NULL)) { // // We have to fail the function if out of memory, or PGetUIInfo returns NULL (in which // case pCombinOptions won't have valid option indices). // // Make sure free any allocated memory. // ERR(("pCombinOptions or pUIInfo is NULL\n")); if (pvRegData) MemFree(pvRegData); if (pCombineOptions) MemFree(pCombineOptions); return FALSE; } // // set the ADD_EURO flag if it has not intentionally been set to FALSE // if (pUIInfo) { if (!(pPrinterData->dwFlags & PFLAGS_EURO_SET)) { if (pUIInfo->dwFlags & FLAG_ADD_EURO) pPrinterData->dwFlags |= PFLAGS_ADD_EURO; pPrinterData->dwFlags |= PFLAGS_EURO_SET; } } VUpdatePrivatePrinterData(hPrinter, pPrinterData, MODE_READ, pUIInfo, pCombineOptions); if ((pstrKeyword = PvGetPrinterDataBinary(hPrinter, REGVAL_KEYWORD_SIZE, REGVAL_KEYWORD_NAME, &dwKeywordSize)) && dwKeywordSize) { // // Skip merging in the keyword feature.option if the driver version // is less than version 3. This is so point and print to OS version less // than NT5 will work. REGVAL_PRINTER_INITED exists only for version 3 // or greater driver // if (!BGetPrinterDataDWord(hPrinter, REGVAL_PRINTER_INITED, &dwVersion)) *pstrKeyword = NUL; // // Convert feature.option keyword names to option indices // VConvertKeywordToIndex(hPrinter, pstrKeyword, dwKeywordSize, pPrinterData->aOptions, pRawData, pUIInfo, pCombineOptions, dwFeatureCount); MemFree(pstrKeyword); } else { SeparateOptionArray(pRawData, pCombineOptions, pPrinterData->aOptions, MAX_PRINTER_OPTIONS, MODE_PRINTER_STICKY); } VFreeParserInfo(&ParserInfo); if (pCombineOptions) MemFree(pCombineOptions); if (pvRegData) MemFree(pvRegData); return TRUE; } BOOL BGetDefaultPrinterProperties( IN HANDLE hPrinter, IN PRAWBINARYDATA pRawData, OUT PPRINTERDATA pPrinterData ) /*++ Routine Description: Return the default printer-sticky property data Arguments: hPrinter - Specifies a handle to the current printer pRawData - Points to raw binary printer description data pPrinterData - Buffer for storing the default printer property info Return Value: TRUE if successful, FALSE if there is an error --*/ { PINFOHEADER pInfoHdr; PUIINFO pUIInfo; // // Allocate memory to hold the default printer property data // ASSERT(pPrinterData && pRawData); ZeroMemory(pPrinterData, sizeof(PRINTERDATA)); pPrinterData->wDriverVersion = gwDriverVersion; pPrinterData->wSize = sizeof(PRINTERDATA); // // Get default printer-sticky option values // InitDefaultOptions(pRawData, pPrinterData->aOptions, MAX_PRINTER_OPTIONS, MODE_PRINTER_STICKY); pPrinterData->dwChecksum32 = pRawData->dwChecksum32; pPrinterData->dwOptions = pRawData->dwPrinterFeatures; // // Ask the parser for a new binary data instance and // use it to initialize the remaining fields of PRINTERDATA. // if (pInfoHdr = InitBinaryData(pRawData, NULL, NULL)) { pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHdr); ASSERT(pUIInfo != NULL); pPrinterData->dwFreeMem = pUIInfo->dwFreeMem; pPrinterData->dwWaitTimeout = pUIInfo->dwWaitTimeout; pPrinterData->dwJobTimeout = pUIInfo->dwJobTimeout; if (pUIInfo->dwFlags & FLAG_TRUE_GRAY) // transfer the default into printer-sticky data pPrinterData->dwFlags |= (PFLAGS_TRUE_GRAY_TEXT | PFLAGS_TRUE_GRAY_GRAPH); FreeBinaryData(pInfoHdr); } // // Initialize any remaining fields // pPrinterData->wProtocol = PROTOCOL_ASCII; pPrinterData->dwFlags |= PFLAGS_CTRLD_AFTER; pPrinterData->wMinoutlinePPEM = DEFAULT_MINOUTLINEPPEM; pPrinterData->wMaxbitmapPPEM = DEFAULT_MAXBITMAPPPEM; #ifndef KERNEL_MODE // // Determine whether the system is running in a metric country. // if (IsMetricCountry()) pPrinterData->dwFlags |= PFLAGS_METRIC; // // Ignore device fonts on non-1252 code page systems. // // NOTE: Adobe wants this to be turned off for NT4 driver. // For NT5 driver, we need to investigate and make sure // this doesn't break anything before turning this off. // Specifically, watch out for NT4-client to NT5 server // connection case. // // Fix MS bug #121883, Adobe bug #235417 // #if 0 #ifndef WINNT_40 if (GetACP() != 1252) pPrinterData->dwFlags |= PFLAGS_IGNORE_DEVFONT; #endif // !WINNT_40 #endif #endif // !KERNEL_MODE return TRUE; } LPCTSTR PtstrSearchDependentFileWithExtension( LPCTSTR ptstrDependentFiles, LPCTSTR ptstrExtension ) /*++ Routine Description: Search the list of dependent files (in REG_MULTI_SZ format) for a file with the specified extension Arguments: ptstrDependentFiles - Points to the list of dependent files ptstrExtension - Specifies the interested filename extension Return Value: Points to the first filename in the dependent file list with the specified extension --*/ { if (ptstrDependentFiles == NULL) { WARNING(("Driver dependent file list is NULL\n")); return NULL; } while (*ptstrDependentFiles != NUL) { LPCTSTR ptstr, ptstrNext; // // Go the end of current string // ptstr = ptstrDependentFiles + _tcslen(ptstrDependentFiles); ptstrNext = ptstr + 1; // // Search backward for '.' character // while (--ptstr >= ptstrDependentFiles) { if (*ptstr == TEXT('.')) { // // If the extension matches, return a pointer to // the current string // if (_tcsicmp(ptstr, ptstrExtension) == EQUAL_STRING) return ptstrDependentFiles; break; } } ptstrDependentFiles = ptstrNext; } return NULL; } PTSTR PtstrGetDriverDirectory( LPCTSTR ptstrDriverDllPath ) /*++ Routine Description: Figure out printer driver directory from the driver DLL's full pathname Arguments: ptstrDriverDllPath - Driver DLL's full pathname Return Value: Pointer to the printer driver directory string NULL if there is an error The returned directory contains a trailing backslash. Caller is responsible for freeing the returned string. --*/ { PTSTR ptstr; INT iLength; ASSERT(ptstrDriverDllPath != NULL); if ((ptstr = _tcsrchr(ptstrDriverDllPath, TEXT(PATH_SEPARATOR))) != NULL) iLength = (INT)(ptstr - ptstrDriverDllPath) + 1; else { WARNING(("Driver DLL path is not fully qualified: %ws\n", ptstrDriverDllPath)); iLength = 0; } if ((ptstr = MemAlloc((iLength + 1) * sizeof(TCHAR))) != NULL) { CopyMemory(ptstr, ptstrDriverDllPath, iLength * sizeof(TCHAR)); ptstr[iLength] = NUL; } else ERR(("Memory allocation failed\n")); return ptstr; } LPCTSTR PtstrSearchStringInMultiSZPair( LPCTSTR ptstrMultiSZ, LPCTSTR ptstrKey ) /*++ Routine Description: Search for the specified key in MultiSZ key-value string pairs Arguments: ptstrMultiSZ - Points to the data to be searched ptstrKey - Specifies the key string Return Value: Pointer to the value string corresponding to the specified key string; NULL if the specified key string is not found --*/ { ASSERT(ptstrMultiSZ != NULL); while (*ptstrMultiSZ != NUL) { // // If the current string matches the specified key string, // then return the corresponding value string // if (_tcsicmp(ptstrMultiSZ, ptstrKey) == EQUAL_STRING) return ptstrMultiSZ + _tcslen(ptstrMultiSZ) + 1; // // Otherwise, advance to the next string pair // ptstrMultiSZ += _tcslen(ptstrMultiSZ) + 1; ptstrMultiSZ += _tcslen(ptstrMultiSZ) + 1; } return NULL; } BOOL BVerifyMultiSZPair( LPCTSTR ptstrData, DWORD dwSize ) /*++ Routine Description: Verify the input data block is in REG_MULTI_SZ format and it consists of multiple string pairs Arguments: ptstrData - Points to the data to be verified dwSize - Size of the data block in bytes Return Value: NONE --*/ { LPCTSTR ptstrEnd; // // Size must be even // ASSERTMSG(dwSize % sizeof(TCHAR) == 0, ("Size is not even: %d\n", dwSize)); dwSize /= sizeof(TCHAR); // // Go through one string pair during each iteration // ptstrEnd = ptstrData + dwSize; while (ptstrData < ptstrEnd && *ptstrData != NUL) { while (ptstrData < ptstrEnd && *ptstrData++ != NUL) NULL; if (ptstrData >= ptstrEnd) { ERR(("Corrupted MultiSZ pair\n")); return FALSE; } while (ptstrData < ptstrEnd && *ptstrData++ != NUL) NULL; if (ptstrData >= ptstrEnd) { ERR(("Corrupted MultiSZ pair\n")); return FALSE; } } // // Look for the last terminating NUL character // if (ptstrData++ >= ptstrEnd) { ERR(("Missing the last NUL terminator\n")); return FALSE; } if (ptstrData < ptstrEnd) { ERR(("Redundant data after the last NUL terminator\n")); } return TRUE; } BOOL BVerifyMultiSZ( LPCTSTR ptstrData, DWORD dwSize ) /*++ Routine Description: Verify the input data block is in REG_MULTI_SZ format Arguments: ptstrData - Points to the data to be verified dwSize - Size of the data block in bytes Return Value: NONE --*/ { LPCTSTR ptstrEnd; // // Size must be even // ASSERTMSG(dwSize % sizeof(TCHAR) == 0, ("Size is not even: %d\n", dwSize)); dwSize /= sizeof(TCHAR); ptstrEnd = ptstrData + dwSize; while (ptstrData < ptstrEnd && *ptstrData != NUL) { while (ptstrData < ptstrEnd && *ptstrData++ != NUL) NULL; if (ptstrData >= ptstrEnd) { ERR(("Corrupted MultiSZ pair\n")); return FALSE; } } // // Look for the last terminating NUL character // if (ptstrData++ >= ptstrEnd) { ERR(("Missing the last NUL terminator\n")); return FALSE; } if (ptstrData < ptstrEnd) { ERR(("Redundant data after the last NUL terminator\n")); } return TRUE; } DWORD DwCountStringsInMultiSZ( IN LPCTSTR ptstrData ) { DWORD dwCount = 0; if (ptstrData) { while (*ptstrData) { dwCount++; ptstrData += wcslen(ptstrData); ptstrData++; } } return dwCount; }