|
|
//////////////////////////////////////////////////////////////////////////////
//
// File Name: fxocPrnt.cpp
//
// Abstract: This provides the printer routines used in the FaxOCM
// code base.
//
// Environment: Windows XP / User Mode
//
// Copyright (c) 2000 Microsoft Corporation
//
// Revision History:
//
// Date: Developer: Comments:
// ----- ---------- ---------
// 17-Feb-1996 Wesley Witt (wesw) Created routines originally from util.cpp
// 21-Mar-2000 Oren Rosenbloom (orenr) Cleaned up, renamed, re-organized fns
// 17-Jul-2000 Eran Yariv (erany) Added CoClassInstalled code
// 08-Jan-2001 Mooly Beery (moolyb) Modified CoClassInstaller (wizard integration)
//////////////////////////////////////////////////////////////////////////////
#include "faxocm.h"
#pragma hdrstop
#include <shellapi.h>
#include <winsprlp.h>
#include <setuputil.h>
// W2K Printer defines
#define prv_W2K_FAX_PORT_NAME _T("MSFAX:") // Win2K Fax printer port name
#define prv_W2K_FAX_DRIVER_NAME _T("Windows NT Fax Driver") // Win2K Fax printer driver name
#define prv_W2K_FAX_MONITOR_NAME _T("Windows NT Fax Monitor") // Win2K Fax printer monitor name
#define prv_W9X_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers\\W9X")
#define prv_NT4_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers\\NT4")
#define prv_PRINTER_DRIVER_FOLDER _T("\\clients\\faxclient\\drivers")
#define prv_SYSTEM32_PATH _T("%windir%\\system32")
#define prv_SERVER_SERVICE_NAME _T("LanmanServer")
#define prv_SPOOLER_SERVICE_NAME _T("Spooler")
//////////////////////// Static Function Prototypes /////////////////////////
static DWORD prv_DeleteFaxPrinter(LPCTSTR lpctstrDriverName, LPCTSTR lpctstrPortName);
static DWORD prv_CreatePrintMonitor(const TCHAR *pszMonitorName, const TCHAR *pszMonitorFile);
static DWORD prv_DeletePrintMonitor(const TCHAR *pszMonitorName);
static DWORD prv_DeleteFaxPrinterDriver(LPTSTR lptstrDriverName, LPTSTR pEnviroment, DWORD dwVersionFlag);
static DWORD prv_AddFaxPrinterDriver(LPCTSTR lpctstrDriverSourcePath,LPCTSTR pEnvironment=NULL);
DWORD IsFaxInstalled (LPBOOL lpbInstalled);
static INT_PTR CALLBACK prv_dlgInstallFaxQuestion(HWND, UINT, WPARAM, LPARAM);
///////////////////////////////
// prv_GVAR
//
//
static struct prv_GVAR { TCHAR szFaxPrinterName[255 + 1]; } prv_GVAR;
static bool bIsPnpInstallation = true;
///////////////////////////////
// fxocPrnt_Init
//
// Initialize the fax printer
// subsystem.
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocPrnt_Init(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Init Print Module"),dwRes); return dwRes; }
///////////////////////////////
// fxocPrnt_Term
//
// Terminate the fax printer
// subsystem.
//
// Params:
// - void.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocPrnt_Term(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Term Print Module"),dwRes); return dwRes; }
///////////////////////////////
// fxocPrnt_Install
//
// Install fax printer monitor and driver(s)
// Note: Doesn't install the actual printer!
//
// Params:
// - pszSubcomponentId
// - pszInstallSection
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocPrnt_Install(const TCHAR *pszSubcomponentId, const TCHAR *pszInstallSection) { DWORD dwReturn = NO_ERROR;
DBG_ENTER( _T("fxocPrnt_Install"), dwReturn, _T("%s - %s"), pszSubcomponentId, pszInstallSection); //
// Before we do anything related to the printer, make sure that the 'LanManServer'
// service is started.
// The AddPrinter() code in the spooler service requires the LanManServer (SMB file sharing service)
// service to be running.
// For some reason LanManServer is not running yet when doing a system install (GUI mode) of
// Windows XP Professional (in Server it does).
//
// it's possible that LanmanServer is not installed on Desktop SKUs
if (!IsDesktopSKU()) { dwReturn = fxocSvc_StartService(prv_SERVER_SERVICE_NAME); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully started '%s' service, continuing Printer Install"), prv_SERVER_SERVICE_NAME); } else { VERBOSE(SETUP_ERR, _T("Failed to start '%s' service, rc = 0x%lx, abandoning ") _T("fax printer installation"), prv_SERVER_SERVICE_NAME, dwReturn);
return dwReturn; } }
// verify that the spooler is up
dwReturn = fxocSvc_StartService(prv_SPOOLER_SERVICE_NAME); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully started '%s' service, continuing Printer Install"), prv_SPOOLER_SERVICE_NAME); } else { VERBOSE(SETUP_ERR, _T("Failed to start '%s' service, rc = 0x%lx, abandoning ") _T("fax printer installation"), prv_SPOOLER_SERVICE_NAME, dwReturn);
return dwReturn; } //
// always attemp to remove W2K fax printer
dwReturn = prv_DeleteFaxPrinter(prv_W2K_FAX_DRIVER_NAME, prv_W2K_FAX_PORT_NAME); if (dwReturn != NO_ERROR) { VERBOSE(DBG_MSG, _T("Failed to delete W2K fax printer, rc = 0x%lx"), dwReturn);
dwReturn = NO_ERROR; } //
// delete the W2K printer driver files
//
dwReturn = prv_DeleteFaxPrinterDriver(prv_W2K_FAX_DRIVER_NAME, NULL, 3); if (dwReturn != NO_ERROR) { VERBOSE(DBG_MSG, _T("Failed to delete W2K fax drivers, rc = 0x%lx"), dwReturn); dwReturn = NO_ERROR; } //
// delete the W2K fax print monitor.
//
dwReturn = prv_DeletePrintMonitor(prv_W2K_FAX_MONITOR_NAME); if (dwReturn != NO_ERROR) { VERBOSE(DBG_MSG, _T("Failed to delete W2K fax monitor, rc = 0x%lx"), dwReturn); dwReturn = NO_ERROR; } //
// okay lets go and create a fax printer monitor.
//
if (dwReturn == NO_ERROR) { // create the print monitor
dwReturn = prv_CreatePrintMonitor(FAX_MONITOR_NAME, FAX_MONITOR_FILE); if (dwReturn != NO_ERROR) { VERBOSE(SETUP_ERR, _T("Fax Printer Install, ") _T("failed to create fax printer monitor, rc=0x%lx"), dwReturn);
} } //
// Copy the fax printer driver files
//
if (dwReturn == NO_ERROR) { dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_PRINTER_DRIVER_FOLDER);
if (dwReturn != NO_ERROR) { VERBOSE(SETUP_ERR, _T("Failed to copy Fax Printer Drivers from '%s', ") _T("attempting to install fax printer anyway..., rc=0x%lx"), prv_SYSTEM32_PATH, dwReturn);
dwReturn = NO_ERROR; } }
if (IsFaxShared()) { //
// For SKUs which support fax sharing, let's add the printer drivers for W9X and NT4 too.
//
dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_W9X_PRINTER_DRIVER_FOLDER,W9X_PRINT_ENV); if (dwReturn != NO_ERROR) { VERBOSE(SETUP_ERR, _T("Failed to copy Fax Printer Drivers for W9X, rc=0x%lx"), dwReturn);
dwReturn = NO_ERROR; } dwReturn = prv_AddFaxPrinterDriver(prv_SYSTEM32_PATH prv_NT4_PRINTER_DRIVER_FOLDER,NT4_PRINT_ENV); if (dwReturn != NO_ERROR) { VERBOSE(SETUP_ERR, _T("Failed to copy Fax Printer Drivers for NT4, rc=0x%lx"), dwReturn);
dwReturn = NO_ERROR; } }
return dwReturn; }
///////////////////////////////
// fxocPrnt_InstallPrinter
//
// Checks whether there are any Fax-capable TAPI devices
// If there are, installs the Fax printer.
//
// Params:
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD fxocPrnt_InstallPrinter() { DWORD dwReturn = NO_ERROR; DWORD dwFaxDevicesCount = 0;
DBG_ENTER( _T("fxocPrnt_InstallPrinter"), dwReturn); //
// Count the number of Fax-capable modems the system has
//
dwReturn = GetFaxCapableTapiLinesCount(&dwFaxDevicesCount, FAX_MODEM_PROVIDER_NAME); if (ERROR_SUCCESS != dwReturn) { CALL_FAIL (GENERAL_ERR, TEXT("GetFaxCapableTapiLinesCount"), dwReturn); //
// Assume no fax-capable devices exist
//
dwFaxDevicesCount = 0; dwReturn = NO_ERROR; } //
// We do not create the printer by default unless;
// 1. There are now fax-capable modems in the system or
// 2. a fax printer was already there.
//
// Otherwise, only the monitor and drivers are installed.
// The printer itself will be added either when an FSP / EFSP is registered or
// when a modem is installed.
//
if (dwFaxDevicesCount && (dwReturn == NO_ERROR)) { TCHAR szFaxPrinterName[255 + 1] = {0};
dwReturn = fxocPrnt_GetFaxPrinterName(szFaxPrinterName, sizeof(szFaxPrinterName) / sizeof(TCHAR)); if (ERROR_SUCCESS != dwReturn) { CALL_FAIL (GENERAL_ERR, TEXT("fxocPrnt_GetFaxPrinterName"), dwReturn); return dwReturn; } //
// Create the fax printer.
//
dwReturn = AddLocalFaxPrinter (szFaxPrinterName, NULL); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Fax Printer Install, created fax printer ") _T("Name = '%s', Driver Name = '%s'"), szFaxPrinterName, FAX_DRIVER_NAME); } else { VERBOSE(SETUP_ERR, _T("fxocPrnt_Install, ") _T("failed to create fax printer, rc = 0x%lx"), dwReturn); } } return dwReturn; }
///////////////////////////////
// fxocPrnt_Uninstall
//
// Remove all fax printers on this
// machine.
//
// Params:
// - pszSubcomponentId
// - pszUninstallSection.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
//
DWORD fxocPrnt_Uninstall(const TCHAR *pszSubcomponentId, const TCHAR *pszUninstallSection) { DWORD dwReturn = NO_ERROR;
// before we do anything related to the printer, make sure that the 'Server'
// service is started.
DBG_ENTER( _T("fxocPrnt_Uninstall"), dwReturn, _T("%s - %s"), pszSubcomponentId, pszUninstallSection);
// it's possible that LanmanServer is not installed on Desktop SKUs
if (!IsDesktopSKU()) { dwReturn = fxocSvc_StartService(prv_SERVER_SERVICE_NAME); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully started '%s' service, continuing Printer uninstall"), prv_SERVER_SERVICE_NAME); } else { VERBOSE(SETUP_ERR, _T("Failed to start '%s' service, rc = 0x%lx, abandoning ") _T("fax printer uninstall"), prv_SERVER_SERVICE_NAME, dwReturn);
return dwReturn; } } // verify that the spooler is up
dwReturn = fxocSvc_StartService(prv_SPOOLER_SERVICE_NAME); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully started '%s' service, continuing Printer Install"), prv_SPOOLER_SERVICE_NAME); } else { VERBOSE(SETUP_ERR, _T("Failed to start '%s' service, rc = 0x%lx, abandoning ") _T("fax printer installation"), prv_SPOOLER_SERVICE_NAME, dwReturn);
return dwReturn; }
// remove the fax printer
prv_DeleteFaxPrinter(FAX_DRIVER_NAME, FAX_MONITOR_PORT_NAME);
// remove fax printer monitor
prv_DeletePrintMonitor(FAX_MONITOR_NAME);
// remove all fax printer drivers
prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, NULL, 3); //
// For SKUs which support fax sharing, remove down-level drivers as well.
//
if (IsFaxShared()) { prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, NT4_PRINT_ENV, 2); prv_DeleteFaxPrinterDriver(FAX_DRIVER_NAME, W9X_PRINT_ENV, 0); } return dwReturn; }
///////////////////////////////
// fxocPrnt_SetFaxPrinterName
//
// Sets the name of the fax printer.
// This must be called prior to the
// creation of the fax printer via
// fxocPrnt_Install.
//
// Params:
// - pszFaxPrinterName - new name for fax printer.
// Returns:
// - void.
//
void fxocPrnt_SetFaxPrinterName(const TCHAR* pszFaxPrinterName) { DBG_ENTER( _T("fxocPrnt_SetFaxPrinterName"), _T("%s"), pszFaxPrinterName);
if (pszFaxPrinterName) { _tcsncpy(prv_GVAR.szFaxPrinterName, pszFaxPrinterName, sizeof(prv_GVAR.szFaxPrinterName) / sizeof(TCHAR)); } else { memset(prv_GVAR.szFaxPrinterName, 0, sizeof(prv_GVAR.szFaxPrinterName)); }
return; }
void fxocPrnt_SetFaxPrinterShared(BOOL IsFaxPrinterShared) { DBG_ENTER( _T("fxocPrnt_SetFaxPrinterShared"), _T("%d"), IsFaxPrinterShared);
HKEY hFaxKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,TRUE,KEY_WRITE); if (hFaxKey) { if (SetRegistryDword(hFaxKey,REGVAL_IS_SHARED_FAX_PRINTER,(IsFaxPrinterShared ? 1 : 0))) { VERBOSE(DBG_MSG, TEXT("Fax is installed in a mode that enables sharing")); } else { VERBOSE(DBG_MSG, TEXT("SetRegistryDword failed (ec=%d)"),GetLastError()); } RegCloseKey(hFaxKey); } else { VERBOSE(SETUP_ERR, TEXT("Failed to create REGKEY_FAX_SETUP, printer won't be shared (ec=%d)"),GetLastError()); }
}
///////////////////////////////
// fxocPrnt_GetFaxPrinterName
//
// Returns the current name of the
// fax printer.
//
// Params:
// - pszFaxPrinterName - OUT
// - dwNumBufChars
// Returns:
// - NO_ERROR on success
// - error code otherwise.
//
DWORD fxocPrnt_GetFaxPrinterName(TCHAR* pszFaxPrinterName, DWORD dwNumBufChars) { DWORD dwReturn = NO_ERROR; DBG_ENTER( _T("fxocPrnt_GetFaxPrinterName"), dwReturn);
if ((pszFaxPrinterName == NULL) || (dwNumBufChars == 0)) { dwReturn = ERROR_INVALID_PARAMETER; return dwReturn; }
if (prv_GVAR.szFaxPrinterName[0] != 0) { _tcsncpy(pszFaxPrinterName, prv_GVAR.szFaxPrinterName, dwNumBufChars); } else { //
// nobody set the fax printer name, so return the default
// table.
_tcsncpy(pszFaxPrinterName, FAX_PRINTER_NAME, dwNumBufChars); }
return dwReturn; } // fxocPrnt_GetFaxPrinterName
LPCTSTR lpctstrDriverFilesW2KandXP[] = { FAX_UI_MODULE_NAME, // FXSUI.DLL
FAX_DRV_MODULE_NAME, // FXSDRV.DLL
FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
FAX_TIFF_MODULE_NAME, // FXSTIFF.DLL
FAX_API_MODULE_NAME, // FXSAPI.DLL
FAX_RES_FILE };
LPCTSTR lpctstrDriverFilesNT4[] = { FAX_NT4_DRV_MODULE_NAME, // FXSDRV4.DLL
FAX_UI_MODULE_NAME, // FXSUI.DLL
FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
FAX_API_MODULE_NAME, // FXSAPI.DLL
FAX_TIFF_FILE, // FXSTIFF.DLL
FAX_RES_FILE };
LPCTSTR lpctstrDriverFilesW9X[] = { FAX_DRV_WIN9X_32_MODULE_NAME, // FXSDRV32.DLL
FAX_DRV_WIN9X_16_MODULE_NAME, // FXSDRV16.DRV
FAX_API_MODULE_NAME, // FXSAPI.DLL
FAX_DRV_UNIDRV_MODULE_NAME, // UNIDRV.DLL
FAX_DRV_UNIDRV_HELP, // UNIDRV.HLP
FAX_DRV_ICONLIB, // ICONLIB.DLL
FAX_WZRD_MODULE_NAME, // FXSWZRD.DLL
FAX_TIFF_FILE, // FXSTIFF.DLL
FAX_RES_FILE };
///////////////////////////////////
// prv_AddFaxPrinterDriver
//
// Add printer driver to the server machine.
// In case of failure, do clean-up and returns FALSE.
// Temp files are deleted allways.
//
// Params:
// - lpctstrDriverSourcePath : The directory where the printer's driver files
// are located (put there by the setup)
// - pEnvironment : for which platform are the drivers added
//
static DWORD prv_AddFaxPrinterDriver(LPCTSTR lpctstrDriverSourcePath,LPCTSTR pEnvironment) { DWORD dwReturn = NO_ERROR; BOOL bSuccess = FALSE; LPCTSTR* filesToCopy = NULL; DWORD dwFileCount = 0; DWORD dwNeededSize = 0; TCHAR szPrinterDriverDirectory[MAX_PATH] = {0}; TCHAR szSourceDir[MAX_PATH] = {0}; DWORD dwNumChars = 0;
DBG_ENTER( _T("prv_AddFaxPrinterDriver"), dwReturn, _T("%s - %s"), lpctstrDriverSourcePath, pEnvironment);
if (!GetPrinterDriverDirectory(NULL, (LPTSTR)pEnvironment, 1, (LPBYTE)szPrinterDriverDirectory, sizeof(szPrinterDriverDirectory), &dwNeededSize)) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, TEXT("GetPrinterDriverDirectory failed - %d."), dwReturn); return dwReturn; }
bSuccess = TRUE;
VERBOSE(DBG_MSG, _T("Printer driver directory is %s\n"), szPrinterDriverDirectory);
if (pEnvironment==NULL) { filesToCopy = lpctstrDriverFilesW2KandXP; dwFileCount = sizeof(lpctstrDriverFilesW2KandXP)/sizeof(LPCTSTR); } else if (_tcsicmp(pEnvironment,NT4_PRINT_ENV)==0) { filesToCopy = lpctstrDriverFilesNT4; dwFileCount = sizeof(lpctstrDriverFilesNT4)/sizeof(LPCTSTR); } else if (_tcsicmp(pEnvironment,W9X_PRINT_ENV)==0) { filesToCopy = lpctstrDriverFilesW9X; dwFileCount = sizeof(lpctstrDriverFilesW9X)/sizeof(LPCTSTR); }
if (bSuccess) { dwNumChars = ExpandEnvironmentStrings(lpctstrDriverSourcePath, szSourceDir, sizeof(szSourceDir) / sizeof(TCHAR)); if (dwNumChars == 0) { VERBOSE(SETUP_ERR, _T("ExpandEnvironmentStrings failed, rc = 0x%lx"), ::GetLastError());
bSuccess = FALSE; } }
if (bSuccess) { bSuccess = MultiFileCopy(dwFileCount, filesToCopy, szSourceDir, szPrinterDriverDirectory);
if (!bSuccess) { VERBOSE(SETUP_ERR, _T("MultiFileCopy failed (ec: %ld)"), GetLastError()); } }
if (bSuccess) {
DRIVER_INFO_3 DriverInfo3; ZeroMemory(&DriverInfo3,sizeof(DRIVER_INFO_3));
// fill DRIVER_INFO_3 depending on pEnv...
bSuccess = FillDriverInfo(&DriverInfo3,pEnvironment); if (bSuccess) { bSuccess = AddPrinterDriverEx(NULL, 3, (LPBYTE)&DriverInfo3, APD_COPY_NEW_FILES|APD_DONT_SET_CHECKPOINT); if (bSuccess) { VERBOSE(DBG_MSG,_T("Successfully added new fax printer drivers")); } else { VERBOSE(SETUP_ERR,_T("AddPrinterDriverEx failed (ec: %ld)"),GetLastError()); } } else { VERBOSE(SETUP_ERR,_T("FillDriverInfo failed, try to continue")); } }
//
// Delete the temporary fax DLL files.
//
if (!MultiFileDelete(dwFileCount, filesToCopy, szPrinterDriverDirectory)) { VERBOSE(SETUP_ERR, _T("MultiFileDelete() failed (ec: %ld)"), GetLastError()); }
if (!bSuccess) { dwReturn = ::GetLastError(); }
return dwReturn; }
///////////////////////////////
// prv_DeletePrinter
//
// Delete printer by name. The driver name and the port name are just for debug print.
//
// Params:
// - pszPrinterName - name of printer to delete
// - pszFaxDriver - name of associated driver
// - pszPortName - name of associated port.
//
static DWORD prv_DeletePrinter(const TCHAR *pszPrinterName, const TCHAR *pszFaxDriver, const TCHAR *pszPortName) { DWORD dwReturn = NO_ERROR; BOOL bSuccess = FALSE; HANDLE hPrinter = NULL; PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL, PRINTER_ALL_ACCESS };
DBG_ENTER( _T("prv_DeletePrinter"), dwReturn, _T("%s - %s - %s"), pszPrinterName, pszFaxDriver, pszPortName);
if ((pszPrinterName == NULL) || (pszFaxDriver == NULL) || (pszPortName == NULL)) { dwReturn = ERROR_INVALID_PARAMETER; return dwReturn; }
bSuccess = ::OpenPrinter((TCHAR*) pszPrinterName, &hPrinter, &PrinterDefaults);
if (bSuccess) { VERBOSE(DBG_MSG, _T("prv_DeletePrinter, deleting ") _T("printer '%s' with Driver Name = '%s', ") _T("Port Name = '%s'"), pszPrinterName, pszFaxDriver, pszPortName);
if (!SetPrinter(hPrinter,0,NULL,PRINTER_CONTROL_PURGE)) { // Don't let a failure here keep us from attempting the delete
VERBOSE(PRINT_ERR,TEXT("SetPrinter failed (purge jobs before uninstall) ec=%d"),GetLastError()); }
bSuccess = ::DeletePrinter(hPrinter);
if (!bSuccess) { dwReturn = ::GetLastError();
VERBOSE(SETUP_ERR, _T("prv_DeletePrinter, failed to delete ") _T("fax printer '%s', rc = 0x%lx"), pszPrinterName, dwReturn); }
bSuccess = ::ClosePrinter(hPrinter);
if (!bSuccess) { dwReturn = ::GetLastError();
VERBOSE(SETUP_ERR, _T("prv_DeletePrinter, failed to Close ") _T("fax printer '%s', rc = 0x%lx"), pszPrinterName, dwReturn); }
hPrinter = NULL; }
return dwReturn; }
///////////////////////////////
// prv_DeleteFaxPrinter
//
// Delete fax printer with driver name and port as passed in params
//
// Params:
// LPCTSTR lpctstrDriverName - printer driver name to delete
// LPCTSTR lpctstrPortName - printer port name
//
//
//
static DWORD prv_DeleteFaxPrinter(LPCTSTR lpctstrDriverName, LPCTSTR lpctstrPortName) { BOOL bSuccess = FALSE; DWORD dwReturn = NO_ERROR; DWORD dwCount = 0; DWORD i = 0; PPRINTER_INFO_2 pPrinterInfo = NULL;
DBG_ENTER(_T("prv_DeleteFaxPrinter"),dwReturn);
pPrinterInfo = (PPRINTER_INFO_2) MyEnumPrinters(NULL, 2, &dwCount, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
VERBOSE(DBG_MSG, _T("DeleteFaxPrinter, found %lu printers installed ") _T("on this computer"), dwCount);
if (pPrinterInfo) { for (i=0; i < dwCount; i++) { // Check if printer has same driver same port name
if (_tcsicmp(pPrinterInfo[i].pDriverName, lpctstrDriverName) == 0 && _tcsicmp(pPrinterInfo[i].pPortName, lpctstrPortName) == 0) { // We can have a Local printer here or a Printer connection.
// we differentiate between the two by the ServerName field of
// PRINTER_INFO_2
if (pPrinterInfo[i].pServerName==NULL) { // this is a local printer.
dwReturn = prv_DeletePrinter(pPrinterInfo[i].pPrinterName, lpctstrDriverName, lpctstrPortName); if (dwReturn != NO_ERROR) { VERBOSE(SETUP_ERR, _T("Failed to delete printer '%s', rc = 0x%lx, ") _T("continuing anyway..."), pPrinterInfo[i].pPrinterName, dwReturn);
dwReturn = NO_ERROR; } } else { // this is a printer connection
if (!DeletePrinterConnection(pPrinterInfo[i].pPrinterName)) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, _T("Failed to delete printer connection '%s', rc = 0x%lx, ") _T("continuing anyway..."), pPrinterInfo[i].pPrinterName, dwReturn);
dwReturn = NO_ERROR; } } } }
MemFree(pPrinterInfo); }
return dwReturn; }
///////////////////////////////
// prv_CreatePrintMonitor
//
// Create the printer monitor
//
// Params:
// - pszMonitorName - name of printer monitor
// - pszMonitorFile - name of print monitor file
// Returns:
// - NO_ERROR on success
// - error code otherwise.
//
static DWORD prv_CreatePrintMonitor(const TCHAR *pszMonitorName, const TCHAR *pszMonitorFile) { BOOL bSuccess = TRUE; DWORD dwReturn = NO_ERROR; MONITOR_INFO_2 MonitorInfo;
DBG_ENTER( _T("prv_CreatePrintMonitor"), dwReturn, _T("%s - %s"), pszMonitorName, pszMonitorFile);
if ((pszMonitorName == NULL) || (pszMonitorFile == NULL)) { dwReturn = ERROR_INVALID_PARAMETER; return dwReturn; }
MonitorInfo.pName = (TCHAR*) pszMonitorName; MonitorInfo.pDLLName = (TCHAR*) pszMonitorFile; MonitorInfo.pEnvironment = NULL;
bSuccess = ::AddMonitor(NULL, 2, (LPBYTE) &MonitorInfo);
if (bSuccess) { VERBOSE(DBG_MSG, _T("Successfully created fax monitor '%s', ") _T("File Name '%s'"), pszMonitorName, pszMonitorFile); } else { dwReturn = ::GetLastError();
if (dwReturn == ERROR_PRINT_MONITOR_ALREADY_INSTALLED) { VERBOSE(DBG_MSG, _T("AddMonitor, failed because '%s' monitor already ") _T("exists. This is fine, let's continue..."), pszMonitorName);
dwReturn = NO_ERROR;
} else { VERBOSE(SETUP_ERR, _T("CreatePrinterMonitor, failed to ") _T("add new print monitor '%s', rc = 0x%lx"), pszMonitorName, dwReturn); } }
return dwReturn; }
///////////////////////////////
// prv_DeletePrintMonitor
//
// Delete the printer monitor
//
// Params:
// - pszMonitorName - name of print monitor to delete
// Returns:
// - NO_ERROR on success
// - error code otherwise.
//
static DWORD prv_DeletePrintMonitor(const TCHAR *pszMonitorName) { BOOL bSuccess = TRUE; DWORD dwReturn = NO_ERROR; DBG_ENTER( _T("prv_DeletePrintMonitor"), dwReturn, _T("%s"), pszMonitorName);
if (pszMonitorName == NULL) { dwReturn = ERROR_INVALID_PARAMETER; return dwReturn; }
bSuccess = ::DeleteMonitor(NULL, NULL, (LPTSTR) pszMonitorName);
if (bSuccess) { VERBOSE(DBG_MSG, _T("DeletePrinterMonitor, successfully ") _T("deleted print monitor name '%s'"), pszMonitorName); } else { dwReturn = ::GetLastError();
if (dwReturn != ERROR_UNKNOWN_PRINT_MONITOR) { VERBOSE(SETUP_ERR, _T("DeletePrinterMonitor, failed to ") _T("remove print monitor '%s', rc = 0x%lx"), pszMonitorName, dwReturn); } else { dwReturn = NO_ERROR; } }
return dwReturn; }
////////////////////////////
// prv_DeleteFaxPrinterDriver
//
// Delete fax printer driver from current machine
// In case of failure, log it and returns FALSE.
//
// Params:
// - LPTSTR lptstrDriverName - Driver name to delete
// - pEnvironment - for which platform are the drivers deleted
// - DWORD dwVersionFlag - The version of the driver that should be deleted.
// Valid valuse {0,1,2,3} only.
// Returns;
// - Returns ERROR_SUCCESS on success, on failue retuen the error code.
//
static DWORD prv_DeleteFaxPrinterDriver(LPTSTR lptstrDriverName, LPTSTR pEnviroment, DWORD dwVersionFlag) { BOOL bSuccess = TRUE; DWORD ec = ERROR_SUCCESS;
DBG_ENTER(_T("prv_DeleteFaxPrinterDriver"),ec);
ASSERTION(dwVersionFlag<=3);
// delete driver.
bSuccess = DeletePrinterDriverEx(NULL, pEnviroment, lptstrDriverName, DPD_DELETE_SPECIFIC_VERSION|DPD_DELETE_ALL_FILES, dwVersionFlag); if (!bSuccess) { ec = GetLastError(); VERBOSE(DBG_MSG, TEXT("DeletePrinterDriverEx() for driver %s, version %ld failed (ec: %ld)"), lptstrDriverName, dwVersionFlag, ec); } else { VERBOSE(DBG_MSG, TEXT("DeletePrinterDriverEx() for driver %s, version %ld succeeded"), lptstrDriverName, dwVersionFlag); }
return ec; }
/***************************************************************************************
** ** ** C o C l a s s I n s t a l l e r s e c t i o n ** ** ** ***************************************************************************************/
#ifdef ENABLE_LOGGING
typedef struct _DIF_DEBUG { DWORD DifValue; LPTSTR DifString; } DIF_DEBUG, *PDIF_DEBUG;
DIF_DEBUG DifDebug[] = { { 0, L"" }, // 0x00000000
{ DIF_SELECTDEVICE, L"DIF_SELECTDEVICE" }, // 0x00000001
{ DIF_INSTALLDEVICE, L"DIF_INSTALLDEVICE" }, // 0x00000002
{ DIF_ASSIGNRESOURCES, L"DIF_ASSIGNRESOURCES" }, // 0x00000003
{ DIF_PROPERTIES, L"DIF_PROPERTIES" }, // 0x00000004
{ DIF_REMOVE, L"DIF_REMOVE" }, // 0x00000005
{ DIF_FIRSTTIMESETUP, L"DIF_FIRSTTIMESETUP" }, // 0x00000006
{ DIF_FOUNDDEVICE, L"DIF_FOUNDDEVICE" }, // 0x00000007
{ DIF_SELECTCLASSDRIVERS, L"DIF_SELECTCLASSDRIVERS" }, // 0x00000008
{ DIF_VALIDATECLASSDRIVERS, L"DIF_VALIDATECLASSDRIVERS" }, // 0x00000009
{ DIF_INSTALLCLASSDRIVERS, L"DIF_INSTALLCLASSDRIVERS" }, // 0x0000000A
{ DIF_CALCDISKSPACE, L"DIF_CALCDISKSPACE" }, // 0x0000000B
{ DIF_DESTROYPRIVATEDATA, L"DIF_DESTROYPRIVATEDATA" }, // 0x0000000C
{ DIF_VALIDATEDRIVER, L"DIF_VALIDATEDRIVER" }, // 0x0000000D
{ DIF_MOVEDEVICE, L"DIF_MOVEDEVICE" }, // 0x0000000E
{ DIF_DETECT, L"DIF_DETECT" }, // 0x0000000F
{ DIF_INSTALLWIZARD, L"DIF_INSTALLWIZARD" }, // 0x00000010
{ DIF_DESTROYWIZARDDATA, L"DIF_DESTROYWIZARDDATA" }, // 0x00000011
{ DIF_PROPERTYCHANGE, L"DIF_PROPERTYCHANGE" }, // 0x00000012
{ DIF_ENABLECLASS, L"DIF_ENABLECLASS" }, // 0x00000013
{ DIF_DETECTVERIFY, L"DIF_DETECTVERIFY" }, // 0x00000014
{ DIF_INSTALLDEVICEFILES, L"DIF_INSTALLDEVICEFILES" }, // 0x00000015
{ DIF_UNREMOVE, L"DIF_UNREMOVE" }, // 0x00000016
{ DIF_SELECTBESTCOMPATDRV, L"DIF_SELECTBESTCOMPATDRV" }, // 0x00000017
{ DIF_ALLOW_INSTALL, L"DIF_ALLOW_INSTALL" }, // 0x00000018
{ DIF_REGISTERDEVICE, L"DIF_REGISTERDEVICE" }, // 0x00000019
{ DIF_NEWDEVICEWIZARD_PRESELECT, L"DIF_NEWDEVICEWIZARD_PRESELECT" }, // 0x0000001A
{ DIF_NEWDEVICEWIZARD_SELECT, L"DIF_NEWDEVICEWIZARD_SELECT" }, // 0x0000001B
{ DIF_NEWDEVICEWIZARD_PREANALYZE, L"DIF_NEWDEVICEWIZARD_PREANALYZE" }, // 0x0000001C
{ DIF_NEWDEVICEWIZARD_POSTANALYZE, L"DIF_NEWDEVICEWIZARD_POSTANALYZE" }, // 0x0000001D
{ DIF_NEWDEVICEWIZARD_FINISHINSTALL, L"DIF_NEWDEVICEWIZARD_FINISHINSTALL" }, // 0x0000001E
{ DIF_UNUSED1, L"DIF_UNUSED1" }, // 0x0000001F
{ DIF_INSTALLINTERFACES, L"DIF_INSTALLINTERFACES" }, // 0x00000020
{ DIF_DETECTCANCEL, L"DIF_DETECTCANCEL" }, // 0x00000021
{ DIF_REGISTER_COINSTALLERS, L"DIF_REGISTER_COINSTALLERS" }, // 0x00000022
{ DIF_ADDPROPERTYPAGE_ADVANCED, L"DIF_ADDPROPERTYPAGE_ADVANCED" }, // 0x00000023
{ DIF_ADDPROPERTYPAGE_BASIC, L"DIF_ADDPROPERTYPAGE_BASIC" }, // 0x00000024
{ DIF_RESERVED1, L"DIF_RESERVED1" }, // 0x00000025
{ DIF_TROUBLESHOOTER, L"DIF_TROUBLESHOOTER" }, // 0x00000026
{ DIF_POWERMESSAGEWAKE, L"DIF_POWERMESSAGEWAKE" }, // 0x00000027
{ DIF_ADDREMOTEPROPERTYPAGE_ADVANCED, L"DIF_ADDREMOTEPROPERTYPAGE_ADVANCED" } // 0x00000028
};
#endif
/*
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// SaveDontShowMeThisAgain
//
// Purpose:
// Check if the user checked the 'Don't show me this again'
// If he did, set the registry key
//
// Params:
// Handle to window
//
// Return Value:
// None
//
// Author:
// Mooly Beery (MoolyB) 17-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
void SaveDontShowMeThisAgain(HWND hwndDlg) { DBG_ENTER(_T("SaveDontShowMeThisAgain"));
//
// let's save the "Don't show me again" state
//
if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_DONT_SHOW), BM_GETCHECK, 0, 0)) { //
// User pressed the "Don't show me again" checkbox
//
HKEY hFaxKey = OpenRegistryKey (HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP, TRUE, KEY_WRITE); if (!hFaxKey) { CALL_FAIL (GENERAL_ERR, TEXT("OpenRegistryKey(REGKEY_FAX_SETUP)"), GetLastError()); } else { if (!SetRegistryDword (hFaxKey, REGVAL_DONT_UNATTEND_INSTALL, 1)) { CALL_FAIL (GENERAL_ERR, TEXT("SetRegistryDword(REGVAL_DONT_UNATTEND_INSTALL)"), GetLastError()); } RegCloseKey (hFaxKey); } } } */
/*
static INT_PTR CALLBACK prv_dlgInstallFaxQuestionPropPage( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
Routine name : prv_dlgInstallFaxQuestionPropPage
Routine description:
Dialogs procedure for "Install fax" dialog
Author:
Eran Yariv (EranY), Jul, 2000
Arguments:
hwndDlg [in] - Handle to dialog box uMsg [in] - Message wParam [in] - First message parameter parameter [in] - Second message parameter
Return Value:
Standard dialog return value
--*/ /*
{ DWORD dwRes = NO_ERROR; DBG_ENTER(_T("prv_dlgInstallFaxQuestionPropPage"));
switch (uMsg) { case WM_INITDIALOG: // no return value here.
PropSheet_SetWizButtons(GetParent(hwndDlg),PSWIZB_NEXT); SetFocus(hwndDlg); if (!CheckDlgButton(hwndDlg,IDC_INSTALL_FAX_NOW,BST_CHECKED)) { dwRes = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("CheckDlgButton"), dwRes); } break; case WM_NOTIFY: switch (((NMHDR*)lParam)->code) { case PSN_WIZNEXT: SaveDontShowMeThisAgain(hwndDlg); //
// let's get the "Install Fax Now" state
//
if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_INSTALL_FAX_NOW), BM_GETCHECK, 0, 0)) { //
// User pressed the "Install Fax Now" checkbox
//
dwRes = InstallFaxUnattended(); if (dwRes!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), dwRes); } } return TRUE; } break;
} return FALSE; } // prv_dlgInstallFaxQuestionPropPage
*/
/*
static INT_PTR CALLBACK prv_dlgInstallFaxQuestion( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
Routine name : prv_dlgInstallFaxQuestion
Routine description:
Dialogs procedure for "Install fax" dialog
Author:
Eran Yariv (EranY), Jul, 2000
Arguments:
hwndDlg [in] - Handle to dialog box uMsg [in] - Message wParam [in] - First message parameter parameter [in] - Second message parameter
Return Value:
Standard dialog return value
--*/ /*
{ INT_PTR iRes = IDIGNORE; DBG_ENTER(_T("prv_dlgInstallFaxQuestion"));
switch (uMsg) { case WM_INITDIALOG: SetFocus(hwndDlg); break;
case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_ANSWER_YES: iRes = IDYES; break;
case IDC_ANSWER_NO: iRes = IDNO; break; } if (IDIGNORE != iRes) { SaveDontShowMeThisAgain(hwndDlg); EndDialog (hwndDlg, iRes); return TRUE; } break; } return FALSE; } // prv_dlgInstallFaxQuestion
*/
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// AllowInstallationProposal
//
// Purpose:
// Verify we can propose to the user to install Fax
// Check if Fax is installed
// Check if the user has marked the 'don't show this again'
//
// Params:
// None
//
// Return Value:
// true - ok to propose the installation of Fax
// false - do not propose the Fax installation
//
// Author:
// Mooly Beery (MoolyB) 17-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
bool AllowInstallationProposal() { DWORD ec = NO_ERROR; BOOL bFaxInstalled = FALSE;
DBG_ENTER(_T("AllowInstallationProposal")); ec = IsFaxInstalled (&bFaxInstalled); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("IsFaxInstalled"), ec); return false; } if (bFaxInstalled) { VERBOSE(DBG_MSG,TEXT("Fax is already installed")); return false; } //
// Let's find out if we're allowed to add a property page
//
BOOL bDontShowThisAgain = FALSE; HKEY hFaxKey = OpenRegistryKey (HKEY_LOCAL_MACHINE, REGKEY_FAX_SETUP, FALSE, KEY_READ); if (!hFaxKey) { //
// No value there
//
ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("OpenRegistryKey(REGKEY_FAX_SETUP)"), ec); // let's go on.
} else { bDontShowThisAgain = GetRegistryDword (hFaxKey,REGVAL_DONT_UNATTEND_INSTALL); RegCloseKey (hFaxKey); } if (bDontShowThisAgain) { //
// User previously checked the "Don't ask me again" checkbox
//
VERBOSE (DBG_MSG, TEXT("Used previously checked the \"Don't ask me again\" checkbox")); return false; }
return true; }
/*
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// HandleNonPnpDevices
//
// Purpose:
// Handles DIF_INSTALLDEVICE
// A new device has finished installing and we check if this is a non PnP device
// if it is we propose the user to install Fax using a message box.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Author:
// Mooly Beery (MoolyB) 17-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD HandleNonPnpDevices() { DWORD ec = NO_ERROR; DBG_ENTER(_T("HandleNonPnpDevices"), ec);
// if this is a PnP installation don't do anything here
if (bIsPnpInstallation) { VERBOSE(DBG_MSG,_T("This is a PnP device installation, exiting")); goto exit; }
// if Fax is installed or the user has checked the 'Don't show me this again' do not propose
if (!AllowInstallationProposal()) { VERBOSE(DBG_MSG,TEXT("Not allowed to install, exit")); goto exit; }
//
// Let's ask the user if he wishes to install a fax now
//
INT_PTR iResult = DialogBox (faxocm_GetAppInstance(), MAKEINTRESOURCE(IDD_INSTALL_FAX), NULL, prv_dlgInstallFaxQuestion); if (iResult==-1) { ec = GetLastError(); CALL_FAIL (RESOURCE_ERR, TEXT("DialogBox(IDD_INSTALL_FAX)"), ec); goto exit; }
if (iResult==IDYES) { //
// User wishes to install the fax now - do so.
//
ec = InstallFaxUnattended(); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), ec); } }
exit: return ec; }
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// GetModemDriverInfo
//
// Purpose:
// Gets the modem's selected driver and retrieves the modem's INF
// filename and section within the INF file
//
// Params:
// IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
// IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
// OUT PSP_DRVINFO_DETAIL_DATA pspDrvInfoDetailData - passes out the driver details
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Caller must call MemFree on returned pointer.
//
// Author:
// Mooly Beery (MoolyB) 28-Mar-2001
///////////////////////////////////////////////////////////////////////////////////////
static DWORD GetModemDriverInfo ( IN HDEVINFO hDeviceInfoSet, IN PSP_DEVINFO_DATA pDeviceInfoData, OUT PSP_DRVINFO_DETAIL_DATA pspDrvInfoDetailData ) { DWORD ec = NO_ERROR; DWORD dwRequiredSize = 0; SP_DRVINFO_DATA spDrvInfoData;
DBG_ENTER(_T("GetModemDriverInfo"), ec);
pspDrvInfoDetailData = NULL; spDrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
if (SetupDiGetSelectedDriver(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData)) { if (!SetupDiGetDriverInfoDetail(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData,NULL,0,&dwRequiredSize)) { ec = GetLastError(); if (ec==ERROR_INSUFFICIENT_BUFFER) { ec = NO_ERROR; if (pspDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)MemAlloc(dwRequiredSize)) { pspDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if (SetupDiGetDriverInfoDetail(hDeviceInfoSet,pDeviceInfoData,&spDrvInfoData,pspDrvInfoDetailData,dwRequiredSize,NULL)) { VERBOSE(DBG_MSG,_T("Driver Inf Name is: %s"),pspDrvInfoDetailData->InfFileName); VERBOSE(DBG_MSG,_T("Driver Section Name is: %s"),pspDrvInfoDetailData->SectionName); VERBOSE(DBG_MSG,_T("Driver Description is: %s"),pspDrvInfoDetailData->DrvDescription); VERBOSE(DBG_MSG,_T("Driver Hardware ID is: %s"),pspDrvInfoDetailData->HardwareID); } else { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail"), ec); } } else { ec = ERROR_NOT_ENOUGH_MEMORY; VERBOSE(GENERAL_ERR, TEXT("MemAlloc failed")); } } else { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail"), ec); } } else { ec = ERROR_INVALID_PARAMETER; VERBOSE(GENERAL_ERR, TEXT("SetupDiGetDriverInfoDetail should have failed")); } } else { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetSelectedDriver"), ec); }
return ec; }
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// SearchModemInfFaxSection
//
// Purpose:
// Search the modem's INF to find if a Fax section exists.
// If a Fax section exists, try to find the InstallFax key
// If it's there, install Fax unattended.
//
// Params:
// IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
// IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Author:
// Mooly Beery (MoolyB) 28-Mar-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD SearchModemInfFaxSection ( IN HDEVINFO hDeviceInfoSet, IN PSP_DEVINFO_DATA pDeviceInfoData ) { DWORD ec = NO_ERROR; DWORD Size = sizeof(DWORD); DWORD Type = 0; DWORD Value = 0; HKEY hDeviceKey = NULL; HKEY hFaxKey = NULL; LPTSTR lptstrInstallFax = NULL;
DBG_ENTER(_T("SearchModemInfFaxSection"), ec);
// get the device key under HKLM\SYSTEM\CurrentControlSet\Control\Class\ClassGUID\InstanceID
hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfoSet,pDeviceInfoData,DICS_FLAG_GLOBAL,0,DIREG_DRV,KEY_READ); if (hDeviceKey==NULL) { CALL_FAIL (GENERAL_ERR, TEXT("SetupDiOpenDevRegKey"), ec); goto exit; } // check if the Fax subkey exists.
hFaxKey = OpenRegistryKey(hDeviceKey,_T("Fax"),FALSE,KEY_READ); if (hFaxKey==NULL) { VERBOSE(DBG_MSG, TEXT("This modem does not have a Fax section, exit...")); ec = NO_ERROR; goto exit; } // this modem has a Fax section.
// let's check if it uses the 'InstallFax' REG_SZ
lptstrInstallFax = GetRegistryString(hFaxKey,_T("InstallFax"),NULL); if (lptstrInstallFax==NULL) { VERBOSE(DBG_MSG, TEXT("This modem does not have an InstallFax REG_SZ in the Fax section, exit...")); ec = NO_ERROR; goto exit; } // check if the InstallFax is 0 (unlikely, but...)
if (_tcsicmp(lptstrInstallFax,_T("0"))==0) { VERBOSE(DBG_MSG, TEXT("This modem does has an InstallFax=0 REG_SZ in the Fax section, exit...")); ec = NO_ERROR; goto exit; } //if (InSystemSetup(hDeviceInfoSet,pDeviceInfoData))
{ // if we're in system setup, we should just notify our component that it should install.
} //else
{ // finally, Install Fax.
ec = InstallFaxUnattended(); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("InstallFaxUnattended"), ec); } }
exit:
if (hDeviceKey) { RegCloseKey(hDeviceKey); } if (hFaxKey) { RegCloseKey(hFaxKey); } return ec; }
*/
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// HandleInstallDevice
//
// Purpose:
// Handles DIF_INSTALLDEVICE
// A new device has finished installing and we're allowed to install a printer
// if Fax is already on the box
// In this case we do the following:
//
// 1. Check if Fax is installed, it it's not then attemp to install Fax based on INF
// 2. Check if there's a Fax printer, if there is leave
// 3. Install a Fax printer
// 4. Ensure the service is up
// 5. Leave
//
// Params:
// IN HDEVINFO hDeviceInfoSet - passed from CoDevice Installer
// IN PSP_DEVINFO_DATA pDeviceInfoData - passed from CoDevice Installer
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Author:
// Eran Yariv (EranY) 17-Jul-2000
// Mooly Beery (MoolyB) 08-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD HandleInstallDevice ( IN HDEVINFO hDeviceInfoSet, IN PSP_DEVINFO_DATA pDeviceInfoData ) { DWORD ec = NO_ERROR; BOOL bFaxInstalled; BOOL bLocalFaxPrinterInstalled;
DBG_ENTER(_T("HandleInstallDevice"), ec);
// Now we know a new modem installation succeeded.
// Let's check if our component is installed.
//
ec = IsFaxInstalled(&bFaxInstalled); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("IsFaxInstalled"), ec); goto exit; } if (!bFaxInstalled) { VERBOSE(DBG_MSG,TEXT("Fax is not installed, search modem's INF for Fax section...")); /*
ec = SearchModemInfFaxSection(hDeviceInfoSet,pDeviceInfoData); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("SearchModemInfFaxSection"), ec); }*/ goto exit; } //
// Let's see if we have a local fax printer
//
ec = IsLocalFaxPrinterInstalled (&bLocalFaxPrinterInstalled); if (ec!=ERROR_SUCCESS) { CALL_FAIL (GENERAL_ERR, TEXT("IsLocalFaxPrinterInstalled"), ec); goto exit; } if (bLocalFaxPrinterInstalled) { VERBOSE(DBG_MSG,TEXT("Fax Printer is installed, exit")); goto exit; } //
// This is the time to install a local fax printer.
//
ec = AddLocalFaxPrinter (FAX_PRINTER_NAME, NULL); if (ERROR_SUCCESS != ec) { CALL_FAIL (GENERAL_ERR, TEXT("AddLocalFaxPrinter"), ec); goto exit; } //
// Make sure the service is running.
// This is important because there may have been jobs in the queue that now, when we have
// a new modem device, can finally be executed.
//
if (!EnsureFaxServiceIsStarted (NULL)) { ec = GetLastError (); CALL_FAIL (GENERAL_ERR, TEXT("EnsureFaxServiceIsStarted"), ec); goto exit; }
exit: return ec; }
/*
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// HandleNewDeviceWizardFinishInstall
//
// Purpose:
// Handles DIF_NEWDEVICEWIZARD_FINISHINSTALL
// A new device has finished installing and we're allowed to add a property page
// asking the user to install Fax
// In this case we do the following:
//
// 1. Check if Fax is installed, if it is leave
// 2. Check if we're allowed to add a property page, if not leave
// 3. Add a property page to the wizard.
// 4. Leave
//
// Params:
// See CoClassInstaller documentation in DDK
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Author:
// Eran Yariv (EranY) 17-Jul-2000
// Mooly Beery (MoolyB) 08-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD HandleNewDeviceWizardFinishInstall ( IN HDEVINFO hDeviceInfoSet, IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL ) { DWORD ec = NO_ERROR; BOOL bFaxInstalled = FALSE; TCHAR* WizardTitle = NULL; TCHAR* WizardSubTitle = NULL; SP_NEWDEVICEWIZARD_DATA nddClassInstallParams = {0}; DWORD dwClassInstallParamsSize = sizeof(SP_NEWDEVICEWIZARD_DATA); HPROPSHEETPAGE hPsp = NULL; PROPSHEETPAGE psp = {0};
DBG_ENTER(_T("HandleNewDeviceWizardFinishInstall"), ec);
if (!AllowInstallationProposal()) { VERBOSE(DBG_MSG,TEXT("Not allowed to install, exit")); goto exit; }
nddClassInstallParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
// get the class install parameters by calling SetupDiGetClassInstallParams
if (!SetupDiGetClassInstallParams( hDeviceInfoSet, pDeviceInfoData, (PSP_CLASSINSTALL_HEADER)&nddClassInstallParams, dwClassInstallParamsSize, NULL)) { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("SetupDiGetClassInstallParams"), ec); goto exit; }
// check whether NumDynamicPages has reached the max
if (nddClassInstallParams.NumDynamicPages>=MAX_INSTALLWIZARD_DYNAPAGES) { VERBOSE (GENERAL_ERR, TEXT("Too many property pages, can't add another one")); ec = ERROR_BUFFER_OVERFLOW; goto exit; } // fill in the PROPSHEETPAGE structure
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.hInstance = faxocm_GetAppInstance(); psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALL_FAX_PROP); psp.pfnDlgProc = prv_dlgInstallFaxQuestionPropPage;
WizardTitle = (TCHAR*)MemAlloc(MAX_PATH * sizeof(TCHAR) ); if(WizardTitle) { if (!LoadString(psp.hInstance, IDS_NEW_DEVICE_TITLE, WizardTitle, MAX_PATH)) { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec); WizardTitle[0] = 0; } else { psp.pszHeaderTitle = WizardTitle; } }
WizardSubTitle = (TCHAR*)MemAlloc(MAX_PATH * sizeof(TCHAR) ); if(WizardSubTitle) { if (!LoadString(psp.hInstance, IDS_NEW_DEVICE_SUBTITLE, WizardSubTitle, MAX_PATH)) { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec); WizardSubTitle[0] = 0; } else { psp.pszHeaderSubTitle = WizardSubTitle; } } // add the page and increment the NumDynamicPages counter
hPsp = CreatePropertySheetPage(&psp); if (hPsp==NULL) { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("CreatePropertySheetPage"), ec); goto exit; }
nddClassInstallParams.DynamicPages[nddClassInstallParams.NumDynamicPages++] = hPsp;
// apply the modified params by calling SetupDiSetClassInstallParams
if (!SetupDiSetClassInstallParams( hDeviceInfoSet, pDeviceInfoData, (PSP_CLASSINSTALL_HEADER)&nddClassInstallParams, dwClassInstallParamsSize)) { ec = GetLastError(); CALL_FAIL (GENERAL_ERR, TEXT("LoadString"), ec); goto exit; }
exit:
return ec; } */ ///////////////////////////////////////////////////////////////////////////////////////
// Function:
// FaxModemCoClassInstaller
//
// Purpose:
// Our Fax CoClassInstaller, handles newly discovered modems
//
// Params:
// See CoClassInstaller documentation in DDK
//
// Return Value:
// NO_ERROR - everything was ok.
// Win32 Error code in case if failure.
//
// Author:
// Eran Yariv (EranY) 17-Jul-2000
// Mooly Beery (MoolyB) 08-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD CALLBACK FaxModemCoClassInstaller ( IN DI_FUNCTION InstallFunction, IN HDEVINFO hDeviceInfoSet, IN PSP_DEVINFO_DATA pDeviceInfoData OPTIONAL, IN OUT PCOINSTALLER_CONTEXT_DATA Context ) { DWORD ec = NO_ERROR;
DBG_ENTER(_T("FaxModemCoClassInstaller"), ec, TEXT("Processing %s request"), DifDebug[InstallFunction].DifString);
// We handle two events:
//
// DIF_INSTALLDEVICE
// A new device has finished installing and we're allowed to install a printer
// if Fax is already on the box
// In this case we do the following:
//
// 1. Check if Fax is installed, if it's not leave
// 2. Check if there's a Fax printer, if there is leave
// 3. Install a Fax printer
// 4. Ensure the service is up
// 5. Leave
//
// DIF_NEWDEVICEWIZARD_FINISHINSTALL
// A new device has finished installing and we're allowed to add a property page
// asking the user to install Fax
// In this case we do the following:
//
// 1. Check if Fax is installed, if it is leave
// 2. Check if we're allowed to add a property page, if not leave
// 3. Add a property page to the wizard.
// 4. Leave
switch (InstallFunction) { case DIF_INSTALLWIZARD: VERBOSE (DBG_MSG, L"Marking installation as potential non PnP"); bIsPnpInstallation = false; break;
case DIF_INSTALLDEVICE: if (!Context->PostProcessing) { //
// The modem device is not installed yet
//
VERBOSE (DBG_MSG, L"Pre-installation, waiting for post-installation call"); ec = ERROR_DI_POSTPROCESSING_REQUIRED; return ec; } if (Context->InstallResult!=NO_ERROR) { //
// The modem device had some problems during installation
//
VERBOSE (DBG_MSG, L"Previous error causing installation failure, 0x%08x", Context->InstallResult); ec = Context->InstallResult; return ec; } if (HandleInstallDevice(hDeviceInfoSet,pDeviceInfoData)!=NO_ERROR) { CALL_FAIL (GENERAL_ERR, TEXT("HandleInstallDevice"), GetLastError()); // do not fail the CoClassInstaller
} /* No UI until futher notice
if (HandleNonPnpDevices()!=NO_ERROR) { CALL_FAIL (GENERAL_ERR, TEXT("HandleNonPnpDevices"), GetLastError()); // do not fail the CoClassInstaller
} */ break;
case DIF_NEWDEVICEWIZARD_FINISHINSTALL: /* No UI until futher notice
Assert(bIsPnpInstallation); if (HandleNewDeviceWizardFinishInstall(hDeviceInfoSet,pDeviceInfoData)!=NO_ERROR) { CALL_FAIL (GENERAL_ERR, TEXT("HandleNewDeviceWizardFinishInstall"), GetLastError()); // do not fail the CoClassInstaller
} */ break;
default: VERBOSE(DBG_MSG,TEXT("We do not handle %s"),DifDebug[InstallFunction].DifString); break; }
return ec; }
|