You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1495 lines
35 KiB
1495 lines
35 KiB
|
|
/*++
|
|
|
|
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;
|
|
}
|
|
|