windows-nt/Source/XPSP1/NT/printscan/print/spooler/wpnpinst/dll16/wpnpin16.c
2020-09-26 16:20:57 +08:00

1773 lines
49 KiB
C

/***************************************************************************
*
* 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;
}