|
|
/*****************************************************************************\
* MODULE: libpriv.cxx * * Contains the source code for internal routines used throughout the library. * * * Copyright (C) 1996-1998 Hewlett Packard Company. * Copyright (C) 1996-1998 Microsoft Corporation. * * History: * 10-Oct-1997 GFS Initial checkin * 10-Jun-1998 CHW Cleaned. Restructured. * \*****************************************************************************/
#include "libpriv.h"
#define strFree(pszStr) {if (pszStr) GlobalFree((HANDLE)pszStr);}
/*****************************************************************************\
* strAlloc * * Allocates a string from the heap. This pointer must be freed with * a call to strFree(). * \*****************************************************************************/ LPTSTR strAlloc( LPCTSTR pszSrc) { DWORD cbSize; LPTSTR pszDst = NULL;
cbSize = (pszSrc ? ((lstrlen(pszSrc) + 1) * sizeof(TCHAR)) : 0);
if (cbSize) {
if (pszDst = (LPTSTR)GlobalAlloc(GPTR, cbSize)) CopyMemory(pszDst, pszSrc, cbSize); }
return pszDst; }
/*****************************************************************************\
* strLoad * * Get string from resource based upon the ID passed in. * \*****************************************************************************/ LPTSTR strLoad( UINT ids) { char szStr[RES_BUFFER];
if (LoadString(g_hLibInst, ids, szStr, sizeof(szStr)) == 0) szStr[0] = TEXT('\0');
return strAlloc(szStr); }
/*****************************************************************************\
* InitStrings * * \*****************************************************************************/ BOOL InitStrings(VOID) { g_szFmtName = strLoad(IDS_FMTNAME); g_szMsgOptions = strLoad(IDS_MSG_OPTIONS); g_szMsgThunkFail = strLoad(IDS_THUNK32FAIL); g_szPrinter = strLoad(IDS_PRINTER); g_szMsgExists = strLoad(IDS_ALREADY_EXISTS); g_szMsgOptCap = strLoad(IDS_MSG_OPTCAP);
return (g_szFmtName && g_szMsgOptions && g_szMsgThunkFail && g_szPrinter && g_szMsgExists && g_szMsgOptCap ); }
/*****************************************************************************\
* FreeeStrings * * \*****************************************************************************/ VOID FreeStrings(VOID) { strFree(g_szFmtName); strFree(g_szMsgOptions); strFree(g_szMsgThunkFail); strFree(g_szPrinter); strFree(g_szMsgExists); strFree(g_szMsgOptCap); }
/*****************************************************************************\
* prv_StrChr * * Looks for the first location where (c) resides. * \*****************************************************************************/ LPTSTR prv_StrChr( LPCTSTR cs, TCHAR c) { while (*cs != TEXT('\0')) {
if (*cs == c) return (LPTSTR)cs;
cs++; }
// Fail to find c in cs.
//
return NULL; }
/****************************************************************************\
* prv_CheesyHash * * Hash function to convert a string to dword representation. * \****************************************************************************/ DWORD prv_CheesyHash( LPCTSTR lpszIn) { LPDWORD lpdwIn; DWORD cbLeft; DWORD dwTmp; DWORD dwRet = 0;
if (lpszIn && (cbLeft = (lstrlen(lpszIn) * sizeof(TCHAR)))) {
// Process in DWORDs as long as possible
//
for (lpdwIn = (LPDWORD)lpszIn; cbLeft > sizeof(DWORD); cbLeft -= sizeof(DWORD)) {
dwRet ^= *lpdwIn++; }
// Process bytes for whatever's left of the string.
//
if (cbLeft) {
for (dwTmp = 0, lpszIn = (LPTSTR)lpdwIn; *lpszIn; lpszIn++) {
dwTmp |= (DWORD)(TCHAR)(*lpszIn); dwTmp <<= 8; }
dwRet ^= dwTmp; } }
return dwRet; }
/*****************************************************************************\
* prv_ParseHostShare * * Parses the FriendlyName (http://host/printers/share/.printer) into its
* Host/Share components. * * This routine returns allocated pointers that must be freed by the caller. * \*****************************************************************************/ BOOL prv_ParseHostShare( LPCTSTR lpszFriendly, LPTSTR *lpszHost, LPTSTR *lpszShare) { LPTSTR lpszPrt; LPTSTR lpszTmp; LPTSTR lpszPos; BOOL bRet = FALSE;
// Initialize the return buffers to NULL.
//
*lpszHost = NULL; *lpszShare = NULL;
// Parse the host-name and the share name. The (lpszFriendly) is
// currently in the format of http://host[:portnumber]/share. We will
// parse this from left->right since the share-name can be a path (we
// wouldn't really know the exact length). However, we do know the
// location for the host-name, and anything after that should be
// the share-name.
//
// First find the ':'. The host-name should begin two "//" after
// that.
//
if (lpszPrt = memAllocStr(lpszFriendly)) {
if (lpszPos = prv_StrChr(lpszPrt, TEXT(':'))) {
lpszPos++; lpszPos++; lpszPos++;
// Get past the host.
//
if (lpszTmp = prv_StrChr(lpszPos, TEXT('/'))) {
// HostName (includes http).
//
*lpszTmp = TEXT('\0'); *lpszHost = memAllocStr(lpszPrt); *lpszTmp = TEXT('/');
// ShareName.
//
if (lpszPos = prv_StrChr(++lpszTmp, TEXT('/'))) {
lpszPos++;
if (lpszTmp = prv_StrChr(lpszPos, TEXT('/'))) {
*lpszTmp = TEXT('\0'); *lpszShare = memAllocStr(lpszPos); *lpszTmp = TEXT('/');
bRet = TRUE;
} else {
goto BadFmt; }
} else {
goto BadFmt; }
} else {
goto BadFmt; }
} else {
BadFmt: DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32 : prv_ParseHostShare - Invalid name <%s>"), lpszFriendly));
if (*lpszHost) memFreeStr(*lpszHost);
if (*lpszShare) memFreeStr(*lpszShare);
*lpszHost = NULL; *lpszShare = NULL; }
memFreeStr(lpszPrt); }
return bRet; }
/****************************************************************************\
* prv_StrPBrk * * DBCS-Aware version of strpbrk. * * NOTE: If this is ever converted/compiled as unicode, then this function * is broken. It would need to be unicode-aware. * * 26-Jun-1998 : ChrisWil * \****************************************************************************/ LPTSTR prv_StrPBrk( LPCTSTR lpszSrch, LPCTSTR lpszTrgt) { LPTSTR lpszPtr;
if (lpszSrch && lpszTrgt) {
for( ; *lpszSrch; lpszSrch = AnsiNext(lpszSrch)) {
for (lpszPtr = (LPTSTR)lpszTrgt; *lpszPtr; lpszPtr = AnsiNext(lpszPtr)) {
if (*lpszSrch == *lpszPtr) {
// First byte matches--see if we need to check
// second byte
//
if (IsDBCSLeadByte(*lpszPtr)) {
if(*(lpszSrch + 1) == *(lpszPtr + 1)) return (LPTSTR)lpszSrch;
} else {
return (LPTSTR)lpszSrch; } } } } }
return NULL; }
/****************************************************************************\
* prv_BuildUniqueID * * Create a unique ID based on lpszModel/lpszPort/Timer. * \****************************************************************************/ DWORD prv_BuildUniqueID( LPCTSTR lpszModel, LPCTSTR lpszPort) { return ((prv_CheesyHash(lpszModel) ^ prv_CheesyHash(lpszPort)) ^ GetTickCount()); }
/****************************************************************************\
* prv_IsNameInUse * * Return whether the name is already in use by the print-subsystem. * \****************************************************************************/ BOOL prv_IsNameInUse( LPCTSTR lpszName) { HANDLE hPrinter;
if (OpenPrinter((LPTSTR)lpszName, &hPrinter, NULL)) {
ClosePrinter(hPrinter);
return TRUE; }
return FALSE; }
/****************************************************************************\
* prv_CreateUniqueName * * Create a unique friendly name for this printer. If (idx) is 0, then * copy the name from the base to the (lpszDst). Otherwise, play some * games with truncating the name so it will fit. * \****************************************************************************/ BOOL prv_CreateUniqueName( LPTSTR lpszDst, LPCTSTR lpszBaseName, DWORD idx) { TCHAR szBaseName[_MAX_NAME_]; int nFormatLength; BOOL bSuccess = FALSE;
if (idx) {
// Create a unique friendly name for each instance.
// Start with:
// "%s %d" After LoadMessage
// "Short Model Name 2" After wsprintf or
// "Very very long long Model Nam 2" After wsprintf
//
// Since wsprintf has no concept of limiting the string size,
// truncate the model name (in a DBCS-aware fashion) to
// the appropriate size, so the whole string fits in _MAX_NAME_ bytes.
// This may cause some name truncation, but only in cases where
// the model name is extremely long.
// nFormatLength is length of string without the model name.
// If wInstance is < 10, format length is 2 (space + digit).
// If wInstance is < 100, format length is 3. Else format
// length is 4. Add 1 to compensate for the terminating NULL,
// which is counted in the total buffer length, but not the string
// length,
//
if (idx < 10) {
nFormatLength = 9 + 1;
} else if (idx < 100) {
nFormatLength = 10 + 1;
} else {
nFormatLength = 11 + 1; }
// Truncate the base name, if necessary,
// then build the output string.
//
lstrcpyn(szBaseName, lpszBaseName, sizeof(szBaseName) - nFormatLength);
// there is already a copy 1 (undecorated base name)
//
wsprintf(lpszDst, g_szFmtName, (LPTSTR)szBaseName, (int)idx + 1); bSuccess = TRUE;
} else {
lstrcpyn(lpszDst, lpszBaseName, _MAX_NAME_);
bSuccess = TRUE; }
return bSuccess; }
/****************************************************************************\
* prv_FindUniqueName * * Find a unique name that isn't already in use by the print subsystem. * Base the name on the friendly name and an instance count. * * This will alter the lpszFriendly; even if function fails. * \****************************************************************************/ BOOL prv_FindUniqueName( LPTSTR lpszFriendly) {
// Since our http:// name is too long for W95, we're going
// to try basing our name off of the model-name.
//
// 28-Jun-1998 : ChrisWil
DWORD idx; TCHAR *pszBase = NULL; BOOL bRes = FALSE; pszBase = memAllocStr( lpszFriendly ); if (!pszBase) { goto Cleanup; }
// Iterate until we have found a unique name we can use.
//
for (idx = 0; idx < MAX_NAMES; idx++) {
prv_CreateUniqueName(lpszFriendly, pszBase, idx);
if (!prv_IsNameInUse(lpszFriendly)) { bRes = TRUE; goto Cleanup; } }
Cleanup:
if (pszBase) { memFreeStr( pszBase ); } return bRes; }
/****************************************************************************\
* prv_IsThisDriverInstalled * * Get the list of all installed printer drivers, and check to see * if the current driver is in the list. If the driver is already * installed, ask the user if we should keep the old one or install * over the top of it. * * returns: RET_OK : OK. * RET_ALLOC_ERROR : Out of memory. * RET_DRIVER_NOT_FOUND : Can't find driver. * \****************************************************************************/ DWORD prv_IsThisDriverInstalled( LPSI lpsi) { DWORD cbNeed; DWORD cbSize; DWORD cDrvs; DWORD i; BOOL bRet; int iRes; LPDRIVER_INFO_1 lpdi1; DWORD dwRet = RET_DRIVER_NOT_FOUND;
// Get the size necessary to store the drivers.
//
cbSize = 0; cDrvs = 0; EnumPrinterDrivers((LPTSTR)NULL, (LPTSTR)NULL, 1, NULL, 0, &cbSize, &cDrvs);
// If we have drivers, then we can look for our installed driver.
//
if (cbSize && (lpdi1 = (LPDRIVER_INFO_1)memAlloc(cbSize))) {
bRet = EnumPrinterDrivers(NULL, NULL, 1, (LPBYTE)lpdi1, cbSize, &cbNeed, &cDrvs);
if (bRet) {
for (i = 0; i < cDrvs; i++) {
if (lstrcmpi(lpsi->szModel, lpdi1[i].pName) == 0) {
dwRet = RET_DRIVER_FOUND; break; } } }
// Free up our allocated buffer.
//
memFree(lpdi1, cbSize);
// If found, then we need to request from the user whether
// to replace the driver.
//
if (dwRet == RET_DRIVER_FOUND) {
iRes = MessageBox(NULL, g_szMsgExists, lpsi->szModel, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1);
if (iRes == IDNO) dwRet = RET_DRIVER_NOT_FOUND; else dwRet = RET_OK; } }
return dwRet; }
/****************************************************************************\
* prv_BuildPrinterInfo * * Allocate and/or initialize a PRINTER_INFO_2 structure from LPSI. Store * the pointer in lpsi->lpPrinterInfo2. * * returns: RET_OK : OK. * RET_ALLOC_ERROR : Out of memory. * \****************************************************************************/ DWORD prv_BuildPrinterInfo( LPSI lpsi) { LPPRINTER_INFO_2 lppi2;
// This code path is always executed just before we call
// AddPrinter. Fill in anything we don't already have.
//
// Allocate memory if we need it.
//
if (lpsi->lpPrinterInfo2 == NULL) {
lpsi->lpPrinterInfo2 = (LPBYTE)memAlloc(sizeof(PRINTER_INFO_2)); }
// Fill in the lppi2.
//
if (lppi2 = (LPPRINTER_INFO_2)lpsi->lpPrinterInfo2) {
lppi2->pPrinterName = lpsi->szFriendly; lppi2->pPortName = lpsi->szPort; lppi2->pDriverName = lpsi->szModel; lppi2->pPrintProcessor = lpsi->szPrintProcessor; lppi2->pDatatype = lpsi->szDefaultDataType; lppi2->Priority = DEF_PRIORITY; lppi2->Attributes = 0;
// Slow Machine?
//
if (0x0002 & GetSystemMetrics(SM_SLOWMACHINE)) lppi2->Attributes |= PRINTER_ATTRIBUTE_QUEUED;
// Point & Print case--make sure that the devmode we use to
// add the printer locally contains the local friendly name
// and not the friendly name it had on the server
//
if (lppi2->pDevMode) {
lstrcpyn((LPSTR)lppi2->pDevMode->dmDeviceName, lpsi->szFriendly, sizeof(lppi2->pDevMode->dmDeviceName)); }
} else {
return RET_ALLOC_ERR; }
return RET_OK; }
/****************************************************************************\
* prv_InstallPrinter * * Install the printer identified by LPSI. If the printer exists, then * call SetPrinter(). Otherwise, call AddPrinter(). * * returns: RET_OK : OK. * RET_ALLOC_ERROR : Out of memory. * RET_ADD_PRINTER_ERROR : Can't add printer. * \****************************************************************************/ DWORD prv_InstallPrinter( LPSI lpsi) { DWORD dwRet; PRINTER_INFO_5 pi5; LPPRINTER_INFO_2 lppi2 = NULL; HANDLE hPrinter = NULL; BOOL bRes = FALSE;
// BuildPrinterInfo will allocate an lppi2 and attach it to lpsi
//
if ((dwRet = prv_BuildPrinterInfo(lpsi)) == RET_OK) {
lppi2 = (LPPRINTER_INFO_2)lpsi->lpPrinterInfo2; dwRet = RET_ADD_PRINTER_ERROR; hPrinter = AddPrinter(NULL, 2, (LPBYTE)lppi2);
DBG_ASSERT((hPrinter != NULL), (TEXT("WPNPIN32: prv_InstallPrinter - Failed AddPrinter"))); }
if (hPrinter) {
// Set the transmission & retry timeouts--remember that the
// subsystem values are in milliseconds!
//
ZeroMemory(&pi5, sizeof(PRINTER_INFO_5)); pi5.pPrinterName = lpsi->szFriendly; pi5.DeviceNotSelectedTimeout = lpsi->wDNSTimeout * ONE_SECOND; pi5.TransmissionRetryTimeout = lpsi->wRetryTimeout * ONE_SECOND; pi5.pPortName = lppi2->pPortName; pi5.Attributes = lppi2->Attributes;
SetPrinter(hPrinter, 5, (LPBYTE)&pi5, 0);
// Set the printer's unique ID so we can delete it correctly later
//
if (lpsi->dwUniqueID = prv_BuildUniqueID(lpsi->szModel, lpsi->szPort)) {
SetPrinterData(hPrinter, (LPTSTR)g_szUniqueID, REG_BINARY, (LPBYTE)&lpsi->dwUniqueID, sizeof(DWORD)); }
ClosePrinter(hPrinter);
dwRet = RET_OK; }
// We don't need lpPrinterInfo2 anymore.
//
if (lpsi->lpPrinterInfo2) {
memFree(lpsi->lpPrinterInfo2, sizeof(PRINTER_INFO_2)); lpsi->lpPrinterInfo2 = NULL; }
// We don't need lpDriverInfo3 anymore
//
if (lpsi->lpDriverInfo3) {
memFree(lpsi->lpDriverInfo3, memGetSize(lpsi->lpDriverInfo3)); lpsi->lpDriverInfo3 = NULL; }
return dwRet; }
/****************************************************************************\
* prv_BuildDriverInfo * * Allocate and initialize a DRIVER_INFO_3 for lpsi. * driver dependent files be copied to the printer-driver-directory. * \****************************************************************************/ BOOL prv_BuildDriverInfo( LPSI lpsi) { LPDRIVER_INFO_3 lpdi3;
// This code path is always executed before we call AddPrinterDriver.
// Set up any data that we don't already have. We always work with
// a DRIVER_INFO_3 on this pass.
//
// Allocate memory, if we need it.
//
if (lpsi->lpDriverInfo3 == NULL) {
lpsi->lpDriverInfo3 = (LPBYTE)memAlloc(sizeof(DRIVER_INFO_3)); }
// Fill in the lpdi3;
//
if (lpdi3 = (LPDRIVER_INFO_3)lpsi->lpDriverInfo3) {
lpdi3->cVersion = (DWORD)lpsi->dwDriverVersion; lpdi3->pName = lpsi->szModel; lpdi3->pEnvironment = (LPTSTR)g_szEnvironment; lpdi3->pDriverPath = lpsi->szDriverFile; lpdi3->pDataFile = lpsi->szDataFile; lpdi3->pConfigFile = lpsi->szConfigFile; lpdi3->pHelpFile = lpsi->szHelpFile; lpdi3->pDefaultDataType = lpsi->szDefaultDataType;
if (lpsi->wFilesUsed && lpsi->lpFiles) lpdi3->pDependentFiles = (LPSTR)lpsi->lpFiles; else lpdi3->pDependentFiles = NULL; }
return (lpsi->lpDriverInfo3 ? TRUE : FALSE); }
/****************************************************************************\
* prv_InstallPrinProcessor * * Copy the print processor file associated with this driver * into the print processor directory and then add it to the * print sub-system. Do not overwrite an existing print * processor of the same name. * \****************************************************************************/ DWORD prv_InstallPrintProcessor( LPSI lpsi, LPCTSTR pszPath) { DWORD dwRet = RET_OK;
LPTSTR lpPrintProcessorDLL; DWORD pcbNeeded; TCHAR buf[_MAX_PATH_];
TCHAR *pszBuf = NULL; TCHAR *pszTemp = NULL; int cbLength = 0; int cbBufLength = 0;
// Add the print processor if required
//
if (lpPrintProcessorDLL = prv_StrPBrk(lpsi->szPrintProcessor, g_szComma)) {
*lpPrintProcessorDLL++ = TEXT('\0'); lstrcpy(buf, g_szNull);
cbLength = lstrlen(pszPath) + lstrlen(g_szBackslash) + lstrlen(lpPrintProcessorDLL) + 1; if (cbLength) { pszTemp = memAlloc( cbLength * sizeof(TCHAR) ); } if (!pszTemp) { dwRet = RET_ALLOC_ERR; goto Cleanup; }
// get the source file
//
lstrcpy(pszTemp, pszPath); lstrcat(pszTemp, g_szBackslash); lstrcat(pszTemp, lpPrintProcessorDLL);
// The DLL must be in the PrintProcessorDirectory
//
GetPrintProcessorDirectory(NULL, NULL, 1, (LPBYTE)buf, sizeof(buf), &pcbNeeded);
cbBufLength = lstrlen(buf) + lstrlen(g_szBackslash) + lstrlen(lpPrintProcessorDLL) + 1; if (cbBufLength) { pszBuf = memAlloc( cbBufLength * sizeof(TCHAR) ); } if (!pszBuf) { dwRet = RET_ALLOC_ERR; goto Cleanup; } lstrcpy(pszBuf, buf); lstrcat(pszBuf, g_szBackslash); lstrcat(pszBuf, lpPrintProcessorDLL);
// Copy the file, but don't overwrite an existing copy of it
//
CopyFile(lpPrintProcessorDLL, pszBuf, TRUE);
AddPrintProcessor(NULL, (LPTSTR)g_szEnvironment, lpPrintProcessorDLL, lpsi->szPrintProcessor);
} else {
DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : No PrintProcessor to add"))); }
Cleanup:
if (pszTemp) { memFree(pszTemp, cbLength * sizeof(TCHAR) ); } if (pszBuf) { memFree(pszBuf, cbBufLength * sizeof(TCHAR) ); } return dwRet; }
/****************************************************************************\
* prv_GetDriverVersion * * Confirm that the driver identified in lpsi is indeed a * valid printer driver, and determine which version it * is. Leave the driver loaded for performance reasons * (since it will get loaded at least twice more). * \****************************************************************************/ DWORD prv_GetDriverVersion( LPSI lpsi, LPTSTR pszPath) { UINT wOldErrorMode; HINSTANCE hDrv = NULL; TCHAR *pszTemp = NULL; INT cbLength = 0; DWORD idError = RET_INVALID_DLL;
wOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
cbLength = lstrlen(pszPath); if (cbLength > 0) {
cbLength += lstrlen(g_szBackslash) + lstrlen(lpsi->szDriverFile) + 1; pszTemp = memAlloc( cbLength * sizeof(TCHAR)); if (!pszTemp) { idError = RET_ALLOC_ERR; goto Cleanup; }
lstrcpy(pszTemp, pszPath); lstrcat(pszTemp, g_szBackslash); lstrcat(pszTemp, lpsi->szDriverFile);
} else {
cbLength = lstrlen(lpsi->szDriverFile) + 1; pszTemp = memAlloc( cbLength * sizeof(TCHAR)); if (!pszTemp) { idError = RET_ALLOC_ERR; goto Cleanup; } lstrcpy(pszTemp, lpsi->szDriverFile); }
// Load the library.
//
hDrv = LoadLibrary(pszTemp); SetErrorMode(wOldErrorMode);
if (hDrv) {
// We successfully loaded the DLL, now we want to confirm that it's
// a printer driver and get its version. We get ourselves into
// all sorts of trouble by calling into the driver before it's
// actually installed, so simply key off the exported functions.
//
idError = RET_OK;
if (GetProcAddress(hDrv, g_szExtDevModePropSheet)) {
lpsi->dwDriverVersion = 0x0400;
} else if (GetProcAddress(hDrv, g_szExtDevMode)) {
lpsi->dwDriverVersion = 0x0300;
} else if (GetProcAddress(hDrv, g_szDevMode)) {
lpsi->dwDriverVersion = 0x0200;
} else {
lpsi->dwDriverVersion = 0x0000;
idError = RET_INVALID_PRINTER_DRIVER; }
FreeLibrary(hDrv); } Cleanup:
if (pszTemp) { memFree(pszTemp, cbLength * sizeof(TCHAR)); } return idError; }
/****************************************************************************\
* prv_UpdateICM * * Add color profiles to the registry. * \****************************************************************************/ BOOL prv_UpdateICM( LPTSTR lpFiles) { TCHAR szPath[_MAX_PATH_]; TCHAR szColor[RES_BUFFER]; UINT wLength; UINT wColorLength; LPTSTR lpTemp = szPath; LPTSTR lpLast = NULL; BOOL bReturn = FALSE;
// Nothing to do if the dependent file list is NULL or empty
//
if (lpFiles && *lpFiles) {
// Add any color profiles that are referenced by this device.
// First, get the system directory & make sure that it ends
// in a backslash
//
wLength = GetSystemDirectory(szPath, sizeof(szPath));
while (lpLast = prv_StrPBrk(lpTemp, g_szBackslash)) {
lpTemp = lpLast + 1;
if (*lpTemp == TEXT('\0')) break; }
if (!lpLast) {
lstrcat(szPath, g_szBackslash); wLength++; }
lpLast = szPath + wLength;
// Get the comparison string for the path.
//
if (!LoadString(g_hLibInst, IDS_COLOR_PATH, szColor, RES_BUFFER)) {
lstrcpy(szColor, g_szColorPath); }
wColorLength = lstrlen(szColor);
lpTemp = lpFiles;
// Now walk down the list of files & compare the beginning of the
// string to "COLOR\\". If it matches, assume that this is a color
// profile and notify the system that it's changing.
//
while (*lpTemp) {
UINT wTempLength = lstrlen(lpTemp);
if (wTempLength > wColorLength) {
BYTE bOldByte = lpTemp[wColorLength]; int nMatch;
lpTemp[wColorLength] = TEXT('\0'); nMatch = lstrcmpi(lpTemp, szColor); lpTemp[wColorLength] = bOldByte;
if (!nMatch) {
lstrcpy(lpLast, lpTemp); bReturn |= UpdateICMRegKey(0, 0, szPath, ICM_ADDPROFILE); } }
lpTemp += (wTempLength+1); } }
return bReturn; }
/****************************************************************************\
* prv_InstallPrinterDriver * * Install a printer-driver into the subsystem. This requires that all * driver dependent files be copied to the printer-driver-directory. * * * returns: RET_OK : OK. * RET_USER_CANCEL : User cancelled driver install. * RET_BROWSE_ERROR : User hits cancel key in browse dialog. * \****************************************************************************/ DWORD prv_InstallPrinterDriver( LPSI lpsi, HWND hWnd) { BOOL bSuccess = FALSE; DWORD dwResult = RET_OK; CHAR szPath[_MAX_PATH_];
if (lpsi->wCommand == CMD_INSTALL_DRIVER) {
// Get the driver version
//
if ( _getcwd(szPath, _MAX_PATH_) == NULL) lstrcpy(szPath, ".");
lpsi->dwDriverVersion = 0; dwResult = prv_GetDriverVersion(lpsi, szPath);
if (dwResult != RET_OK) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : prv_GetDriverVersion Failed")));
// The AddPrinterDriver code will check the version
// number. I think.
//
lpsi->dwDriverVersion = 0x0400; }
// Install the printprocessor if one is provided.
//
prv_InstallPrintProcessor(lpsi, szPath);
// Build the driver-info.
//
if (prv_BuildDriverInfo(lpsi)) {
if (!(bSuccess = AddPrinterDriver(NULL, 3, lpsi->lpDriverInfo3))) {
if (ERROR_PRINTER_DRIVER_ALREADY_INSTALLED == GetLastError()) {
bSuccess = TRUE; } } }
if (bSuccess) {
prv_UpdateICM(((LPDRIVER_INFO_3)(lpsi->lpDriverInfo3))->pDependentFiles); } }
return RET_OK; }
/*****************************************************************************\
* GetCommandLineArgs(LPSI, LPCTSTR) * * Parse the DAT file to retrieve Web PnP Install options. * * LPCWSTR is the name of the dat file. The dat file contains: * * /i * /x Web Print calls * /b Printer name lpsi*>szFriendly * /f inf file lpsi*>INFfileName * /r Port name lpsi*>szPort * /m Printer model lpsi*>szModel * /n Share name lpsi*>ShareName * /a Bin file lpsi*>BinName * \*****************************************************************************/ int GetCommandLineArgs( LPSI lpsi, LPCTSTR lpDatFile) { int i; int count = 0; DWORD bytesRead = 0; LPTSTR lpstrCmd; HANDLE hFile = NULL; WCHAR wideBuf[1024]; TCHAR buf[1024]; UCHAR ch;
DBG_MSG(DBG_LEV_INFO, (TEXT("The File to be Read - %s"), lpDatFile));
hFile = CreateFile(lpDatFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE)) return 0;
i = ReadFile(hFile, (LPVOID)wideBuf, sizeof(wideBuf), &bytesRead, NULL);
CloseHandle(hFile);
if ( i == 0 || bytesRead == 0 ) return 0;
DBG_MSG(DBG_LEV_INFO, (TEXT("Number bytes read - %lu"), bytesRead));
// convert wide buffer to MBCS
//
lstrcpy(buf, g_szNull);
i = WideCharToMultiByte(CP_ACP, 0, wideBuf, -1, buf, sizeof(buf), NULL, NULL);
if (i == 0) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32: ParseCmdLineArgs: Faild MBCS convert")));
return 0; // 0 args parsed
}
// Our dat-file is in unicode format, so we need to skip over the FFFE
// signature at the beginning of the file.
//
lpstrCmd = buf; ch = *lpstrCmd++; ch = *lpstrCmd++;
// skip over any white space
//
while (isspace(ch)) ch = *lpstrCmd++;
DBG_MSG(DBG_LEV_INFO, (TEXT("UCHAR N: %#X"), ch));
// process each switch character '/' or '-' as encountered
//
while (ch == TEXT('/') || ch == TEXT('-')) {
ch = (UCHAR)tolower(*lpstrCmd++);
// process multiple switch characters as needed
//
switch (ch) {
case TEXT('a'): // .bin file name
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != TEXT('"')) {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid BinFile Name (/a)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->BinName[i++] = ch; ch = *lpstrCmd++; } lpsi->BinName[i] = TEXT('\0'); if (ch != TEXT('\0')) ch = *lpstrCmd++;
count++; } break;
case TEXT('b'): // printer name
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != TEXT('"')) {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Printer Name (/b)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->szFriendly[i++] = ch; ch = *lpstrCmd++; } lpsi->szFriendly[i] = TEXT('\0'); if (ch != TEXT('\0')) ch = *lpstrCmd++;
count++; } break;
case TEXT('f'): // INF file name
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != TEXT('"')) {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid InfFile Name (/f)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->INFfileName[i++] = ch; ch = *lpstrCmd++; } lpsi->INFfileName[i] = TEXT('\0'); if (ch != '\0') ch = *lpstrCmd++;
count++; } break;
case TEXT('i'): // unknown
ch = *lpstrCmd++; // 'f'
if (ch != TEXT('\0')) ch = *lpstrCmd++; // space
count++; break;
case TEXT('m'): // printer model
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != '"') {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid PrinterModel Name (/m)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->szModel[i++] = ch; ch = *lpstrCmd++; } lpsi->szModel[i] = TEXT('\0'); if (ch != TEXT('\0')) ch = *lpstrCmd++;
count++; } break;
case TEXT('n'): // share name
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != TEXT('"')) {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Share Name (/n)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->ShareName[i++] = ch; ch = *lpstrCmd++; } lpsi->ShareName[i] = TEXT('\0'); if (ch != TEXT('\0')) ch = *lpstrCmd++;
count++; } break;
case TEXT('r'): // port name
ch = *lpstrCmd++; // skip over any following white space
while (isspace(ch)) { ch = *lpstrCmd++; }
if (ch != TEXT('"')) {
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Port Name (/r)")));
return RET_INVALID_DAT_FILE;
} else {
// skip over quote
ch = *lpstrCmd++;
// copy the name
i = 0; while (ch != TEXT('"') && ch != TEXT('\0')) { lpsi->szPort[i++] = ch; ch = *lpstrCmd++; } lpsi->szPort[i] = TEXT('\0'); if (ch != TEXT('\0')) ch = *lpstrCmd++;
count++; } break;
case TEXT('x'): // unknown
ch = *lpstrCmd++; count++; break;
case TEXT('?'): // help
MessageBox(NULL, g_szMsgOptions, g_szMsgOptCap, MB_OK); break;
default: /* invalid option */
DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Option")));
break;
} //switch
while (isspace(ch)) ch = *lpstrCmd++;
} // while / or -
return count; }
/****************************************************************************\
* PrintLPSI * * Print out the contents of the LPSI structure. * \****************************************************************************/ VOID prv_PrintLPSI( LPSI lpsi) { DBG_MSG(DBG_LEV_INFO, (TEXT("LPSI Structure Dump"))); DBG_MSG(DBG_LEV_INFO, (TEXT("-------------------"))); DBG_MSG(DBG_LEV_INFO, (TEXT("dwDriverVersion : %#lX"), lpsi->dwDriverVersion )); DBG_MSG(DBG_LEV_INFO, (TEXT("dwUniqueID : %d") , lpsi->dwUniqueID )); DBG_MSG(DBG_LEV_INFO, (TEXT("bNetPrinter : %d") , lpsi->bNetPrinter )); DBG_MSG(DBG_LEV_INFO, (TEXT("wFilesUsed : %d") , lpsi->wFilesUsed )); DBG_MSG(DBG_LEV_INFO, (TEXT("wFilesAllocated : %d") , lpsi->wFilesAllocated )); DBG_MSG(DBG_LEV_INFO, (TEXT("wRetryTimeout : %d") , lpsi->wRetryTimeout )); DBG_MSG(DBG_LEV_INFO, (TEXT("wDNSTimeout : %d") , lpsi->wDNSTimeout )); DBG_MSG(DBG_LEV_INFO, (TEXT("bDontQueueFiles : %d") , lpsi->bDontQueueFiles )); DBG_MSG(DBG_LEV_INFO, (TEXT("bNoTestPage : %d") , lpsi->bNoTestPage )); DBG_MSG(DBG_LEV_INFO, (TEXT("hModelInf : %d") , lpsi->hModelInf )); DBG_MSG(DBG_LEV_INFO, (TEXT("lpPrinterInfo2 : %d") , lpsi->lpPrinterInfo2 )); DBG_MSG(DBG_LEV_INFO, (TEXT("lpDriverInfo3 : %d") , lpsi->lpDriverInfo3 )); DBG_MSG(DBG_LEV_INFO, (TEXT("szFriendly : %s") , lpsi->szFriendly )); DBG_MSG(DBG_LEV_INFO, (TEXT("szModel : %s") , lpsi->szModel )); DBG_MSG(DBG_LEV_INFO, (TEXT("szDefaultDataType : %s") , lpsi->szDefaultDataType)); DBG_MSG(DBG_LEV_INFO, (TEXT("BinName : %s") , lpsi->BinName )); DBG_MSG(DBG_LEV_INFO, (TEXT("ShareName : %s") , lpsi->ShareName )); DBG_MSG(DBG_LEV_INFO, (TEXT("INFfileName : %s") , lpsi->INFfileName )); DBG_MSG(DBG_LEV_INFO, (TEXT("szPort : %s") , lpsi->szPort )); DBG_MSG(DBG_LEV_INFO, (TEXT("szDriverFile : %s") , lpsi->szDriverFile )); DBG_MSG(DBG_LEV_INFO, (TEXT("szDataFile : %s") , lpsi->szDataFile )); DBG_MSG(DBG_LEV_INFO, (TEXT("szConfigFile : %s") , lpsi->szConfigFile )); DBG_MSG(DBG_LEV_INFO, (TEXT("szHelpFile : %s") , lpsi->szHelpFile )); DBG_MSG(DBG_LEV_INFO, (TEXT("szPrintProcessor : %s") , lpsi->szPrintProcessor )); DBG_MSG(DBG_LEV_INFO, (TEXT("szVendorSetup : %s") , lpsi->szVendorSetup )); DBG_MSG(DBG_LEV_INFO, (TEXT("szVendorInstaller : %s") , lpsi->szVendorInstaller));
#if 0
DWORD cch; PTSTR pszFile;
DBG_MSG(DBG_LEV_INFO, (TEXT("Files:"))); DBG_MSG(DBG_LEV_INFO, (TEXT("------")));
for (cch = 0, pszFile = lpsi->lpFiles; *pszFile; pszFile += cch) DBG_MSG(DBG_LEV_INFO, (TEXT("%s"), pszFile);
#endif
}
/****************************************************************************\
* AddOnePrinter * * Add a single printer (including the driver and print-processor). * \****************************************************************************/ DWORD AddOnePrinter( LPSI lpsi, HWND hWnd) { DWORD dwResult = RET_OK; DWORD cbNeeded; TCHAR ch; TCHAR srcINF[_MAX_PATH_];
#if 1 // Since our http:// name is too long for W95, we're going
// to try basing our name off of the model-name.
//
// 28-Jun-1998 : ChrisWil
lstrcpy(lpsi->szFriendly, lpsi->szModel); #endif
// Build a unique-name from the friendly-name.
//
if (prv_FindUniqueName(lpsi->szFriendly)) {
// Determine if we need to add a new driver. If there is already a
// driver for this printer, ask if the user wants to re-install or
// use the old one.
//
if ((dwResult = prv_IsThisDriverInstalled(lpsi)) == RET_OK) {
lpsi->wCommand = 0;
} else if (dwResult == RET_DRIVER_NOT_FOUND) {
// Set it up to install the printer driver.
//
lpsi->wCommand = CMD_INSTALL_DRIVER; dwResult = RET_OK;
DBG_MSG(DBG_LEV_INFO, (TEXT("WPNPIN32 : AddOnePrinter - Driver Will be installed"))); }
// We need info about the driver even if we don't plan to
// install/re-install it
//
if (dwResult == RET_OK) {
// Get current directory and prepend to INF file name
//
if ( _getcwd(srcINF, _MAX_PATH_) == NULL) lstrcpy(srcINF, g_szDot);
lstrcat(srcINF, g_szBackslash); lstrcat(srcINF, lpsi->INFfileName); lstrcpy(lpsi->INFfileName, srcINF);
// Get the Printer driver directory and store in lpsi->szRes
// This is used for copying the files
//
GetPrinterDriverDirectory(NULL, NULL, 1, (LPBYTE)lpsi->szDriverDir, sizeof(lpsi->szDriverDir), &cbNeeded);
// Parse the INF file and store info in lpsi. This will
// add the driver to the print subsystem.
//
if ((dwResult = ParseINF16(lpsi)) != RET_OK) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : ParseINF16 - Failed"))); } }
// Install the printer-driver. This routine will verify if the
// (lpsi->wCommand indicates whether the driver should be installed.
//
if (dwResult == RET_OK) dwResult = prv_InstallPrinterDriver(lpsi, hWnd);
// Install the Printer.
//
if (dwResult == RET_OK) dwResult = prv_InstallPrinter(lpsi);
} else {
DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : AddOnePrinter : UniqueName failure")));
dwResult = RET_NO_UNIQUE_NAME; }
// Debug output of LPSI.
//
prv_PrintLPSI(lpsi);
// Clean up memory.
//
if (lpsi->lpPrinterInfo2) {
memFree(lpsi->lpPrinterInfo2, memGetSize(lpsi->lpPrinterInfo2)); lpsi->lpPrinterInfo2 = NULL; }
if (lpsi->lpDriverInfo3) {
memFree(lpsi->lpDriverInfo3, memGetSize(lpsi->lpDriverInfo3)); lpsi->lpDriverInfo3 = NULL; }
if (lpsi->lpFiles) {
HP_GLOBAL_FREE(lpsi->lpFiles); lpsi->lpFiles = NULL; }
if (lpsi->lpVcpInfo) {
HP_GLOBAL_FREE(lpsi->lpVcpInfo); lpsi->lpVcpInfo = NULL; }
return dwResult; }
/*****************************************************************************\
* prvMsgBox * * Displays a string-id in a messagebox. * \*****************************************************************************/ UINT prvMsgBox( HWND hWnd, LPCTSTR lpszCap, UINT idTxt, UINT fMB) { LPTSTR pszTxt; UINT uRet = 0;
if (pszTxt = strLoad(idTxt)) {
uRet = MessageBox(hWnd, pszTxt, lpszCap, fMB);
strFree(pszTxt); }
return uRet; }
|