Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2902 lines
86 KiB

//////////////////////////////////////////////////////////////////////////////
//
// File Name: faxocm.cpp
//
// Abstract: This file implements the OCM setup for fax.
//
// Environment: windows XP / User Mode
//
// Coding Style: Any function, variable, or typedef preceded with the
// "prv_" prefix (short for "local"), implies that
// it is visible only within the scope of this file.
// For functions and variables, it implies they are
// static.
//
// Copyright (c) 2000 Microsoft Corporation
//
// Revision History:
//
// Date: Developer: Comments:
// ----- ---------- ---------
// 15-Mar-2000 Oren Rosenbloom (orenr) Created from old faxocm.cpp by wesx
//////////////////////////////////////////////////////////////////////////////
#include "faxocm.h"
#pragma hdrstop
#include <shellapi.h>
#include <systrayp.h>
/////////////////////////////// Local Defines ////////////////////////////
#define prv_TOTAL_NUM_PROGRESS_BAR_TICKS 12
// These two are defined in %SDXROOT%\SHELL\EXT\SYSTRAY\DLL\systray.h too.
// This is a duplicate definition that has to remain in sync.
// We don't use the systray.h because we have local builds and we're
// not enlisted on the whole project.
#define FAX_STARTUP_TIMER_ID 7
#define FAX_SHUTDOWN_TIMER_ID 99
///////////////////////////////
// prv_Component_t
//
// Stores the information we
// get from the OC Manager
// for use by the rest of the
// faxocm.dll.
//
typedef struct prv_Component_t
{
DWORD dwExpectedOCManagerVersion;
TCHAR szComponentID[255 + 1];
TCHAR szSubComponentID[255 + 1]; // Needed for prv_dlgOcmWizardPage
HINF hInf;
DWORD dwSetupMode;
DWORDLONG dwlFlags;
UINT uiLanguageID;
TCHAR szSourcePath[_MAX_PATH + _MAX_FNAME + 1];
TCHAR szUnattendFile[_MAX_PATH + _MAX_FNAME + 1];
OCMANAGER_ROUTINES Helpers;
EXTRA_ROUTINES Extras;
HSPFILEQ hQueue;
DWORD dwProductType;
PRODUCT_SKU_TYPE InstalledProductSKU;
DWORD InstalledProductBuild;
} prv_Component_t;
///////////////////////////////
// prv_GVAR
//
// Global variables visible
// only within this file
// scope.
//
static struct prv_GVAR
{
BOOL bInited;
HINSTANCE hInstance;
DWORD dwCurrentOCManagerVersion;
prv_Component_t Component;
} prv_GVAR =
{
FALSE, // bInited
NULL // hInstance
};
//
// Delay Load support
//
#include <delayimp.h>
EXTERN_C
FARPROC
WINAPI
DelayLoadFailureHook (
UINT unReason,
PDelayLoadInfo pDelayInfo
);
PfnDliHook __pfnDliFailureHook = DelayLoadFailureHook;
//////////////////// Static Function Prototypes //////////////////////////////
static void prv_UpdateProgressBar(DWORD dwNumTicks);
static DWORD prv_GetSectionToProcess(const TCHAR *pszCurrentSection,
TCHAR *pszSectionToProcess,
DWORD dwNumBufChars);
static DWORD prv_ValidateVersion(SETUP_INIT_COMPONENT *pSetupInit);
static DWORD prv_SetSetupData(const TCHAR *pszComponentId,
SETUP_INIT_COMPONENT *pSetupInit);
static DWORD prv_OnPreinitialize(void);
static DWORD prv_OnInitComponent(LPCTSTR pszComponentId,
SETUP_INIT_COMPONENT *pSetupInitComponent);
static DWORD prv_OnExtraRoutines(LPCTSTR pszComponentId,
EXTRA_ROUTINES *pExtraRoutines);
static DWORD prv_OnSetLanguage(UINT uiLanguageID);
static DWORD_PTR prv_OnQueryImage(void);
static DWORD prv_OnSetupRequestPages(LPCTSTR pszComponentId,
WizardPagesType uiType,
PSETUP_REQUEST_PAGES pSetupRequestPages);
static DWORD prv_OnWizardCreated(void);
static DWORD prv_OnQuerySkipPage(void);
static DWORD prv_OnQuerySelStateChange(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
UINT uiState,
UINT uiFlags);
static DWORD prv_OnCalcDiskSpace(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
DWORD addComponent,
HDSKSPC dspace);
static DWORD prv_OnQueueFileOps(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
HSPFILEQ hQueue);
static DWORD prv_OnNotificationFromQueue(void);
static DWORD prv_OnQueryStepCount(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId);
static DWORD prv_OnCompleteInstallation(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId);
static DWORD prv_OnCleanup(void);
static DWORD prv_OnQueryState(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
UINT uiState);
static DWORD prv_OnNeedMedia(void);
static DWORD prv_OnAboutToCommitQueue(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId);
static DWORD prv_RunExternalProgram(LPCTSTR pszComponent,
DWORD state);
static DWORD prv_EnumSections(HINF hInf,
const TCHAR *component,
const TCHAR *key,
DWORD index,
INFCONTEXT *pic,
TCHAR *name);
static DWORD prv_CleanupNetShares(LPCTSTR pszComponent,
DWORD state);
static DWORD prv_CompleteFaxInstall(const TCHAR *pszSubcomponentId,
const TCHAR *pszInstallSection);
static DWORD prv_CompleteFaxUninstall(const TCHAR *pszSubcomponentId,
const TCHAR *pszUninstallSection);
static DWORD prv_UninstallFax(const TCHAR *pszSubcomponentId,
const TCHAR *pszUninstallSection);
static DWORD prv_NotifyStatusMonitor(WPARAM wParam);
static DWORD prv_ShowUninstalledFaxShortcut(void);
static INT_PTR CALLBACK prv_dlgOcmWizardPage(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
///////////////////////////////
// faxocm_IsInited
//
// Returns TRUE if OCM is
// initialized, FALSE, otherwise
//
// Params:
// - void
// Returns:
// - TRUE if initialized.
// - FALSE otherwise.
//
BOOL faxocm_IsInited(void)
{
return prv_GVAR.bInited;
}
///////////////////////////////
// faxocm_GetAppInstance
//
// Returns the hInstance of
// this DLL.
//
// Params:
// - void
// Returns:
// - Instance of this DLL.
//
HINSTANCE faxocm_GetAppInstance(void)
{
return prv_GVAR.hInstance;
}
///////////////////////////////
// faxocm_GetComponentID
//
// Returns the Component ID
// passed to us via the OC
// Manager
//
// Params:
// - pszComponentID - ID of top level component
// - dwNumBufChars - # chars pszComponentID can hold
// Returns:
// - NO_ERROR on success.
// - error code otherwise
//
DWORD faxocm_GetComponentID(TCHAR *pszComponentID,
DWORD dwNumBufChars)
{
DWORD dwReturn = NO_ERROR;
if ((pszComponentID == NULL) ||
(dwNumBufChars == 0))
{
return ERROR_INVALID_PARAMETER;
}
_tcsncpy(pszComponentID, prv_GVAR.Component.szComponentID, dwNumBufChars);
return dwReturn;
}
///////////////////////////////
// faxocm_GetComponentFileQueue
//
// Returns the file queue
// given to us by the OC Manager
//
// The file queue is used by
// the Setup API functions for
// copying/deleting files.
//
// Params:
// - void
// Returns:
// - Handle to file queue
//
HSPFILEQ faxocm_GetComponentFileQueue(void)
{
return prv_GVAR.Component.hQueue;
}
///////////////////////////////
// faxocm_GetComponentInfName
//
// Returns the full path to the
// faxsetup.inf file.
//
// Params:
// - buffer to fill with path, must be at least MAX_PATH long
// Returns:
// - NO_ERROR - in case of success
// - Win32 Error code - otherwise
//
BOOL faxocm_GetComponentInfName(TCHAR* szInfFileName)
{
BOOL bRes = TRUE;
DBG_ENTER(_T("faxocm_GetComponentInfName"),bRes);
(*szInfFileName) = NULL;
if (GetWindowsDirectory(szInfFileName,MAX_PATH)==0)
{
CALL_FAIL(SETUP_ERR,TEXT("GetWindowsDirectory"),GetLastError());
bRes = FALSE;
goto exit;
}
if (_tcslen(szInfFileName)+_tcslen(FAX_INF_PATH)>(MAX_PATH-1))
{
VERBOSE(SETUP_ERR,_T("MAX_PATH too short to create INF path"));
bRes = FALSE;
goto exit;
}
_tcscat(szInfFileName,FAX_INF_PATH);
exit:
return bRes;
}
///////////////////////////////
// faxocm_GetComponentInf
//
// Returns the handle to the
// faxsetup.inf file.
//
// Params:
// - void
// Returns:
// - Handle to faxsetup.inf file
//
HINF faxocm_GetComponentInf(void)
{
return prv_GVAR.Component.hInf;
}
///////////////////////////////
// faxocm_GetComponentSetupMode
//
// Returns the setup mode as
// given to us by OC Manager.
//
// Params:
// - void.
// Returns:
// - Setup mode as given to us by OC Manager
//
DWORD faxocm_GetComponentSetupMode(void)
{
return prv_GVAR.Component.dwSetupMode;
}
///////////////////////////////
// faxocm_GetComponentFlags
//
// Returns the flags as
// given to us by OC Manager.
//
// Params:
// - void
// Returns:
// - Flags as given to us by OC Manager
//
DWORDLONG faxocm_GetComponentFlags(void)
{
return prv_GVAR.Component.dwlFlags;
}
///////////////////////////////
// faxocm_GetComponentLangID
//
// Returns the Language ID
// given to us by OC Manager.
//
// Params:
// - void.
// Returns:
// - Language ID as given to us by OC Manager
//
UINT faxocm_GetComponentLangID(void)
{
return prv_GVAR.Component.uiLanguageID;
}
///////////////////////////////
// faxocm_GetComponentSourcePath
//
// Returns the Source Path
// given to us by OC Manager.
//
// Params:
// - pszSourcePath - OUT - buffer to hold source path
// - dwNumBufChars - # of characters pszSourcePath can hold.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD faxocm_GetComponentSourcePath(TCHAR *pszSourcePath,
DWORD dwNumBufChars)
{
DWORD dwReturn = NO_ERROR;
if ((pszSourcePath == NULL) ||
(dwNumBufChars == 0))
{
return ERROR_INVALID_PARAMETER;
}
_tcsncpy(pszSourcePath, prv_GVAR.Component.szSourcePath, dwNumBufChars);
return dwReturn;
}
///////////////////////////////
// faxocm_GetComponentUnattendFile
//
// Returns the Unattend Path
// given to us by OC Manager.
//
// Params:
// - pszUnattendFile - OUT - buffer to hold unattend path
// - dwNumBufChars - # of characters pszSourcePath can hold.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
DWORD faxocm_GetComponentUnattendFile(TCHAR *pszUnattendFile,
DWORD dwNumBufChars)
{
DWORD dwReturn = NO_ERROR;
if ((pszUnattendFile == NULL) ||
(dwNumBufChars == 0))
{
return ERROR_INVALID_PARAMETER;
}
_tcsncpy(pszUnattendFile, prv_GVAR.Component.szUnattendFile, dwNumBufChars);
return dwReturn;
}
////////////////////////////////////
// faxocm_GetComponentHelperRoutines
//
// Returns the pointer to the Helper
// data and functions as given to us
// by OC Manager.
//
// Params:
// - void.
// Returns:
// - Ptr to helper routines as given to us by OC Manager.
//
OCMANAGER_ROUTINES* faxocm_GetComponentHelperRoutines(void)
{
return &prv_GVAR.Component.Helpers;
}
////////////////////////////////////
// faxocm_GetComponentExtraRoutines
//
// Returns the pointer to the Helper
// data and functions as given to us
// by OC Manager.
//
// Params:
// - void
// Returns:
// - Ptr to extra info as given to us by OC Manager.
//
EXTRA_ROUTINES* faxocm_GetComponentExtraRoutines(void)
{
return &prv_GVAR.Component.Extras;
}
////////////////////////////////////
// faxocm_GetProductType
//
// Returns the product type as given
// to us by OC Manager.
//
// Params:
// - void.
// Returns:
// - Product type as given to us by OC Manager.
//
DWORD faxocm_GetProductType(void)
{
return prv_GVAR.Component.dwProductType;
}
////////////////////////////////////
// faxocm_GetVersionInfo
//
// Returns the version # as given
// to us by OC Manager.
//
// Params:
// - pdwExpectedOCManagerVersion - OUT - self explanatory.
// - pdwCurrentOCManagerVersion - OUT - self explanatory.
// Returns:
// - void.
//
void faxocm_GetVersionInfo(DWORD *pdwExpectedOCManagerVersion,
DWORD *pdwCurrentOCManagerVersion)
{
if (pdwExpectedOCManagerVersion)
{
*pdwExpectedOCManagerVersion =
prv_GVAR.Component.dwExpectedOCManagerVersion;
}
if (pdwCurrentOCManagerVersion)
{
*pdwCurrentOCManagerVersion = prv_GVAR.dwCurrentOCManagerVersion;
}
return;
}
void faxocm_GetProductInfo(PRODUCT_SKU_TYPE* pInstalledProductSKU,
DWORD* dwInstalledProductBuild)
{
if (pInstalledProductSKU)
{
*pInstalledProductSKU = prv_GVAR.Component.InstalledProductSKU;
}
if (dwInstalledProductBuild)
{
*dwInstalledProductBuild = prv_GVAR.Component.InstalledProductBuild;
}
}
extern "C"
BOOL FaxControl_DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
///////////////////////////////
// DllMain
//
// DLL Entry Point
//
// Params:
// hInstance - Instance handle
// Reason - Reason for the entrypoint being called
// Context - Context record
//
// Returns:
// TRUE - Initialization succeeded
// FALSE - Initialization failed
//
extern "C"
DWORD DllMain(HINSTANCE hInst,
DWORD Reason,
LPVOID Context)
{
DBG_ENTER(_T("DllMain"));
switch (Reason)
{
case DLL_PROCESS_ATTACH:
// initialize our global variables
memset(&prv_GVAR, 0, sizeof(prv_GVAR));
prv_GVAR.hInstance = hInst;
// Initialize Debug Support
//
VERBOSE(DBG_MSG,_T("FxsOcm.dll loaded - DLL_PROCESS_ATTACH"));
DisableThreadLibraryCalls(hInst);
break;
case DLL_PROCESS_DETACH:
// terminate Debug Support
VERBOSE(DBG_MSG,_T("FxsOcm.dll unloaded - DLL_PROCESS_DETACH"));
break;
default:
VERBOSE(DBG_MSG,_T("DllMain, received some weird 'Reason' ")
_T("for this fn, Reason = %lu"), Reason);
break;
}
//
// Pass DllMain call to ATL supplied DllMain
//
return FaxControl_DllMain (hInst, Reason, Context);
}
///////////////////////////////
// FaxOcmSetupProc
//
// Entry point for OC Manager.
//
// The OC Manager calls this function
// to drive this DLL.
//
// Params:
// - pszComponentId - major component
// - pszSubcomponentId - component found if user presses "Details"
// - uiFunction - what stage of setup we are in.
// - uiParam1 - dependent on uiFunction - could be anything.
// - pParam2 - dependent on uiFunction - could be anything.
//
// Returns:
// DWORD indicating error or success.
//
//
DWORD_PTR FaxOcmSetupProc(IN LPWSTR pszComponentId,
IN LPWSTR pszSubcomponentId,
IN UINT uiFunction,
IN UINT uiParam1,
IN OUT PVOID pParam2)
{
DWORD_PTR rc = 0;
DBG_ENTER( _T("FaxOcmSetupProc"),
_T("%s - %s"),
pszComponentId,
pszSubcomponentId);
VERBOSE(DBG_MSG, _T("FaxOcmSetup proc called with function '%s'"),
fxocDbg_GetOcFunction(uiFunction));
switch(uiFunction)
{
case OC_PREINITIALIZE:
rc = prv_OnPreinitialize();
break;
case OC_INIT_COMPONENT:
rc = prv_OnInitComponent(pszComponentId,
(PSETUP_INIT_COMPONENT) pParam2);
break;
case OC_EXTRA_ROUTINES:
rc = prv_OnExtraRoutines(pszComponentId, (PEXTRA_ROUTINES)pParam2);
break;
case OC_SET_LANGUAGE:
rc = prv_OnSetLanguage(uiParam1);
break;
case OC_QUERY_IMAGE:
// Argh! I hate casting handles to DWORDs
rc = prv_OnQueryImage();
break;
case OC_REQUEST_PAGES:
rc = prv_OnSetupRequestPages(pszComponentId,
(WizardPagesType)uiParam1, (PSETUP_REQUEST_PAGES)pParam2);
break;
case OC_QUERY_CHANGE_SEL_STATE:
rc = prv_OnQuerySelStateChange(pszComponentId,
pszSubcomponentId,
uiParam1,
(UINT)((UINT_PTR)pParam2));
break;
case OC_CALC_DISK_SPACE:
rc = prv_OnCalcDiskSpace(pszComponentId,
pszSubcomponentId,
uiParam1,
pParam2);
// sometimes the OC Manager gives us NULL subcomponent IDs,
// so just ignore them.
if (rc == ERROR_INVALID_PARAMETER)
{
rc = NO_ERROR;
}
break;
case OC_QUEUE_FILE_OPS:
SET_DEBUG_FLUSH(TRUE);
rc = prv_OnQueueFileOps(pszComponentId,
pszSubcomponentId,
(HSPFILEQ)pParam2);
SET_DEBUG_FLUSH(FALSE);
// OC Manager calls us twice on this function. Once with a subcomponent ID
// of NULL, and the second time with a subcomponent ID of "Fax".
// Since we are going to be called a second time with a valid ID (i.e. "Fax")
// disregard the first call and process the second call.
if (rc == ERROR_INVALID_PARAMETER)
{
rc = NO_ERROR;
}
break;
case OC_NOTIFICATION_FROM_QUEUE:
rc = prv_OnNotificationFromQueue();
break;
case OC_QUERY_STEP_COUNT:
rc = prv_OnQueryStepCount(pszComponentId, pszSubcomponentId);
// OC Manager calls us twice on this function. Once with a subcomponent ID
// of NULL, and the second time with a subcomponent ID of "Fax".
// Since we are going to be called a second time with a valid ID (i.e. "Fax")
// disregard the first call and process the second call.
if (rc == ERROR_INVALID_PARAMETER)
{
rc = NO_ERROR;
}
break;
case OC_COMPLETE_INSTALLATION:
SET_DEBUG_FLUSH(TRUE);
rc = prv_OnCompleteInstallation(pszComponentId, pszSubcomponentId);
SET_DEBUG_FLUSH(FALSE);
// OC Manager calls us twice on this function. Once with a subcomponent ID
// of NULL, and the second time with a subcomponent ID of "Fax".
// Since we are going to be called a second time with a valid ID (i.e. "Fax")
// disregard the first call and process the second call.
if (rc == ERROR_INVALID_PARAMETER)
{
rc = NO_ERROR;
}
break;
case OC_CLEANUP:
rc = prv_OnCleanup();
// OC Manager calls us twice on this function. Once with a subcomponent ID
// of NULL, and the second time with a subcomponent ID of "Fax".
// Since we are going to be called a second time with a valid ID (i.e. "Fax")
// disregard the first call and process the second call.
if (rc == ERROR_INVALID_PARAMETER)
{
rc = NO_ERROR;
}
break;
case OC_QUERY_STATE:
rc = prv_OnQueryState(pszComponentId, pszSubcomponentId, uiParam1);
break;
case OC_NEED_MEDIA:
rc = prv_OnNeedMedia();
break;
case OC_ABOUT_TO_COMMIT_QUEUE:
rc = prv_OnAboutToCommitQueue(pszComponentId, pszSubcomponentId);
break;
case OC_QUERY_SKIP_PAGE:
rc = prv_OnQuerySkipPage();
break;
case OC_WIZARD_CREATED:
rc = prv_OnWizardCreated();
break;
default:
rc = NO_ERROR;
break;
}
return rc;
}
///////////////////////////////
// prv_ValidateVersion
//
// Validates that the version
// of OC Manager this DLL was written
// for is compatible with the version
// of OC Manager that is currently
// driving us.
//
// Params:
// - pSetupInit - setup info as given to us by OC Manager.
//
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_ValidateVersion(SETUP_INIT_COMPONENT *pSetupInit)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER(TEXT("prv_ValidateVersion"), dwReturn);
if (OCMANAGER_VERSION <= pSetupInit->OCManagerVersion)
{
// the version we expect is lower or the same than the version
// than OC Manager understands. This means that a newer OC
// Manager should still be able to drive older components, so
// return the version we support to OC Manager, and it will decide
// if it can drive this component or not.
VERBOSE( DBG_MSG,
_T("OC Manager version: 0x%x, ")
_T("FaxOcm Expected Version: 0x%x, seems OK"),
pSetupInit->OCManagerVersion,
OCMANAGER_VERSION);
pSetupInit->ComponentVersion = OCMANAGER_VERSION;
}
else
{
// we were written for a newer version of OC Manager than the
// OC Manager driving this component. Fail.
VERBOSE( SETUP_ERR,
_T("OC Manager version: 0x%x, ")
_T("FaxOcm Expected Version: 0x%x, unsupported, abort."),
pSetupInit->OCManagerVersion,
OCMANAGER_VERSION);
dwReturn = ERROR_CALL_NOT_IMPLEMENTED;
}
return dwReturn;
}
///////////////////////////////
// prv_SetSetupData
//
// Initialize our global variable containing
// the prv_Component_t information.
//
// Params:
// - pszComponentId - id as it appears in SysOc.inf
// - pSetupInit - OC Manager setup info.
//
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_SetSetupData(const TCHAR *pszComponentId,
SETUP_INIT_COMPONENT *pSetupInit)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER(TEXT("prv_SetSetupData"), dwReturn, TEXT("%s"), pszComponentId);
if ((pszComponentId == NULL) ||
(pSetupInit == NULL))
{
return ERROR_INVALID_PARAMETER;
}
if (dwReturn == NO_ERROR)
{
memset(&prv_GVAR.Component, 0, sizeof(prv_GVAR.Component));
prv_GVAR.dwCurrentOCManagerVersion = pSetupInit->OCManagerVersion;
_tcsncpy(prv_GVAR.Component.szComponentID,
pszComponentId,
sizeof(prv_GVAR.Component.szComponentID) / sizeof(TCHAR));
// szSubComponentID will be set in OC_QUERY_STATE, because
// we don't have it now
_tcsncpy(prv_GVAR.Component.szSourcePath,
pSetupInit->SetupData.SourcePath,
sizeof(prv_GVAR.Component.szSourcePath) / sizeof(TCHAR));
_tcsncpy(prv_GVAR.Component.szUnattendFile,
pSetupInit->SetupData.UnattendFile,
sizeof(prv_GVAR.Component.szUnattendFile) / sizeof(TCHAR));
prv_GVAR.Component.hInf = pSetupInit->ComponentInfHandle;
prv_GVAR.Component.dwlFlags = pSetupInit->SetupData.OperationFlags;
prv_GVAR.Component.dwProductType = pSetupInit->SetupData.ProductType;
prv_GVAR.Component.dwSetupMode = pSetupInit->SetupData.SetupMode;
prv_GVAR.Component.dwExpectedOCManagerVersion = OCMANAGER_VERSION;
memcpy(&prv_GVAR.Component.Helpers,
&pSetupInit->HelperRoutines,
sizeof(prv_GVAR.Component.Helpers));
}
return dwReturn;
}
///////////////////////////////
// prv_GetSectionToProcess
//
// This determines if we are
// clean installing, upgrading,
// uninstalling, etc, and returns
// the correct install section in the
// faxsetup.inf to process.
//
// Params:
// - pszCurrentSection
// - pszSectionToProcess - OUT
// - dwNumBufChars - # of characters pszSectionToProcess can hold.
//
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_GetSectionToProcess(const TCHAR *pszCurrentSection,
TCHAR *pszSectionToProcess,
DWORD dwNumBufChars)
{
DWORD dwReturn = NO_ERROR;
BOOL bInstall = TRUE;
DBG_ENTER( TEXT("prv_GetSectionToProcess"),
dwReturn,
TEXT("%s"),
pszCurrentSection);
if ((pszCurrentSection == NULL) ||
(pszSectionToProcess == NULL) ||
(dwNumBufChars == 0))
{
return ERROR_INVALID_PARAMETER;
}
const TCHAR *pszInfKeyword = fxState_GetInstallType(pszCurrentSection);
// okay, get that section's value, which will be an install/uninstall
// section in the INF.
if (pszInfKeyword)
{
dwReturn = fxocUtil_GetKeywordValue(pszCurrentSection,
pszInfKeyword,
pszSectionToProcess,
dwNumBufChars);
}
else
{
dwReturn = ::GetLastError();
VERBOSE(SETUP_ERR,
_T("fxState_GetInstallType failed, rc = 0x%lx"),
dwReturn);
}
return dwReturn;
}
///////////////////////////////
// prv_UpdateProgressBar
//
// Update the progress bar displayed in the
// OC Manager dialog. This simply tells
// the OC Manager to increment the dialog by
// the specified # of ticks.
//
// Params:
// - dwNumTicks - # of ticks to increment by.
//
// Returns:
// - void
//
static void prv_UpdateProgressBar(DWORD dwNumTicks)
{
// update the progress bar based on the number of ticks the caller
// would like to set.
DBG_ENTER(TEXT("prv_UpdateProgressBar"), TEXT("%d"), dwNumTicks);
if (prv_GVAR.Component.Helpers.TickGauge)
{
for (DWORD i = 0; i < dwNumTicks; i++)
{
prv_GVAR.Component.Helpers.TickGauge(
prv_GVAR.Component.Helpers.OcManagerContext);
}
}
}
///////////////////////////////
// prv_OnPreinitialize()
//
// Handler for OC_PREINITIALIZE
//
// Params:
// Returns:
// - Either OCFLAG_UNICODE or
// OCFLAG_ANSI, depending on
// what this DLL supports.
// This DLL supports both.
static DWORD prv_OnPreinitialize(VOID)
{
return OCFLAG_UNICODE;
}
///////////////////////////////
// prv_OnInitComponent()
//
// Handler for OC_INIT_COMPONENT
//
// Params:
// - pszComponentId - ID specified in SysOc.inf (probably "Fax")
// - pSetupInitComponent - OC Manager Setup info
//
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_OnInitComponent(LPCTSTR pszComponentId,
SETUP_INIT_COMPONENT *pSetupInitComponent)
{
BOOL bSuccess = FALSE;
DWORD dwReturn = NO_ERROR;
UINT uiErrorAtLineNumber = 0;
DBG_ENTER(TEXT("prv_OnInitComponent"), dwReturn, TEXT("%s"), pszComponentId);
if ((pszComponentId == NULL) ||
(pSetupInitComponent == NULL))
{
return ERROR_INVALID_PARAMETER;
}
// save the setup data.
if (dwReturn == NO_ERROR)
{
dwReturn = prv_SetSetupData(pszComponentId, pSetupInitComponent);
}
// Initialize debug so that we can get the debug settings specified
// in the faxocm.inf file.
fxocDbg_Init((faxocm_GetComponentInf()));
// Validate the version of OC Manager against the version we expect
if (dwReturn == NO_ERROR)
{
dwReturn = prv_ValidateVersion(pSetupInitComponent);
}
// Notice we do NOT need to call 'SetupOpenAppendInfFile'
// since OC Manager already appends the layout.inf to the hInf
// for us.
bSuccess = ::SetupOpenAppendInfFile(NULL, prv_GVAR.Component.hInf, NULL);
if (!bSuccess)
{
dwReturn = ::GetLastError();
VERBOSE( DBG_MSG,
_T("SetupOpenAppendInfFile failed to append ")
_T("the layout inf to the component Inf"));
}
//
// initialize all the subsystems and Upgrade
//
if (dwReturn == NO_ERROR)
{
fxState_Init();
fxocUtil_Init();
fxocFile_Init();
fxocMapi_Init();
fxocPrnt_Init();
fxocReg_Init();
fxocSvc_Init();
fxUnatnd_Init();
fxocUpg_Init();
}
// set our initialized flag.
if (dwReturn == NO_ERROR)
{
prv_GVAR.bInited = TRUE;
VERBOSE( DBG_MSG,
_T("OnInitComponent, ComponentID: '%s', ")
_T("SourcePath: '%s', Component Inf Handle: 0x%0x"),
prv_GVAR.Component.szComponentID,
prv_GVAR.Component.szSourcePath,
prv_GVAR.Component.hInf);
}
else
{
// XXX - OrenR - 03/23/2000
// We should probably clean up here
prv_GVAR.bInited = FALSE;
VERBOSE( SETUP_ERR,
_T("OnInitComponent, ComponentID: '%s'")
_T("SourcePath: '%s', Component Inf Handle: 0x%0x ")
_T("Failed to Append Layout.inf file, dwReturn = %lu"),
prv_GVAR.Component.szComponentID,
prv_GVAR.Component.szSourcePath,
prv_GVAR.Component.hInf,
dwReturn);
}
// Load product SKU and Version (if exists)
HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,FALSE,KEY_READ);
if (hKey)
{
// write the SKU into the registry
prv_GVAR.Component.InstalledProductSKU = PRODUCT_SKU_TYPE(GetRegistryDword(hKey,REGVAL_PRODUCT_SKU));
prv_GVAR.Component.InstalledProductBuild = GetRegistryDword(hKey,REGVAL_PRODUCT_BUILD);
RegCloseKey(hKey);
}
else
{
VERBOSE(DBG_MSG,_T("Failed to open fax setup registry, dwReturn = 0x%lx"),GetLastError());
}
// Output to debug our current setup state.
fxState_DumpSetupState();
return dwReturn;
}
///////////////////////////////
// prv_OnCleanup
//
// Called just before this
// DLL is unloaded
//
// Params:
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_OnCleanup(void)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER(TEXT("prv_OnCleanup"), dwReturn);
// terminate the subsystems in reverse order from which they we
// intialized.
fxUnatnd_Term();
fxocSvc_Term();
fxocReg_Term();
fxocPrnt_Term();
fxocMapi_Term();
fxocFile_Term();
fxocUtil_Term();
fxState_Term();
// this closes the log file, so do this last...
fxocDbg_Term();
return dwReturn;
}
///////////////////////////////
// prv_OnCalcDiskSpace
//
// Handler for OC_CALC_DISK_SPACE
// OC Manager calls this function
// so that it can determine how
// much disk space we require.
//
// Params:
// - pszComponentId - From SysOc.inf (usually "fax")
// - pszSubcomponentId -
// - addComponent - non-zero if installing, 0 if uninstalling
// - dspace - handle to disk space abstraction.
//
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_OnCalcDiskSpace(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
DWORD addComponent,
HDSKSPC dspace)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER( TEXT("prv_OnCalcDiskSpace"),
dwReturn,
TEXT("%s - %s"),
pszComponentId,
pszSubcomponentId);
if (dwReturn == NO_ERROR)
{
dwReturn = fxocFile_CalcDiskSpace(pszSubcomponentId,
addComponent,
dspace);
}
return dwReturn;
}
///////////////////////////////
// prv_OnQueueFileOps
//
// Handler for OC_QUEUE_FILE_OPS
// This fn will queue all the files
// specified for copying and deleting
// in the INF install section.
//
// Params:
// - pszCompnentId
// - pszSubcomponentId
// - hQueue - Handle to queue abstraction.
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_OnQueueFileOps(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
HSPFILEQ hQueue)
{
DWORD dwReturn = NO_ERROR;
BOOL bInstallSelected = FALSE;
BOOL bSelectionStateChanged = FALSE;
DBG_ENTER( TEXT("prv_OnQueueFileOps"),
dwReturn,
TEXT("%s - %s"),
pszComponentId,
pszSubcomponentId);
if ((pszComponentId == NULL) ||
(pszSubcomponentId == NULL) ||
(hQueue == NULL))
{
return ERROR_INVALID_PARAMETER;
}
// save our Queue Handle.
prv_GVAR.Component.hQueue = hQueue;
dwReturn = faxocm_HasSelectionStateChanged(pszSubcomponentId,
&bSelectionStateChanged,
&bInstallSelected,
NULL);
if (dwReturn != NO_ERROR)
{
VERBOSE( SETUP_ERR,
_T("HasSelectionStateChanged failed, rc = 0x%lx"),
dwReturn);
return dwReturn;
}
// our selection state has changed, install or uninstall based on
// the current selection state.
if (bSelectionStateChanged == TRUE)
{
TCHAR szSectionToProcess[255 + 1] = {0};
VERBOSE( DBG_MSG,
_T("Beginning Queuing of Files: ComponentID: '%s', ")
_T("SubComponentID: '%s', Selection State has ")
_T("changed to %lu ==> Installing/Uninstalling"),
pszComponentId, pszSubcomponentId,
bInstallSelected);
if (dwReturn == NO_ERROR)
{
dwReturn = prv_GetSectionToProcess(
pszSubcomponentId,
szSectionToProcess,
sizeof(szSectionToProcess) / sizeof(TCHAR));
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to get section to process ")
_T("rc = 0x%lx"),
dwReturn);
}
}
if (dwReturn == NO_ERROR)
{
if (bInstallSelected)
{
//
// Install
//
//
// Prepare for the Upgrade : Save different Settings
//
dwReturn = fxocUpg_SaveSettings();
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING,
_T("Failed to prepare for the Upgrade : save settings during upgrade to Windows-XP Fax. ")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
// install files
dwReturn = fxocFile_Install(pszSubcomponentId,
szSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_MSG,
_T("Failed Fax File operations, ")
_T("for subcomponent '%s', section '%s', ")
_T("rc = 0x%lx"), pszSubcomponentId,
szSectionToProcess, dwReturn);
}
}
else
{
//
// Uninstall
//
dwReturn = prv_UninstallFax(pszSubcomponentId,
szSectionToProcess);
}
}
}
else
{
VERBOSE(DBG_MSG,
_T("End Queuing of Files, ComponentID: '%s', ")
_T("SubComponentID: '%s', Selection State has NOT ")
_T("changed, doing nothing, bInstallSelected=%lu"),
pszComponentId, pszSubcomponentId,
bInstallSelected);
}
return dwReturn;
}
///////////////////////////////
// prv_OnCompleteInstallation
//
// Handler for OC_COMPLETE_INSTALLATION.
// This is called after the queue is
// committed. It is here that we
// make our registery changes, add
// fax service, and create the fax printer.
//
// Params:
// - pszComponentId
// - pszSubcomponentId.
// Returns:
// - NO_ERROR if success.
// - error code otherwise.
//
static DWORD prv_OnCompleteInstallation(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId)
{
BOOL bSelectionStateChanged = FALSE;
BOOL bInstallSelected = FALSE;
DWORD dwReturn = NO_ERROR;
DBG_ENTER( TEXT("prv_OnCompleteInstallation"),
dwReturn,
TEXT("%s - %s"),
pszComponentId,
pszSubcomponentId);
// Do post-installation processing in the cleanup section.
// This way we know all components queued for installation
// have beein installed before we do our stuff.
if (!pszSubcomponentId || !*pszSubcomponentId)
{
return ERROR_INVALID_PARAMETER;
}
dwReturn = faxocm_HasSelectionStateChanged(pszSubcomponentId,
&bSelectionStateChanged,
&bInstallSelected,
NULL);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("HasSelectionStateChanged failed, rc = 0x%lx"),
dwReturn);
return dwReturn;
}
// if our selection state has changed, then install/uninstall
if (bSelectionStateChanged)
{
TCHAR szSectionToProcess[255 + 1] = {0};
//
// Fake report to prevent re-entrancy
//
g_InstallReportType = bInstallSelected ? REPORT_FAX_UNINSTALLED : REPORT_FAX_INSTALLED;
dwReturn = prv_GetSectionToProcess(
pszSubcomponentId,
szSectionToProcess,
sizeof(szSectionToProcess) / sizeof(TCHAR));
if (dwReturn == NO_ERROR)
{
// if the Install checkbox is selected, then install
if (bInstallSelected)
{
dwReturn = prv_CompleteFaxInstall(pszSubcomponentId,
szSectionToProcess);
}
else
{
// if the install checkbox is not selected, then uninstall.
dwReturn = prv_CompleteFaxUninstall(pszSubcomponentId,
szSectionToProcess);
}
}
else
{
VERBOSE(SETUP_ERR,
_T("Failed to get section to process ")
_T("rc = 0x%lx"), dwReturn);
}
//
// Report real installation state in case someone asks
//
g_InstallReportType = REPORT_FAX_DETECT;
if (ERROR_SUCCESS == dwReturn)
{
//
// Installation / Uninstallation is successfully complete.
// Notify the 'Printers and Faxes' folder it should refresh itself.
//
RefreshPrintersAndFaxesFolder();
}
}
return dwReturn;
} // prv_OnCompleteInstallation
///////////////////////////////
// prv_CompleteFaxInstall
//
// Called by prv_OnCompleteInstallation
// this function creates the program
// groups/shortcuts, registry entries,
// fax service, fax printer, etc.
//
// Params:
// - pszSubcomponentId
// - pszSectionToProcess
//
static DWORD prv_CompleteFaxInstall(const TCHAR *pszSubcomponentId,
const TCHAR *pszSectionToProcess)
{
DWORD dwReturn = NO_ERROR;
fxState_UpgradeType_e UpgradeType = FXSTATE_UPGRADE_TYPE_NONE;
DBG_ENTER( TEXT("prv_CompleteFaxInstall"),
dwReturn,
TEXT("%s - %s"),
pszSubcomponentId,
pszSectionToProcess);
if ((pszSubcomponentId == NULL) ||
(pszSectionToProcess == NULL))
{
return ERROR_INVALID_PARAMETER;
}
UpgradeType = fxState_IsUpgrade();
// Create Program Group/Shortcuts
// We create the shortcuts first because at the very worst case, if we
// fail everything else, the applications should be somewhat robust enough
// to be able to correct or notify the user of problems that could not
// be notified during install.
VERBOSE(DBG_MSG,_T("Creating program groups and shortcuts..."));
dwReturn = fxocLink_Install(pszSubcomponentId,pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to create program ")
_T("groups/shortcuts for fax. This is a non-fatal ")
_T("error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
prv_UpdateProgressBar(1);
// Load the unattended data if applicable
if ((fxState_IsUnattended()) || (UpgradeType == FXSTATE_UPGRADE_TYPE_WIN9X))
{
VERBOSE(DBG_MSG,
_T("CompleteInstall, state is unattended ")
_T("or we are upgrading from Win9X, ")
_T("caching unattended data from INF file"));
// load our unattended data
dwReturn = fxUnatnd_LoadUnattendedData();
if (dwReturn == NO_ERROR)
{
// set up the fax printer name
fxocPrnt_SetFaxPrinterName(fxUnatnd_GetPrinterName());
fxocPrnt_SetFaxPrinterShared(fxUnatnd_GetIsPrinterShared());
}
else
{
VERBOSE(SETUP_ERR,
_T("Failed to load unattended data, ")
_T("non-fatal error, continuing anyway...")
_T("rc = 0x%lx"), dwReturn);
dwReturn = NO_ERROR;
}
}
prv_UpdateProgressBar(1);
// install the registry settings as specified in the INF file
VERBOSE(DBG_MSG,_T("Installing Registry..."));
dwReturn = fxocReg_Install(pszSubcomponentId,pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install registry settings ")
_T("for fax installation. This is a fatal ")
_T("error, abandoning fax install...rc=0x%lx"),
dwReturn);
goto cleanup;
}
prv_UpdateProgressBar(1);
// migrate existing SBS registry
if (UpgradeType == FXSTATE_UPGRADE_TYPE_W2K)
{
VERBOSE(DBG_MSG,_T("Migrating existing registry..."));
dwReturn = fxocUpg_MoveRegistry();
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to migrate existing registry.")
_T("This is a non-fatal ")
_T("error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
prv_UpdateProgressBar(1);
// Install Fax Printer/Monitor support
// Create a fax printer and monitor
VERBOSE(DBG_MSG,_T("Installing Fax Monitor and printer drivers..."));
dwReturn = fxocPrnt_Install(pszSubcomponentId,pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install fax printer drivers and ")
_T("fax monitor. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
VERBOSE(DBG_MSG,_T("Installing Fax printer..."));
dwReturn = fxocPrnt_InstallPrinter();
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install fax printer. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
prv_UpdateProgressBar(1);
// Create fax directories
dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_CREATEDIR);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install create directories ")
_T("for fax. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
prv_UpdateProgressBar(1);
// Install Services
// Install any services as specified in the section of the INF file
VERBOSE(DBG_MSG,_T("Installing Fax Service..."));
dwReturn = fxocSvc_Install(pszSubcomponentId,pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install fax service. ")
_T("This is a fatal ")
_T("error, abandoning fax install...rc=0x%lx"),
dwReturn);
goto cleanup;
}
// Try installing the fax printer another time.
// If first attempt succeeded, this will return without doing anything.
// This is because BrookTrout TSP exposes TAPI devices only when it sees the Fax
// service installed.
VERBOSE(DBG_MSG,_T("Installing Fax printer..."));
dwReturn = fxocPrnt_InstallPrinter();
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install fax printer. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
prv_UpdateProgressBar(1);
// Install Exchange Support
VERBOSE(DBG_MSG,_T("Installing Fax MAPI extension..."));
dwReturn = fxocMapi_Install(pszSubcomponentId,pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install exchange support for ")
_T("fax. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
prv_UpdateProgressBar(1);
// Delete Directories at upgrade
VERBOSE(DBG_MSG, _T("Creating directories..."));
//
// At upgrade, before deleting of directories, take care of their content
//
dwReturn = fxocUpg_MoveFiles();
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING,
_T("Failed to clear previous fax directories. ")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_DELDIR);
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING,
_T("Failed to delete directories. ")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
prv_UpdateProgressBar(1);
// create/delete the Shares
VERBOSE(DBG_MSG, _T("Create shares..."));
dwReturn = fxocFile_ProcessShares(pszSectionToProcess);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to install shares ")
_T("for fax. This is a fatal ")
_T("error, abandoning fax installation...rc=0x%lx"),
dwReturn);
goto cleanup;
}
if ((fxState_IsUnattended()) || (UpgradeType == FXSTATE_UPGRADE_TYPE_WIN9X))
{
VERBOSE(DBG_MSG, _T("Saving unattended data to registry"));
//
// this will read from the unattended file list of the uninstalled fax applications
// and update the fxocUpg.prvData, which is used later, in fxocUpg_GetUpgradeApp()
// to decide whether or not to show the "Where Did My Fax Go" shortcut.
//
dwReturn = fxUnatnd_SaveUnattendedData();
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to save unattended data")
_T("to the registry. This is a non-fatal ")
_T("error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
prv_ShowUninstalledFaxShortcut();
prv_UpdateProgressBar(1);
dwReturn = prv_NotifyStatusMonitor(FAX_STARTUP_TIMER_ID);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to notify Status Monitor.")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
prv_UpdateProgressBar(1);
//
// Complete the Upgrade : Restore settings that were saved at Preparation stage
//
dwReturn = fxocUpg_RestoreSettings();
if (dwReturn != NO_ERROR)
{
VERBOSE(DBG_WARNING,
_T("Failed to restore previous fax applications settings after their uninstall. ")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
prv_UpdateProgressBar(1);
cleanup:
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Complete Fax Install failed, rc = 0x%lx"),
dwReturn);
// now we attemp a rollback, if we're here, things are quite bad as it is.
// we'll try to remove shortcuts, remove the service, etc.
// the files will remain on the machine.
TCHAR szUninstallSection[MAX_PATH] = {0};
if( fxocUtil_GetUninstallSection(pszSubcomponentId,szUninstallSection,MAX_PATH)==NO_ERROR)
{
VERBOSE(DBG_MSG,_T("Performing rollback, using section %s."),szUninstallSection);
if (prv_UninstallFax(pszSubcomponentId,szUninstallSection)==NO_ERROR)
{
VERBOSE(DBG_MSG,_T("Rollback (prv_UninstallFax) successful..."));
}
else
{
// not setting dwReturn explicitly to preserve to original cause for failure.
VERBOSE(SETUP_ERR,_T("Rollback (prv_UninstallFax) failed, rc = 0x%lx"),GetLastError());
}
if (prv_CompleteFaxUninstall(pszSubcomponentId,szUninstallSection)==NO_ERROR)
{
VERBOSE(DBG_MSG,_T("Rollback (prv_CompleteFaxUninstall) successful..."));
}
else
{
// not setting dwReturn explicitly to preserve to original cause for failure.
VERBOSE(SETUP_ERR,_T("Rollback (prv_CompleteFaxUninstall) failed, rc = 0x%lx"),GetLastError());
}
}
else
{
// not setting dwReturn explicitly to preserve to original cause for failure.
VERBOSE(SETUP_ERR,_T("fxocUtil_GetUninstallSection failed, rc = 0x%lx"),GetLastError());
}
}
return dwReturn;
} // prv_CompleteFaxInstall
///////////////////////////////
// prv_CompleteFaxUninstall
//
// Called by prv_OnCompleteInstallation
// to uninstall the fax. Since most
// of the work is done before we even
// queue our files to delete, the only
// thing we really do here is remove the
// program group/shortcuts.
//
// Params:
// - pszSubcomponentId
// - pszSectionToProcess
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
static DWORD prv_CompleteFaxUninstall(const TCHAR *pszSubcomponentId,
const TCHAR *pszSectionToProcess)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER( TEXT("prv_CompleteFaxUninstall"),
dwReturn,
TEXT("%s - %s"),
pszSubcomponentId,
pszSectionToProcess);
if ((pszSubcomponentId == NULL) ||
(pszSectionToProcess == NULL))
{
return ERROR_INVALID_PARAMETER;
}
// Uninstall directories
if (dwReturn == NO_ERROR)
{
dwReturn = fxocFile_ProcessDirectories(pszSectionToProcess,INF_KEYWORD_DELDIR);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall directories ")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
// uninstall subsystems in the reverse order they were installed in.
if (dwReturn == NO_ERROR)
{
// notice we ignore the return codes, we will attempt to completely
// uninstall even if something fails to uninstall.
// Remove Program Group/Shortcuts
dwReturn = fxocLink_Uninstall(pszSubcomponentId,
pszSectionToProcess);
}
return dwReturn;
} // prv_CompleteFaxUninstall
///////////////////////////////
// prv_UninstallFax
//
// Uninstalls fax from the user's
// computer. This does everything
// except the program group delete. It
// will remove the fax printer,
// fax service, exchange updates,
// registry, and file deletion.
static DWORD prv_UninstallFax(const TCHAR *pszSubcomponentId,
const TCHAR *pszUninstallSection)
{
DWORD dwReturn = NO_ERROR;
DBG_ENTER( TEXT("prv_UninstallFax"),
dwReturn,
TEXT("%s - %s"),
pszSubcomponentId,
pszUninstallSection);
if ((pszSubcomponentId == NULL) ||
(pszUninstallSection == NULL))
{
return ERROR_INVALID_PARAMETER;
}
// Notice when we uninstall our files, we want to clean up
// everything else first, to ensure that we can successfully
// remove the files.
// Uninstall shares
if (dwReturn == NO_ERROR)
{
dwReturn = fxocFile_ProcessShares(pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall shares ")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
// Uninstall Fax Printer/Monitor support
if (dwReturn == NO_ERROR)
{
dwReturn = fxocPrnt_Uninstall(pszSubcomponentId,
pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall fax printer ")
_T("and monitor. This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
// Uninstall Exchange Support
if (dwReturn == NO_ERROR)
{
fxocMapi_Uninstall(pszSubcomponentId,pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall fax exchange support")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
// we have to tell the status monitor to shut itself down before
// we shut down the service, since it calls FaxUnregisterEvents...
if (dwReturn == NO_ERROR)
{
dwReturn = prv_NotifyStatusMonitor(FAX_SHUTDOWN_TIMER_ID);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to notify Status Monitor.")
_T("This is a non-fatal error, continuing fax install...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
// Notice we uninstall our service first before uninstalling
// the files.
if (dwReturn == NO_ERROR)
{
fxocSvc_Uninstall(pszSubcomponentId,
pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall fax service. ")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
if (dwReturn == NO_ERROR)
{
// Uninstall Registry
fxocReg_Uninstall(pszSubcomponentId,
pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall fax registry. ")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
if (dwReturn == NO_ERROR)
{
// uninstall files
dwReturn = fxocFile_Uninstall(pszSubcomponentId,
pszUninstallSection);
if (dwReturn != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("Failed to uninstall fax files. ")
_T("This is a non-fatal error, ")
_T("continuing with uninstall attempt...rc=0x%lx"),
dwReturn);
dwReturn = NO_ERROR;
}
}
return dwReturn;
}
///////////////////////////////
// prv_OnNotificationFromQueue
//
// Handler for OC_NOTIFICATION_FROM_QUEUE
//
// NOTE: although this notification is defined,
// it is currently unimplemented in oc manager
//
static DWORD prv_OnNotificationFromQueue(void)
{
return NO_ERROR;
}
///////////////////////////////
// prv_OnQueryStepCount
//
// This query by the OC Manager
// determines how many "ticks"
// on the progress bar we would
// like shown.
//
// We only update the progress
// bar during an install (for
// no good reason!). It seems
// that all OC components do this.
//
// Params:
// - pszComponentId
// - pszSubcomponentId
// Returns:
// - NO_ERROR on success
// - error code otherwise.
//
static DWORD prv_OnQueryStepCount(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId)
{
DWORD dwErr = 0;
DWORD dwNumSteps = 0;
BOOL bInstallSelected = FALSE;
BOOL bSelectionStateChanged = FALSE;
DBG_ENTER( TEXT("prv_OnQueryStepCount"),
dwNumSteps,
TEXT("%s - %s"),
pszComponentId,
pszSubcomponentId);
if (!pszSubcomponentId || !*pszSubcomponentId)
{
return ERROR_INVALID_PARAMETER;
}
dwErr = faxocm_HasSelectionStateChanged(pszSubcomponentId,
&bSelectionStateChanged,
&bInstallSelected,
NULL);
if (dwErr != NO_ERROR)
{
VERBOSE(SETUP_ERR,
_T("HasSelectionStateChanged failed, rc = 0x%lx"),
dwErr);
return 0;
}
if (bSelectionStateChanged)
{
if (bInstallSelected)
{
dwNumSteps = prv_TOTAL_NUM_PROGRESS_BAR_TICKS;
}
}
return dwNumSteps;
}
///////////////////////////////
// prv_OnExtraRoutines
//
// OC Manager giving us some
// extra routines. Save them.
//
// Params:
// - pszComponentId
// - pExtraRoutines - pointer to extra OC Manager fns.
// Returns:
// - NO_ERROR on success.
// - error code otherwise
//
static DWORD prv_OnExtraRoutines(LPCTSTR pszComponentId,
EXTRA_ROUTINES *pExtraRoutines)
{
DWORD dwResult = NO_ERROR;
DBG_ENTER( TEXT("prv_OnExtraRoutines"),
dwResult,
TEXT("%s"),
pszComponentId);
if ((pszComponentId == NULL) ||
(pExtraRoutines == NULL))
{
dwResult = ERROR_INVALID_PARAMETER;
return dwResult;
}
memcpy(&prv_GVAR.Component.Extras,
pExtraRoutines,
sizeof(prv_GVAR.Component.Extras));
dwResult = NO_ERROR;
return dwResult;
}
///////////////////////////////
// prv_OnSetLanguage
//
// Handler for OC_SET_LANGUAGE
// the OC Manager is requesting
// we change to the specified language.
// Since there is no GUI, this is not
// an issue.
//
// Params:
// Return:
// - TRUE indicating successfully
// changed language.
//
static DWORD prv_OnSetLanguage(UINT uiLanguageID)
{
// return false; // this is what OCGEN returns
prv_GVAR.Component.uiLanguageID = uiLanguageID;
return TRUE;
}
///////////////////////////////
// prv_OnQueryImage
//
// Handler for OC_QUERY_IMAGE
// this returns the handle to the
// loaded icon for displaying in the
// Add/Remove dialog.
//
// Params:
// Returns:
// - HBITMAP - handle to loaded bitmap
//
static DWORD_PTR prv_OnQueryImage(void)
{
DWORD_PTR dwResult = (DWORD_PTR)INVALID_HANDLE_VALUE;
DBG_ENTER(TEXT("prv_OnQueryImage"));
dwResult = (DWORD_PTR) LoadBitmap(faxocm_GetAppInstance(),
MAKEINTRESOURCE(IDI_FAX_ICON));
return dwResult;
}
///////////////////////////////
// prv_OnSetupRequestPages
//
// Handler for OC_REQUEST_PAGES.
// We don't have a GUI, so we
// return 0 pages.
//
// Params:
// - uiType - specifies a type from the
// WizardPagesType enumerator.
// - Pointer to SETUP_REQUEST_PAGES
// structure.
// Returns:
// - 0, no pages to display
//
//
static DWORD prv_OnSetupRequestPages(
LPCTSTR pszComponentId,
WizardPagesType uiType,
PSETUP_REQUEST_PAGES pSetupRequestPages)
{
DWORD dwReturn = 0;
PROPSHEETPAGE psp = {0};
DBG_ENTER( _T("prv_OnSetupRequestPages"),
dwReturn,
_T("%s - %d"),
pszComponentId,
uiType);
// Don't show pages if it's unattended
if (fxState_IsUnattended())
{
dwReturn = 0;
goto exit;
}
// Only show pages in WizPagesEarly
if (uiType != WizPagesEarly)
{
dwReturn = 0;
goto exit;
}
if (!IsFaxShared())
{
VERBOSE(DBG_MSG, _T("Sharing not supported in this SKU, don't show wizard page"));
dwReturn = 0;
goto exit;
}
if (pSetupRequestPages->MaxPages < 1)
{
dwReturn = 1;
goto exit;
}
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.hInstance = faxocm_GetAppInstance();
psp.pszTemplate = MAKEINTRESOURCE(IDD_OCM_WIZARD_PAGE);
psp.pfnDlgProc = prv_dlgOcmWizardPage;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_WIZARD_PAGE_TITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_WIZARD_PAGE_SUBTITLE);
pSetupRequestPages->Pages[0] = CreatePropertySheetPage(&psp);
if (!pSetupRequestPages->Pages[0])
{
VERBOSE(SETUP_ERR,_T("CreatePropertySheetPage failed, ec=%d"), GetLastError());
dwReturn = 0;
goto exit;
}
dwReturn = 1;
exit:
return dwReturn;
}
///////////////////////////////
// prv_OnWizardCreated
//
// Handler for OC_WIZARD_CREATED
// Do nothing.
//
static DWORD prv_OnWizardCreated(void)
{
return NO_ERROR;
}
///////////////////////////////
// prv_OnQuerySelStateChange
//
// Handle for OC_QUERY_CHANGE_SEL_STATE
// OC Manager is asking us if it is
// okay for the user to select/unselect
// this component from the Add/Remove
// list. We want to allow the user
// to NOT install this as well, so
// always allow the user to change the
// selection state.
//
// Params:
// - pszComponentId
// - pszSubcomponentId
// - uiState - Specifies proposed new selection
// state. 0 => not selected, 1 => selected.
// - uiFlags - Could be OCQ_ACTUAL_SELECTION or 0.
// If it is OCQ_ACTUAL_SELECTION then the user
// actually selected/deselected the pszSubcomponentId.
// If it is 0, it is being turned on or off
// because the parent needs that subcomponent.
//
// Returns:
// - TRUE - allow selection change
//
//
static DWORD prv_OnQuerySelStateChange(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
UINT uiState,
UINT uiFlags)
{
// always allow the user to change the selection state of the component.
return TRUE;
}
///////////////////////////////
// prv_OnQueryState
//
// Handler for OC_QUERY_STATE
// OC Manager is asking us if the
// given subcomponent is installed or
// not. Since the OC Manager keeps a
// record of this for itself, we rely
// on it to keep track of our installed
// state.
//
// Params:
// - pszComponentId
// - pszSubcomponentId
// - uiState - Install state OC Manager thinks we are in.
// Returns:
// - SubcompUseOCManagerDefault - use whatever state
// OC Manager thinks we are in.
//
static DWORD prv_OnQueryState(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId,
UINT uiState)
{
DWORD dwState = SubcompOff;
DBG_ENTER(_T("prv_OnQueryState"));
// szSubComponentID should've been set during OC_INIT_COMPONENT, but
// we don't have it there. So set it here.
_tcsncpy(prv_GVAR.Component.szSubComponentID,
pszComponentId,
ARR_SIZE(prv_GVAR.Component.szSubComponentID));
if (uiState==OCSELSTATETYPE_CURRENT)
{
// when asking about the current state, use the default (either user initiated or from answer file)
dwState = SubcompUseOcManagerDefault;
}
else
{
HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP, FALSE,KEY_READ);
if (hKey)
{
DWORD dwInstalled = 0;
if (GetRegistryDwordEx(hKey,REGVAL_FAXINSTALLED,&dwInstalled)==NO_ERROR)
{
if (dwInstalled)
{
VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' is set, assume component is installed"));
dwState = SubcompOn;
}
else
{
VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' is zero, assume component is not installed"));
}
}
else
{
VERBOSE(DBG_MSG,_T("REG_DWORD 'Installed' does not exist, assume component is not installed"));
}
}
else
{
VERBOSE(DBG_MSG,_T("HKLM\\Software\\Microsoft\\Fax\\Setup does not exist, assume component is not installed"));
}
if (hKey)
{
RegCloseKey(hKey);
}
}
return dwState;
}
///////////////////////////////
// prv_OnNeedMedia
//
// Handler for OC_NEED_MEDIA
// Allows us to fetch our own
// media - for example, from the
// Internet. We don't need anything
// so just move on.
//
// Params:
// Returns:
// - FALSE - don't need any media
//
//
static DWORD prv_OnNeedMedia(void)
{
return FALSE;
}
///////////////////////////////
// prv_OnAboutToCommitQueue
//
// Handler for OC_ABOUT_TO_COMMIT_QUEUE
// Tells us that OC Manager is about
// to commit to queue. We don't really
// care, do nothing.
//
// Params:
// - pszComponentId
// - pszSubcomponentId.
// Returns:
// - NO_ERROR on success.
// - error code otherwise.
//
static DWORD prv_OnAboutToCommitQueue(LPCTSTR pszComponentId,
LPCTSTR pszSubcomponentId)
{
DWORD dwReturn = NO_ERROR;
// don't think we need to do anything here yet.
return dwReturn;
}
///////////////////////////////
// prv_OnQuerySkipPage
//
// Handler for OC_QUERY_SKIP_PAGE
//
// Params:
// Returns:
//
//
static DWORD prv_OnQuerySkipPage(void)
{
return FALSE;
}
///////////////////////////////
// faxocm_HasSelectionStateChanged
//
// This fn tells us if our selection
// state in the Add/Remove programs
// dialog box has changed since it
// was started, and it also tells us
// our current selection state.
//
// Params:
// - pszSubcomponentId
// - pbCurrentSelected - OUT
// - pbOriginallySelected - OUT
// Returns:
// - TRUE if selection state has changed
// - FALSE otherwise.
//
DWORD faxocm_HasSelectionStateChanged(LPCTSTR pszSubcomponentId,
BOOL *pbSelectionStateChanged,
BOOL *pbCurrentlySelected,
BOOL *pbOriginallySelected)
{
DWORD dwReturn = NO_ERROR;
BOOL bCurrentlySelected = FALSE;
BOOL bOriginallySelected = FALSE;
BOOL bSelectionChanged = TRUE;
PQUERYSELECTIONSTATE_ROUTINEW pQuerySelectionState = NULL;
DBG_ENTER( TEXT("faxocm_HasSelectionStateChanged"),
dwReturn,
TEXT("%s"),
pszSubcomponentId);
// if pszSubcomponentId == NULL, we are hosed.
Assert(pszSubcomponentId != NULL);
Assert(pbSelectionStateChanged != NULL);
if ((pszSubcomponentId == NULL) ||
(pbSelectionStateChanged == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER);
return dwReturn=ERROR_INVALID_PARAMETER;
}
pQuerySelectionState = prv_GVAR.Component.Helpers.QuerySelectionState;
if (pQuerySelectionState)
{
// are we currently selected.
bCurrentlySelected = pQuerySelectionState(
prv_GVAR.Component.Helpers.OcManagerContext,
pszSubcomponentId,
OCSELSTATETYPE_CURRENT);
bOriginallySelected = pQuerySelectionState(
prv_GVAR.Component.Helpers.OcManagerContext,
pszSubcomponentId,
OCSELSTATETYPE_ORIGINAL);
if (bOriginallySelected == bCurrentlySelected)
{
bSelectionChanged = FALSE;
}
else
{
bSelectionChanged = TRUE;
}
}
// if we are not in stand alone mode, and we are upgrading the OS, then assume that
// the selection state has changed. We do this because we would like to force an
// install of fax during an upgrade from NT or W2K. Currently (as of 05/02/2000)
// OC Manager reports an upgrade type of WINNT when upgrading from W2K. This is valid
// because fax is always installed in W2K (the user could not uninstall it), and therefore
// whenever we upgrade, bSelectionChanged will always be FALSE, which will prevent
// the new fax from being installed. NOT GOOD. This fixes that.
if ( (fxState_IsStandAlone() == FALSE) &&
((fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_W2K) ||
(fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_REPAIR) ||
(fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_XP_DOT_NET)))
{
if (bOriginallySelected && bCurrentlySelected)
{
// only if Fax was installed and is now marked for installation during OS upgrade
// we force re-installation.
// If both were false, this can't return true because it'll cause an uninstall
// going and we'll try to uninstall a non existing Fax.
// This happens when upgrading XP build without Fax to another.
// This causes many setup error (in setupapi logs) and disturbes setup people.
// this condition takes care of this problem.
bSelectionChanged = TRUE;
}
}
if (pbCurrentlySelected)
{
*pbCurrentlySelected = bCurrentlySelected;
}
if (pbOriginallySelected)
{
*pbOriginallySelected = bOriginallySelected;
}
*pbSelectionStateChanged = bSelectionChanged;
return dwReturn;
}
///////////////////////////////
// prv_NotifyStatusMonitor
//
// This function notifies the shell
// to load FXSST.DLL (Status Monitor)
// It is done by sending a private message
// to STOBJECT.DLL window.
//
//
// Params:
// - WPARAM wParam -
// either FAX_STARTUP_TIMER_ID or
// FAX_SHUTDOWN_TIMER_ID
//
// Returns:
// - NO_ERROR if notification succeeded
// - Win32 Error code otherwise.
//
static DWORD prv_NotifyStatusMonitor(WPARAM wParam)
{
DWORD dwRet = NO_ERROR;
HWND hWnd = NULL;
DBG_ENTER(TEXT("prv_NotifyStatusMonitor"),dwRet);
// We need to send a WM_TIMER to a window identified by the class name SYSTRAY_CLASSNAME
// The timer ID should be FAX_STARTUP_TIMER_ID
hWnd = FindWindow(SYSTRAY_CLASSNAME,NULL);
if (hWnd==NULL)
{
dwRet = GetLastError();
CALL_FAIL(SETUP_ERR,TEXT("FindWindow"),dwRet);
goto exit;
}
SendMessage(hWnd,WM_TIMER,wParam,0);
exit:
return dwRet;
}
static INT_PTR CALLBACK prv_dlgWhereDidMyFaxGoQuestion
(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine name : prv_dlgWhereDidMyFaxGoQuestion
Routine description:
Dialogs procedure for "Where did my fax go" dialog
Author:
Mooly Beery (MoolyB), Mar, 2001
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_dlgWhereDidMyFaxGoQuestion"));
switch (uMsg)
{
case WM_INITDIALOG:
SetFocus(hwndDlg);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
if (BST_CHECKED == ::SendMessage (::GetDlgItem (hwndDlg, IDC_REMOVE_LINK), BM_GETCHECK, 0, 0))
{
// we should remove the link.
// we do this by processing our INF in the section that deals
// with this link. This way we're sure it can be localized at will
// and we'll always remove the correct link.
TCHAR szInfFileName[2*MAX_PATH] = {0};
if (faxocm_GetComponentInfName(szInfFileName))
{
_tcscat(szInfFileName,_T(",Fax.UnInstall.PerUser.WhereDidMyFaxGo"));
if (LPSTR pszInfCommandLine = UnicodeStringToAnsiString(szInfFileName))
{
LaunchINFSection(hwndDlg,prv_GVAR.hInstance,pszInfCommandLine,1);
MemFree(pszInfCommandLine);
}
}
}
EndDialog (hwndDlg, iRes);
return TRUE;
}
break;
}
return FALSE;
} // prv_dlgWhereDidMyFaxGoQuestion
///////////////////////////////////////////////////////////////////////////////////////
// Function:
// WhereDidMyFaxGo
//
// Purpose:
// When a machine running SBS5.0 client was upgraded to Windows-XP
// We show a link called 'Where did my Fax go' in the start menu
// at the same location where the SBS5.0 shortcuts used to be.
// When clicking this link it calls this function that raises
// a dialog to explain to the user where the Windows-XP Fax's
// shortcuts are, and asks the user whether to delete this link.
//
// Params:
// None
//
// Return Value:
// NO_ERROR - in case of success
// Win32 Error code otherwise
//
// Author:
// Mooly Beery (MoolyB) 17-Jan-2001
///////////////////////////////////////////////////////////////////////////////////////
DWORD WhereDidMyFaxGo(void)
{
DWORD dwRet = NO_ERROR;
DBG_ENTER(TEXT("WhereDidMyFaxGo"),dwRet);
HMODULE hFaxRes = LoadLibraryEx(FAX_RES_FILE, NULL, LOAD_LIBRARY_AS_DATAFILE);
if(!hFaxRes)
{
dwRet = GetLastError();
CALL_FAIL (RESOURCE_ERR, TEXT("LoadLibraryEx(FxsRes.dll)"), dwRet);
return dwRet;
}
INT_PTR iResult = DialogBox (hFaxRes,
MAKEINTRESOURCE(IDD_WHERE_DID_MY_FAX_GO),
NULL,
prv_dlgWhereDidMyFaxGoQuestion);
if (iResult==-1)
{
dwRet = GetLastError();
CALL_FAIL (RESOURCE_ERR, TEXT("DialogBox(IDD_WHERE_DID_MY_FAX_GO)"), dwRet);
}
FreeLibrary(hFaxRes);
return dwRet;
}
DWORD prv_ShowUninstalledFaxShortcut(void)
/*++
Routine name : prv_ShowUninstalledFaxShortcut
Routine description:
Show Shortcut of "Where Did My Fax Go ? " in the All Programs.
Author:
Iv Garber (IvG), Jun, 2001
Return Value:
Standard Win32 error code
--*/
{
DBG_ENTER(_T("prv_ShowUninstalledFaxShortcut"));
//
// In cases we upgraded from a machine running SBS2000 Client/Server or XP Client and we want to
// add a 'Where did my Fax go' shortcut.
// we want to add it to the current user as well as every user.
//
if (fxocUpg_GetUpgradeApp() != FXSTATE_NONE)
{
//
// first add the shortcut to the current user.
//
TCHAR szInfFileName[2*MAX_PATH] = {0};
if (faxocm_GetComponentInfName(szInfFileName))
{
_tcscat(szInfFileName,_T(",Fax.Install.PerUser.AppUpgrade"));
if (LPSTR pszInfCommandLine = UnicodeStringToAnsiString(szInfFileName))
{
LaunchINFSection(NULL,prv_GVAR.hInstance,pszInfCommandLine,1);
MemFree(pszInfCommandLine);
}
}
else
{
CALL_FAIL(SETUP_ERR,TEXT("faxocm_GetComponentInfName"),GetLastError());
}
//
// now change the PerUserStub to point to the section that creates the link for every user.
//
HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_ACTIVE_SETUP_NT, FALSE,KEY_ALL_ACCESS);
if (hKey)
{
if (LPTSTR lptstrPerUser = GetRegistryString(hKey,_T("StubPath"),NULL))
{
TCHAR szLocalPerUserStub[MAX_PATH*2] = {0};
_tcscpy(szLocalPerUserStub,lptstrPerUser);
_tcscat(szLocalPerUserStub,REGVAL_ACTIVE_SETUP_PER_USER_APP_UPGRADE);
if (!SetRegistryString(hKey,_T("StubPath"),szLocalPerUserStub))
{
CALL_FAIL(SETUP_ERR,TEXT("SetRegistryString"),GetLastError());
}
MemFree(lptstrPerUser);
}
else
{
CALL_FAIL(SETUP_ERR,TEXT("GetRegistryString"),GetLastError());
}
RegCloseKey(hKey);
}
else
{
CALL_FAIL(SETUP_ERR,TEXT("OpenRegistryKey"),GetLastError());
}
}
return NO_ERROR;
}
BOOL prv_ShouldShowPage()
/*++
Routine name : prv_ShouldShowPage
Routine description: Checks whether the OCM wizard page should be shown
Author: Jonathan Barner (jobarner), May 2002
Arguments: none
Return value: TRUE - show, FALSE - don't show
--*/
{
BOOL bSelectionStateChanged = FALSE;
BOOL bInstallSelected = FALSE;
if (faxocm_HasSelectionStateChanged(prv_GVAR.Component.szSubComponentID,
&bSelectionStateChanged,
&bInstallSelected,
NULL) != NO_ERROR)
{
return FALSE;
}
return (bSelectionStateChanged && bInstallSelected);
}
static INT_PTR CALLBACK prv_dlgOcmWizardPage(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
/*++
Routine name : prv_dlgOcmWizardPage
Routine description: Dialog procedure for OCM Wizard page dialog
Author: Jonathan Barner (jobarner), May 2002
Arguments and return values: Standard dialog return value
--*/
{
switch (uMsg)
{
case WM_INITDIALOG:
// Set default to "do not share printer"
CheckRadioButton(hwndDlg, IDC_SHARE_PRINTER, IDC_DO_NOT_SHARE_PRINTER,
IDC_DO_NOT_SHARE_PRINTER);
break;
case WM_NOTIFY:
switch(((NMHDR FAR*)lParam)->code)
{
case PSN_SETACTIVE:
{
LONG_PTR lReturn = prv_ShouldShowPage() ? 0 : -1;
if (lReturn == 0)
{
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
}
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, lReturn);
return TRUE;
}
break;
case PSN_WIZNEXT:
BOOL fShouldShare = (IsDlgButtonChecked(hwndDlg, IDC_SHARE_PRINTER) == BST_CHECKED);
fxocPrnt_SetFaxPrinterShared(fShouldShare);
break;
}
break;
}
return FALSE;
} // prv_dlgOcmWizardPage
LPCTSTR lplpszFaxFolder[][2] = {
{FAX_QUEUE_DIR, SD_FAX_FOLDERS},
{FAX_INBOX_DIR, SD_FAX_FOLDERS},
{FAX_SENTITEMS_DIR, SD_FAX_FOLDERS},
{FAX_ACTIVITYLOG_DIR, SD_FAX_FOLDERS},
{FAX_COMMONCOVERPAGES_DIR, SD_COMMON_COVERPAGES}};
/*++
Routine description:
Sets security info on Fax directories under "Documents and settings" tree
Arguments:
lpszCommonAppData [in] - name of Common App directory, for example
C:\Documents and Settings\All Users\Application Data
Return Value: Win32 Error code
Notes:
This function is called after converting the file system from FAT to NTFS
(during the call to SecureUserProfiles()).
The security of folders under system32 are handled by convert.exe itself.
Written by: jobarner, 08/2002
--*/
HRESULT SecureFaxServiceDirectories(LPCTSTR lpszCommonAppData)
{
DWORD dwRet;
DWORD ec = ERROR_SUCCESS;
BOOL bFaxInstalled = FALSE;
TCHAR szDir[MAX_PATH] = {'\0'};
int iResult;
int i;
DBG_ENTER( _T("SecureFaxServiceDirectories"), ec);
ec = IsFaxInstalled (&bFaxInstalled);
if (ec!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), ec);
return ec;
}
if (!bFaxInstalled)
{
VERBOSE(DBG_MSG, _T("Fax is not installed, quitting"));
return ERROR_SUCCESS;
}
for (i=0; i<ARR_SIZE(lplpszFaxFolder); i++)
{
iResult = _sntprintf(szDir,
ARR_SIZE(szDir) -1,
TEXT("%s\\%s"),
lpszCommonAppData,
lplpszFaxFolder[i][0]);
if (iResult<0)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
ec = ERROR_INSUFFICIENT_BUFFER;
}
else
{
dwRet = SetDirSecurity(szDir, lplpszFaxFolder[i][1]);
if (dwRet!=ERROR_SUCCESS)
{
VERBOSE(DBG_WARNING, _T("SetDirSecurity() failed, ec = %ld."), dwRet);
ec = dwRet;
}
}
}
return ec;
}