|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
libutil.c
Abstract:
Utility functions
Environment:
Windows NT printer drivers
Revision History:
08/13/96 -davidx- Added CopyString functions and moved SPRINTF functions.
08/13/96 -davidx- Added devmode conversion routine and spooler API wrapper functions.
03/13/96 -davidx- Created it.
--*/
#include "lib.h"
//
// Digit characters used for converting numbers to ASCII
//
const CHAR gstrDigitString[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//
// Variable to control the amount of debug messages generated
//
#if DBG
INT giDebugLevel = DBG_WARNING;
#endif
DWORD HashKeyword( LPCSTR pKeywordStr )
/*++
Routine Description:
Generate a hash value for the given string.
Arguments:
pKeywordStr - The string to generate the hash value for, single byte ANSI null terminated.
Return Value:
Hash value.
--*/
{ LPBYTE pbuf = (LPBYTE) pKeywordStr; DWORD dwHashValue = 0;
//
// Note that only the last 32 characters of the keyword string are significant.
//
while (*pbuf) dwHashValue = (dwHashValue << 1) ^ *pbuf++;
return(dwHashValue); }
PTSTR DuplicateString( IN LPCTSTR ptstrSrc )
/*++
Routine Description:
Make a duplicate of the specified character string
Arguments:
ptstrSrc - Specifies the source string to be duplicated
Return Value:
Pointer to the duplicated string, NULL if there is an error
--*/
{ PTSTR ptstrDest; INT iSize;
if (ptstrSrc == NULL) return NULL;
iSize = SIZE_OF_STRING(ptstrSrc);
if (ptstrDest = MemAlloc(iSize)) CopyMemory(ptstrDest, ptstrSrc, iSize); else ERR(("Couldn't duplicate string: %ws\n", ptstrSrc));
return ptstrDest; }
VOID CopyStringW( OUT PWSTR pwstrDest, IN PCWSTR pwstrSrc, IN INT iDestSize )
/*++
Routine Description:
Copy Unicode string from source to destination
Arguments:
pwstrDest - Points to the destination buffer pwstrSrc - Points to source string iDestSize - Size of destination buffer (in characters)
Return Value:
NONE
Note:
If the source string is shorter than the destination buffer, unused chars in the destination buffer is filled with NUL.
--*/
{ PWSTR pwstrEnd;
ASSERT(pwstrDest && pwstrSrc && iDestSize > 0); pwstrEnd = pwstrDest + (iDestSize - 1);
while ((pwstrDest < pwstrEnd) && ((*pwstrDest++ = *pwstrSrc++) != NUL)) NULL;
while (pwstrDest <= pwstrEnd) *pwstrDest++ = NUL; }
VOID CopyStringA( OUT PSTR pstrDest, IN PCSTR pstrSrc, IN INT iDestSize )
/*++
Routine Description:
Copy ANSI string from source to destination
Arguments:
pstrDest - Points to the destination buffer pstrSrc - Points to source string iDestSize - Size of destination buffer (in characters)
Return Value:
NONE
Note:
If the source string is shorter than the destination buffer, unused chars in the destination buffer is filled with NUL.
--*/
{ PSTR pstrEnd;
ASSERT(pstrDest && pstrSrc && iDestSize > 0); pstrEnd = pstrDest + (iDestSize - 1);
while ((pstrDest < pstrEnd) && (*pstrDest++ = *pstrSrc++) != NUL) NULL;
while (pstrDest <= pstrEnd) *pstrDest++ = NUL; }
PVOID MyGetPrinter( IN HANDLE hPrinter, IN DWORD dwLevel )
/*++
Routine Description:
Wrapper function for GetPrinter spooler API
Arguments:
hPrinter - Identifies the printer in question dwLevel - Specifies the level of PRINTER_INFO_x structure requested
Return Value:
Pointer to a PRINTER_INFO_x structure, NULL if there is an error
--*/
{ PVOID pv = NULL; DWORD dwBytesNeeded;
if (!GetPrinter(hPrinter, dwLevel, NULL, 0, &dwBytesNeeded) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pv = MemAlloc(dwBytesNeeded)) && GetPrinter(hPrinter, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded)) { return pv; }
ERR(("GetPrinter failed: %d\n", GetLastError())); MemFree(pv); return NULL; }
PVOID MyEnumForms( IN HANDLE hPrinter, IN DWORD dwLevel, OUT PDWORD pdwFormsReturned )
/*++
Routine Description:
Wrapper function for EnumForms spooler API
Arguments:
hPrinter - Identifies the printer in question dwLevel - Specifies the level of FORM_INFO_x structure requested pdwFormsReturned - Returns the number of FORM_INFO_x structures enumerated
Return Value:
Pointer to an array of FORM_INFO_x structures, NULL if there is an error
--*/
{ PVOID pv = NULL; DWORD dwBytesNeeded;
if (!EnumForms(hPrinter, dwLevel, NULL, 0, &dwBytesNeeded, pdwFormsReturned) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pv = MemAlloc(dwBytesNeeded)) && EnumForms(hPrinter, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded, pdwFormsReturned)) { return pv; }
ERR(("EnumForms failed: %d\n", GetLastError())); MemFree(pv); *pdwFormsReturned = 0; return NULL; }
#ifndef KERNEL_MODE
PVOID MyGetForm( IN HANDLE hPrinter, IN PTSTR ptstrFormName, IN DWORD dwLevel )
/*++
Routine Description:
Wrapper function for GetForm spooler API
Arguments:
hPrinter - Identifies the printer in question ptstrFormName - Specifies the name of interested form dwLevel - Specifies the level of FORM_INFO_x structure requested
Return Value:
Pointer to a FORM_INFO_x structures, NULL if there is an error
--*/
{ PVOID pv = NULL; DWORD cb;
if (!GetForm(hPrinter, ptstrFormName, dwLevel, NULL, 0, &cb) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pv = MemAlloc(cb)) && GetForm(hPrinter, ptstrFormName, dwLevel, pv, cb, &cb)) { return pv; }
ERR(("GetForm failed: %d\n", GetLastError())); MemFree(pv); return NULL; }
#endif // !KERNEL_MODE
PVOID MyGetPrinterDriver( IN HANDLE hPrinter, IN HDEV hDev, IN DWORD dwLevel )
/*++
Routine Description:
Wrapper function for GetPrinterDriver spooler API
Arguments:
hPrinter - Identifies the printer in question hDev - GDI handle to current printer device context dwLevel - Specifies the level of DRIVER_INFO_x structure requested
Return Value:
Pointer to a DRIVER_INFO_x structure, NULL if there is an error
--*/
{ #if !defined(WINNT_40) || !defined(KERNEL_MODE)
PVOID pv = NULL; DWORD dwBytesNeeded;
if (!GetPrinterDriver(hPrinter, NULL, dwLevel, NULL, 0, &dwBytesNeeded) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pv = MemAlloc(dwBytesNeeded)) && GetPrinterDriver(hPrinter, NULL, dwLevel, pv, dwBytesNeeded, &dwBytesNeeded)) { return pv; }
ERR(("GetPrinterDriver failed: %d\n", GetLastError())); MemFree(pv);
#else // WINNT_40 && KERNEL_MODE
PDRIVER_INFO_3 pDriverInfo3 = NULL;
ASSERT(hDev != NULL);
if (hDev) { //
// hDev is available, so we can use Eng-calls to get driver_info_3 fields.
//
PWSTR pwstrDriverFile, pwstrDataFile; INT iDriverNameSize, iDataNameSize; PWSTR pwstrDepFiles; DWORD dwDepSize, dwDepSizeWithPath; PTSTR ptstrDriverDir = NULL;
//
// EngGetPrinterDriver is not available on NT4. So we'll fake a
// DRIVER_INFO_3 structure and fill in pDriverPath and pDataFile fields.
//
pwstrDriverFile = EngGetDriverName(hDev); pwstrDataFile = EngGetPrinterDataFileName(hDev);
if (!pwstrDriverFile || !pwstrDataFile) { RIP(("Driver and/or data filename is NULL\n")); return NULL; }
//
// The pDependentFiles field is currently only used by PS driver.
//
pwstrDepFiles = PtstrGetPrinterDataString(hPrinter, REGVAL_DEPFILES, &dwDepSize);
if (pwstrDepFiles && !BVerifyMultiSZ(pwstrDepFiles, dwDepSize)) { RIP(("Dependent file list is not in MULTI_SZ format\n")); MemFree(pwstrDepFiles); pwstrDepFiles = NULL; }
if (pwstrDepFiles && ((ptstrDriverDir = PtstrGetDriverDirectory((LPCTSTR)pwstrDriverFile)) == NULL)) { RIP(("Can't get driver directory from driver file name\n")); MemFree(pwstrDepFiles); pwstrDepFiles = NULL; }
iDriverNameSize = SIZE_OF_STRING(pwstrDriverFile); iDataNameSize = SIZE_OF_STRING(pwstrDataFile);
if (pwstrDepFiles == NULL) dwDepSizeWithPath = 0; else dwDepSizeWithPath = dwDepSize + DwCountStringsInMultiSZ((LPCTSTR)pwstrDepFiles) * _tcslen(ptstrDriverDir) * sizeof(TCHAR);
pDriverInfo3 = MemAllocZ(sizeof(DRIVER_INFO_3) + iDriverNameSize+iDataNameSize+dwDepSizeWithPath);
if (pDriverInfo3 == NULL) { ERR(("Memory allocation failed\n")); MemFree(pwstrDepFiles); MemFree(ptstrDriverDir); return NULL; }
pDriverInfo3->cVersion = 3; pDriverInfo3->pDriverPath = (PWSTR) ((PBYTE) pDriverInfo3 + sizeof(DRIVER_INFO_3)); pDriverInfo3->pDataFile = (PWSTR) ((PBYTE) pDriverInfo3->pDriverPath + iDriverNameSize);
CopyMemory(pDriverInfo3->pDriverPath, pwstrDriverFile, iDriverNameSize); CopyMemory(pDriverInfo3->pDataFile, pwstrDataFile, iDataNameSize);
if (pwstrDepFiles) { PTSTR ptstrSrc, ptstrDest; INT iDirLen;
ptstrSrc = pwstrDepFiles; ptstrDest = pDriverInfo3->pDependentFiles = (PWSTR) ((PBYTE) pDriverInfo3->pDataFile + iDataNameSize);
iDirLen = _tcslen(ptstrDriverDir);
while (*ptstrSrc) { INT iNameLen;
//
// Copy the driver dir path (the last char is '\')
//
CopyMemory(ptstrDest, ptstrDriverDir, iDirLen * sizeof(TCHAR)); ptstrDest += iDirLen;
//
// Copy the dependent file name
//
iNameLen = _tcslen(ptstrSrc); CopyMemory(ptstrDest, ptstrSrc, iNameLen * sizeof(TCHAR)); ptstrDest += iNameLen + 1;
ptstrSrc += iNameLen + 1; } }
MemFree(pwstrDepFiles); MemFree(ptstrDriverDir);
return((PVOID)pDriverInfo3); }
#endif // WINNT_40 && KERNEL_MODE
return NULL; }
VOID VGetSpoolerEmfCaps( IN HANDLE hPrinter, OUT PBOOL pbNupOption, OUT PBOOL pbReversePrint, IN DWORD cbOut, OUT PVOID pSplCaps )
/*++
Routine Description:
Figure out what EMF features (such as N-up and reverse-order printing) the spooler can support
Arguments:
hPrinter - Handle to the current printer pbNupOption - Whether spooler supports N-up pbReversePrint - Whether spooler supports reverse-order printing cbOut - size in byte of output buffer pointed by pSplCaps pSplCaps - Get all spooler caps
Return Value:
NONE
--*/
#define REGVAL_EMFCAPS TEXT("PrintProcCaps_EMF")
{ PVOID pvData; DWORD dwSize, dwType, dwStatus;
if (pbNupOption) *pbNupOption = FALSE;
if (pbReversePrint) *pbReversePrint = FALSE;
#if !defined(WINNT_40)
pvData = NULL; dwStatus = GetPrinterData(hPrinter, REGVAL_EMFCAPS, &dwType, NULL, 0, &dwSize);
if ((dwStatus == ERROR_MORE_DATA || dwStatus == ERROR_SUCCESS) && (dwSize >= sizeof(PRINTPROCESSOR_CAPS_1)) && (pvData = MemAlloc(dwSize)) && (GetPrinterData(hPrinter, REGVAL_EMFCAPS, &dwType, pvData, dwSize, &dwSize) == ERROR_SUCCESS)) { PPRINTPROCESSOR_CAPS_1 pEmfCaps = pvData;
if (pbNupOption) *pbNupOption = (pEmfCaps->dwNupOptions & ~1) != 0;
if (pbReversePrint) *pbReversePrint = (pEmfCaps->dwPageOrderFlags & REVERSE_PRINT) != 0;
if (pSplCaps) { CopyMemory(pSplCaps, pEmfCaps, min(cbOut, sizeof(PRINTPROCESSOR_CAPS_1))); } } else { ERR(("GetPrinterData PrintProcCaps_EMF failed: %d\n", dwStatus)); }
MemFree(pvData);
#endif // !WINNT_40
}
PCSTR StripDirPrefixA( IN PCSTR pstrFilename )
/*++
Routine Description:
Strip the directory prefix off a filename (ANSI version)
Arguments:
pstrFilename - Pointer to filename string
Return Value:
Pointer to the last component of a filename (without directory prefix)
--*/
{ PCSTR pstr;
if (pstr = strrchr(pstrFilename, PATH_SEPARATOR)) return pstr + 1;
return pstrFilename; }
#if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
PVOID MemRealloc( IN PVOID pvOldMem, IN DWORD cbOld, IN DWORD cbNew )
/*++
Routine Description:
Change the size of a specified memory block. The size can increase or decrease.
Arguments:
pvOldMem - Pointer to the old memory block to be reallocated. cbOld - old size in bytes of the memory block cbNew - new size in bytes of the reallocated memory block
Return Value:
If succeeds, it returns pointer to the reallocated memory block. Otherwise, it returns NULL.
--*/
{ PVOID pvNewMem;
if (!(pvNewMem = MemAlloc(cbNew))) { ERR(("Memory allocation failed\n")); return NULL; }
if (pvOldMem) { if (cbOld) { CopyMemory(pvNewMem, pvOldMem, min(cbOld, cbNew)); }
MemFree(pvOldMem); }
return pvNewMem; }
#endif // !KERNEL_MODE || USERMODE_DRIVER
|