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.
 
 
 
 
 
 

3035 lines
83 KiB

//=--------------------------------------------------------------------------=
// inseng.cpp
//=--------------------------------------------------------------------------=
// Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
//
//
#include "asctlpch.h"
#include "ipserver.h"
#include <wininet.h>
#include "util.h"
#include "globals.h"
#include "asinsctl.h"
#include "dispids.h"
#include "resource.h"
#include "util2.h"
#include <mshtml.h>
// for ASSERT and FAIL
//
SZTHISFILE
WCHAR wszInsFile [] = L"InstallList";
WCHAR wszBaseUrl [] = L"BaseUrl";
WCHAR wszCabName [] = L"CabName";
#define EVENT_ONSTARTINSTALL 0
#define EVENT_ONSTARTCOMPONENT 1
#define EVENT_ONSTOPCOMPONENT 2
#define EVENT_ONSTOPINSTALL 3
#define EVENT_ONENGINESTATUSCHANGE 4
#define EVENT_ONENGINEPROBLEM 5
#define EVENT_ONCHECKFREESPACE 6
#define EVENT_ONCOMPONENTPROGRESS 7
#define EVENT_ONSTARTINSTALLEX 8
#define EVENT_CANCEL 10
static VARTYPE rgI4[] = { VT_I4 };
static VARTYPE rgI4_2[] = { VT_I4, VT_I4 };
static VARTYPE rgStartComponent[] = { VT_BSTR, VT_I4, VT_BSTR };
static VARTYPE rgStopComponent[] = { VT_BSTR, VT_I4, VT_I4, VT_BSTR, VT_I4 };
static VARTYPE rgStopInstall[] = { VT_I4, VT_BSTR, VT_I4 };
static VARTYPE rgEngineProblem[] = { VT_I4 };
static VARTYPE rgCheckFreeSpace[] = { VT_BSTR, VT_I4, VT_BSTR, VT_I4, VT_BSTR, VT_I4 };
static VARTYPE rgComponentProgress[] = { VT_BSTR, VT_I4, VT_BSTR, VT_BSTR, VT_I4, VT_I4 };
#define WM_INSENGCALLBACK WM_USER+34
static EVENTINFO rgEvents [] = {
{ DISPID_ONSTARTINSTALL, 1, rgI4 }, // (long percentDone)
{ DISPID_ONSTARTCOMPONENT, 3, rgStartComponent },
{ DISPID_ONSTOPCOMPONENT, 5, rgStopComponent },
{ DISPID_ONSTOPINSTALL, 3, rgStopInstall },
{ DISPID_ENGINESTATUSCHANGE, 2, rgI4_2 },
{ DISPID_ONENGINEPROBLEM, 1, rgEngineProblem },
{ DISPID_ONCHECKFREESPACE, 6, rgCheckFreeSpace },
{ DISPID_ONCOMPONENTPROGRESS, 6, rgComponentProgress },
{ DISPID_ONSTARTINSTALLEX, 2, rgI4_2 },
};
UINT g_uCDAutorunMsg;
unsigned long g_ulOldAutorunSetting;
const char g_cszIEJITInfo[] = "Software\\Microsoft\\Active Setup\\JITInfo";
const char g_cszPolicyExplorer[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
const char g_cszAutorunSetting[] = "NoDriveTypeAutoRun";
//=---------------------------------------------
// SetAutorunSetting
//=---------------------------------------------
unsigned long SetAutorunSetting(unsigned long ulValue)
{
HKEY hKey;
unsigned long ulOldSetting;
unsigned long ulNewSetting = ulValue;
DWORD dwSize = sizeof(unsigned long);
if( RegOpenKeyEx(HKEY_CURRENT_USER, g_cszPolicyExplorer , 0, KEY_READ|KEY_WRITE, &hKey ) == ERROR_SUCCESS )
{
if( RegQueryValueEx(hKey, g_cszAutorunSetting, 0, NULL, (unsigned char*)&ulOldSetting, &dwSize ) == ERROR_SUCCESS )
{
RegSetValueEx(hKey, g_cszAutorunSetting, 0, REG_BINARY, (const unsigned char*)&ulNewSetting, 4);
}
else
ulOldSetting = WINDOWS_DEFAULT_AUTOPLAY_VALUE;
RegFlushKey( hKey );
RegCloseKey( hKey );
}
return ulOldSetting;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::Create
//=--------------------------------------------------------------------------=
// global static function that creates an instance of the control an returns
// an IUnknown pointer for it.
//
// Parameters:
// IUnknown * - [in] controlling unknown for aggregation
//
// Output:
// IUnknown * - new object.
//
// Notes:
//
IUnknown *CInstallEngineCtl::Create(IUnknown *pUnkOuter)
{
// make sure we return the private unknown so that we support aggegation
// correctly!
//
BOOL bSuccess;
CInstallEngineCtl *pNew = new CInstallEngineCtl(pUnkOuter, &bSuccess);
if(bSuccess)
return pNew->PrivateUnknown();
else
{
delete pNew;
return NULL;
}
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::CInstallEngineCtl
//=--------------------------------------------------------------------------=
//
// Parameters:
// IUnknown * - [in]
//
// Notes:
//
#pragma warning(disable:4355) // using 'this' in constructor, safe here
CInstallEngineCtl::CInstallEngineCtl(IUnknown *pUnkOuter, BOOL *pbSuccess)
: COleControl(pUnkOuter, OBJECT_INSTALLENGINECTL, (IDispatch *)this)
{
HRESULT hr;
DWORD dwVersion = 0;
*pbSuccess = TRUE;
_hIcon = NULL;
// null out all base urls
ZeroMemory( _rpszUrlList, sizeof(LPSTR) * MAX_URLS);
_uCurrentUrl = 0;
_pProgDlg = NULL;
_pinseng = NULL;
_pszErrorString = NULL;
_hDone = NULL;
_hResult = NOERROR;
m_readyState = READYSTATE_COMPLETE;
_uAllowGrovel = 0xffffffff;
_fNeedReboot = FALSE;
_szDownloadDir[0] = 0;
_fEventToFire = FALSE;
_dwSavedEngineStatus = 0;
_dwSavedSubStatus = 0;
_dwFreezeEvents = 0;
_dwProcessComponentsFlags = 0;
_dwMSTrustKey = (DWORD)-1;
_uCurrentUrl = 0xffffffff;
_fReconcileCif = FALSE;
_fLocalCifSet = FALSE;
_fDoingIEInstall = FALSE;
_uInstallMode = 0;
_uInstallPad = 0;
_strCurrentID = NULL;
_strCurrentName = NULL;
_strCurrentString = NULL;
_fInstalling = FALSE;
_bCancelPending = FALSE;
_bDeleteURLList = FALSE;
_bNewWebSites = FALSE;
_fJITInstall = FALSE;
// Register for the special CD Autorun message.
g_uCDAutorunMsg = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
hr = CoCreateInstance(CLSID_InstallEngine, NULL, CLSCTX_INPROC_SERVER,
IID_IInstallEngine2,(void **) &_pinseng);
if(_pinseng)
{
_pinseng->SetDownloadDir(NULL);
_pinseng->SetInstallOptions(INSTALLOPTIONS_DOWNLOAD |
INSTALLOPTIONS_INSTALL |
INSTALLOPTIONS_DONTALLOWXPLATFORM);
_pinseng->SetHWND(GetActiveWindow());
_pinseng->RegisterInstallEngineCallback((IInstallEngineCallback *)this);
}
else
*pbSuccess = FALSE;
_dwLastPhase = 0xffffffff;
// set up our initial size ... + 6 so we can have raised edge
m_Size.cx = 6 + GetSystemMetrics(SM_CXICON);
m_Size.cy = 6 + GetSystemMetrics(SM_CYICON);
#ifdef TESTCERT
UpdateTrustState();
#endif
SetControlFont();
}
#pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::~CInstallEngineCtl
//=--------------------------------------------------------------------------=
//
// Notes:
//
CInstallEngineCtl::~CInstallEngineCtl()
{
if(_pinseng)
{
_pinseng->SetHWND(NULL);
_pinseng->UnregisterInstallEngineCallback();
_pinseng->Release();
}
for(int i = 0; i < MAX_URLS; i++)
if(_rpszUrlList[i])
delete _rpszUrlList[i];
// Is all this needed? Only in case where OnStopInstall is never called...
if(_pProgDlg)
delete _pProgDlg;
if(_pszErrorString)
free(_pszErrorString);
if (_dwMSTrustKey != (DWORD)-1)
WriteMSTrustKey(FALSE, _dwMSTrustKey);
#ifdef TESTCERT
ResetTestrootCertInTrustState();
#endif
// delete ActiveSetup value from IE4\Options
WriteActiveSetupValue(FALSE);
if (g_hFont)
{
DeleteObject(g_hFont);
g_hFont = NULL;
}
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl:RegisterClassData
//=--------------------------------------------------------------------------=
// register the window class information for your control here.
// this information will automatically get cleaned up for you on DLL shutdown.
//
// Output:
// BOOL - FALSE means fatal error.
//
// Notes:
//
BOOL CInstallEngineCtl::RegisterClassData()
{
WNDCLASS wndclass;
// TODO: register any additional information you find interesting here.
// this method is only called once for each type of control
//
memset(&wndclass, 0, sizeof(WNDCLASS));
wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
wndclass.lpfnWndProc = COleControl::ControlWindowProc;
wndclass.hInstance = g_hInstance;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wndclass.lpszClassName = WNDCLASSNAMEOFCONTROL(OBJECT_INSTALLENGINECTL);
return RegisterClass(&wndclass);
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::BeforeCreateWindow
//=--------------------------------------------------------------------------=
// called just before the window is created. Great place to set up the
// window title, etc, so that they're passed in to the call to CreateWindowEx.
// speeds things up slightly.
//
// Notes:
//
void CInstallEngineCtl::BeforeCreateWindow()
{
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
BOOL CInstallEngineCtl::AfterCreateWindow()
{
MarkJITInstall();
return TRUE;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::InternalQueryInterface
//=--------------------------------------------------------------------------=
// qi for things only we support.
//
// Parameters:
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CInstallEngineCtl::InternalQueryInterface(REFIID riid, void **ppvObjOut)
{
IUnknown *pUnk;
*ppvObjOut = NULL;
// TODO: if you want to support any additional interrfaces, then you should
// indicate that here. never forget to call COleControl's version in the
// case where you don't support the given interface.
//
if (DO_GUIDS_MATCH(riid, IID_IInstallEngine)) {
pUnk = (IUnknown *)(IInstallEngine *)this;
} else{
return COleControl::InternalQueryInterface(riid, ppvObjOut);
}
pUnk->AddRef();
*ppvObjOut = (void *)pUnk;
return S_OK;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::LoadTextState
//=--------------------------------------------------------------------------=
// load in our text state for this control.
//
// Parameters:
// IPropertyBag * - [in] property bag to read from
// IErrorLog * - [in] errorlog object to use with proeprty bag
//
// Output:
// HRESULT
//
// Notes:
// - NOTE: if you have a binary object, then you should pass an unknown
// pointer to the property bag, and it will QI it for IPersistStream, and
// get said object to do a Load()
//
STDMETHODIMP CInstallEngineCtl::LoadTextState(IPropertyBag *pPropertyBag, IErrorLog *pErrorLog)
{
VARIANT v;
VARIANT v2;
HRESULT hr;
VariantInit(&v);
v.vt = VT_BSTR;
v.bstrVal = NULL;
VariantInit(&v2);
v2.vt = VT_BSTR;
v2.bstrVal = NULL;
// try to load in the property. if we can't get it, then leave
// things at their default.
//
v.vt = VT_BSTR;
v.bstrVal = NULL;
hr = pPropertyBag->Read(::wszBaseUrl, &v, pErrorLog);
if(SUCCEEDED(hr))
hr = put_BaseUrl(v.bstrVal);
VariantClear(&v);
//
// IMPORTANT: Trident no longer defaults to VT_BSTR if no variant type is specified
//
v.vt = VT_BSTR;
v.bstrVal = NULL;
hr = pPropertyBag->Read(::wszCabName, &v, pErrorLog);
if(SUCCEEDED(hr))
hr = pPropertyBag->Read(::wszInsFile, &v2, pErrorLog);
if(SUCCEEDED(hr))
{
hr = SetCifFile(v.bstrVal, v2.bstrVal);
}
VariantClear(&v);
VariantClear(&v2);
return S_OK;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::LoadBinaryState
//=--------------------------------------------------------------------------=
// loads in our binary state using streams.
//
// Parameters:
// IStream * - [in] stream to write to.
//
// Output:
// HRESULT
//
// Notes:
//
const DWORD STREAMHDR_MAGIC = 12345678L;
STDMETHODIMP CInstallEngineCtl::LoadBinaryState(IStream *pStream)
{
DWORD sh;
HRESULT hr;
// first read in the streamhdr, and make sure we like what we're getting
//
hr = pStream->Read(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// sanity check
//
if (sh != STREAMHDR_MAGIC )
return E_UNEXPECTED;
return(S_OK);
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::SaveTextState
//=--------------------------------------------------------------------------=
// saves out the text state for this control using a property bag.
//
// Parameters:
// IPropertyBag * - [in] the property bag with which to work.
// BOOL - [in] if TRUE, then write out ALL properties, even
// if they're their the default value ...
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::SaveTextState(IPropertyBag *pPropertyBag, BOOL fWriteDefaults)
{
return S_OK;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::SaveBinaryState
//=--------------------------------------------------------------------------=
// save out the binary state for this control, using the given IStream object.
//
// Parameters:
// IStream * - [in] save to which you should save.
//
// Output:
// HRESULT
//
// Notes:
// - it is important that you seek to the end of where you saved your
// properties when you're done with the IStream.
//
STDMETHODIMP CInstallEngineCtl::SaveBinaryState(IStream *pStream)
{
DWORD sh = STREAMHDR_MAGIC;
HRESULT hr;
// write out the stream hdr.
//
hr = pStream->Write(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// write out he control state information
//
return hr;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::OnDraw
//=--------------------------------------------------------------------------=
//
// Parameters:
// DWORD - [in] drawing aspect
// HDC - [in] HDC to draw to
// LPCRECTL - [in] rect we're drawing to
// LPCRECTL - [in] window extent and origin for meta-files
// HDC - [in] HIC for target device
// BOOL - [in] can we optimize dc handling?
//
// Output:
// HRESULT
//
// Notes:
//
HRESULT CInstallEngineCtl::OnDraw(DWORD dvAspect, HDC hdcDraw, LPCRECTL prcBounds,
LPCRECTL prcWBounds, HDC hicTargetDevice, BOOL fOptimize)
{
// To provide visual appearence in DESIGN MODE only
if(DesignMode())
{
if(!_hIcon)
_hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_INSTALLENGINE));
DrawEdge(hdcDraw, (LPRECT)(LPCRECT)prcBounds, EDGE_RAISED, BF_RECT | BF_MIDDLE);
if(_hIcon)
DrawIcon(hdcDraw, prcBounds->left + 3, prcBounds->top + 3, _hIcon);
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CInstallEngineCtl::WindowProc
//=--------------------------------------------------------------------------=
// window procedure for this control. nothing terribly exciting.
//
// Parameters:
// see win32sdk on window procs.
//
// Notes:
//
typedef HRESULT (WINAPI *CHECKFORVERSIONCONFLICT) ();
LRESULT CInstallEngineCtl::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
// TODO: handle any messages here, like in a normal window
// proc. note that for special keys, you'll want to override and
// implement OnSpecialKey.
//
LRESULT lres;
CALLBACK_PARAMS *pcbp;
switch (msg)
{
case WM_ERASEBKGND:
if (KeepTransparent(m_hwnd, msg, wParam, lParam, &lres))
return lres;
break;
case WM_ACTIVATE:
case WM_ACTIVATEAPP:
{
DWORD fActive = LOWORD(wParam);
if(fActive == WA_ACTIVE || fActive == WA_CLICKACTIVE ||
fActive == TRUE)
{
CHECKFORVERSIONCONFLICT pVerCon;
HINSTANCE hInseng= LoadLibrary("inseng.dll");
if(hInseng)
{
pVerCon = (CHECKFORVERSIONCONFLICT)
GetProcAddress(hInseng, "CheckForVersionConflict");
if(pVerCon)
pVerCon();
FreeLibrary(hInseng);
}
}
}
return TRUE;
case WM_INSENGCALLBACK:
pcbp = (CALLBACK_PARAMS *) lParam;
switch(wParam)
{
case EVENT_ONENGINESTATUSCHANGE:
FireEvent( &::rgEvents[EVENT_ONENGINESTATUSCHANGE],
pcbp->dwStatus, pcbp->dwSubstatus );
break;
case EVENT_ONSTARTINSTALL:
FireEvent(&::rgEvents[EVENT_ONSTARTINSTALL], (long) pcbp->dwSize);
break;
case EVENT_ONSTARTCOMPONENT:
FireEvent(&::rgEvents[EVENT_ONSTARTCOMPONENT],
pcbp->strID, (long) pcbp->dwSize, pcbp->strName);
break;
case EVENT_ONSTOPCOMPONENT:
FireEvent(&::rgEvents[EVENT_ONSTOPCOMPONENT], pcbp->strID, (long) pcbp->dwResult,
(long) pcbp->dwPhase, pcbp->strName, (long) pcbp->dwStatus);
break;
case EVENT_ONSTOPINSTALL:
FireEvent(&::rgEvents[EVENT_ONSTOPINSTALL], (long) pcbp->dwResult,
pcbp->strString, (long) pcbp->dwStatus);
break;
case EVENT_ONENGINEPROBLEM:
FireEvent(&::rgEvents[EVENT_ONENGINEPROBLEM], (long) pcbp->dwStatus);
break;
case EVENT_ONCHECKFREESPACE:
FireEvent(&::rgEvents[EVENT_ONCHECKFREESPACE], pcbp->chWin,
(long) pcbp->dwWin, pcbp->chInstall,
(long) pcbp->dwInstall, pcbp->chDL, (long) pcbp->dwDL);
break;
case EVENT_ONCOMPONENTPROGRESS:
FireEvent(&::rgEvents[EVENT_ONCOMPONENTPROGRESS], pcbp->strID,
(long) pcbp->dwPhase, pcbp->strName, pcbp->strString,
(long)pcbp->dwDL, (long) pcbp->dwSize);
break;
case EVENT_CANCEL:
Abort(0);
break;
case EVENT_ONSTARTINSTALLEX:
FireEvent(&::rgEvents[EVENT_ONSTARTINSTALLEX], (long) pcbp->dwDL, (long) pcbp->dwSize);
break;
default:
break;
}
break;
default:
break;
}
return OcxDefWindowProc(msg, wParam, lParam);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
STDMETHODIMP CInstallEngineCtl::FreezeEvents(BOOL bFreeze)
{
if(bFreeze)
_dwFreezeEvents++;
else
{
if(_dwFreezeEvents)
{
_dwFreezeEvents--;
// if we go to zero, fire our EngineStatus change event if we have one
if(_dwFreezeEvents == 0 && _fEventToFire)
{
_FireEngineStatusChange(_dwSavedEngineStatus, _dwSavedSubStatus);
_fEventToFire = FALSE;
}
}
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::get_EngineStatus(long * theenginestatus)
{
if(!_pinseng)
return E_UNEXPECTED;
return _pinseng->GetEngineStatus((DWORD *)theenginestatus);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::get_ReadyState(long * thestate)
{
CHECK_POINTER(thestate);
*thestate = m_readyState;
return(NOERROR);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::Abort(long lFlag)
{
if(!_pinseng)
{
_bCancelPending = TRUE;
return E_UNEXPECTED;
}
if ( _pinseng->Abort(lFlag) != NOERROR )
_bCancelPending = TRUE;
return NOERROR;
}
void CInstallEngineCtl::_FireCancel(DWORD dwStatus)
{
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_CANCEL, NULL);
}
STDMETHODIMP CInstallEngineCtl::SetLocalCif(BSTR strCif, long FAR* lResult)
{
*lResult = E_FAIL;
//Allow SetLocalCif only for local cif file. See windows# 541710 and winseraid #24036
if (strCif[1] == L'\\')
return E_ACCESSDENIED;
if(!_pinseng)
return E_UNEXPECTED;
MAKE_ANSIPTR_FROMWIDE(pszCif, strCif);
*lResult = _pinseng->SetLocalCif(pszCif);
if(SUCCEEDED(*lResult))
_fLocalCifSet = TRUE;
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::SetCifFile(BSTR strCabName, BSTR strCifName)
{
HRESULT hr;
if(!_pinseng)
return E_UNEXPECTED;
MAKE_ANSIPTR_FROMWIDE(pszCabName, strCabName);
MAKE_ANSIPTR_FROMWIDE(pszCifName, strCifName);
if(_fLocalCifSet)
{
// if we are using a local cif, we won't get the new cif right away
_fReconcileCif = TRUE;
lstrcpyn(_szCifCab, pszCabName, sizeof(_szCifCab));
lstrcpyn(_szCifFile, pszCifName, sizeof(_szCifFile));
hr = S_OK;
}
else
{
// If we did not check yet, do it.
if (_dwMSTrustKey == (DWORD)-1)
{
_dwMSTrustKey = MsTrustKeyCheck();
// If MS is not a trusted provider.
// Make it for the duration of the install
if (_dwMSTrustKey != 0)
WriteMSTrustKey(TRUE, _dwMSTrustKey);
}
hr = _pinseng->SetCifFile(pszCabName, pszCifName);
}
return hr;
}
#define IE_KEY "Software\\Microsoft\\Internet Explorer"
#define VERSION_KEY "Version"
LONG CInstallEngineCtl::_OpenJITKey(HKEY *phKey, REGSAM samAttr)
{
char szTemp[MAX_PATH];
WORD rdwVer[4] = { 0 };
HKEY hIE;
DWORD dwDumb;
DWORD dwVer;
if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, IE_KEY, 0, KEY_READ, &hIE) == ERROR_SUCCESS)
{
dwDumb = sizeof(szTemp);
if(RegQueryValueEx(hIE, VERSION_KEY, 0, NULL, (LPBYTE)szTemp, &dwDumb) == ERROR_SUCCESS)
{
ConvertVersionString(szTemp, rdwVer, '.');
}
RegCloseKey(hIE);
}
dwVer = rdwVer[0];
wsprintf(szTemp, "%s\\%d", g_cszIEJITInfo, dwVer);
return(RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0, samAttr, phKey));
}
void CInstallEngineCtl::_DeleteURLList()
{
HKEY hJITKey;
if ( _OpenJITKey(&hJITKey, KEY_READ) == ERROR_SUCCESS )
{
RegDeleteKey(hJITKey, "URLList");
RegCloseKey(hJITKey);
}
}
void CInstallEngineCtl::_WriteURLList()
{
HKEY hJITKey;
HKEY hUrlKey;
char cNull = '\0';
if ( _OpenJITKey(&hJITKey, KEY_READ) == ERROR_SUCCESS )
{
if (RegCreateKeyEx(hJITKey, "URLList", 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hUrlKey, NULL) == ERROR_SUCCESS)
{
for(UINT i=0; i < MAX_URLS; i++)
{
if ( _rpszUrlList[i] )
{
RegSetValueEx(hUrlKey, _rpszUrlList[i], 0, REG_SZ, (const unsigned char *) &cNull, sizeof(cNull));
}
}
RegCloseKey(hUrlKey);
}
RegCloseKey(hJITKey);
}
}
void CInstallEngineCtl::_WriteRegionToReg(LPSTR szRegion)
{
HKEY hJITKey;
if (_OpenJITKey(&hJITKey, KEY_WRITE) == ERROR_SUCCESS)
{
RegSetValueEx(hJITKey, "DownloadSiteRegion", 0, REG_SZ, (const unsigned char *) szRegion, strlen(szRegion)+1);
RegCloseKey(hJITKey);
}
}
STDMETHODIMP CInstallEngineCtl::SetSitesFile(BSTR strUrl, BSTR strRegion, BSTR strLocale, long FAR* lResult)
{
char szBuf[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
HKEY hKey;
HKEY hUrlKey;
UINT uUrlNum = 0;
HRESULT hr = E_FAIL;
MAKE_ANSIPTR_FROMWIDE(pszUrl, strUrl);
MAKE_ANSIPTR_FROMWIDE(pszRegion, strRegion);
MAKE_ANSIPTR_FROMWIDE(pszLocale, strLocale);
// first check to see if we should use local stuff
if(pszUrl[0] == 0)
{
_fDoingIEInstall = TRUE;
// find the ie major version, add it to JIT key
if(_OpenJITKey(&hKey, KEY_READ) == ERROR_SUCCESS)
{
dwSize = sizeof(_uInstallMode);
RegQueryValueEx(hKey, "InstallType", NULL, NULL, (BYTE *) &_uInstallMode, &dwSize);
/*
if(_uInstallMode == WEBINSTALL)
{
if(RegOpenKeyEx(hKey, "URLList", 0, KEY_READ, &hUrlKey) == ERROR_SUCCESS)
{
// need to read out urls and put them in rpszUrlList
for(int i = 0; uUrlNum < MAX_URLS; i++)
{
dwSize = sizeof(szBuf);
if(RegEnumValue(hUrlKey, i, szBuf, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
_rpszUrlList[uUrlNum] = new char[dwSize + 1];
if(_rpszUrlList[uUrlNum])
{
lstrcpy(_rpszUrlList[uUrlNum], szBuf);
// we found at least one url so "NOERROR"
uUrlNum++;
}
}
else
break;
}
RegCloseKey(hUrlKey);
}
if (uUrlNum > 0)
{
// We got atleast one URL from the registry.
// Check if the URLs are still valid.
hr = _PickWebSites(NULL, NULL, NULL, TRUE, TRUE);
}
}
else */if(_uInstallMode == WEBINSTALL_DIFFERENTMACHINE)
{
hr = NOERROR;
}
_szDownloadDir[0] = 0;
dwSize = sizeof(_szDownloadDir);
if(RegQueryValueEx(hKey, "UNCDownloadDir", NULL, NULL, (BYTE *) (_szDownloadDir), &dwSize) == ERROR_SUCCESS)
{
// if its a web install, set download dir to UNCDownloadDir
if(_uInstallMode == WEBINSTALL || _uInstallMode == WEBINSTALL_DIFFERENTMACHINE)
{
if(GetFileAttributes(_szDownloadDir) != 0xffffffff)
_pinseng->SetDownloadDir(_szDownloadDir);
}
else if(_uInstallMode == CDINSTALL ||
_uInstallMode == NETWORKINSTALL ||
_uInstallMode == LOCALINSTALL)
{
// setup szBuf with file:// at beginning
lstrcpy(szBuf, "file://");
lstrcat(szBuf, _szDownloadDir);
_rpszUrlList[uUrlNum] = new char[lstrlen(szBuf) + 1];
if(_rpszUrlList[uUrlNum])
{
lstrcpy(_rpszUrlList[uUrlNum], szBuf);
// we found at least one url so "NOERROR"
uUrlNum++;
hr = NOERROR;
}
}
}
RegCloseKey(hKey);
}
}
if (hr != NOERROR)
{
hr = _PickWebSites(pszUrl, pszRegion, pszLocale, FALSE);
}
if(SUCCEEDED(hr) && _rpszUrlList[0])
{
_uCurrentUrl = 0;
_pinseng->SetBaseUrl(_rpszUrlList[_uCurrentUrl]);
}
*lResult = hr;
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::put_BaseUrl(BSTR strBaseUrl)
{
if(!_pinseng)
return E_UNEXPECTED;
MAKE_ANSIPTR_FROMWIDE(pszBaseUrl, strBaseUrl);
return _pinseng->SetBaseUrl(pszBaseUrl);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::put_DownloadDir(BSTR strDownloadDir)
{
// Due to security issues, this method is effectively being disabled.
return S_OK;
if(!_pinseng)
return E_UNEXPECTED;
MAKE_ANSIPTR_FROMWIDE(pszDownloadDir, strDownloadDir);
return _pinseng->SetDownloadDir(pszDownloadDir);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::IsComponentInstalled(BSTR strComponentID, long *lResult)
{
if(!_pinseng)
return E_UNEXPECTED;
// Ask about grovelling for installed apps here
//
// add code to automatically enable grovel if the specified event is signalled
//
const TCHAR szEnableGrovelEventName[] = TEXT("WindowsUpdateCriticalUpdateGrovelEnable");
if(_uAllowGrovel == 0xffffffff)
{
HANDLE evAllowGrovel = OpenEvent(
EVENT_ALL_ACCESS,
FALSE,
szEnableGrovelEventName
);
if (evAllowGrovel != NULL)
{
if (WaitForSingleObject(evAllowGrovel, 0) == WAIT_OBJECT_0)
{
//
// if the event is signaled, we reset the event, and set _uAllowGrovel=1 which
// means we've already agreed on groveling
//
_uAllowGrovel = 1;
}
CloseHandle(evAllowGrovel);
}
}
if (_uAllowGrovel == 0xffffffff)
{
LPSTR pszTitle;
char szMess[512];
_pinseng->GetDisplayName(NULL, &pszTitle);
LoadSz(IDS_GROVELMESSAGE, szMess, sizeof(szMess));
ModalDialog(TRUE);
if(MessageBox(m_hwnd, szMess, pszTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
_uAllowGrovel = 0;
else
_uAllowGrovel = 1;
ModalDialog(FALSE);
if(pszTitle)
CoTaskMemFree(pszTitle);
}
if (_uAllowGrovel != 1)
{
*lResult = ICI_UNKNOWN;
return NOERROR;
}
else
{
MAKE_ANSIPTR_FROMWIDE(pszComponentID, strComponentID);
return _pinseng->IsComponentInstalled(pszComponentID, (DWORD *)lResult);
}
}
STDMETHODIMP CInstallEngineCtl::get_DisplayName(BSTR ComponentID, BSTR *name)
{
LPSTR psz;
MAKE_ANSIPTR_FROMWIDE(pszID, ComponentID);
_pinseng->GetDisplayName(pszID, &psz);
if(psz)
{
*name = BSTRFROMANSI(psz);
CoTaskMemFree(psz);
}
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::get_Size(BSTR strComponentID, long *lResult)
{
HRESULT hr;
COMPONENT_SIZES cs;
if(!_pinseng)
return E_UNEXPECTED;
cs.cbSize = sizeof(COMPONENT_SIZES);
MAKE_ANSIPTR_FROMWIDE(pszComponentID, strComponentID);
hr = _pinseng->GetSizes(pszComponentID, &cs);
*lResult = cs.dwDownloadSize;
return hr;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::get_TotalDownloadSize(long *totalsize)
{
HRESULT hr;
COMPONENT_SIZES cs;
if(!_pinseng)
return E_UNEXPECTED;
cs.cbSize = sizeof(COMPONENT_SIZES);
hr = _pinseng->GetSizes(NULL, &cs);
*totalsize = cs.dwDownloadSize;
return hr;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::get_TotalDependencySize(long *totaldepsize)
{
HRESULT hr;
COMPONENT_SIZES cs;
if(!_pinseng)
return E_UNEXPECTED;
cs.cbSize = sizeof(COMPONENT_SIZES);
hr = _pinseng->GetSizes(NULL, &cs);
*totaldepsize = cs.dwDependancySize;
return hr;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::SetAction(BSTR strComponentID, long action, long *lResult)
{
if(!_pinseng)
return E_UNEXPECTED;
MAKE_ANSIPTR_FROMWIDE(pszComponentID, strComponentID);
*lResult = 0;
HRESULT hr = _pinseng->SetAction(pszComponentID, action, 0xffffffff);
if(hr == E_PENDING)
{
char szTitle[128];
char szErrBuf[256];
LoadSz(IDS_TITLE, szTitle, sizeof(szTitle));
LoadSz(IDS_ERRDOINGINSTALL, szErrBuf, sizeof(szErrBuf));
MsgBox(szTitle, szErrBuf);
}
if(hr == S_FALSE)
*lResult = 1;
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::ProcessComponents(long lFlags)
{
DWORD status;
HANDLE hThread;
if(!_pinseng)
return E_UNEXPECTED;
if(!_fInstalling)
{
_fInstalling = TRUE;
// make sure engine is ready
_pinseng->GetEngineStatus(&status);
if(status == ENGINESTATUS_READY)
{
// spawn thread to do install
_dwProcessComponentsFlags = lFlags;
// only allow certain options thru script
_dwProcessComponentsFlags &= 0xffffffef;
if ((hThread = CreateThread(NULL, 0, DoInstall, (LPVOID) this, 0, &status)) != NULL)
CloseHandle(hThread);
}
}
return NOERROR;
}
void CInstallEngineCtl::_DoInstall()
{
HRESULT hr = NOERROR;
char szBuf[512];
char szTitle[128];
BOOL fNeedWebSites = FALSE;
DWORD dwMSTrustKey = (DWORD)-1;
AddRef();
_hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
_dwInstallStatus = 0;
if(!_hDone)
hr = E_FAIL;
// If we did not check yet, do it.
if (dwMSTrustKey == (DWORD)-1)
{
dwMSTrustKey = MsTrustKeyCheck();
// If MS is not a trusted provider. Make it for the duration of the install
if (dwMSTrustKey != 0)
WriteMSTrustKey(TRUE, dwMSTrustKey, _fJITInstall);
}
// Add reg value so that if IE4 base is installed, it would think that it
// is being run from Active Setup. This would prevent softboot from being
// kicked off by IE4 base.
WriteActiveSetupValue(TRUE);
if(_fDoingIEInstall)
{
// figure out whether we need to hit the web or not
// for beta1 we assume we never do for CD/NETWORK
COMPONENT_SIZES Sizes;
if(_uInstallMode == WEBINSTALL || _uInstallMode == WEBINSTALL_DIFFERENTMACHINE)
{
ZeroMemory(&Sizes, sizeof(COMPONENT_SIZES));
Sizes.cbSize = sizeof(COMPONENT_SIZES);
if(SUCCEEDED(_pinseng->GetSizes(NULL, &Sizes)))
{
if(Sizes.dwDownloadSize == 0)
{
// in webdownload case, with everything local, no need to reoncile cif
_fReconcileCif = FALSE;
}
else
{
// if we don't have any web sites then we need them
if(!_rpszUrlList[0])
fNeedWebSites = TRUE;
}
}
}
else
{
// for CD, NETWORK, LOCALINSTALL, here we check for path
hr = _CheckInstallPath(&fNeedWebSites);
// no need to reconcile the cif - it won't even be there!
_fReconcileCif = FALSE;
}
}
if(SUCCEEDED(hr))
{
_dwInstallStatus = 0;
if(!(_dwProcessComponentsFlags & PROCESSCOMPONENT_NOPROGRESSUI))
{
_pProgDlg = new CProgressDlg(g_hInstance, m_hwnd, m_hwndParent, this);
if(_pProgDlg)
_pProgDlg->DisplayWindow(TRUE);
}
}
if(SUCCEEDED(hr) && fNeedWebSites)
{
// member boolean to track whether whether websites need to
// be written back to the URLList.
_bNewWebSites = TRUE;
hr = _PickWebSites(NULL, NULL, NULL, FALSE);
if(SUCCEEDED(hr))
{
_pinseng->SetBaseUrl(_rpszUrlList[0]);
_uCurrentUrl = 0;
}
}
if ( SUCCEEDED(hr) && _bCancelPending )
{
hr = E_ABORT;
_bCancelPending = FALSE;
}
if(SUCCEEDED(hr) && _fReconcileCif)
{
hr = _pinseng->SetCifFile(_szCifCab, _szCifFile);
if(SUCCEEDED(hr))
{
WaitForEvent(_hDone, NULL);
hr = _hResult;
_fReconcileCif = FALSE;
}
}
if ( SUCCEEDED(hr) && _bCancelPending )
{
hr = E_ABORT;
_bCancelPending = FALSE;
}
if(SUCCEEDED(hr))
{
hr = _CheckForDiskSpace();
}
if(SUCCEEDED(hr))
{
COMPONENT_SIZES cs;
cs.cbSize = sizeof(COMPONENT_SIZES);
if(SUCCEEDED(_pinseng->GetSizes(NULL, &cs)))
{
_FireOnStartInstallExEvent(cs.dwDownloadSize, cs.dwInstallSize + cs.dwWinDriveSize);
}
if ( SUCCEEDED(hr) && _bCancelPending )
{
hr = E_ABORT;
_bCancelPending = FALSE;
}
if ( SUCCEEDED(hr) )
{
hr = _pinseng->DownloadComponents(_dwProcessComponentsFlags);
if(SUCCEEDED(hr))
{
WaitForEvent(_hDone, NULL);
hr = _hResult;
}
}
}
if(SUCCEEDED(hr))
{
// Prepare the install
// Create the error string
_pszErrorString = (char *) malloc(ERROR_STRING_SIZE);
_iErrorStringSize = ERROR_STRING_SIZE;
if(_pszErrorString)
LoadSz(IDS_SUMMARYHEADING, _pszErrorString, 2048);
else
hr = E_OUTOFMEMORY;
}
if(SUCCEEDED(hr))
{
if(_pProgDlg && (_dwProcessComponentsFlags & PROCESSCOMPONENT_NOINSTALLUI))
_pProgDlg->DisplayWindow(FALSE);
hr = _pinseng->InstallComponents(EXECUTEJOB_IGNORETRUST);
if(SUCCEEDED(hr))
{
WaitForEvent(_hDone, NULL);
hr = _hResult;
}
}
if (dwMSTrustKey != (DWORD)-1)
{
WriteMSTrustKey(FALSE, dwMSTrustKey);
}
dwMSTrustKey = (DWORD)-1;
// delete ActiveSetup value from IE4\Options
WriteActiveSetupValue(FALSE);
if(_pProgDlg)
{
delete _pProgDlg;
_pProgDlg = NULL;
}
LoadSz(IDS_FINISH_TITLE, szTitle, sizeof(szTitle));
// show appropriate summary ui
if( !(_dwProcessComponentsFlags & PROCESSCOMPONENT_NOSUMMARYUI))
{
if(SUCCEEDED(hr))
{
if(_pszErrorString)
MsgBox(szTitle, _pszErrorString);
}
else if(hr == E_ABORT)
{
LoadSz(IDS_INSTALLCANCELLED, szBuf, sizeof(szBuf));
MsgBox(szTitle, szBuf);
}
else if( _pszErrorString )
{
MsgBox(szTitle, _pszErrorString);
}
else
{
LoadSz(IDS_ERRGENERAL, szBuf, sizeof(szBuf));
MsgBox(szTitle, szBuf);
}
}
if(SUCCEEDED(hr))
{
if(_dwInstallStatus & STOPINSTALL_REBOOTNEEDED)
{
if(!(_dwProcessComponentsFlags & PROCESSCOMPONENT_DELAYREBOOT))
{
if( !MyRestartDialog(m_hwnd, TRUE) )
_dwInstallStatus |= STOPINSTALL_REBOOTREFUSED;
}
else
_fNeedReboot = TRUE;
}
}
_FireOnStopInstallEvent(hr, NULL, _dwInstallStatus);
_dwProcessComponentsFlags = 0;
if(_pszErrorString)
{
free(_pszErrorString);
_pszErrorString = NULL;
}
if(_hDone)
{
CloseHandle(_hDone);
_hDone = NULL;
}
_fInstalling = FALSE;
Release();
}
HRESULT CInstallEngineCtl::_PickWebSites(LPCSTR pszSites, LPCSTR pszLocale, LPCSTR pszRegion, BOOL bKeepExisting)
{
UINT uCurrentUrl;
char szUrl[INTERNET_MAX_URL_LENGTH];
char szRegion[MAX_DISPLAYNAME_LENGTH];
char szLocale[3];
HRESULT hr = NOERROR;
HKEY hKey;
DWORD dwSize;
szRegion[0] = 0;
szUrl[0] = 0;
szLocale[0] = 0;
if(!bKeepExisting)
{
for(uCurrentUrl = 0; uCurrentUrl < MAX_URLS; uCurrentUrl++)
{
if(_rpszUrlList[uCurrentUrl])
{
delete _rpszUrlList[uCurrentUrl];
_rpszUrlList[uCurrentUrl] = 0;
}
}
}
// find the first empty url
for(uCurrentUrl = 0; uCurrentUrl < MAX_URLS && _rpszUrlList[uCurrentUrl]; uCurrentUrl++);
// fill out all our fields
if(!pszSites || (*pszSites == '\0'))
{
// read info out of JIT key
if(_OpenJITKey(&hKey, KEY_READ) == ERROR_SUCCESS)
{
dwSize = sizeof(szUrl);
RegQueryValueEx(hKey, "DownloadSiteURL", NULL, NULL, (BYTE *) szUrl, &dwSize);
if(!pszLocale ||(*pszLocale == '\0'))
{
dwSize = sizeof(szLocale);
RegQueryValueEx(hKey, "Local", NULL, NULL, (BYTE *) szLocale, &dwSize);
}
else
lstrcpyn(szLocale, pszLocale, sizeof(szLocale));
if(!pszRegion||(*pszRegion == '\0'))
{
dwSize = sizeof(szRegion);
RegQueryValueEx(hKey, "DownloadSiteRegion", NULL, NULL, (BYTE *) szRegion, &dwSize);
}
else
lstrcpyn(szRegion, pszRegion, sizeof(szRegion));
RegCloseKey(hKey);
}
}
else
{
lstrcpyn(szUrl, pszSites, INTERNET_MAX_URL_LENGTH);
if(pszLocale)
lstrcpyn(szLocale, pszLocale, sizeof(szLocale));
if(pszRegion)
lstrcpyn(szRegion, pszRegion, sizeof(szRegion));
}
if(szUrl[0])
{
SITEQUERYPARAMS SiteParam;
IDownloadSiteMgr *pISitemgr;
IDownloadSite **ppISite = NULL;
IDownloadSite *pISite;
DOWNLOADSITE *psite;
BYTE *pPicks = NULL;
UINT uNumToPick;
UINT uFirstSite = 0xffffffff;
UINT j;
UINT uNumSites = 0;
ZeroMemory(&SiteParam, sizeof(SITEQUERYPARAMS));
SiteParam.cbSize = sizeof(SITEQUERYPARAMS);
// if we have a locale, use it
if(szLocale[0])
SiteParam.pszLang = szLocale;
hr = CoCreateInstance(CLSID_DownloadSiteMgr, NULL,
CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER,
IID_IDownloadSiteMgr, (LPVOID *)&pISitemgr);
if (SUCCEEDED(hr))
{
hr = pISitemgr->Initialize(szUrl, &SiteParam);
if (SUCCEEDED(hr))
{
// assume we fail. if we add at least one url, set to OK
hr = E_FAIL;
while (SUCCEEDED(pISitemgr->EnumSites(uNumSites, &pISite)))
{
pISite->Release();
uNumSites++;
}
ppISite = new IDownloadSite *[uNumSites];
for(j=0; j < uNumSites;j++)
{
pISitemgr->EnumSites(j, &(ppISite[j]));
}
// if we don't have a region, show ui
// NOTE: szRegion better be valid and
// better have atleast MAX_DISPLAYNAME_LENGTH buffer size
if(!szRegion[0])
{
_PickRegionAndFirstSite(ppISite, uNumSites, szRegion, &uFirstSite);
}
pPicks = new BYTE[uNumSites];
// zero out picks array
for(j=0; j < uNumSites; j++)
pPicks[j] = 0;
// find out number of urls we will add
uNumToPick = MAX_URLS - uCurrentUrl;
if(uNumToPick > uNumSites)
uNumToPick = uNumSites;
if(uNumToPick > 0)
{
if(uFirstSite != 0xffffffff)
{
pPicks[uFirstSite] = 1;
uNumToPick--;
}
_PickRandomSites(ppISite, pPicks, uNumSites, uNumToPick, szRegion);
}
// now all sites we want are marked with one in pPicks
for(j = 0; j < uNumSites; j++)
{
if(pPicks[j])
{
if(SUCCEEDED(ppISite[j]->GetData(&psite)))
{
_rpszUrlList[uCurrentUrl] = new char[lstrlen(psite->pszUrl) + 1];
if(_rpszUrlList[uCurrentUrl])
{
lstrcpy(_rpszUrlList[uCurrentUrl], psite->pszUrl);
uCurrentUrl++;
hr = NOERROR;
}
}
}
}
}
for(j = 0; j < uNumSites; j++)
ppISite[j]->Release();
if(ppISite)
delete ppISite;
if(pPicks)
delete pPicks;
pISitemgr->Release();
}
}
else
hr = E_FAIL;
return hr;
}
void CInstallEngineCtl::_PickRandomSites(IDownloadSite **ppISite, BYTE *pPicks, UINT uNumSites, UINT uNumToPick, LPSTR pszRegion)
{
UINT uStart, uIncrement, uFirst;
uStart = GetTickCount() % uNumSites;
if(uNumSites > 1)
uIncrement = GetTickCount() % (uNumSites - 1);
while(uNumToPick)
{
// if already picked or not in correct region, find next
uFirst = uStart;
while(pPicks[uStart] || !IsSiteInRegion(ppISite[uStart], pszRegion))
{
uStart++;
if(uStart >= uNumSites)
uStart -= uNumSites;
if(uStart == uFirst)
break;
}
if(!pPicks[uStart])
{
pPicks[uStart] = 1;
uStart += uIncrement;
if(uStart >= uNumSites)
uStart -= uNumSites;
uNumToPick--;
}
else
break;
}
}
typedef struct
{
IDownloadSite **ppISite;
UINT uNumSites;
LPSTR pszRegion;
UINT uFirstSite;
} SITEDLGPARAMS;
void FillRegionList(SITEDLGPARAMS *psiteparams, HWND hDlg)
{
DOWNLOADSITE *pSite;
HWND hRegion = GetDlgItem(hDlg, IDC_REGIONS);
for(UINT i = 0; i < psiteparams->uNumSites; i++)
{
psiteparams->ppISite[i]->GetData(&pSite);
if(ComboBox_FindStringExact(hRegion, 0, pSite->pszRegion) == CB_ERR)
ComboBox_AddString(hRegion, pSite->pszRegion);
}
ComboBox_SetCurSel(hRegion, 0);
}
void FillSiteList(SITEDLGPARAMS *psiteparams, HWND hDlg)
{
char szRegion[MAX_DISPLAYNAME_LENGTH];
int uPos;
DOWNLOADSITE *pSite;
HWND hSite = GetDlgItem(hDlg, IDC_SITES);
ListBox_ResetContent(hSite);
ComboBox_GetText(GetDlgItem(hDlg, IDC_REGIONS), szRegion, MAX_DISPLAYNAME_LENGTH);
// copy the new Region name into the psiteparams struct.
if ( psiteparams->pszRegion)
lstrcpyn(psiteparams->pszRegion, szRegion, MAX_DISPLAYNAME_LENGTH);
for(UINT i = 0; i < psiteparams->uNumSites; i++)
{
if(IsSiteInRegion(psiteparams->ppISite[i], szRegion))
{
psiteparams->ppISite[i]->GetData(&pSite);
uPos = ListBox_AddString(hSite, pSite->pszFriendlyName);
if(uPos != LB_ERR)
ListBox_SetItemData(hSite, uPos, i);
}
}
ListBox_SetCurSel(hSite, 0);
}
INT_PTR CALLBACK SiteListDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SITEDLGPARAMS *psiteparam;
switch (uMsg)
{
case WM_INITDIALOG:
// Do some init stuff
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) lParam);
psiteparam = (SITEDLGPARAMS *) lParam;
FillRegionList(psiteparam, hwnd);
FillSiteList(psiteparam, hwnd);
return FALSE;
case WM_COMMAND:
psiteparam = (SITEDLGPARAMS *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch (LOWORD(wParam))
{
case IDOK:
// get the region
ComboBox_GetText(GetDlgItem(hwnd, IDC_REGIONS), psiteparam->pszRegion, MAX_PATH);
psiteparam->uFirstSite = (UINT)ListBox_GetItemData(GetDlgItem(hwnd, IDC_SITES),
ListBox_GetCurSel(GetDlgItem(hwnd, IDC_SITES)));
EndDialog(hwnd, IDOK);
break;
case IDC_REGIONS:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
FillSiteList(psiteparam, hwnd);
}
break;
default:
return FALSE;
}
break;
default:
return(FALSE);
}
return TRUE;
}
void CInstallEngineCtl::_PickRegionAndFirstSite(IDownloadSite **ppISite, UINT uNumSites, LPSTR szRegion, UINT *puFirstSite)
{
SITEDLGPARAMS siteparam;
siteparam.ppISite = ppISite;
siteparam.uNumSites = uNumSites;
siteparam.pszRegion = szRegion;
DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_SITELIST), _pProgDlg ? _pProgDlg->GetHWND() : m_hwnd,
SiteListDlgProc, (LPARAM)&siteparam);
*puFirstSite = siteparam.uFirstSite;
_WriteRegionToReg(siteparam.pszRegion);
}
HRESULT CInstallEngineCtl::_CheckInstallPath(BOOL *pfNeedWebSites)
{
// MAX_PATH and enough to hold "file://" (if needed)
char szBuf[MAX_PATH + 10];
HKEY hKey = NULL;
DWORD dwSize;
*pfNeedWebSites = FALSE;
HRESULT hr = NOERROR;
if(!_PathIsIEInstallPoint(_szDownloadDir))
{
// If Win9x, turn-off the AutoRun thing before showing the Dlg.
if (g_fSysWin95)
g_ulOldAutorunSetting = SetAutorunSetting((unsigned long)WINDOWS_AUTOPLAY_OFF);
// create and show the dialog
INT_PTR ret = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_LOCATE), m_hwnd,
LocationDlgProc, (LPARAM)this);
// Now reset the AutoRun settings for Win9x
if (g_fSysWin95)
SetAutorunSetting(g_ulOldAutorunSetting);
if(ret == IDCANCEL)
{
hr = E_ABORT;
}
else if(ret == IDC_INTERNET)
{
*pfNeedWebSites = TRUE;
}
else
{
// mike wants to copy new _szDownloadDir back into the registry...
// take what we have and replace the current baseurl with it
if(_rpszUrlList[0])
{
delete _rpszUrlList[0];
_rpszUrlList[0] = 0;
}
lstrcpy(szBuf, "file://");
lstrcat(szBuf, _szDownloadDir);
_rpszUrlList[0] = new char[lstrlen(szBuf) + 1];
if(_rpszUrlList[0])
{
lstrcpy(_rpszUrlList[0], szBuf);
_pinseng->SetBaseUrl(_rpszUrlList[0]);
}
else
hr = E_OUTOFMEMORY;
}
}
return hr;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes: For the CD AutoSplash suppression code, the values for iHandledAutoCD are
// iHandledAutoCD == -1 ===> no need to suppress AutoCD.
// iHandledAutoCD == 0 ===> need to suppress but not suppressed yet
// iHandledAutoCD == 1 ===> finished suppressing AutoCD.
//=--------------------------------------------------------------------------=
#define AUTOCD_WAIT 30
#define AUTOCD_SLEEP 500
INT_PTR CALLBACK LocationDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Code to suppress the AutoRun when the CD is inserted.
static HCURSOR hCurOld = NULL;
static int iHandledAutoCD = -1; // -1 ==> do not need to suppress AutoCD
static int iCount = 0;
CInstallEngineCtl *pctl = (CInstallEngineCtl *) GetWindowLongPtr(hDlg, DWLP_USER);
// Special case handling for the Autorun message.
// When this dialog receives the AutoRun message, suppres it.
if ( uMsg == g_uCDAutorunMsg)
{
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR)1);
iHandledAutoCD = 1; // 1 ==> finished suppressing the AutoCD Splash
return TRUE;
}
switch(uMsg)
{
case WM_INITDIALOG:
{
char szBuf[MAX_PATH];
char szBuf2[MAX_PATH];
UINT drvType;
HWND hwndCb = GetDlgItem(hDlg, IDC_LOCATIONLIST);
int defSelect = 0;
int pos;
LPSTR psz = NULL;
// Setup the default behaviour for AutoCD suppression
iHandledAutoCD = -1; // -1 ==> do not need to suppress AutoCD
pctl = (CInstallEngineCtl *) lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pctl);
pctl->_pinseng->GetDisplayName(NULL, &psz);
SetWindowText(hDlg, psz);
szBuf2[0] = 0;
if(pctl->_uInstallMode == CDINSTALL)
{
// Only if this dialog involves CD insertion, do we need to bother about
// CDINSTALL - need to handle AutoRun suppression.
// This method is needed only if we are running on NT.
if ( g_fSysWinNT )
iHandledAutoCD = 0; // 0 ==> we need to suppress, but not suppressed yet.
LoadSz(IDS_CDNOTFOUND, szBuf, sizeof(szBuf));
SetDlgItemText(hDlg, IDC_TEXT1, szBuf);
if(LoadSz(IDS_CDPLEASEINSERT, szBuf, sizeof(szBuf)))
wsprintf(szBuf2, szBuf, psz);
SetDlgItemText(hDlg, IDC_TEXT2, szBuf2);
lstrcpy(szBuf, "x:\\");
for(char chDir = 'A'; chDir <= 'Z'; chDir++)
{
szBuf[0] = chDir;
drvType = GetDriveType(szBuf);
if(drvType != DRIVE_UNKNOWN && drvType != DRIVE_NO_ROOT_DIR)
{
pos = ComboBox_AddString(hwndCb, szBuf);
if(ANSIStrStrI(pctl->_szDownloadDir, szBuf))
defSelect = pos;
}
}
}
else
{
LoadSz(IDS_NETWORKNOTFOUND, szBuf, sizeof(szBuf));
SetDlgItemText(hDlg, IDC_TEXT1, szBuf);
if(LoadSz(IDS_NETWORKPLEASEFIND, szBuf, sizeof(szBuf)))
wsprintf(szBuf2, szBuf, psz);
SetDlgItemText(hDlg, IDC_TEXT2, szBuf2);
ComboBox_AddString(hwndCb, pctl->_szDownloadDir);
defSelect = 0;
}
// add internet to list
// it is important that the internet is last; we depend on it later
LoadSz(IDS_INTERNET, szBuf, sizeof(szBuf));
ComboBox_AddString(hwndCb, szBuf);
ComboBox_SetCurSel(hwndCb, defSelect);
if(psz)
CoTaskMemFree(psz);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BROWSE:
{
char szBuf[MAX_PATH];
char szBuf2[MAX_PATH];
HWND hwndCb = GetDlgItem(hDlg, IDC_LOCATIONLIST);
LPSTR psz;
szBuf2[0] = 0;
pctl->_pinseng->GetDisplayName(NULL, &psz);
if(LoadSz(IDS_FINDFOLDER, szBuf, sizeof(szBuf)))
wsprintf(szBuf2, szBuf, psz);
szBuf[0] = 0;
ComboBox_GetText(hwndCb, szBuf, sizeof(szBuf));
if(BrowseForDir(hDlg, szBuf, szBuf2))
{
ComboBox_SetText(hwndCb, szBuf);
}
if(psz)
CoTaskMemFree(psz);
}
break;
case IDOK:
{
HWND hwndCb = GetDlgItem(hDlg, IDC_LOCATIONLIST);
char szBuf[MAX_PATH];
char szBuf2[MAX_PATH];
// If User selected INTERNET, go on irresepective of CD or not.
// I am counting on the fact that the last item I added was internet!
int iSel = ComboBox_GetCurSel(hwndCb);
if(iSel == ComboBox_GetCount(hwndCb) - 1)
{
EndDialog(hDlg, IDC_INTERNET);
}
else
{
// If Splash suppression needs to be done, wait for it before continuing.
if ( iHandledAutoCD == 0 ) // i.e. need to suppress, but NOT suppressed yet.
{
// Change cursor to WAIT for the very first time only.
if (hCurOld == NULL)
hCurOld = SetCursor(LoadCursor(NULL,(IDC_WAIT)));
// Wait for the DlgBox to suppress the AutoCD (if possible)
if ( iHandledAutoCD != 1
&& iCount < AUTOCD_WAIT )
{
Sleep(AUTOCD_SLEEP);
PostMessage(hDlg, uMsg, wParam, lParam);
iCount ++;
}
else
{
// Enough of waiting, pretend supressed and move on.
iHandledAutoCD = 1;
PostMessage(hDlg,uMsg,wParam,lParam);
}
}
else
{
if ( hCurOld )
{
// Now that we have finished waiting for suppression, restore cursor.
SetCursor(hCurOld);
hCurOld = NULL;
}
ComboBox_GetText(hwndCb, szBuf, sizeof(szBuf));
if(pctl->_uInstallMode == CDINSTALL)
{
if(lstrlen(szBuf) == 3)
{
// this is just drive letter. add dir to it
lstrcpy(szBuf + 3, pctl->_szDownloadDir + 3);
}
}
if(pctl->_PathIsIEInstallPoint(szBuf))
{
lstrcpy(pctl->_szDownloadDir, szBuf);
EndDialog(hDlg, IDOK);
}
else
{
// NOT VALID: Need to start again on this dialog.
LPSTR psz;
pctl->_pinseng->GetDisplayName(NULL, &psz);
LoadSz(IDS_NOTVALIDLOCATION, szBuf, sizeof(szBuf));
wsprintf(szBuf2, szBuf, psz);
MessageBox(hDlg, szBuf2, psz, MB_OK | MB_ICONSTOP);
// If there was a need for AutoSplash suppression on our way here, we need to
// re-initialize our need to AutoSplash suppression for the next round.
if ( iHandledAutoCD != -1) // -1 ==> No suppression required.
{
iHandledAutoCD = 0;
hCurOld = NULL;
iCount = 0;
}
}
}
}
}
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
BOOL CInstallEngineCtl::_PathIsIEInstallPoint(LPCSTR pszPath)
{
// in the future this can actually check the path for the files we need
return(GetFileAttributes(pszPath) != 0xffffffff);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::FinalizeInstall(long lFlags)
{
if(lFlags & FINALIZE_DOREBOOT)
{
if(_fNeedReboot)
{
MyRestartDialog(m_hwnd, !(lFlags & FINALIZE_NOREBOOTPROMPT));
}
}
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::HandleEngineProblem(long lAction)
{
_dwAction = (DWORD) lAction;
return NOERROR;
}
STDMETHODIMP CInstallEngineCtl::CheckFreeSpace(long lPad, long FAR* lEnough)
{
*lEnough = 1;
_uInstallPad = lPad;
return NOERROR;
}
BOOL CInstallEngineCtl::_IsEnoughSpace(LPSTR szSpace1, DWORD dwSize1, LPSTR szSpace2, DWORD dwSize2,
LPSTR szSpace3, DWORD dwSize3)
{
COMPONENT_SIZES cs;
char szRoot[5] = "?:\\";
BOOL fEnough = TRUE;
char szBuf[MAX_DISPLAYNAME_LENGTH];
UINT pArgs[2];
cs.cbSize = sizeof(COMPONENT_SIZES);
// clear out strings
szSpace1[0] = 0;
szSpace2[0] = 0;
szSpace3[0] = 0;
if(SUCCEEDED(_pinseng->GetSizes(NULL, &cs)))
{
if(cs.chWinDrive)
{
szRoot[0] = cs.chWinDrive;
if(GetSpace(szRoot) < (DWORD) (_uInstallPad + (long) cs.dwWinDriveReq))
{
LoadSz(IDS_DISKSPACE, szBuf, sizeof(szBuf));
pArgs[0] = (UINT) cs.dwWinDriveReq + _uInstallPad;
pArgs[1] = (UINT) szRoot[0];
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID) szBuf, 0, 0, szSpace1, dwSize1, (va_list *) pArgs);
fEnough = FALSE;
}
}
if(cs.chInstallDrive)
{
szRoot[0] = cs.chInstallDrive;
if(GetSpace(szRoot) < cs.dwInstallDriveReq)
{
LoadSz(IDS_DISKSPACE, szBuf, sizeof(szBuf));
pArgs[0] = (UINT) cs.dwInstallDriveReq;
pArgs[1] = (UINT) szRoot[0];
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID) szBuf, 0, 0, szSpace2, dwSize2, (va_list *) pArgs);
fEnough = FALSE;
}
}
if(cs.chDownloadDrive)
{
szRoot[0] = cs.chDownloadDrive;
if(GetSpace(szRoot) < cs.dwDownloadDriveReq)
{
LoadSz(IDS_DISKSPACE, szBuf, sizeof(szBuf));
pArgs[0] = (UINT) cs.dwDownloadDriveReq;
pArgs[1] = (UINT) szRoot[0];
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID) szBuf, 0, 0, szSpace3, dwSize3, (va_list *) pArgs);
fEnough = FALSE;
}
}
}
else
fEnough = FALSE;
return fEnough;
}
HRESULT CInstallEngineCtl::_CheckForDiskSpace()
{
HRESULT hr = NOERROR;
char szBuf1[MAX_DISPLAYNAME_LENGTH];
char szBuf2[MAX_DISPLAYNAME_LENGTH];
char szBuf3[MAX_DISPLAYNAME_LENGTH];
if(!_IsEnoughSpace(szBuf1, sizeof(szBuf1),szBuf2, sizeof(szBuf2), szBuf3, sizeof(szBuf3) ))
hr = _ShowDiskSpaceDialog();
return hr;
}
HRESULT CInstallEngineCtl::_ShowDiskSpaceDialog()
{
HWND hwnd;
if(_pProgDlg)
hwnd = _pProgDlg->GetHWND();
else
hwnd = m_hwnd;
// create and show the dialog
INT_PTR ret = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_DISKSPACE), hwnd,
DiskSpaceDlgProc, (LPARAM) this);
if(ret == IDOK)
return NOERROR;
else
return E_ABORT;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
INT_PTR CALLBACK DiskSpaceDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CInstallEngineCtl *pctl = (CInstallEngineCtl *) GetWindowLongPtr(hDlg, DWLP_USER);
switch(uMsg)
{
case WM_INITDIALOG:
{
char szBuf1[MAX_DISPLAYNAME_LENGTH];
char szBuf2[MAX_DISPLAYNAME_LENGTH];
char szBuf3[MAX_DISPLAYNAME_LENGTH];
pctl = (CInstallEngineCtl *) lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pctl);
pctl->_IsEnoughSpace(szBuf1, sizeof(szBuf1), szBuf2, sizeof(szBuf2), szBuf3, sizeof(szBuf3));
SetDlgItemText(hDlg, IDC_SPACE1, szBuf1);
SetDlgItemText(hDlg, IDC_SPACE2, szBuf2);
SetDlgItemText(hDlg, IDC_SPACE3, szBuf3);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
char szBuf1[MAX_DISPLAYNAME_LENGTH];
char szBuf2[MAX_DISPLAYNAME_LENGTH];
char szBuf3[MAX_DISPLAYNAME_LENGTH];
if(!pctl->_IsEnoughSpace(szBuf1, sizeof(szBuf1), szBuf2, sizeof(szBuf2), szBuf3, sizeof(szBuf3)))
{
SetDlgItemText(hDlg, IDC_SPACE1, szBuf1);
SetDlgItemText(hDlg, IDC_SPACE2, szBuf2);
SetDlgItemText(hDlg, IDC_SPACE3, szBuf3);
}
else
EndDialog(hDlg, IDOK);
}
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnEngineStatusChange(DWORD dwEngineStatus, DWORD sub)
{
BOOL fSetEvent = FALSE;
if((_dwOldStatus == ENGINESTATUS_LOADING)&&(_dwOldStatus != dwEngineStatus))
{
if (_dwMSTrustKey != (DWORD)-1)
{
WriteMSTrustKey(FALSE, _dwMSTrustKey);
}
_dwMSTrustKey = (DWORD)-1;
}
if((_dwOldStatus == ENGINESTATUS_LOADING) && (_dwOldStatus != dwEngineStatus) && _hDone)
{
_hResult = sub;
fSetEvent = TRUE;
}
else
{
if(_dwFreezeEvents)
{
_fEventToFire = TRUE;
_dwSavedEngineStatus = dwEngineStatus;
_dwSavedSubStatus = sub;
}
else
{
_FireEngineStatusChange(dwEngineStatus, sub);
}
}
_dwOldStatus = dwEngineStatus;
if(fSetEvent)
SetEvent(_hDone);
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireEngineStatusChange(DWORD dwEngineStatus, DWORD sub)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.dwStatus = dwEngineStatus;
cbp.dwSubstatus = sub;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONENGINESTATUSCHANGE, (LPARAM) &cbp);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnStartInstall(DWORD dwDLSize, DWORD dwTotalSize)
{
if(_pszErrorString)
{
// if we get OnStartInstall and we are installing,
// We intentionally swallow this onStartInstall
if(_pProgDlg)
_pProgDlg->SetInsProgGoal(dwTotalSize);
}
else
{
// this is OnStartInstall for download
if(_pProgDlg)
_pProgDlg->SetDownloadProgGoal(dwDLSize);
_FireOnStartInstallEvent(dwDLSize);
}
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireOnStartInstallEvent(DWORD dwTotalSize)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.dwSize = dwTotalSize;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONSTARTINSTALL, (LPARAM) &cbp);
}
void CInstallEngineCtl::_FireOnStartInstallExEvent(DWORD dwDLSize, DWORD dwInsSize)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.dwSize = dwInsSize;
cbp.dwDL = dwDLSize;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONSTARTINSTALLEX, (LPARAM) &cbp);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnStartComponent(LPCSTR pszID, DWORD dwDLSize,
DWORD dwInstallSize, LPCSTR pszName)
{
_strCurrentID = BSTRFROMANSI(pszID);
_strCurrentName = BSTRFROMANSI(pszName);
_strCurrentString = BSTRFROMANSI("");
_FireOnStartComponentEvent(pszID, dwDLSize, pszName);
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnEngineProblem(DWORD dwProblem, LPDWORD pdwAction)
{
HRESULT hr = S_FALSE;
if((dwProblem == ENGINEPROBLEM_DOWNLOADFAIL) && _rpszUrlList[0])
{
// if we have at least one url in list, do switching ourselves
if( ((_uCurrentUrl + 1) < MAX_URLS) && _rpszUrlList[_uCurrentUrl + 1])
{
_uCurrentUrl++;
_pinseng->SetBaseUrl(_rpszUrlList[_uCurrentUrl]);
*pdwAction = DOWNLOADFAIL_RETRY;
hr = S_OK;
}
}
else
{
_dwAction = 0;
_FireOnEngineProblem(dwProblem);
*pdwAction = _dwAction;
if(*pdwAction != 0)
hr = S_OK;
}
return hr;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireOnEngineProblem(DWORD dwProblem)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.dwStatus = dwProblem;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONENGINEPROBLEM, (LPARAM) &cbp);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireOnStartComponentEvent(LPCSTR pszID, DWORD dwTotalSize, LPCSTR pszName)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.strID = BSTRFROMANSI(pszID);
cbp.strName = BSTRFROMANSI(pszName);
cbp.dwSize = dwTotalSize;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONSTARTCOMPONENT, (LPARAM) &cbp);
SysFreeString(cbp.strID);
SysFreeString(cbp.strName);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnComponentProgress(LPCSTR pszID, DWORD dwPhase, LPCSTR pszString, LPCSTR pszMsgString, ULONG ulSofar, ULONG ulMax)
{
char szBuf[512];
char szRes[512];
// _FireOnComponentProgress(dwPhase, ulSofar, ulMax);
if(!_pProgDlg)
return NOERROR;
if(dwPhase != _dwLastPhase)
{
_dwLastPhase = dwPhase;
// Set up progress for this phase
UINT id;
switch(dwPhase)
{
case INSTALLSTATUS_INITIALIZING :
id = IDS_PREPARE;
break;
case INSTALLSTATUS_DOWNLOADING :
id = IDS_DOWNLOADING;
break;
case INSTALLSTATUS_EXTRACTING :
id = IDS_EXTRACTING;
break;
case INSTALLSTATUS_CHECKINGTRUST :
id = IDS_CHECKTRUST;
break;
case INSTALLSTATUS_RUNNING :
id = IDS_INSTALLING;
break;
default :
id = IDS_NOPHASE;
}
LoadSz(id, szRes, sizeof(szRes));
wsprintf(szBuf, szRes, pszString);
// Setup text for this phase
_pProgDlg->SetProgText(szBuf);
}
if(dwPhase == INSTALLSTATUS_DOWNLOADING)
_pProgDlg->SetDownloadProgress(ulSofar);
else if(dwPhase == INSTALLSTATUS_RUNNING)
_pProgDlg->SetInsProgress(ulSofar);
return NOERROR;
}
void CInstallEngineCtl::_FireOnComponentProgress(DWORD dwPhase, DWORD dwSoFar, DWORD dwTotal)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.strID = _strCurrentID;
cbp.strName = _strCurrentName;
cbp.strString = _strCurrentString;
cbp.dwPhase = dwPhase;
cbp.dwSize = dwTotal;
cbp.dwDL = dwSoFar;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONCOMPONENTPROGRESS, (LPARAM) &cbp);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnStopComponent(LPCSTR pszID, HRESULT hrError, DWORD dwPhase, LPCSTR pszString, DWORD dwStatus)
{
char szBuf[512];
char szRes[512];
void *pTemp;
if(_strCurrentID)
{
SysFreeString(_strCurrentID);
_strCurrentID = NULL;
}
if(_strCurrentName)
{
SysFreeString(_strCurrentName);
_strCurrentName = NULL;
}
if(_strCurrentString)
{
SysFreeString(_strCurrentString);
_strCurrentString = NULL;
}
if(_pszErrorString)
{
if(FAILED(hrError))
{
// failed AND installing
UINT id;
switch(dwPhase)
{
case INSTALLSTATUS_INITIALIZING :
id = IDS_ERRPREPARE;
break;
case INSTALLSTATUS_DOWNLOADING :
case INSTALLSTATUS_COPYING :
id = IDS_ERRDOWNLOAD;
break;
case INSTALLSTATUS_DEPENDENCY :
id = IDS_ERRDEPENDENCY;
break;
case INSTALLSTATUS_EXTRACTING :
id = IDS_ERREXTRACTING;
break;
case INSTALLSTATUS_RUNNING :
id = IDS_ERRINSTALLING;
break;
case INSTALLSTATUS_CHECKINGTRUST :
id = IDS_ERRNOTTRUSTED;
break;
default :
id = IDS_NOPHASE;
}
LoadSz(id, szRes, sizeof(szRes));
}
else
{
LoadSz(IDS_SUCCEEDED, szRes, sizeof(szRes));
}
// After loading the appropriate message into szRes, now tag it to _pszErrorString.
// Make sure that _pszErrorString is big enough for the new data being appended
wsprintf(szBuf, szRes, pszString);
// This is assuming only ANSI characters. None of the strings in this control must be UNICODE!!
if ( lstrlen(szBuf) >= (_iErrorStringSize - lstrlen(_pszErrorString)) )
{
// Realloc _pszErrorString by ERROR_STRING_INCREMENT
pTemp = realloc(_pszErrorString, _iErrorStringSize + ERROR_STRING_INCREMENT);
if ( pTemp != NULL )
{ // realloc succeeded. Update the string pointer and sizes.
_pszErrorString = (char *) pTemp;
_iErrorStringSize += ERROR_STRING_INCREMENT;
}
else
{ // No memory. Abandon summary logging.
free(_pszErrorString);
_pszErrorString = NULL;
}
}
if (_pszErrorString)
lstrcat(_pszErrorString, szBuf);
}
if ( FAILED(hrError) && hrError != E_ABORT &&
(dwPhase == INSTALLSTATUS_DOWNLOADING || dwPhase == INSTALLSTATUS_CHECKINGTRUST) )
{
_bDeleteURLList = TRUE;
}
_FireOnStopComponentEvent(pszID, hrError, dwPhase, pszString, dwStatus);
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireOnStopComponentEvent(LPCSTR pszID, HRESULT hrError, DWORD dwPhase, LPCSTR pszString, DWORD dwStatus)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.strID = BSTRFROMANSI(pszID);
cbp.strName = BSTRFROMANSI(pszString);
cbp.dwResult = (DWORD) hrError;
cbp.dwPhase = dwPhase;
cbp.dwStatus = dwStatus;
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONSTOPCOMPONENT, (LPARAM) &cbp);
SysFreeString(cbp.strID);
SysFreeString(cbp.strName);
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
STDMETHODIMP CInstallEngineCtl::OnStopInstall(HRESULT hrError, LPCSTR szError, DWORD dwStatus)
{
_hResult = hrError;
_dwInstallStatus = dwStatus;
if ( _bDeleteURLList )
_DeleteURLList();
else
if ( _bNewWebSites )
_WriteURLList();
SetEvent(_hDone);
return NOERROR;
}
//=--------------------------------------------------------------------------=
// Function name here
//=--------------------------------------------------------------------------=
// Function description
//
// Parameters:
//
// Returns:
//
// Notes:
//
void CInstallEngineCtl::_FireOnStopInstallEvent(HRESULT hrError, LPCSTR szError, DWORD dwStatus)
{
CALLBACK_PARAMS cbp = { 0 };
cbp.dwResult = (DWORD) hrError;
cbp.dwStatus = dwStatus;
cbp.strString = BSTRFROMANSI( szError ? szError : "");
SendMessage(m_hwnd, WM_INSENGCALLBACK, (WPARAM) EVENT_ONSTOPINSTALL, (LPARAM) &cbp);
SysFreeString(cbp.strString);
}
void CInstallEngineCtl::MarkJITInstall()
{
HRESULT hr = S_OK;
IOleClientSite *pClientSite = NULL;
IHTMLDocument2 *pDoc = NULL;
BSTR bstrURL = NULL;
IOleContainer *pContainer = NULL;
hr = GetClientSite(&pClientSite);
if (SUCCEEDED(hr))
{
hr = pClientSite->GetContainer(&pContainer);
if (SUCCEEDED(hr))
{
hr = pContainer->QueryInterface(IID_IHTMLDocument2, (LPVOID *)&pDoc);
if (SUCCEEDED(hr))
{
hr = pDoc->get_URL(&bstrURL);
if (SUCCEEDED(hr) && bstrURL)
{
HKEY hKeyActiveSetup;
char szJITPage[INTERNET_MAX_URL_LENGTH] = "";
DWORD dwSize = INTERNET_MAX_URL_LENGTH;
DWORD dwType;
BSTR bstrJITPage = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Active Setup"),
0,
KEY_READ,
&hKeyActiveSetup))
{
if (ERROR_SUCCESS == RegQueryValueEx(
hKeyActiveSetup,
TEXT("JITSetupPage"),
NULL,
&dwType,
(LPBYTE) szJITPage,
&dwSize
))
{
bstrJITPage = BSTRFROMANSI(szJITPage);
if (bstrJITPage)
{
if (0 == lstrcmpiW(bstrJITPage, bstrURL))
{
// If the URL points to an internal resource,
// it's probably safe to assume this is a JIT install.
_fJITInstall = TRUE;
}
SysFreeString(bstrJITPage);
}
}
RegCloseKey(hKeyActiveSetup);
}
SysFreeString(bstrURL);
}
pDoc->Release();
}
pContainer->Release();
}
pClientSite->Release();
}
}
DWORD WINAPI DoInstall(LPVOID pv)
{
CInstallEngineCtl *p = (CInstallEngineCtl *) pv;
HRESULT hr = CoInitialize(NULL);
p->_DoInstall();
if(SUCCEEDED(hr))
CoUninitialize();
return 0;
}