//=--------------------------------------------------------------------------= // inseng.cpp //=--------------------------------------------------------------------------= // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved. // // #include "asctlpch.h" #include "ipserver.h" #include #include "util.h" #include "globals.h" #include "asinsctl.h" #include "dispids.h" #include "resource.h" #include "util2.h" #include // 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; }