|
|
/*****************************************************************************\
* MODULE: webpnp.cxx * * This module contains routines which read/write printer-configuration * data to a BIN-File. The file format is depicted below. The file begins * with a header indicating the number of (pData) items. THIS DOES NOT * include the DEVMODEW in its item-count. So, at a minimum, this code * could result in the setting of a DEVMODE, or just setting the printer * data, depending upon the header information. * * * DEVBIN_HEAD DEVBIN_INFO ...-> DEVBIN_INFO * -------------------------------------------------------------------------- * | | cbSize | cbSize | * | bDevMode |------------------------------|------------------------------| * | cItems | | | | cbData | | | | cbData | * | | Type | Key | Name |----------| Type | Key | Name |----------| * | | | | | DevModeW | | | | pData 0 | * -------------------------------------------------------------------------- * * The usage scenario is for webWritePrinterInfo() to query a printer and * write out the DEVMODEW and Printer-Configuration data to this file-format. * On a call to webReadPrinterInfo(), a particular printer is opened, and * the BIN-File is read. The printer is then reset to the information * contained in the BIN-File. This is accomplished by doing a GetPrinter(2) * on the opened-printer, then re-configuring the PRINT_INFO_2 information * and reseting the the printer through SetPrinter(2). * * Likewise, if there exists printer-data, the information is set to the * opened printer through SetPrinterData() calls. * * * NOTE: The DEVMODE is always the FIRST entry in this file following the * DEVBIN_HEAD. * * NOTE: The (cItems) only refers to the (Printer-Data) fields. It does * not count the DEVMODEW. * * NOTE: The processing for ICM-Profile enumeration is performed in unicode * strings and only converted to TCHAR type strings on callbacks to * the caller of the enum API. This is desirable to maintain a level * of consistency when dealing with text. * * * Copyright (C) 1996-1997 Microsoft Corporation * Copyright (C) 1996-1997 Hewlett Packard * * history: * 25-Feb-1997 <chriswil> created. * \*****************************************************************************/
#include "spllibp.hxx"
#include <winspool.h>
#include <winsplp.h>
#include <icm.h>
#include <wininet.h>
/***************************************\
* Static Strings. \***************************************/ static CONST WCHAR s_wszCopyFiles[] = L"CopyFiles"; static CONST WCHAR s_wszDir[] = L"Directory"; static CONST WCHAR s_wszFil[] = L"Files"; static CONST WCHAR s_wszMod[] = L"Module"; static CONST CHAR s_szGCFP[] = "GenerateCopyFilePaths";
/*****************************************************************************\
* web_GAlloc (Local Routine) * * Allocates a block of memory. * \*****************************************************************************/ inline LPVOID web_GAlloc( DWORD cbSize) { return new BYTE[cbSize]; }
/*****************************************************************************\
* web_GFree (Local Routine) * * Deletes the memory-block allocated via web_GAlloc(). * \*****************************************************************************/ inline BOOL web_GFree( LPVOID lpMem) { delete [] lpMem;
return TRUE; }
/*****************************************************************************\
* web_AlignSize (Local Routine) * * Returns size (bytes) of the memory-block. This returns a 64 bit aligned * value. * \*****************************************************************************/ inline DWORD web_AlignSize( DWORD cbSize) { return ((cbSize & 7) ? cbSize + (8 - (cbSize & 7)) : cbSize); }
/*****************************************************************************\
* web_StrSizeW (Local Routine) * * Returns size (bytes) of the string. This includes the NULL terminator. * \*****************************************************************************/ inline DWORD web_StrSizeW( LPCWSTR lpszStr) { return ((lstrlenW(lpszStr) + 1) * sizeof(WCHAR)); }
/*****************************************************************************\
* web_NextStrW (Local Routine) * * Returns pointer to the next-item in a string array. * \*****************************************************************************/ inline LPWSTR web_NextStrW( LPCWSTR lpszStr) { return ((LPWSTR)lpszStr + (lstrlenW(lpszStr) + 1)); }
/*****************************************************************************\
* web_NextItem (Local Routine) * * Returns pointer to the next-item in the BIN-File. * \*****************************************************************************/ inline LPDEVBIN_INFO web_NextItem( LPDEVBIN_INFO lpInfo) { return (LPDEVBIN_INFO)(((LPBYTE)lpInfo) + lpInfo->cbSize); }
/*****************************************************************************\
* web_MBtoWC (Local Routine) * * Converts a MultiByte string to a Unicode string. * \*****************************************************************************/ inline DWORD web_MBtoWC( LPWSTR lpszWC, LPCSTR lpszMB, DWORD cbSize) { cbSize = (DWORD)MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszMB, -1, lpszWC, (int)(cbSize / sizeof(WCHAR)));
return (cbSize * sizeof(WCHAR)); }
/*****************************************************************************\
* web_WCtoTC (Local Routine) * * Converts a Unicode string to a string appropriate for the built library. * The size must account for the NULL terminator when specifying size. * \*****************************************************************************/ inline LPTSTR web_WCtoTC( LPCWSTR lpwszWC, DWORD cchWC) { LPTSTR lpszTC; DWORD cbSize;
cbSize = cchWC * sizeof(TCHAR);
if (lpszTC = (LPTSTR)web_GAlloc(cbSize)) {
#ifdef UNICODE
//
// Use CopyMemory, not lstrcpyn. This allows strings
// with nulls in them...(e.g. MULTI_SZ regsitry values
//
CopyMemory(lpszTC, lpwszWC, cbSize);
#else
WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, lpwszWC, cchWC, lpszTC, cchWC, NULL, NULL); #endif
}
return lpszTC; }
/*****************************************************************************\
* web_OpenDirectoryW (Local Routine) * * Open a handle to a directory. * \*****************************************************************************/ inline HANDLE web_OpenDirectoryW( LPCWSTR lpwszDir) { return CreateFileW(lpwszDir, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); }
/*****************************************************************************\
* web_OpenFileRead (Local Routine) * * Open a file for reading. * \*****************************************************************************/ inline HANDLE web_OpenFileRead( LPCTSTR lpszName) { return CreateFile(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); }
/*****************************************************************************\
* web_OpenFileWrite (Local Routine) * * Open a file for writing. * \*****************************************************************************/ inline HANDLE web_OpenFileWrite( LPCTSTR lpszName) { return CreateFile(lpszName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); }
/*****************************************************************************\
* web_LockMap (Local Routine) * * Locks the map-view. * \*****************************************************************************/ inline LPVOID web_LockMap( HANDLE hMap) { LPWEB_FILEMAP lpMap; LPVOID lpPtr = NULL;
if (lpMap = (LPWEB_FILEMAP)hMap) lpPtr = MapViewOfFile(lpMap->hMap, FILE_MAP_READ, 0, 0, 0);
return lpPtr; }
/*****************************************************************************\
* web_UnlockMap (Local Routine) * * Unlocks the map-view. * \*****************************************************************************/ inline BOOL web_UnlockMap( LPVOID lpPtr) { return UnmapViewOfFile(lpPtr); }
/*****************************************************************************\
* web_OpenMap (Local Routine) * * Opens a file-mapping object. * \*****************************************************************************/ HANDLE web_OpenMap( LPCTSTR lpszFile) { LPWEB_FILEMAP lpMap; DWORD cbSize;
if (lpMap = (LPWEB_FILEMAP)web_GAlloc(sizeof(WEB_FILEMAP))) {
lpMap->hFile = web_OpenFileRead(lpszFile);
if (lpMap->hFile && (lpMap->hFile != INVALID_HANDLE_VALUE)) {
if (cbSize = GetFileSize(lpMap->hFile, NULL)) {
lpMap->hMap = CreateFileMapping(lpMap->hFile, NULL, PAGE_READONLY, 0, cbSize, NULL);
if (lpMap->hMap) return (HANDLE)lpMap; }
CloseHandle(lpMap->hFile); }
web_GFree(lpMap); }
return NULL; }
/*****************************************************************************\
* web_CloseMap (Local Routine) * * Closes file-mapping object. * \*****************************************************************************/ BOOL web_CloseMap( HANDLE hMap) { LPWEB_FILEMAP lpMap; BOOL bRet = FALSE;
if (lpMap = (LPWEB_FILEMAP)hMap) {
CloseHandle(lpMap->hMap); CloseHandle(lpMap->hFile);
bRet = web_GFree(lpMap); }
return bRet; }
/*****************************************************************************\
* web_GAllocStrW (Local Routine) * * Allocates a unicode string buffer. * \*****************************************************************************/ LPWSTR web_GAllocStrW( LPCWSTR lpszStr) { LPWSTR lpszMem; DWORD cbSize;
if (lpszStr == NULL) return NULL;
cbSize = web_StrSizeW(lpszStr);
if (lpszMem = (LPWSTR)web_GAlloc(cbSize)) CopyMemory(lpszMem, lpszStr, cbSize);
return lpszMem; }
/*****************************************************************************\
* web_LoadModuleW * * Loads the module by first looking in the path. If this fails it attempts * to load from the driver-directory. * \*****************************************************************************/ HMODULE web_LoadModuleW( LPCWSTR lpwszMod) { HMODULE hLib = NULL; hLib = LoadLibraryW(lpwszMod);
return hLib; }
/*****************************************************************************\
* web_FindRCharW * * Searches for the first occurence of (cch) in a string in reverse order. * \*****************************************************************************/ LPWSTR web_FindRCharW( LPWSTR lpszStr, WCHAR cch) { int nLimit;
if (nLimit = lstrlenW(lpszStr)) {
lpszStr += nLimit;
while ((*lpszStr != cch) && nLimit--) lpszStr--;
if (nLimit >= 0) return lpszStr; }
return NULL; }
/*****************************************************************************\
* web_GetDrvDirW * * Returns: LPWSTR - the printer driver dir, minus the architecture subdir. * Example: Returns something like "%WINDIR%\SYSTEM32\SPOOL\DRIVERS" * \*****************************************************************************/ LPWSTR web_GetDrvDirW(VOID) { LPWSTR lpwszDrvDir; LPWSTR lpwszFind; DWORD cbSize;
//
// Call once to get size of buffer needed.
//
cbSize = 0; GetPrinterDriverDirectoryW(NULL, NULL, 1, NULL, 0, &cbSize);
//
// Alloc a buffer.
//
if (cbSize && (lpwszDrvDir = (LPWSTR)web_GAlloc(cbSize)) ) { //
// Get the driver directory.
//
if (GetPrinterDriverDirectoryW(NULL, NULL, 1, (LPBYTE)lpwszDrvDir, cbSize, &cbSize)) {
//
// Find the parent-directory of the driver-path.
//
if (lpwszFind = web_FindRCharW(lpwszDrvDir, L'\\')) {
*lpwszFind = L'\0';
return lpwszDrvDir; } } //
// Free memory if we fail.
//
web_GFree(lpwszDrvDir); }
return NULL; }
/*****************************************************************************\
* web_BuildNameW * * Takes path, name, extension strings and builds a fully-qualified * string representing the file. This can also be used to build other * names. * \*****************************************************************************/ LPWSTR web_BuildNameW( LPCWSTR lpwszPath, LPCWSTR lpwszName, LPCWSTR lpwszExt) { DWORD cch; LPWSTR lpwszFull;
//
// Calculate the size necessary to hold the full-path filename.
//
cch = lstrlenW(L"\\"); cch += (lpwszPath ? lstrlenW(lpwszPath) : 0); cch += (lpwszName ? lstrlenW(lpwszName) : 0); cch += (lpwszExt ? lstrlenW(lpwszExt) : 0);
if (lpwszFull = (LPWSTR)web_GAlloc(((cch + 1) * sizeof(WCHAR)))) {
if (lpwszPath) {
if (lpwszExt) StringCchPrintfW(lpwszFull, cch+1, L"%s\\%s%s", lpwszPath, lpwszName, lpwszExt); else StringCchPrintfW(lpwszFull, cch+1, L"%s\\%s", lpwszPath, lpwszName);
} else {
if (lpwszExt) StringCchPrintfW(lpwszFull, cch+1, L"%s%s", lpwszName, lpwszExt); else StringCchPrintfW(lpwszFull, cch+1, L"%s", lpwszName); } }
return lpwszFull; }
/*****************************************************************************\
* web_GetCurDirW * * Returns string indicating current-directory. * \*****************************************************************************/ LPWSTR web_GetCurDirW(VOID) { DWORD cbSize; LPWSTR lpwszDir = NULL;
cbSize = GetCurrentDirectoryW(0, NULL);
if (cbSize && (lpwszDir = (LPWSTR)web_GAlloc((cbSize * sizeof(WCHAR))))) GetCurrentDirectoryW(cbSize, lpwszDir);
return lpwszDir; }
/*****************************************************************************\
* web_MakeFullKeyW (Local Routine) * * Creates a full registry-key from the key/sub-key strings. * \*****************************************************************************/ LPWSTR web_MakeFullKeyW( LPCWSTR lpszKey, LPCWSTR lpszSKey) { DWORD cbSize; LPWSTR lpszFKey = NULL;
if (lpszKey && lpszSKey) {
cbSize = web_StrSizeW(lpszKey) + web_StrSizeW(lpszSKey) + sizeof(WCHAR);
if (lpszFKey = (LPWSTR)web_GAlloc(cbSize)) {
if (*lpszKey) StringCbPrintfW(lpszFKey, cbSize, L"%ws\\%ws", lpszKey, lpszSKey); else StringCbPrintfW(lpszFKey, cbSize, L"%ws", lpszSKey); } }
return lpszFKey; }
/*****************************************************************************\
* web_KeyExistsW (Local Routine) * * Checks to see if the printer-key exists. * \*****************************************************************************/ BOOL web_KeyExistsW( HANDLE hPrinter, LPCWSTR lpszKey) { DWORD cbSize; DWORD dwRet;
cbSize = 0; dwRet = EnumPrinterKeyW(hPrinter, lpszKey, NULL, 0, &cbSize);
return (cbSize && (dwRet == ERROR_MORE_DATA)); }
/*****************************************************************************\
* web_EnumPrinterSubKeysW (Local Routine) * * Returns an array of printer-keys for the specified key. * \*****************************************************************************/ LPWSTR web_EnumPrinterSubKeysW( HANDLE hPrinter, LPCWSTR lpszKey) { DWORD cbSize; DWORD dwRet; LPWSTR aszSKeys;
//
// Determine the size necessary for enumerating all the
// sub-keys for this key.
//
cbSize = 0; dwRet = EnumPrinterKeyW(hPrinter, lpszKey, NULL, 0, &cbSize);
//
// If OK, then proceed to the enumeration.
//
if (cbSize && (dwRet == ERROR_MORE_DATA)) { //
// Allocate the space for retrieving the keys.
//
if (aszSKeys = (LPWSTR)web_GAlloc(cbSize)) { //
// Enumerate the sub-keys for this level in (lpszKey).
//
dwRet = EnumPrinterKeyW(hPrinter, lpszKey, aszSKeys, cbSize, &cbSize);
if (dwRet == ERROR_SUCCESS) return aszSKeys;
web_GFree(aszSKeys); } }
return NULL; }
/*****************************************************************************\
* web_EnumPrinterDataW (Local Routine) * * Returns an array of printer-data-values for the specified key. * \*****************************************************************************/ LPPRINTER_ENUM_VALUES web_EnumPrinterDataW( HANDLE hPrinter, LPCWSTR lpszKey, LPDWORD lpcItems) { DWORD cbSize; DWORD dwRet; LPPRINTER_ENUM_VALUES apevData;
//
// Set the enumerated items to zero.
//
*lpcItems = 0;
//
// Determine the size necessary to store the enumerated data.
//
cbSize = 0; dwRet = EnumPrinterDataExW(hPrinter, lpszKey, NULL, 0, &cbSize, lpcItems);
//
// If OK, then proceed to enumerate and write the values to the
// BIN-File.
//
if (cbSize && (dwRet == ERROR_MORE_DATA)) {
if (apevData = (LPPRINTER_ENUM_VALUES)web_GAlloc(cbSize)) { //
// Enumerate all values for the specified key. This
// returns an array of value-structs.
//
dwRet = EnumPrinterDataExW(hPrinter, lpszKey, (LPBYTE)apevData, cbSize, &cbSize, lpcItems);
if (dwRet == ERROR_SUCCESS) return apevData;
web_GFree(apevData); } }
return NULL; }
/*****************************************************************************\
* web_GetPrtNameW * * Returns a Wide-Char string representing the printer-name. * \*****************************************************************************/ LPWSTR web_GetPrtNameW( HANDLE hPrinter) { DWORD cbSize; DWORD cbNeed; LPPRINTER_INFO_2W lppi; LPWSTR lpszPrtName = NULL;
//
// Get the necessary size for the printer-info-struct.
//
cbSize = 0; GetPrinterW(hPrinter, 2, NULL, 0, &cbSize);
//
// Allocate storage for holding the print-info structure.
//
if (cbSize && (lppi = (LPPRINTER_INFO_2W)web_GAlloc(cbSize))) {
if (GetPrinterW(hPrinter, 2, (LPBYTE)lppi, cbSize, &cbNeed)) {
lpszPrtName = web_GAllocStrW(lppi->pPrinterName); }
web_GFree(lppi); }
return lpszPrtName; }
/*****************************************************************************\
* web_GetPrtDataW (Local Routine) * * Returns data for the specified key. * \*****************************************************************************/ LPBYTE web_GetPrtDataW( HANDLE hPrinter, LPCWSTR lpszKey, LPCWSTR lpszVal) { DWORD dwType; DWORD cbSize; DWORD dwRet; LPBYTE lpData;
cbSize = 0; GetPrinterDataExW(hPrinter, lpszKey, lpszVal, &dwType, NULL, 0, &cbSize);
if (cbSize && (lpData = (LPBYTE)web_GAlloc(cbSize))) {
dwRet = GetPrinterDataExW(hPrinter, lpszKey, lpszVal, &dwType, lpData, cbSize, &cbSize);
if (dwRet == ERROR_SUCCESS) return lpData;
web_GFree(lpData); }
return NULL; }
/*****************************************************************************\
* web_CreateDirW (Local Routine) * * Creates the specified directory, if it doesn't exist. * \*****************************************************************************/ BOOL web_CreateDirW( LPCWSTR lpwszDir) { HANDLE hDir; BOOL bRet = FALSE;
hDir = web_OpenDirectoryW(lpwszDir);
if (hDir && (hDir != INVALID_HANDLE_VALUE)) {
CloseHandle(hDir);
bRet = TRUE;
} else {
bRet = CreateDirectoryW(lpwszDir, NULL); }
return bRet; }
/*****************************************************************************\
* web_GetICMDirW (Local Routine) * * Loads the ICM-Module and returns the target color-directory. If the * module isn't loaded then return NULL indicating there is no color * modules to load. * \*****************************************************************************/ LPWSTR web_GetICMDirW( HANDLE hPrinter, DWORD dwCliInfo, LPCWSTR lpwszDir, LPCWSTR lpwszKey) { HMODULE hLib; LPWSTR lpwszMod; WEBGENCOPYFILEPATHPROC pfn; SPLCLIENT_INFO_1 sci; LPWSTR lpwszSrc; LPWSTR lpwszDst; LPWSTR lpwszDrv; LPWSTR lpwszPrtName; DWORD cbSrc; DWORD cbDst; DWORD dwRet; LPWSTR lpwszRet = NULL;
//
// Load associated module. (e.g. color module)
//
if (lpwszMod = (LPWSTR)web_GetPrtDataW(hPrinter, lpwszKey, s_wszMod)) {
if (hLib = web_LoadModuleW(lpwszMod)) { //
// Call into module to normalize the source/target
// paths.
//
if (pfn = (WEBGENCOPYFILEPATHPROC)GetProcAddress(hLib, s_szGCFP)) {
if (lpwszPrtName = web_GetPrtNameW(hPrinter)) {
if (lpwszDrv = web_GetDrvDirW()) {
cbSrc = (MAX_PATH + INTERNET_MAX_HOST_NAME_LENGTH + 1) * sizeof(WCHAR); cbDst = (MAX_PATH + 1) * sizeof(WCHAR);
if (lpwszSrc = (LPWSTR)web_GAlloc(cbSrc)) {
if (lpwszDst = (LPWSTR)web_GAlloc(cbDst)) {
sci.dwSize = sizeof(SPLCLIENT_INFO_1); sci.pMachineName = NULL; sci.pUserName = NULL; sci.dwBuildNum = 0; sci.dwMajorVersion = webGetOSMajorVer(dwCliInfo); sci.dwMinorVersion = webGetOSMinorVer(dwCliInfo);
StringCbPrintfW(lpwszSrc, cbSrc, L"%s\\%s", lpwszDrv, lpwszDir); StringCbCopyW(lpwszDst, cbDst, lpwszDir);
dwRet = (*pfn)(lpwszPrtName, lpwszDir, (LPBYTE)&sci, 1, lpwszSrc, &cbSrc, lpwszDst, &cbDst, COPYFILE_FLAG_SERVER_SPOOLER);
if (dwRet == ERROR_SUCCESS) {
lpwszRet = web_GAllocStrW(lpwszDst); }
web_GFree(lpwszDst); }
web_GFree(lpwszSrc); }
web_GFree(lpwszDrv); }
web_GFree(lpwszPrtName); } }
FreeLibrary(hLib); }
web_GFree(lpwszMod); }
return lpwszRet; }
/*****************************************************************************\
* web_BuildCopyDirW (Local Routine) * * This routine builds the src or dst directory for the CopyFiles. It does the * following things: * * 1) loads optional module (if exists) and calls into it to adjust pathnames * 2) builds fully-qualified CopyFiles directory * 3) return the directory name * * Upon return this will represent the true path to the ICM profiles for the * specified key. * \*****************************************************************************/ LPWSTR web_BuildCopyDirW( HANDLE hPrinter, DWORD dwCliInfo, LPCWSTR lpwszKey) { LPWSTR lpwszDir; LPWSTR lpwszDrvDir; LPWSTR lpwszICM; LPWSTR lpwszRet = NULL;
//
// Return the directory-value for the specified ICM key.
//
if (lpwszDir = (LPWSTR)web_GetPrtDataW(hPrinter, lpwszKey, s_wszDir)) { //
// Return the printer-driver-directory-root.
//
if (lpwszDrvDir = web_GetDrvDirW()) { //
// If called from the server, then call into the color-module
// to get the target-directory. Otherwise, just return the
// driver directory.
//
lpwszICM = web_GetICMDirW(hPrinter, dwCliInfo, lpwszDir, lpwszKey);
//
// If the module loaded and return a valid target-directory, then
// we can return this as our path to the ICM profiles.
//
if (lpwszICM != NULL) { lpwszRet = web_BuildNameW( lpwszDrvDir, lpwszICM, NULL); web_GFree(lpwszICM); // Free up the memory allocated in web_GetICMDirW
}
web_GFree(lpwszDrvDir); }
web_GFree(lpwszDir); }
return lpwszRet; }
/*****************************************************************************\
* web_CopyFilesW (Local Routine) * * This routine copies the point & print "CopyFiles" for the given key. * It copies files from the web point & print setup-source to the directory * specified by the "Directory" value under given key. * * Use : Processed in the context of the print-client. * \*****************************************************************************/ BOOL web_CopyFilesW( HANDLE hPrinter, LPCWSTR lpwszDir, LPCWSTR lpwszKey) { LPWSTR awszFiles; LPWSTR lpwszFile; LPWSTR lpwszCurDir; LPWSTR lpwszSrcFile; LPWSTR lpwszDstFile; LPWSTR lpwszPrtName; BOOL bRet = FALSE;
//
// Get the files under the specified ICM key.
//
if (awszFiles = (LPWSTR)web_GetPrtDataW(hPrinter, lpwszKey, s_wszFil)) { //
// Get our current-directory.
//
if (lpwszCurDir = web_GetCurDirW()) {
if (lpwszPrtName = web_GetPrtNameW(hPrinter)) { //
// For each file in the list, we will need to build our source
// and destination directories to copy our ICM profiles.
//
for (bRet = TRUE, lpwszFile = awszFiles; bRet && *lpwszFile; ) {
bRet = FALSE;
if (lpwszSrcFile = web_BuildNameW(lpwszCurDir, lpwszFile, NULL)) {
if (lpwszDstFile = web_BuildNameW(lpwszDir, lpwszFile, NULL)) { //
// Copy the ICM profile to the target directory.
//
bRet = CopyFileW(lpwszSrcFile, lpwszDstFile, FALSE);
web_GFree(lpwszDstFile); }
web_GFree(lpwszSrcFile); }
lpwszFile = web_NextStrW(lpwszFile); }
web_GFree(lpwszPrtName); }
web_GFree(lpwszCurDir); }
web_GFree(awszFiles); }
return bRet; }
/*****************************************************************************\
* web_TraverseCopyFilesW (Local Routine) * * This routine recursively traverses the printer-registry-settings for * the CopyFiles keys. * * Use : Processed in the context of the print-client. * \*****************************************************************************/ BOOL web_TraverseCopyFilesW( HANDLE hPrinter, LPCWSTR lpwszDir, LPCWSTR lpwszKey) { LPWSTR awszSKeys; LPWSTR lpwszSKey; LPWSTR lpwszFKey; LPWSTR lpwszFDir; DWORD dwType; DWORD dwCliInfo; BOOL bRet = FALSE;
//
// Get the array of keys under the specified key in the registry.
//
if (awszSKeys = web_EnumPrinterSubKeysW(hPrinter, lpwszKey)) { //
// For each sub-key in the array, we need to build the path of
// where we'll place the ICM files.
//
for (bRet = TRUE, lpwszSKey = awszSKeys; *lpwszSKey && bRet; ) {
bRet = FALSE; //
// The enum-routine returns a relative path, so we must build
// a fully-qualified registry-path.
//
if (lpwszFKey = web_MakeFullKeyW(lpwszKey, lpwszSKey)) {
dwCliInfo = webCreateOSInfo();
if (lpwszFDir = web_BuildCopyDirW(hPrinter, dwCliInfo, lpwszFKey)) { //
// Create the ICM directory if it doesn't exist. Proceed
// to traverse the ICM-keys for more sub-keys.
//
if (web_CreateDirW(lpwszFDir)) bRet = web_TraverseCopyFilesW(hPrinter, lpwszFDir, lpwszFKey);
web_GFree(lpwszFDir); }
web_GFree(lpwszFKey); }
lpwszSKey = web_NextStrW(lpwszSKey); }
//
// Free up the array.
//
web_GFree(awszSKeys);
//
// Process the ICM files for the specified key. If this
// is our top-level key (CopyFiles), then don't bother
// with the initialization. i.e. there should be no
// (module, files, directory) keys at this level.
//
if (bRet && lstrcmpiW(lpwszKey, s_wszCopyFiles)) bRet = web_CopyFilesW(hPrinter, lpwszDir, lpwszKey); }
return bRet; }
/*****************************************************************************\
* web_WriteHeader (Local Routine) * * Outputs the header for the BIN-file. The parameters to this routine * specify whether there is a DEVMODE contained in the file, as well as a * count of all the device-data-items. * \*****************************************************************************/ BOOL web_WriteHeader( HANDLE hFile, DWORD cItems, BOOL bDevMode) { DWORD dwWr = 0; DEVBIN_HEAD dbh; BOOL bRet;
//
// Setup the header information.
//
dbh.cItems = cItems; dbh.bDevMode = bDevMode;
//
// Make sure our header is positioned at the beginning of the file.
//
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
//
// Write out the header. Check to make sure that all was written
// succesfully.
//
bRet = WriteFile(hFile, &dbh, sizeof(DEVBIN_HEAD), &dwWr, NULL);
return ((bRet && (dwWr != sizeof(DEVBIN_HEAD))) ? FALSE : bRet); }
/*****************************************************************************\
* web_ReadDevMode (Local Routine) * * Reads the devmode-structure from the BIN-File and sets the printer with * the information. Since our data from the BIN-File is in the format * of UNICODE, we must take care to only use (W) functions. * * Use : Processed in the context of the print-client. * \*****************************************************************************/ BOOL web_ReadDevMode( LPDEVBIN_HEAD lpdbh, HANDLE hPrinter, LPCTSTR lpszPrtName) { LPDEVBIN_INFO lpdbi; LPPRINTER_INFO_2W lppi; LPDEVMODEW lpdm; DWORD cbSize; DWORD cbNeed; BOOL bRet = FALSE;
//
// Set our pointer past the header. The DEVMODE always occupies the
// first entry in our item-list.
//
lpdbi = (LPDEVBIN_INFO)(lpdbh + 1);
//
// First let's see how big our buffer will need to
// be in order to hold the PRINTER_INFO_2W.
//
cbSize = 0; GetPrinterW(hPrinter, 2, NULL, 0, &cbSize);
//
// Allocate storage for holding the print-info structure as well
// as the new devmode data we will be copying.
//
if (cbSize && (lppi = (LPPRINTER_INFO_2W)web_GAlloc(cbSize + lpdbi->cbData))) { //
// Retrieve our current printer-settings.
//
if (GetPrinterW(hPrinter, 2, (LPBYTE)lppi, cbSize, &cbNeed)) { //
// If our printer has a DEVMODE, then we can continue on
// with initializing it with our BIN-File DEVMODE. Otherwise,
// there's no sense setting a devmode to a printer that
// doesn't have one...return TRUE in this case.
//
if (lppi->pDevMode) { //
// Set the new devmode pointer. We will be appending our
// DEVMODE (from the file) to the PRINTER_INFO_2 structure
// that we have just grabbed. Reset the pointers to
// reflect the new-position of the DEVMODE.
//
lppi->pDevMode = (LPDEVMODEW)(((LPBYTE)lppi) + cbSize); lpdm = lppi->pDevMode;
//
// Copy our new devmode to the printer-info struct.
// This is appended on to the structure.
//
// Since this data was obtained by file, the pointer
// is actually a byte offset.
//
CopyMemory(lpdm, ((LPBYTE)lpdbi) + lpdbi->pData, lpdbi->cbData);
//
// Copy the new printer-name to the DEVMODE. Since our
// routines deal strictly with unicode, we need to do
// the correct conversion in case this library was built
// as ansi.
//
#ifdef UNICODE
StringCchCopy(lpdm->dmDeviceName, CCHDEVICENAME, lpszPrtName); #else
lpdm->dmDeviceName[CCHDEVICENAME - 1] = (WCHAR)0;
web_MBtoWC(lpdm->dmDeviceName, lpszPrtName, sizeof(lpdm->dmDeviceName) - sizeof(WCHAR)); #endif
//
// Write out our new printer-settings.
//
bRet = SetPrinterW(hPrinter, 2, (LPBYTE)lppi, 0);
} else {
bRet = TRUE; } }
web_GFree(lppi); }
return bRet; }
/*****************************************************************************\
* web_ReadDevData (Local Routine) * * Reads the device-configuration-data from the BIN-File and sets the * printer with the information. * * Use : Processed in the context of the print-client. * \*****************************************************************************/ BOOL web_ReadDevData( LPDEVBIN_HEAD lpdbh, HANDLE hPrinter) { LPDEVBIN_INFO lpdbi; LPWSTR lpszKey; LPWSTR lpszVal; LPBYTE lpbData; DWORD idx; DWORD dwRet; BOOL bRet;
PWSTR lpszNewKey = NULL; PWSTR lpszNewVal = NULL; PBYTE lpbNewData = NULL;
//
// Set our pointer past the header. The DEVMODE always occupies the
// first entry (If a DEVMODE exists).
//
lpdbi = (LPDEVBIN_INFO)(lpdbh + 1);
//
// If there's a DEVMODE, skip over it and point to the Printer-Data
// entries.
//
if (lpdbh->bDevMode) lpdbi = web_NextItem(lpdbi);
//
// Loop through our items and set the data to the registry.
//
for (idx = 0, bRet = TRUE; (idx < lpdbh->cItems) && bRet; idx++) { //
// Remarshall the byte-offsets into pointers.
//
lpszKey = (LPWSTR)(((LPBYTE)lpdbi) + lpdbi->pKey); lpszVal = (LPWSTR)(((LPBYTE)lpdbi) + lpdbi->pValue); lpbData = (LPBYTE)(((LPBYTE)lpdbi) + lpdbi->pData);
//
// We have to copy the data into a new buffer to avoid 64 bit mis-alignment.
//
lpszNewKey = new WCHAR[(lpdbi->pValue - lpdbi->pKey) / sizeof (WCHAR)]; lpszNewVal = new WCHAR[(lpdbi->pData - lpdbi->pValue) / sizeof (WCHAR)]; lpbNewData = new BYTE[lpdbi->cbData];
if (!lpszNewKey || !lpszVal || !lpbData) { bRet = FALSE; } else { CopyMemory (lpszNewKey, lpszKey, lpdbi->pValue - lpdbi->pKey); CopyMemory (lpszNewVal, lpszVal, lpdbi->pData - lpdbi->pValue); CopyMemory (lpbNewData, lpbData, lpdbi->cbData); }
if (bRet) { //
// Set the printer-data. Since our file-format
// deals with UNICODE-strings, we will use the
// Wide-API.
//
dwRet = SetPrinterDataExW(hPrinter, lpszNewKey, lpszNewVal, lpdbi->dwType, lpbNewData, lpdbi->cbData); //
// If the data is set-correctly, then continue on
// to the next-item. Otherwise, set us up to return
// false.
//
if (dwRet == ERROR_SUCCESS) {
lpdbi = web_NextItem(lpdbi);
} else {
bRet = FALSE; } }
if (lpszNewKey) { delete [] lpszNewKey; lpszNewKey = NULL; }
if (lpszNewVal) { delete [] lpszNewVal; lpszNewVal = NULL; }
if (lpbNewData) { delete [] lpbNewData; lpbNewData = NULL; }
}
//
// Once the registry is initialized with the printer-data, we need
// to parse the printer-data-registry for the ICM (CopyFiles), to
// initialize ICM profiles.
//
if (bRet && web_KeyExistsW(hPrinter, s_wszCopyFiles)) bRet = web_TraverseCopyFilesW(hPrinter, NULL, s_wszCopyFiles);
return bRet; }
/*****************************************************************************\
* web_WriteDevMode (Local Routine) * * Output the DEVMODEW struct to the BIN-File. Since we are storing this * to a file, we make sure that our format is consistent across various * processes. Our choice is to use UNICODE API as a means to query and store * the DEVMODE information. * \*****************************************************************************/ BOOL web_WriteDevMode( HANDLE hFile, HANDLE hPrinter, LPBOOL lpbDevMode) { DWORD cbSize; DWORD cbNeed; DWORD cbDevMode; DWORD dwWr; LPDEVBIN_INFO lpdbi; LPPRINTER_INFO_2W lppi; BOOL bRet = FALSE;
//
// Set the default return for a devmode.
//
*lpbDevMode = FALSE;
//
// Retrieve the size to store the printer-info-2 struct.
//
cbSize = 0; GetPrinterW(hPrinter, 2, NULL, 0, &cbSize);
//
// Allocate the printer-info-2 struct and proceed
// to pull out the devmode information.
//
if (cbSize && (lppi = (LPPRINTER_INFO_2W)web_GAlloc(cbSize))) { //
// Retreive the printer-info-2 and write out the
// DEVMODEW part of this structure.
//
if (GetPrinterW(hPrinter, 2, (LPBYTE)lppi, cbSize, &cbNeed)) { //
// Allocate space for the devmode and our header information.
// Align this on DWORD boundries.
//
if (lppi->pDevMode) { //
// The DEVMODE will need to include driver-specific
// information if such is stored in this DEVMODE.
//
cbDevMode = lppi->pDevMode->dmSize + lppi->pDevMode->dmDriverExtra;
//
// Calculate the DWORD aligned size that we will need
// to store our DEVMODE information to file.
//
cbSize = web_AlignSize(sizeof(DEVBIN_INFO) + cbDevMode);
//
// Get the DEVMODE from the PRINTER_INFO_2 struct. and
// write to file. We want to take care to
//
if (lpdbi = (LPDEVBIN_INFO)web_GAlloc(cbSize)) { //
// Setup our memory-block. The DEVMODEW will
// occupy the first item in the array. Since
// it's not associated with printer-data-information,
// we will not store any (NAME and TYPE).
//
// Since this structure will inevitably be written
// to file, we must marshall the pointers and store
// only byte-offsets.
//
lpdbi->cbSize = cbSize; lpdbi->dwType = 0; lpdbi->pKey = 0; lpdbi->pValue = 0; lpdbi->pData = sizeof(DEVBIN_INFO); lpdbi->cbData = cbDevMode;
CopyMemory(((LPBYTE)lpdbi) + lpdbi->pData, lppi->pDevMode, cbDevMode);
//
// Write the information to file. Check the return
// to verify bytes were written correctly.
//
bRet = WriteFile(hFile, lpdbi, cbSize, &dwWr, NULL);
if (bRet && (dwWr != cbSize)) bRet = FALSE;
//
// Indicate that a devmode was written.
//
*lpbDevMode = TRUE;
web_GFree(lpdbi); }
} else {
bRet = TRUE; *lpbDevMode = FALSE; } }
web_GFree(lppi); }
return bRet; }
/*****************************************************************************\
* web_WriteKeyItem (Local Routine) * * Writes one item to the file. * \*****************************************************************************/ BOOL web_WriteKeyItem( HANDLE hFile, LPCWSTR lpszKey, LPPRINTER_ENUM_VALUES lpPEV) { DWORD cbKeySize; DWORD cbKey; DWORD cbName; DWORD cbSize; DWORD dwWr; LPDEVBIN_INFO lpdbi; BOOL bWrite = FALSE;
//
// Calculate aligned sizes for the key-name and key-value strings.
//
cbKeySize = web_StrSizeW(lpszKey); cbKey = web_AlignSize(cbKeySize); cbName = web_AlignSize(lpPEV->cbValueName);
//
// Calculate size necessary to hold our DEVBIN_INFO information
// which is written to file.
//
cbSize = sizeof(DEVBIN_INFO) + cbKey + cbName + web_AlignSize (lpPEV->cbData);
//
// Allocate space for the structure.
//
if (lpdbi = (LPDEVBIN_INFO)web_GAlloc(cbSize)) { //
// Initialize the structure elements. Since this information
// is written to file, we must take care to convert the
// pointers to byte-offsets.
//
lpdbi->cbSize = cbSize; lpdbi->dwType = lpPEV->dwType; lpdbi->pKey = sizeof(DEVBIN_INFO); lpdbi->pValue = lpdbi->pKey + cbKey; lpdbi->pData = lpdbi->pValue + cbName; lpdbi->cbData = lpPEV->cbData;
CopyMemory(((LPBYTE)lpdbi) + lpdbi->pKey , lpszKey , cbKeySize); CopyMemory(((LPBYTE)lpdbi) + lpdbi->pValue, lpPEV->pValueName, lpPEV->cbValueName); CopyMemory(((LPBYTE)lpdbi) + lpdbi->pData , lpPEV->pData , lpPEV->cbData);
bWrite = WriteFile(hFile, lpdbi, lpdbi->cbSize, &dwWr, NULL);
if (bWrite && (dwWr != lpdbi->cbSize)) bWrite = FALSE;
web_GFree(lpdbi); }
return bWrite; }
/*****************************************************************************\
* web_WriteKeyData (Local Routine) * * Outputs the Printer-Configuration-Data to the BIN-File. This writes * all info for the specified key. * * returns: number of items written to file. * (-1) if an error occurs. * \*****************************************************************************/ int web_WriteKeyData( HANDLE hFile, HANDLE hPrinter, LPCWSTR lpszKey) { LPPRINTER_ENUM_VALUES apevData; BOOL bWr; int idx; int nItems = -1;
//
// Only write data if we are given a valid-key.
//
if ((lpszKey == NULL) || (*lpszKey == (WCHAR)0)) return 0;
//
// Enumerate all data for the specified key and write to the file.
//
if (apevData = web_EnumPrinterDataW(hPrinter, lpszKey, (LPDWORD)&nItems)) { //
// Write all the values for this key.
//
for (idx = 0, bWr = TRUE; (idx < nItems) && bWr; idx++) bWr = web_WriteKeyItem(hFile, lpszKey, apevData + idx);
if (bWr == FALSE) nItems = -1;
web_GFree(apevData); }
return nItems; }
/*****************************************************************************\
* web_WriteDevData (Local Routine) * * Recursively traverses the printer registry and writes out the settings * to file. * \*****************************************************************************/ BOOL web_WriteDevData( HANDLE hFile, HANDLE hPrinter, LPCWSTR lpszKey, LPDWORD lpcItems) { LPWSTR aszSKeys; LPWSTR lpszSKey; LPWSTR lpszFKey; DWORD dwRet; INT cItems; BOOL bRet = FALSE;
if (aszSKeys = web_EnumPrinterSubKeysW(hPrinter, lpszKey)) {
for (bRet = TRUE, lpszSKey = aszSKeys; *lpszSKey && bRet; ) {
if (lpszFKey = web_MakeFullKeyW(lpszKey, lpszSKey)) {
bRet = web_WriteDevData(hFile, hPrinter, lpszFKey, lpcItems);
web_GFree(lpszFKey); }
lpszSKey = web_NextStrW(lpszSKey); }
//
// Free up the array.
//
web_GFree(aszSKeys);
//
// Write the keys/values to the file.
//
if (bRet) {
cItems = web_WriteKeyData(hFile, hPrinter, lpszKey);
if (cItems >= 0) *lpcItems += cItems; else bRet = FALSE; } }
return bRet; }
/*****************************************************************************\
* web_ICMEnumCallBack (Local Routine) * * This routine takes the UNICODE (lpwszDir, lpwszFile) and converts it to * the appropriate string prior to making the callback to the caller. * * Use : Processed in the context of the print-server. * \*****************************************************************************/ BOOL web_ICMEnumCallBack( LPCWSTR lpwszDir, LPCWSTR lpwszFile, FARPROC fpEnum, LPVOID lpParm) { LPTSTR lpszDir; LPTSTR lpszFile; BOOL bRet = FALSE;
if (lpszDir = web_WCtoTC(lpwszDir, lstrlenW(lpwszDir) + 1)) {
if (lpszFile = web_WCtoTC(lpwszFile, lstrlenW(lpwszFile) + 1)) {
bRet = (*(WEBENUMICMPROC)fpEnum)(lpszDir, lpszFile, lpParm);
web_GFree(lpszFile); }
web_GFree(lpszDir); }
return bRet; }
/*****************************************************************************\
* web_EnumFilesW (Local Routine) * * This routine enums the point & print "files" under the "copyfiles" path * for the printer. This is called once we're at the end of a sub-key list * in the registry. * * Use : Processed in the context of the print-server. * \*****************************************************************************/ BOOL web_EnumFilesW( HANDLE hPrinter, DWORD dwCliInfo, LPCWSTR lpwszKey, FARPROC fpEnum, LPVOID lpParm) { LPWSTR awszFiles; LPWSTR lpwszFile; LPWSTR lpwszDir; BOOL bRet = FALSE;
//
// For this ICM key, we will grab the list of ICM profiles that are
// necessary.
//
if (awszFiles = (LPWSTR)web_GetPrtDataW(hPrinter, lpwszKey, s_wszFil)) { //
// Get the src-directory for the ICM profiles under the given key.
//
if (lpwszDir = web_BuildCopyDirW(hPrinter, dwCliInfo, lpwszKey)) {
for (bRet = TRUE, lpwszFile = awszFiles; *lpwszFile && bRet; ) { //
// Make the callback to the caller. In order to do this,
// we must make sure our strings are in the appropriate
// format according to what the caller expects (ie. unicode
// or ansi).
//
bRet = web_ICMEnumCallBack(lpwszDir, lpwszFile, fpEnum, lpParm);
lpwszFile = web_NextStrW(lpwszFile); }
web_GFree(lpwszDir); }
web_GFree(awszFiles); }
return bRet; }
/*****************************************************************************\
* web_EnumCopyFilesW (similar to TraverseCopyFiles) (Local Routine) * * This routine recursively traverses the printer-registry-settings for * the CopyFiles keys. Since the API's used in this routine are only * available in UNICODE, this should be a (W) type routine. * * Use : Processed in the context of the print-server. * \*****************************************************************************/ BOOL web_EnumCopyFilesW( HANDLE hPrinter, DWORD dwCliInfo, LPCWSTR lpwszKey, FARPROC fpEnum, LPVOID lpParm) { LPWSTR awszSKeys; LPWSTR lpwszSKey; LPWSTR lpwszFKey; DWORD dwType; BOOL bRet = FALSE;
//
// Returns an array of keys stored under the printer registry.
//
if (awszSKeys = web_EnumPrinterSubKeysW(hPrinter, lpwszKey)) { //
// For each key, look to see if it contains other sub-keys. We
// recursively traverse the registry until we hit a key with
// no sub-keys.
//
for (bRet = TRUE, lpwszSKey = awszSKeys; *lpwszSKey && bRet; ) {
bRet = FALSE; //
// Since the enum-routine only returns relative key-values,
// we need to build the fully-qualified key-path.
//
if (lpwszFKey = web_MakeFullKeyW(lpwszKey, lpwszSKey)) {
bRet = web_EnumCopyFilesW(hPrinter, dwCliInfo, lpwszFKey, fpEnum, lpParm);
web_GFree(lpwszFKey); } //
// Next key in list.
//
lpwszSKey = web_NextStrW(lpwszSKey); }
//
// Free up the array.
//
web_GFree(awszSKeys);
//
// Process the files for the specified key. If this
// is our top-level key (CopyFiles), then don't bother
// with the initialization. i.e. there should be no
// (module, files, directory) keys at this level.
//
if (bRet && lstrcmpiW(lpwszKey, s_wszCopyFiles)) bRet = web_EnumFilesW(hPrinter, dwCliInfo, lpwszKey, fpEnum, lpParm); }
return bRet; }
/*****************************************************************************\
* webEnumPrinterInfo * * This routine enumerates the information stored in the registery. Depending * upon the (dwType) passed in, it can enumerate different types of information. * * Use : Called from the Printer-Server to enumerate the copyfiles sections * of the registry. This also provides a callback to allow the caller * to trap the profiles so they may be added to the CAB list. * * Use : Called from the printer-server to enumerate ICM information. * \*****************************************************************************/ BOOL webEnumPrinterInfo( HANDLE hPrinter, DWORD dwCliInfo, DWORD dwType, FARPROC fpEnum, LPVOID lpParm) { BOOL bEnum = TRUE;
//
// Call enumeration functions for various enumeration types.
//
switch (dwType) {
case WEB_ENUM_ICM: if (web_KeyExistsW(hPrinter, s_wszCopyFiles)) bEnum = web_EnumCopyFilesW(hPrinter, dwCliInfo, s_wszCopyFiles, fpEnum, lpParm); break;
default: case WEB_ENUM_KEY: // NOT IMPLEMENTED
bEnum = FALSE; }
return bEnum; }
/*****************************************************************************\
* webWritePrinterInfo * * This routine reads the DEVMODE and Configuration-Data from the specified * printer, and writes this to a .BIN file. * * Use : Called from the printer-server to write the registry settings to file. * \*****************************************************************************/ BOOL webWritePrinterInfo( HANDLE hPrinter, LPCTSTR lpszBinFile) { HANDLE hFile; BOOL bDevMode; DWORD cItems; BOOL bRet = FALSE;
//
// Open the BIN file for writing.
//
hFile = web_OpenFileWrite(lpszBinFile);
if (hFile && (hFile != INVALID_HANDLE_VALUE)) { //
// Output the header. This basically reserves
// space at the beginning of the file to store
// the item-count.
//
if (web_WriteHeader(hFile, 0, FALSE)) { //
// Write out the devmode-info.
//
if (web_WriteDevMode(hFile, hPrinter, &bDevMode)) { //
// Write out devdata-info. The (cItems) indicates how
// many driver-specific entries were written.
//
cItems = 0; if (web_WriteDevData(hFile, hPrinter, L"", &cItems)) bRet = web_WriteHeader(hFile, cItems, bDevMode); } }
CloseHandle(hFile); }
return bRet; }
/*****************************************************************************\
* webReadPrinterInfo * * This routine reads the DEVMODE and Configuration-Data from the specified * BIN-File, and sets the printer-handle with the attributes. * * Use : Called from the printer-client to initialize the registry. * \*****************************************************************************/ BOOL webReadPrinterInfo( HANDLE hPrinter, LPCTSTR lpszPrtName, LPCTSTR lpszBinFile) { HANDLE hMap; LPDEVBIN_HEAD lpdbh; BOOL bRet = FALSE;
//
// Open the BIN file for writing.
//
if (hMap = web_OpenMap(lpszBinFile)) {
if (lpdbh = (LPDEVBIN_HEAD)web_LockMap(hMap)) { //
// Only if we have a DevMode should we write out the information.
//
if (!lpdbh->bDevMode || web_ReadDevMode(lpdbh, hPrinter, lpszPrtName)) { //
// Only if we have printer-data items should we proceed
// to write out the information.
//
if (!lpdbh->cItems || web_ReadDevData(lpdbh, hPrinter)) {
bRet = TRUE; } }
web_UnlockMap((LPVOID)lpdbh); }
web_CloseMap(hMap); }
return bRet; }
/*****************************************************************************\
* WebPnpEntry * * This routine is called by PrintWizard prior to installing the printer. * Currently, we can find no value to this, but it is a nice balance to the * WebPnpPostEntry() routine. * * Use : Called from the print-client prior to printer installation. * \*****************************************************************************/ BOOL WebPnpEntry( LPCTSTR lpszCmdLine) { return TRUE; }
BOOL PrinterExists( HANDLE hPrinter) { DWORD cbNeeded; DWORD Error; BOOL rc = FALSE; LPPRINTER_INFO_2 pPrinter; DWORD cbPrinter;
cbPrinter = 0x400; pPrinter = (PPRINTER_INFO_2) web_GAlloc ( cbPrinter );
if( !pPrinter ) return FALSE;
if( !GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbNeeded ) ) { Error = GetLastError( );
if( Error == ERROR_INSUFFICIENT_BUFFER ) { web_GFree (pPrinter); pPrinter = (PPRINTER_INFO_2)web_GAlloc ( cbNeeded );
if( pPrinter ) { cbPrinter = cbNeeded;
if( GetPrinter( hPrinter, 2, (LPBYTE)pPrinter, cbPrinter, &cbNeeded ) ) { rc = TRUE; } } } else if( Error == ERROR_INVALID_HANDLE ) { SetLastError( ERROR_INVALID_PRINTER_NAME ); } } else { rc = TRUE; }
if( pPrinter ) { web_GFree ( pPrinter ); }
return rc; }
/*****************************************************************************\
* WebPnpPostEntry * * This routine is called via PrintWizard after a printer has been added. This * provides the oportunity for the web-pnp-installer to initialize the * registry settings and files according to the information provided in the * BIN-File. The (fConnection) flag indicates whether the printer was * installed via RPC or HTTP. If it was RPC, then it's not necessary to do * any printer-settings. * * Use : Called from the print-client after printer installation. * \*****************************************************************************/ BOOL WebPnpPostEntry( BOOL fConnection, LPCTSTR lpszBinFile, LPCTSTR lpszPortName, LPCTSTR lpszPrtName) { HANDLE hPrinter; PRINTER_DEFAULTS pd; BOOL bRet = TRUE;
if (fConnection == FALSE) { //
// Setup the printer-defaults to
// allow printer-changes.
//
pd.pDatatype = NULL; pd.pDevMode = NULL; pd.DesiredAccess = PRINTER_ALL_ACCESS;
//
// Open the printer specified.
//
if (OpenPrinter((LPTSTR)lpszPrtName, &hPrinter, &pd)) {
if (!PrinterExists(hPrinter) && GetLastError () == ERROR_ACCESS_DENIED) { ConfigurePort( NULL, GetDesktopWindow (), (LPTSTR) lpszPortName); }
bRet = webReadPrinterInfo(hPrinter, lpszPrtName, lpszBinFile);
ClosePrinter(hPrinter); } }
return bRet; }
|