|
|
/***************************************************************************
* * File Name: WPNPIN16.C * * Copyright 1997 Hewlett-Packard Company. * All rights reserved. * * 11311 Chinden Blvd. * Boise, Idaho 83714 * * * Description: Source code for WPNPIN16.DLL * * Author: Garth Schmeling * * * Modification history: * * Date Initials Change description * * 10-10-97 GFS Initial checkin * * * ***************************************************************************/
#include "wpnpin16.h"
/*--------------- For Debug -------------------------*/ //#define GARTH_DEBUG 1
/*****************************************************************************\
* strFree * * Free allocated string. * \*****************************************************************************/ VOID strFree( HANDLE hszStr, LPSTR pszStr) { if (hszStr && pszStr) GlobalUnlock(hszStr);
if (hszStr) GlobalFree(hszStr); }
/*****************************************************************************\
* strAlloc * * Allocates a string from the heap. This pointer must be freed with * a call to strFree(). * \*****************************************************************************/ LPSTR strAlloc( LPHANDLE phSrc, LPCSTR pszSrc) { DWORD cbSize; LPSTR pszDst = NULL;
*phSrc = NULL; cbSize = (pszSrc ? (lstrlen(pszSrc) + 1) : 0);
if (cbSize && (*phSrc = GlobalAlloc(GPTR, cbSize))) {
if (pszDst = (LPSTR)GlobalLock(*phSrc)) lstrcpy(pszDst, pszSrc); }
return pszDst; }
/*****************************************************************************\
* strLoad * * Get string from resource based upon the ID passed in. * \*****************************************************************************/ LPSTR strLoad( LPHANDLE phszStr, UINT ids) { char szStr[_MAX_RESBUF];
if (LoadString(g_hInst, ids, szStr, sizeof(szStr)) == 0) szStr[0] = '\0';
return strAlloc(phszStr, szStr); }
/*****************************************************************************\
* InitStrings * * \*****************************************************************************/ BOOL InitStrings(VOID) { cszDefaultPrintProcessor = strLoad(&hszDefaultPrintProcessor, IDS_DEFAULT_PRINTPROCESSOR); cszMSDefaultDataType = strLoad(&hszMSDefaultDataType , IDS_DEFAULT_DATATYPE); cszDefaultColorPath = strLoad(&hszDefaultColorPath , IDS_COLOR_PATH); cszFileInUse = strLoad(&hszFileInUse , IDS_ERR_FILE_IN_USE);
return (cszDefaultPrintProcessor && cszMSDefaultDataType && cszDefaultColorPath && cszFileInUse); }
/*****************************************************************************\
* FreeeStrings * * \*****************************************************************************/ VOID FreeStrings(VOID) { strFree(hszDefaultPrintProcessor, cszDefaultPrintProcessor); strFree(hszMSDefaultDataType , cszMSDefaultDataType); strFree(hszDefaultColorPath , cszDefaultColorPath); strFree(hszFileInUse , cszFileInUse); }
/*****************************************************************************\
* DllEntryPoint * * \*****************************************************************************/ BOOL FAR PASCAL DllEntryPoint( DWORD dwReason, WORD hInst, WORD wDS, WORD wHeapSize, DWORD dwReserved1, WORD wReserved2) { if (g_hInst == NULL) {
g_hInst = (HINSTANCE)hInst;
if (InitStrings() == FALSE) return FALSE; }
return thk_ThunkConnect16(cszDll16, cszDll32, hInst, dwReason); }
//-----------------------------------------------------------------------
// Function: lstrpbrk(lpSearch,lpTargets)
//
// Action: DBCS-aware version of strpbrk.
//
// Return: Pointer to the first character that in lpSearch that is also
// in lpTargets. NULL if not found.
//
// Comment: Use nested loops to avoid allocating memory for DBCS stuff.
//-----------------------------------------------------------------------
LPSTR WINAPI lstrpbrk(LPSTR lpSearch, LPSTR lpTargets) { LPSTR lpOneTarget;
if (lpSearch AND lpTargets) { for (; *lpSearch; lpSearch=AnsiNext(lpSearch)) { for (lpOneTarget=lpTargets; *lpOneTarget; lpOneTarget=AnsiNext(lpOneTarget)) { if (*lpSearch==*lpOneTarget) { // First byte matches--see if we need to check
// second byte
if (IsDBCSLeadByte(*lpOneTarget)) { if (*(lpSearch+1) == *(lpOneTarget+1)) return lpSearch; } else return lpSearch; } } } }
return NULL; }
//-----------------------------------------------------------------------
// Function: lstrtok(lpSearch,lpTargets)
//
// Action: DBCS-aware version of strtok.
//
// Return: Pointer to next non-NULL token if found, NULL if not.
//-----------------------------------------------------------------------
LPSTR WINAPI lstrtok(LPSTR lpSearch, LPSTR lpTargets) { static LPSTR lpLastSearch; LPSTR lpFound; LPSTR lpReturn=NULL;
if (lpSearch) lpLastSearch=lpSearch;
for (; lpLastSearch AND *lpLastSearch; lpLastSearch=AnsiNext(lpLastSearch)) { // Skip leading white space
while (' '==*lpLastSearch OR '\t'==*lpLastSearch) lpLastSearch++;
if (lpFound=lstrpbrk(lpLastSearch,lpTargets)) { if (lpFound==lpLastSearch) // Ignore NULL tokens
continue;
lpReturn=lpLastSearch; *lpFound='\0'; lpLastSearch=lpFound+1; break; } else { lpReturn=lpLastSearch; lpLastSearch=NULL; break; } }
return lpReturn; }
//--------------------------------------------------------------------
// Function: FindCorrectSection(szInfFile,szManufacturer,szModel,szSection)
//
// Action: Find the install section in the inf file that corresponds
// to the model name. This may require several different approaches.
// Try the most likely first and then try others.
//
// Side effect: Put the section name in szSection.
//
// Return: TRUE if the section was found, FALSE if not.
//
//--------------------------------------------------------------------
BOOL WINAPI FindCorrectSection( LPSTR szInfFile, LPSTR szManufacturer, LPSTR szModel, LPSTR szSection) { HINF hInf = 0; HINFLINE hInfLine = 0; int i = 0; int nCount = 0; int nCopied = 0; int nFields = 0; BOOL bHaveManu = FALSE; char lpszBuf[_MAX_LINE]; char lpszTemp[_MAX_LINE]; char lpszTemp2[_MAX_LINE];
// Open the INF file.
if (OK != IpOpen(szInfFile, &hInf)) { return FALSE; }
lstrcpy(lpszBuf, cszNull); lstrcpy(lpszTemp, cszNull); lstrcpy(lpszTemp2, cszNull);
// Try # 1 to get the manufacturer's section name
// Look for a section corresponding to the manufacturer's
// name. Copy it to lpszBuf. Open that section below.
if (OK == IpFindFirstLine(hInf, szManufacturer, NULL, &hInfLine)) { lstrcpy(lpszBuf, szManufacturer); bHaveManu = TRUE;
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #1, Main [HP] Section"));
} // Try # 1
// Try # 2 to get the manufacturer's section name
// Try the main [Manufacturer] section.
// Cycle through each name expecting the name to be in the
// Strings section.
if (!bHaveManu AND (OK == IpFindFirstLine(hInf, "Manufacturer", NULL, &hInfLine))) { // Get the number of lines
if (OK == IpGetLineCount(hInf, "Manufacturer", &nCount)) { for (i = 0; i < nCount; i++) { lpszBuf[0] = '\0'; lpszTemp[0] = '\0'; if (OK == IpGetStringField(hInf, hInfLine, 0, lpszTemp, _MAX_LINE, &nCopied)) { GenFormStrWithoutPlaceHolders(lpszBuf,lpszTemp,hInf);
// Garth: Use CompareString with the
// IGNORE_CASE, IGNORE_KANATYPE, and IGNORE_WIDTH flags
if (lstrcmpi(szManufacturer, lpszBuf) == 0) { // We have found the manufacturer name, see if
// there is a key on the right
nFields = 0; if ( (OK == IpGetFieldCount(hInf, hInfLine, &nFields)) AND (nFields > 0) ) { if (OK == IpGetStringField(hInf, hInfLine, 1, lpszBuf, _MAX_LINE, &nCopied)) { // There was a value on the right. It is stored in lpszBuf.
// Just try to use it below as the name of the main section.
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #2 Before NULL, lpszTemp = %s", lpszTemp)); DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Manual Install = %s", lpszBuf));
lpszTemp[0] = '\0'; } } else { // There was no value on the right, use the name from
// lpszTemp
lpszBuf[0] = '\0'; lstrcpy(lpszBuf, lpszTemp);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #3 Manual")); }
bHaveManu = TRUE; break; } }
if (OK != IpFindNextLine(hInf, &hInfLine)) { break; } } }
} // Try # 2
// Try # 3 to get the manufacturer's section name
// Try the main [Manufacturer] section.
// The printer manufacturer name does not match the
// driver manufacturer name. (IE Canon and Epson with GCA)
// Check to see if there is only one name in the manufacturer section.
if (!bHaveManu AND (OK == IpFindFirstLine(hInf, "Manufacturer", NULL, &hInfLine))) { // Get the number of lines
if (OK == IpGetLineCount(hInf, "Manufacturer", &nCount)) { if (nCount IS 1) { // Only one line in manufaturer section.
// This has to be our guy.
// See if there is a key on the right
nFields = 0; lpszBuf[0] = '\0'; IpGetFieldCount(hInf, hInfLine, &nFields);
if (nFields > 0) { if (OK == IpGetStringField(hInf, hInfLine, 1, lpszBuf, _MAX_LINE, &nCopied)) { // There was a value on the right. It is stored in lpszBuf.
// Try to use it below as the name of the main section.
//
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Before NULL <%s>", lpszTemp)); DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #4 One Manual <%s>", lpszBuf));
lpszTemp[0] = '\0'; bHaveManu = TRUE; } } else { // There was no value on the right. Get the key on the left.
if (OK == IpGetStringField(hInf, hInfLine, 0, lpszBuf, _MAX_LINE, &nCopied)) { lpszTemp[0] = '\0'; bHaveManu = TRUE;
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #6 One Manual")); } } } }
} // Try # 3
// Try # 4 to get the manufacturer's section name
// Try a [PnP] section.
if (!bHaveManu AND (OK == IpFindFirstLine(hInf, "PnP", NULL, &hInfLine))) { lpszBuf[0] = '\0'; lstrcpy(lpszBuf, "PnP"); bHaveManu = TRUE;
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #6 [Pnp]"));
} // Try # 4
// Try # 6. Get the install section associated with this
// manufacturer and model.
//
// Look for a manufacturer's section with a profile key
// corresponding to the model name. The first key on the RHS
// should be the model section name.
//
if (bHaveManu AND (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine))) { DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Found first line <%s>", lpszBuf)); DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Search for this model <%s>", szModel));
lstrcpy(lpszTemp, cszNull);
if (OK == IpGetProfileString(hInf,lpszBuf,szModel,lpszTemp,_MAX_LINE)) { DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Profile string before lstrtok"));
lstrtok(lpszTemp, cszComma);
// quick check of model section name
//
if (OK == IpFindFirstLine(hInf, lpszTemp, NULL, &hInfLine)) { if ( (OK == IpGetProfileString(hInf,lpszTemp,"CopyFiles",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DataSection",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DriverFile",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DataFile",lpszTemp2,_MAX_LINE))) { lstrcpyn(szSection, lpszTemp, _MAX_PATH_); IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #7 Found Correct Section"));
return TRUE; }
// We have a bad INF file:
// We have the manufacturer name and the model name and an
// install section, but it doesn't have any of the keys we need.
// bail.
//
IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #8 Bad INF file"));
return FALSE; } }
// The model name doesn't appear as a profile string.
// Perhaps a variable from the Strings sections appears in its place.
// Try that.
if ( (OK == IpGetLineCount(hInf, lpszBuf, &nCount)) AND (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine)) ) { for (i = 0; i < nCount; i++) { lstrcpy(lpszTemp, cszNull);
if (OK == IpGetStringField(hInf, hInfLine, 0, lpszTemp, _MAX_LINE, &nCopied)) { GenFormStrWithoutPlaceHolders(lpszTemp2,lpszTemp,hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : lpszTemp2=%s, lpszTemp=%s", lpszTemp2, lpszTemp));
if (lstrcmpi(szModel, lpszTemp2) == 0) { // The model name has a string var on the left
// Get field 1. This is the install section name.
if (OK == IpGetStringField(hInf, hInfLine, 1, lpszTemp, _MAX_LINE, &nCopied)) { DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : Before lstrtok comma"));
lstrtok(lpszTemp, cszComma);
// quick check of model section name
//
if (OK == IpFindFirstLine(hInf, lpszTemp, NULL, &hInfLine)) { if ((OK == IpGetProfileString(hInf,lpszTemp,"CopyFiles",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DataSection",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DriverFile",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszTemp,"DataFile",lpszTemp2,_MAX_LINE))) { lstrcpyn(szSection, lpszTemp, _MAX_PATH_); IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #9 Strings Found Correct Section"));
return TRUE; }
// We have a bad INF file:
// We have the manufacturer name and the model name and an
// install section, but it doesn't have any of the keys we need.
// bail.
//
IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #10 Strings Bad INF File"));
return FALSE; } } } }
if (OK != IpFindNextLine(hInf, &hInfLine)) { break; } } }
} // Try # 6
// Try # 7
// Check to see if there is a valid InstallSection.
//
if (OK == IpFindFirstLine(hInf, "InstallSection", NULL, &hInfLine)) { // quick check of InstallSection
if (OK == IpFindFirstLine(hInf, "InstallSection", NULL, &hInfLine)) { if ((OK == IpGetProfileString(hInf,"InstallSection","CopyFiles",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,"InstallSection","DataSection",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,"InstallSection","DriverFile",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,"InstallSection","DataFile",lpszTemp2,_MAX_LINE))) { lstrcpyn(szSection, "InstallSection", _MAX_PATH_); IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #11 Found correct InstallSection"));
return TRUE; } }
} // Try # 7
// Try # 8.
// Try the [Strings] section.
if (OK == IpFindFirstLine(hInf, "Strings", NULL, &hInfLine)) { // Get the number of lines
if (OK == IpGetLineCount(hInf, "Strings", &nCount)) { for (i = 0; i < nCount; i++) { lpszBuf[0] = '\0'; lpszTemp[0] = '\0'; if (OK == IpGetStringField(hInf, hInfLine, 1, lpszTemp, _MAX_LINE, &nCopied)) { // Garth: Use CompareString with the
// IGNORE_CASE, IGNORE_KANATYPE, and IGNORE_WIDTH flags
if (lstrcmpi(szModel, lpszTemp) == 0) { // The model name has a string var on the left
if (OK == IpGetStringField(hInf, hInfLine, 0, lpszBuf, _MAX_LINE, &nCopied)) { // There was a value on the left, try to use it
if (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine)) { // quick check of Strings
if (OK == IpFindFirstLine(hInf, lpszBuf, NULL, &hInfLine)) { if ((OK == IpGetProfileString(hInf,lpszBuf,"CopyFiles",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszBuf,"DataSection",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszBuf,"DriverFile",lpszTemp2,_MAX_LINE)) OR (OK == IpGetProfileString(hInf,lpszBuf,"DataFile",lpszTemp2,_MAX_LINE))) { lstrcpyn(szSection, lpszBuf, _MAX_PATH_); IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #12 Found String = Model Section"));
return TRUE; } } } } } } } } } // Try # 8
// No more ideas, Give up.
//
IpClose(hInf);
DBG_MSG(DBG_LEV_INFO, ("FindCorrectSection : #13 Failed to find section"));
return FALSE; }
//-----------------------------------------------------------------------
// Function: GetInfOption(hInf,lpszSection,bDataSection,bLocalize,
// lpszDataSection,lpszKeyName,lpszBuffer,wBufSize)
//
// Action: Get the specified keyword from the INF file. Look in the
// appropriate section(s)
//
// Note: Keys may always appear in lpszSection, and may appear in
// lpszDataSection if bDataSection is TRUE. If the key appears
// in both sections, the value from lpszSection takes precedence.
//
// Return: TRUE if we got the option, FALSE if not
//-----------------------------------------------------------------------
BOOL NEAR PASCAL GetInfOption(HINF hInf, LPSTR lpszSection, BOOL bDataSection, BOOL bLocalize, LPSTR lpszDataSection, LPSTR lpszKeyName, LPSTR lpszBuffer, WORD wBufSize) { LPSTR lpszTemp; BOOL bAllocated; BOOL bSuccess;
if (bLocalize && wBufSize && (lpszTemp=(LPSTR)(HP_GLOBAL_ALLOC_DLL(max(wBufSize,_MAX_PATH_))))) { bAllocated=TRUE; } else { lpszTemp=lpszBuffer; bAllocated=FALSE; }
if (OK == IpGetProfileString(hInf,lpszSection,lpszKeyName,lpszTemp,wBufSize)) { bSuccess=TRUE; } else if (bDataSection && (OK == IpGetProfileString(hInf,lpszDataSection, lpszKeyName,lpszTemp,wBufSize))) { bSuccess=TRUE; } else bSuccess=FALSE;
if (bAllocated) { if (bSuccess) GenFormStrWithoutPlaceHolders(lpszBuffer,lpszTemp,hInf);
HP_GLOBAL_FREE(lpszTemp); }
return bSuccess; }
//-----------------------------------------------------------------------
// Function: myatoi(pszInt)
//
// Yup, the first function that everyone writes!
//-----------------------------------------------------------------------
int WINAPI myatoi( LPSTR pszInt) { int nRet; char cSave;
for (nRet = 0; ; ++pszInt) {
if ((cSave = (*pszInt - (char)'0')) > 9) break;
nRet = (nRet * 10) + cSave; }
return nRet; }
//------------------------------------------------------------------------
// Function: ZeroMem(lpData,wCount)
//
// Action: Zero-initialize wCount bytes at lpData (duh)
//
// Return: VOID
//------------------------------------------------------------------------
VOID WINAPI ZeroMem(LPVOID lpData, WORD wCount) { LPBYTE lpBuf=(LPBYTE)lpData;
while (wCount--) { *lpBuf='\0'; lpBuf++; } }
//--------------------------------------------------------------------
// Function: FlushCachedPrinterFiles(void)
//
// Action: Flush printer driver files that might be cached by the
// system. Two caches exist--one maintained by USER, and one
// maintained by winspl16.drv (for old drivers)
//
// Return: Void
//--------------------------------------------------------------------
VOID WINAPI FlushCachedPrinterFiles() { HWND hWndMsgSvr; HMODULE hModWinspl16;
// Send a message to MSGSVR32 to flush the default printer's cached DC.
if (hWndMsgSvr = FindWindow(cszMsgSvr, NULL)) SendMessage(hWndMsgSvr, WM_USER+0x010A, 0, 0L);
// If WINSPL16 is in memory, force it to flush its cache
if (hModWinspl16 = GetModuleHandle(cszWinspl16)) { WEPPROC fpWep;
if (fpWep = (WEPPROC)GetProcAddress(hModWinspl16, "WEP")) { fpWep(0); } } }
//------------------------------------------------------------------
// Function: RenameFailed(lpsi,lpFileSpec)
//
// Action: Handle the case where the rename failed. Give the user a
// chance to close existing apps and shut down printers.
//
// Return: 0 if the file isn't loaded (use default handling)
// VCPN_ABORT if file is in use & user cancelled
// VCPN_RETRY if file is in use & user wants to retry
//------------------------------------------------------------------
LRESULT NEAR PASCAL RenameFailed(LPSI lpsi, LPVCPFILESPEC lpFileSpec) { char szFile[_MAX_PATH_];
if (vsmGetStringName(lpFileSpec->vhstrFileName,szFile,sizeof(szFile)) && GetModuleHandle(szFile)) { char Message[_MAX_PATH_];
// File is in use by the system--give the user the chance to shut
// down existing applications, then continue.
if ( LoadString(g_hInst, IDS_ERR_FILE_IN_USE, Message, _MAX_PATH_) IS 0) { DBG_MSG(DBG_LEV_INFO, ("RenameFailed : Could not load string, file in use"));
lstrcpy(Message, cszFileInUse); } if (IDCANCEL IS MessageBox(NULL, Message, szFile, MB_ICONEXCLAMATION|MB_RETRYCANCEL|MB_DEFBUTTON2)) { return VCPN_ABORT; } else { // Flush any cached printers & retry
FlushCachedPrinterFiles(); return VCPN_RETRY; } }
return 0; }
//------------------------------------------------------------------
// Function: MyVcpCallbackProc(lpvObj,uMsg,wParam,lParam,lparamRef)
//
// Action: This simply passes through to vcpUICallbackProc, with one
// exception: If a file is in use in the system, we warn the
// user and give them a chance to close existing apps.
//
// Return: Whatever RenameFailed or vcpUICallbackProc return.
//------------------------------------------------------------------
LRESULT CALLBACK MyVcpCallbackProc(LPVOID lpvObj, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSI lpsi) { LRESULT lResult = 0;
if ((VCPM_FILERENAME + VCPM_ERRORDELTA) IS uMsg) lResult = RenameFailed(lpsi,(LPVCPFILESPEC)lpvObj);
if (! lResult) { lResult = vcpUICallbackProc(lpvObj,uMsg,wParam,lParam, (LPARAM)lpsi->lpVcpInfo); }
return lResult; }
//-------------------------------------------------------------------
// Function: OpenQueue(lpsi, lpVcpInfo, lpbOpened)
//
// Action: Initialize lpVcpInfo and open the queue. *lpbOpened reflects
// whether or not we actually opened the queue.
//
// Return: TRUE if successful, FALSE if not.
//-------------------------------------------------------------------
BOOL NEAR PASCAL OpenQueue(LPSI lpsi, LPVCPUIINFO lpVcpInfo, BOOL FAR *lpbOpened) { BOOL bSuccess = FALSE;
// Initialize the structure
ZeroMem(lpVcpInfo, sizeof(VCPUIINFO));
lpVcpInfo->flags = VCPUI_CREATEPROGRESS; lpVcpInfo->hwndParent = NULL;
lpsi->lpVcpInfo = (LPBYTE) lpVcpInfo;
// Open the queue
if (RET_OK IS VcpOpen((VIFPROC)MyVcpCallbackProc, (LPARAM)lpsi)) { bSuccess = TRUE; *lpbOpened = TRUE; } else { // Couldn't open the queue, so clear lpVcpInfo
lpsi->lpVcpInfo = NULL; *lpbOpened = FALSE; }
return bSuccess; }
//-------------------------------------------------------------------
// Function: GenInstallCallback(lpGenInfo,lpsi)
//
// Action: This gets called for each file to be queued. Add it to
// the list identified by lpsi->lpFiles, then queue it
// to be copied to the system directory
//
// Return: GENN_SKIP if it's a copy (we queue it ourselves),
// GENN_OK otherwise.
//-------------------------------------------------------------------
LRESULT WINAPI GenInstallCallback(LPGENCALLBACKINFO lpGenInfo, LPSI lpsi) { int wLength; int wMaxLength; int wChunk;
if (GENO_COPYFILE != lpGenInfo->wOperation) return GENN_OK;
// Save the dependent file in lpsi->lpFiles. wFilesAllocated and
// wFilesUsed are used to keep track of memory usage.
wLength = lstrlen(lpGenInfo->pszDstFileName);
// Pad the length if it's going to LDID_COLOR
if (LDID_COLOR IS lpGenInfo->ldidDst) wMaxLength = wLength + MAX_COLOR_PATH; else wMaxLength = wLength;
wChunk = max(256,wMaxLength);
// This is where we allocate lpFiles the first time
if (! lpsi->lpFiles) { if (lpsi->lpFiles = (unsigned char *)HP_GLOBAL_ALLOC_DLL(wChunk)) { lpsi->wFilesAllocated = wChunk; } else { return GENN_SKIP; } }
// double NULL terminated
if ((lpsi->wFilesUsed + wMaxLength + 2) > lpsi->wFilesAllocated) { LPSTR lpNew;
lpNew = (unsigned char *)HP_GLOBAL_REALLOC_DLL(lpsi->lpFiles, lpsi->wFilesAllocated + wChunk, GMEM_ZEROINIT);
if (lpNew) { lpsi->wFilesAllocated += wChunk; lpsi->lpFiles = (unsigned char *) lpNew; } else { return GENN_SKIP; } }
// Add this file to the list && ensure that it's doubly-NULL
// terminated. If it's going to LDID_COLOR, prepend "COLOR\"
// to the string
if (LDID_COLOR IS lpGenInfo->ldidDst) { char ColorPath[MAX_COLOR_PATH]; if ( LoadString(g_hInst, IDS_COLOR_PATH, ColorPath, MAX_COLOR_PATH) IS 0) { strcpy(ColorPath, "COLOR\\"); }
strcpy((LPSTR)(lpsi->lpFiles + lpsi->wFilesUsed), ColorPath); lpsi->wFilesUsed += strlen(ColorPath); }
strcpy((LPSTR)(lpsi->lpFiles + lpsi->wFilesUsed), lpGenInfo->pszDstFileName); lpsi->wFilesUsed += (wLength + 1); lpsi->lpFiles[lpsi->wFilesUsed] = '\0';
return GENN_SKIP; }
//-------------------------------------------------------------------
// Function: QueueNewInf(lpsi, lpdn)
//
// Action: Call GenInstallEx to queue up the files we need to copy.
//
// Return: TRUE if we should continue, FALSE if not.
//-------------------------------------------------------------------
BOOL WINAPI QueueNewInf(LPSI lpsi, LPDRIVER_NODE lpdn) { if (lpdn) { return (RET_OK == GenInstallEx((HINF)lpsi->hModelInf, lpdn->lpszSectionName, GENINSTALL_DO_FILES, NULL, (GENCALLBACKPROC)GenInstallCallback, (LPARAM)lpsi)); }
return FALSE; }
//-------------------------------------------------------------------
// Function: CloseQueue(lpsi, bSuccessSoFar, bOpened)
//
// Action: Close the VCP queue and report any errors to the user.
// If bSuccessSoFar is FALSE, abandon the queue & return FALSE
//
// Return: TRUE if the copy was successful, FALSE if not.
//-------------------------------------------------------------------
BOOL NEAR PASCAL CloseQueue(LPSI lpsi, BOOL bSuccessSoFar, BOOL bOpened) { BOOL bSuccess = FALSE;
if (! bOpened) bSuccess = bSuccessSoFar; else { if (! bSuccessSoFar) VcpClose(VCPFL_ABANDON, NULL); else if (lpsi->bDontQueueFiles) { VcpClose(VCPFL_ABANDON, NULL); bSuccess=TRUE; }
// The queue is now closed, so clear lpsi->lpVcpInfo
if (lpsi->lpVcpInfo) lpsi->lpVcpInfo = NULL; }
return bSuccess; }
//-----------------------------------------------------------------------
// Function: WrapVcpCopy(lpsi,lpfnQueueFunction,lpdn)
//
// Action: Wrap lpfnQueueFunction inside calls to open & close the
// queue. If lpsi->bDontCopyFiles is TRUE, we'll close the
// queue without copying anything.
//
// Return: TRUE if everything went smoothly, FALSE if not.
//-----------------------------------------------------------------------
BOOL WINAPI WrapVcpCopy(LPSI lpsi, LPQUEUEPROC lpfnQueueFunction, LPDRIVER_NODE lpdn)
{ VCPUIINFO VcpInfo; BOOL bSuccess=FALSE; BOOL bOpened=FALSE;
if (OpenQueue(lpsi, &VcpInfo, &bOpened)) { BOOL bQueuedOK;
bQueuedOK = lpfnQueueFunction(lpsi, lpdn);
bSuccess = CloseQueue(lpsi, bQueuedOK, bOpened); }
return bSuccess; }
//--------------------------------------------------------------------
// Function: PrintLPSI(lpsi)
//
// Action: Print out the contents of the LPSI
//
// Side effect: None
//
// Return: VOID
//
//--------------------------------------------------------------------
VOID PrintLPSI(LPSI lpsi) { DBG_MSG(DBG_LEV_INFO, ("LPSI : dwDriverVersion : %#lX", (DWORD)lpsi->dwDriverVersion)); DBG_MSG(DBG_LEV_INFO, ("LPSI : dwUniqueID : %d" , lpsi->dwUniqueID)); DBG_MSG(DBG_LEV_INFO, ("LPSI : bNetPrinter : %d" , lpsi->bNetPrinter)); DBG_MSG(DBG_LEV_INFO, ("LPSI : wFilesUsed : %d" , lpsi->wFilesUsed)); DBG_MSG(DBG_LEV_INFO, ("LPSI : wFilesAllocated : %d" , lpsi->wFilesAllocated)); DBG_MSG(DBG_LEV_INFO, ("LPSI : wRetryTimeout : %d" , lpsi->wRetryTimeout)); DBG_MSG(DBG_LEV_INFO, ("LPSI : wDNSTimeout : %d" , lpsi->wDNSTimeout)); DBG_MSG(DBG_LEV_INFO, ("LPSI : bDontQueueFiles : %d" , lpsi->bDontQueueFiles)); DBG_MSG(DBG_LEV_INFO, ("LPSI : bNoTestPage : %d" , lpsi->bNoTestPage)); DBG_MSG(DBG_LEV_INFO, ("LPSI : hModelInf : %0X" , lpsi->hModelInf)); DBG_MSG(DBG_LEV_INFO, ("LPSI : lpPrinterInfo2 : %d" , lpsi->lpPrinterInfo2)); DBG_MSG(DBG_LEV_INFO, ("LPSI : lpDriverInfo3 : %d" , lpsi->lpDriverInfo3)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szFriendly : %s" , lpsi->szFriendly)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szModel : %s" , lpsi->szModel)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szDefaultDataType : %s" , lpsi->szDefaultDataType)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szBinName : %s" , lpsi->BinName)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szShareName : %s" , lpsi->ShareName)); DBG_MSG(DBG_LEV_INFO, ("LPSI : INFfileName : %s" , lpsi->INFfileName)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szPort : %s" , lpsi->szPort)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szDriverFile : %s" , lpsi->szDriverFile)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szDataFile : %s" , lpsi->szDataFile)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szConfigFile : %s" , lpsi->szConfigFile)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szHelpFile : %s" , lpsi->szHelpFile)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szPrintProcessor : %s" , lpsi->szPrintProcessor)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szVendorSetup : %s" , lpsi->szVendorSetup)); DBG_MSG(DBG_LEV_INFO, ("LPSI : szVendorInstaller : %s" , lpsi->szVendorInstaller)); }
//-----------------------------------------------------------------------
// Function: FindSelectedDriver(lpsi, lpdn)
//
// Action: Try to find the install section associated with the specified
// model. If the currently selected driver matches the model, we
// get all the required info from it.
//
// Note: Upon entry
// lpdn->lpszSectionName
// has the name of the correct section in the INF file.
//
// Return: TRUE is successful, FALSE if not.
//-----------------------------------------------------------------------
BOOL WINAPI FindSelectedDriver( LPSI lpsi, LPDRIVER_NODE lpdn) { HINFLINE hInfDummy; HINF myHINF; WORD wTest; BOOL bDataSection=FALSE; BOOL bQueuedOK; char szData[_MAX_PATH_]; char szTimeout[10]; char lpSection[_MAX_PATH_];
// Extract all of our information from the INF file.
// Open the INF file.
if (OK != IpOpen(lpsi->INFfileName, &myHINF)) { return FALSE; }
lstrcpyn(lpSection, lpdn->lpszSectionName, _MAX_PATH_);
if (OK != IpFindFirstLine(myHINF, lpSection, NULL, &hInfDummy)) { IpClose(myHINF); return FALSE; } lpsi->hModelInf = (int) myHINF;
// Build the dependent file list now.
lpsi->bDontQueueFiles=TRUE; bQueuedOK = WrapVcpCopy(lpsi,QueueNewInf,lpdn); lpsi->bDontQueueFiles = FALSE;
if (!bQueuedOK) { IpClose(myHINF); lpsi->hModelInf = 0; return FALSE; }
if (!lpsi->wFilesUsed) { IpClose(myHINF); lpsi->hModelInf = 0; return FALSE; }
// Check for a data section. If none is specified, then the
// data section is the section associated with this device.
// The DataSection key can only appear in the installer section
// (for obvious reasons).
bDataSection=GetInfOption(myHINF,lpSection,FALSE,FALSE,NULL, cszDataSection,szData,sizeof(szData));
// Don't change szData below this line! (It may contain the
// data section name)
// Get the driver name (default is the primary section name)
if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszDriverFile,lpsi->szDriverFile,sizeof(lpsi->szDriverFile))) { lstrcpyn(lpsi->szDriverFile,lpSection,sizeof(lpsi->szDriverFile)); }
// Get the data file name (default is the primary section name)
if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszDataFile,lpsi->szDataFile,sizeof(lpsi->szDataFile))) { lstrcpyn(lpsi->szDataFile,lpSection,sizeof(lpsi->szDataFile)); }
// Get the config file name (default is the driver name)
if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszConfigFile,lpsi->szConfigFile,sizeof(lpsi->szConfigFile))) { lstrcpyn(lpsi->szConfigFile,lpsi->szDriverFile, sizeof(lpsi->szConfigFile)); }
// Get the help file (default is none)
GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszHelpFile,lpsi->szHelpFile,sizeof(lpsi->szHelpFile));
// Get the Print Processor (default comes from resources)
if (!GetInfOption(myHINF,lpSection,bDataSection,TRUE,szData, cszPrintProcessor,lpsi->szPrintProcessor, sizeof(lpsi->szPrintProcessor))) { if (LoadString(g_hInst,IDS_DEFAULT_PRINTPROCESSOR, lpsi->szPrintProcessor,sizeof(lpsi->szPrintProcessor)) IS 0) { DBG_MSG(DBG_LEV_INFO, ("FindSelectedDriver : Could not load string, default print processor"));
lstrcpy(lpsi->szPrintProcessor, cszDefaultPrintProcessor); } }
// Get the Default Data Type (default comes from resources)
if (!GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszDefaultDataType,lpsi->szDefaultDataType, sizeof(lpsi->szDefaultDataType))) { if ( LoadString(g_hInst,IDS_DEFAULT_DATATYPE, lpsi->szDefaultDataType,sizeof(lpsi->szDefaultDataType)) IS 0) { DBG_MSG(DBG_LEV_INFO, ("FindSelectedDriver : Could not load string, default data type"));
lstrcpy(lpsi->szDefaultDataType, cszMSDefaultDataType); } }
// Get the Vendor Setup (default is none)
GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszVendorSetup,lpsi->szVendorSetup,sizeof(lpsi->szVendorSetup));
// Get the Vendor Installer (default is none)
GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszVendorInstaller,lpsi->szVendorInstaller, sizeof(lpsi->szVendorInstaller));
// Get the device timeouts (ClearPrinterInfo defaults to 15 & 45)
if (GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszRetryTimeout,szTimeout,sizeof(szTimeout))) { if (wTest=myatoi(szTimeout)) lpsi->wRetryTimeout=wTest; }
if (GetInfOption(myHINF,lpSection,bDataSection,FALSE,szData, cszNotSelectedTimeout,szTimeout,sizeof(szTimeout))) { if (wTest=myatoi(szTimeout)) lpsi->wDNSTimeout=wTest; }
// Decide whether or not we should use the test page. Test page is
// skipped if the INF specifically requests it, if we have a
// vendor-supplied DLL, or if the port is in conflict.
if ( (lpsi->szVendorSetup[0]) || (lpsi->szVendorInstaller[0]) || GetInfOption(myHINF, lpSection, bDataSection, FALSE, szData, cszNoTestPage, szTimeout, sizeof(szTimeout))) { lpsi->bNoTestPage=TRUE; }
IpClose(myHINF); lpsi->hModelInf = 0;
return TRUE; }
//--------------------------------------------------------------------
// Function: CreateDriverNode()
//
// Action: Create a driver node and initialize it..
//
// Side effect: Allocates memory that must be freed by caller..
//
// Return: RET_OK on success.
//
//--------------------------------------------------------------------
RETERR WINAPI CreateDriverNode( LPLPDRIVER_NODE lplpdn, UINT Rank, UINT InfType, unsigned InfDate, LPCSTR lpszDevDescription, LPCSTR lpszDrvDescription, LPCSTR lpszProviderName, LPCSTR lpszMfgName, LPCSTR lpszInfFileName, LPCSTR lpszSectionName, DWORD dwPrivateData) { int DrvDescLen = 0; int DevDescLen = 0; int SectionLen = 0; LPSTR lpszTemp;
// Compute a allocate space for the variable part of the DRIVER node
//
DrvDescLen = lstrlen(lpszDrvDescription); DevDescLen = lstrlen(lpszDevDescription); SectionLen = lstrlen(lpszSectionName);
*lplpdn = (LPDRIVER_NODE) HP_GLOBAL_ALLOC_DLL(sizeof(DRIVER_NODE) + DrvDescLen + DevDescLen + SectionLen + (2 * MAX_DEVICE_ID_LEN) + _MAX_PATH_ + NSTRINGS);
if (*lplpdn == NULL) { return(ERR_DI_LOW_MEM); } else { (*lplpdn)->Rank = Rank; (*lplpdn)->InfType = InfType; (*lplpdn)->InfDate = InfDate;
// For compatibility copy the DevDescription into lpszDescription
lpszTemp = (LPSTR)((DWORD)(*lplpdn) + sizeof(DRIVER_NODE)); lstrcpy(lpszTemp, lpszDevDescription); (*lplpdn)->lpszDescription = lpszTemp;
// New. Copy the Drv description into the lpszDrvDescription
lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(DevDescLen + 1)); lstrcpy(lpszTemp, lpszDevDescription); (*lplpdn)->lpszDrvDescription = lpszTemp;
lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(DrvDescLen + 1)); lstrcpy(lpszTemp, lpszSectionName); (*lplpdn)->lpszSectionName = lpszTemp;
// Init HardwareID and CompatIDs buffers to empty strings
lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(SectionLen + 1)); *lpszTemp = '\0'; (*lplpdn)->lpszHardwareID = lpszTemp;
lpszTemp = (LPSTR)((DWORD)(lpszTemp) + (DWORD)(MAX_DEVICE_ID_LEN + 1)); *lpszTemp = '\0'; (*lplpdn)->lpszCompatIDs = lpszTemp;
(*lplpdn)->atInfFileName = GlobalAddAtom(lpszInfFileName);
if (lpszMfgName != NULL) { (*lplpdn)->atMfgName = GlobalAddAtom(lpszMfgName); } if (lpszProviderName != NULL) { (*lplpdn)->atProviderName = GlobalAddAtom(lpszProviderName); }
return(RET_OK); } }
//--------------------------------------------------------------------
//
// Function: HaveAllFiles(lpsi)
//
// Action: Do we have all printer driver dependent files in this directory?
//
// Return: TRUE if all found, FALSE if not
//
//--------------------------------------------------------------------
BOOL WINAPI HaveAllFiles(LPSI lpsi, LPSTR cszPath) { int result; LPSTR lpThisFile; struct stat statBuf; char fileSpec[_MAX_PATH_]; BOOL fileNotFound = FALSE;
// Verify that all the dependent files are in the directory
// pointed to by cszPath.
//
for (lpThisFile = (char *)lpsi->lpFiles; *lpThisFile; lpThisFile += (lstrlen(lpThisFile) + 1)) { // Get data associated with file
lstrcpy(fileSpec, cszPath); lstrcat(fileSpec, cszBackslash); lstrcat(fileSpec, lpThisFile); result = stat( fileSpec, (struct stat *)&statBuf);
// Check if statistics are valid:
if ( result ISNT 0 ) { DBG_MSG(DBG_LEV_INFO, ("HaveAllFiles : File not found <%s>", fileSpec));
fileNotFound = TRUE; break; } }
return !fileNotFound; }
//--------------------------------------------------------------------
//
// Function: CopyNeededFiles(lpsi, cszPath)
//
// Action: Copy all printer driver files for this printer from the
// source directory to the requied printer driver directory.
//
// Return: RET_OK on success.
// RET_FILE_COPY_ERROR is there is a file copy error
//
//--------------------------------------------------------------------
DWORD WINAPI CopyNeededFiles(LPSI lpsi, LPSTR cszPath) { DWORD dwResult = RET_OK; LONG lResult; LPSTR lpThisFile; OFSTRUCT ofStrSrc; OFSTRUCT ofStrDest; HFILE hfSrcFile, hfDstFile; char fileSource[_MAX_PATH_]; char fileDest[_MAX_PATH_]; char destDir[_MAX_PATH_];
DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : About to flush printer files"));
lstrcpy(destDir, lpsi->szDriverDir);
if (lstrcmpi(destDir, cszPath) IS 0) {
// all required files are in the destination directory
//
return RET_OK; }
// Flush any cached files the system may be holding
//
FlushCachedPrinterFiles();
LZStart();
for (lpThisFile = (char *)lpsi->lpFiles; *lpThisFile; lpThisFile += (lstrlen(lpThisFile) + 1)) {
lstrcpy(fileSource, cszNull); lstrcat(fileSource, cszPath); lstrcat(fileSource, cszBackslash); lstrcat(fileSource, lpThisFile);
lstrcpy(fileDest, cszNull); lstrcat(fileDest, destDir); lstrcat(fileDest, cszBackslash); lstrcat(fileDest, lpThisFile);
lResult = -1;
if (hfSrcFile = LZOpenFile(fileSource, &ofStrSrc, OF_READ)) {
if (hfDstFile = LZOpenFile(fileDest, &ofStrDest, OF_CREATE)) { #if 0
lResult = CopyLZFile(hfSrcFile, hfDstFile); #else
// Hack. If spooler has a file locked, then this call
// would fail resulting in the class-installer being called
// to copy the files. But for some reason, the class-installer
// prompts a path-dialog wanting to know where the files
// are. Several attempts at fixing up the device-info
// struct with path-information failed to remedy this
// situation. Therefore, for now, we will prevent this
// CopyLZFile() from returning error to keep away from
// the class-installer until this problem can be figured
// out.
//
// See the caller of this routine to see how the class-
// installer is called.
//
CopyLZFile(hfSrcFile, hfDstFile);
lResult = 0; #endif
LZClose(hfDstFile);
} else {
DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : Could not create dst-file <%s>", fileDest)); }
LZClose(hfSrcFile);
} else {
DBG_MSG(DBG_LEV_INFO, ("CopyNeededFiles : Could not create src-file <%s>", fileSource)); }
if (lResult < 0) {
dwResult = RET_FILE_COPY_ERROR; break; } }
LZDone();
return dwResult; }
//--------------------------------------------------------------------
// Function: ParseINF16(LPSI)
//
// Action: Parse the INF file and store required info in LPSI.
//
// Return: RET_OK on success.
// RET_SECT_NOT_FOUND if no install section for this model
// RET_DRIVER_NODE_ERROR if memory error
// RET_INVALID_INFFILE other problem with INF file
//
//--------------------------------------------------------------------
RETERR FAR PASCAL ParseINF16(LPSI lpsi) { RETERR ret = RET_OK; LPDRIVER_NODE lpdn = NULL; char szManufacturer[_MAX_PATH_]; char szSection[_MAX_PATH_]; char cszPath[_MAX_PATH_];
// Get the manufacturer
//
lstrcpyn(szManufacturer,lpsi->szModel,sizeof(szManufacturer)); lstrtok(szManufacturer,cszSpace);
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : Search inf<%s> mfg<%s> model<%s>", lpsi->INFfileName, szManufacturer, lpsi->szModel));
// Get the correct section name
if (!FindCorrectSection(lpsi->INFfileName, szManufacturer, lpsi->szModel, szSection)) { if (lstrcmpi(szManufacturer, "HP") IS 0) { lstrcpy(szManufacturer, "Hewlett-Packard");
if (!FindCorrectSection(lpsi->INFfileName, szManufacturer, lpsi->szModel, szSection)) { DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Failed"));
return RET_SECT_NOT_FOUND;
} else {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Succeeded")); }
} else {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Failed"));
return RET_SECT_NOT_FOUND; }
} else {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindCorrectSection Succeeded")); }
// Create a driver node
//
if (RET_OK != CreateDriverNode(&lpdn, 0, INFTYPE_TEXT, NULL, lpsi->szModel, cszNull, cszNull, szManufacturer, lpsi->INFfileName, szSection, 0)) { DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : CreateDriverNode Failed"));
return RET_DRIVER_NODE_ERROR;
} else {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : CreateDriverNode Succeeded")); }
// Find the selected driver and dependent files in the INF. Store in lpsi.
//
if (! FindSelectedDriver(lpsi, lpdn)) {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindSelectedDriver Failed"));
if (lpdn->atInfFileName ISNT 0) GlobalDeleteAtom(lpdn->atInfFileName); if (lpdn->atMfgName ISNT 0) GlobalDeleteAtom(lpdn->atMfgName); if (lpdn->atProviderName ISNT 0) GlobalDeleteAtom(lpdn->atProviderName);
HP_GLOBAL_FREE(lpdn);
return RET_INVALID_INFFILE;
} else {
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : FindSelectedDriver Succeeded")); }
// If there is not a driver already installed for this printer,
// Copy the driver files to the driver directory.
if (lpsi->wCommand IS CMD_INSTALL_DRIVER) {
if ( getcwd(cszPath, _MAX_PATH_) IS NULL) lstrcpy(cszPath, ".");
if ((HaveAllFiles(lpsi, cszPath) IS TRUE) AND (CopyNeededFiles(lpsi, cszPath) IS RET_OK) ) { // We have all the needed files in the directory pointed to by cszPath.
// They have been copied to the printer driver directory.
ret = RET_OK;
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : All files copied to final directory"));
} else {
#define HKEY_LOCAL_MACHINE (( HKEY ) 0x80000002 )
DEVICE_INFO *lpdi;
ret = DiCreateDeviceInfo(&lpdi, lpsi->szModel, 0, HKEY_LOCAL_MACHINE, NULL, "Printer", NULL);
// Install the driver files. This will only copy files that
// need to be copied.
//
if (ret IS OK) {
LPDRIVER_NODE oldDN = NULL; oldDN = lpdi->lpSelectedDriver; lpdi->lpSelectedDriver = lpdn; ret = DiCallClassInstaller(DIF_INSTALLDEVICEFILES, lpdi); lpdi->lpSelectedDriver = oldDN; oldDN = NULL; DiDestroyDeviceInfoList(lpdi); lpdi = NULL; }
switch (ret) {
case OK: case ERR_DI_NOFILECOPY: ret = RET_OK; break; case ERR_DI_USER_CANCEL: ret = RET_USER_CANCEL; break; case ERR_DI_LOW_MEM: ret = RET_ALLOC_ERR; break; case ERR_DI_BAD_INF: ret = RET_INVALID_INFFILE; break;
case ERR_DI_INVALID_DEVICE_ID: case ERR_DI_INVALID_COMP_DEVICE_LIST: case ERR_DI_REG_API: // Error returned by Reg API.
case ERR_DI_BAD_DEV_INFO: // Device Info struct invalid
case ERR_DI_INVALID_CLASS_INSTALLER: // Registry entry / DLL invalid
case ERR_DI_DO_DEFAULT: // Take default action
case ERR_DI_BAD_CLASS_INFO: // Class Info Struct invalid
case ERR_DI_BAD_MOVEDEV_PARAMS: // Bad Move Device Params struct
case ERR_DI_NO_INF: // No INF found on OEM disk
case ERR_DI_BAD_PROPCHANGE_PARAMS: // Bad property change param struct
case ERR_DI_BAD_SELECTDEVICE_PARAMS: // Bad Select Device Parameters
case ERR_DI_BAD_REMOVEDEVICE_PARAMS: // Bad Remove Device Parameters
case ERR_DI_BAD_ENABLECLASS_PARAMS: // Bad Enable Class Parameters
case ERR_DI_FAIL_QUERY: // Fail the Enable Class query
case ERR_DI_API_ERROR: // DI API called incorrectly
case ERR_DI_BAD_PATH: // An OEM path was specified incorrectly
default: ret = RET_BROWSE_ERROR; break; }
DBG_MSG(DBG_LEV_INFO, ("ParseINF16 : DiCallClassInstaller %s", (ret IS OK ? "succeded" : "failed"))); }
} // if wCommand IS CMD_INSTALL_DRIVER
// We don't need the driver node anymore
// Clean up and delete
//
if (lpdn->atInfFileName ISNT 0) GlobalDeleteAtom(lpdn->atInfFileName); if (lpdn->atMfgName ISNT 0) GlobalDeleteAtom(lpdn->atMfgName); if (lpdn->atProviderName ISNT 0) GlobalDeleteAtom(lpdn->atProviderName); HP_GLOBAL_FREE(lpdn);
return ret; }
/*****************************************************************************\
* LibMain * * Entry-point initialization. * \*****************************************************************************/ #if 0
int CALLBACK LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine) { g_hInst = NULL; g_hInst = (HINSTANCE) hModule; return 1; }
#else
BOOL FAR PASCAL LibMain( HANDLE hInst, int nAttach, LPVOID pContext) { if (g_hInst == NULL) {
g_hInst = (HINSTANCE)hInst;
if (InitStrings()) return thk_ThunkConnect16(cszDll16, cszDll32, hInst, 1);
}
return FALSE; }
#endif
/*****************************************************************************\
* Windows Exit Proceedure (WEP) * * \*****************************************************************************/ int CALLBACK WEP(int exportType) { FreeStrings();
return 1; }
|