#include #include #include // Globals #ifdef LOGO3_SUPPORT_AUTOINSTALL CList g_CDLList; CMutexSem g_mxsCDL; UINT g_Timer; #endif Logo3CodeDLBSC::Logo3CodeDLBSC(CSoftDist *pSoftDist, IBindStatusCallback *pClientBSC, LPSTR szCodeBase, LPWSTR wzDistUnit) : _cRef(1) , _pIBinding(NULL) , _pClientBSC(pClientBSC) , _bPrecacheOnly(FALSE) , _pbc(NULL) , _pSoftDist(pSoftDist) #ifdef LOGO3_SUPPORT_AUTOINSTALL , _uiTimer(0) , _hProc(INVALID_HANDLE_VALUE) #endif { DEBUG_ENTER((DBG_DOWNLOAD, None, "Logo3CodeDLBSC::Logo3CodeDLBSC", "this=%#x, %#x, %#x, %.80q, %.80wq", this, pSoftDist, pClientBSC, szCodeBase, wzDistUnit )); DWORD len = 0; _szCodeBase = new char[lstrlen(szCodeBase) + 1]; if (_szCodeBase) { lstrcpy(_szCodeBase, szCodeBase); } if (_pClientBSC) { _pClientBSC->AddRef(); } if (_pSoftDist) { _pSoftDist->AddRef(); } len = WideCharToMultiByte(CP_ACP,0, wzDistUnit, -1, NULL, 0, NULL, NULL); _szDistUnit = new TCHAR[len]; if (_szDistUnit) { WideCharToMultiByte(CP_ACP, 0, wzDistUnit , -1, _szDistUnit, len, NULL, NULL); } DEBUG_LEAVE(0); } Logo3CodeDLBSC::~Logo3CodeDLBSC() { DEBUG_ENTER((DBG_DOWNLOAD, None, "Logo3CodeDLBSC::~Logo3CodeDLBSC", "this=%#x", this )); if (_pClientBSC) { _pClientBSC->Release(); } if (_pbc) { _pbc->Release(); } if (_pSoftDist) { _pSoftDist->Release(); } delete [] _szCodeBase; delete [] _szDistUnit; DEBUG_LEAVE(0); } /* * * IUnknown Methods * */ STDMETHODIMP Logo3CodeDLBSC::QueryInterface(REFIID riid, void **ppv) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppv )); HRESULT hr = E_NOINTERFACE; *ppv = NULL; if (riid == IID_IUnknown || riid == IID_IBindStatusCallback) { *ppv = (IBindStatusCallback *)this; } if (*ppv != NULL) { ((IUnknown *)*ppv)->AddRef(); hr = S_OK; } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP_(ULONG) Logo3CodeDLBSC::AddRef() { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "Logo3CodeDLBSC::IUnknown::AddRef", "this=%#x", this )); ULONG ulRet = ++_cRef; DEBUG_LEAVE(ulRet); return ulRet; } STDMETHODIMP_(ULONG) Logo3CodeDLBSC::Release() { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "Logo3CodeDLBSC::IUnknown::Release", "this=%#x", this )); if (--_cRef) { DEBUG_LEAVE(_cRef); return _cRef; } delete this; DEBUG_LEAVE(0); return 0; } /* * * IBindStatusCallback Methods * */ STDMETHODIMP Logo3CodeDLBSC::OnStartBinding(DWORD grfBSCOption, IBinding *pib) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnStartBinding", "this=%#x, %#x, %#x", this, grfBSCOption, pib )); HRESULT hr = S_OK; if (_pIBinding != NULL) { _pIBinding->Release(); } _pIBinding = pib; if (_pIBinding != NULL) { _pIBinding->AddRef(); } if (_pClientBSC != NULL) { hr = _pClientBSC->OnStartBinding(grfBSCOption, pib); } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::OnStopBinding(HRESULT hr, LPCWSTR szError) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnStopBinding", "this=%#x, %#x, %.80wq", this, hr, szError )); #ifdef LOGO3_SUPPORT_AUTOINSTALL CLock lck(g_mxsCDL); // Mutex this method #endif DWORD dwSize = 0; LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo = NULL; SHELLEXECUTEINFO sei; TCHAR achShortName[MAX_PATH]; HANDLE hFile = INVALID_HANDLE_VALUE; LPWSTR pwzUrl = NULL; #ifdef LOGO3_SUPPORT_AUTOINSTALL // These vars are used for trust verification. // AS TODO: Get these values from QI'ing and QS'ing from the // client BindStatusCallback. For now, just use NULL values. IInternetHostSecurityManager *pHostSecurityManager = NULL; HWND hWnd = (HWND)INVALID_HANDLE_VALUE; PJAVA_TRUST pJavaTrust = NULL; #endif AddRef(); // RevokeBindStatusCallback() will destroy us too soon. if (_pIBinding != NULL) { _pIBinding->Release(); _pIBinding = NULL; } #ifdef LOGO3_SUPPORT_AUTOINSTALL lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer; dwSize = MAX_CACHE_ENTRY_INFO_SIZE; GetUrlCacheEntryInfo(_szCodeBase, lpCacheEntryInfo, &dwSize); GetShortPathName(lpCacheEntryInfo->lpszLocalFileName, achShortName, MAX_PATH); // Do trust verification if (!_bPrecacheOnly) { if ( (hFile = CreateFile(achShortName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } Ansi2Unicode(_szCodeBase, &pwzUrl); hr = _wvt.VerifyTrust(hFile, hWnd, &pJavaTrust, pwzUrl, pHostSecurityManager); SAFEDELETE(pJavaTrust); SAFEDELETE(pwzUrl); CloseHandle(hFile); } #endif #ifdef LOGO3_SUPPORT_AUTOINSTALL if (_bPrecacheOnly) { #endif if (SUCCEEDED(hr)) { // Mark all downloads of the same group to be downloaded hr = _pSoftDist->Logo3DownloadNext(); } else { // Get last download's group and search for another one to download hr = _pSoftDist->Logo3DownloadRedundant(); } if ((FAILED(hr) && hr != E_PENDING) || hr == S_FALSE) { _pClientBSC->OnStopBinding(hr, szError); RecordPrecacheValue(hr); } #ifdef LOGO3_SUPPORT_AUTOINSTALL } else { sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; sei.hwnd = NULL; sei.lpVerb = NULL; // "Open" is the default verb sei.lpFile = achShortName; sei.lpParameters = NULL; sei.lpDirectory = NULL; sei.nShow = SW_SHOWDEFAULT; sei.lpIDList = NULL; sei.lpClass = NULL; sei.hkeyClass = 0; sei.dwHotKey = 0; sei.hIcon = INVALID_HANDLE_VALUE; sei.cbSize = sizeof(sei); if (!ShellExecuteEx(&sei)) { goto Exit; } _hProc = sei.hProcess; if (!g_Timer) { g_Timer = SetTimer(NULL, (UINT)this, TIMEOUT_INTERVAL, TimeOutProc); } g_CDLList.AddTail(this); AddRef(); } #endif Assert(_pbc); RevokeBindStatusCallback(_pbc, this); _pbc->Release(); _pbc = NULL; Release(); DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::OnObjectAvailable(REFIID riid, IUnknown *punk) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnObjectAvailable", "this=%#x, %#x, %#x", this, &riid, punk )); HRESULT hr = S_OK; if (_pClientBSC) { hr = _pClientBSC->OnObjectAvailable(riid, punk); } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::GetPriority(LONG *pnPriority) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::GetPriority", "this=%#x, %#x", this, pnPriority )); HRESULT hr = S_OK; if (_pClientBSC) { hr = _pClientBSC->GetPriority(pnPriority); } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::OnLowResource(DWORD dwReserved) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnLowResource", "this=%#x, %#x", this, dwReserved )); HRESULT hr = S_OK; if (_pClientBSC) { hr = _pClientBSC->OnLowResource(dwReserved); } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnProgress", "this=%#x, %#x, %#x, %#x, %.80wq", this, ulProgress, ulProgressMax, ulStatusCode, szStatusText )); HRESULT hr = S_OK; if (_pClientBSC) { hr = _pClientBSC->OnProgress(ulProgress, ulProgressMax, ulStatusCode, szStatusText); } DEBUG_LEAVE(hr); return hr; } STDMETHODIMP Logo3CodeDLBSC::GetBindInfo(DWORD *pgrfBINDF, BINDINFO *pbindInfo) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::GetBindInfo", "this=%#x, %#x, %#x", this, pgrfBINDF, pbindInfo )); HRESULT hr = S_OK; *pgrfBINDF |= BINDF_ASYNCHRONOUS; if (_pClientBSC) { hr = _pClientBSC->GetBindInfo(pgrfBINDF, pbindInfo); if (*pgrfBINDF & BINDF_SILENTOPERATION) { _bPrecacheOnly = TRUE; } } DEBUG_LEAVE(S_OK); return S_OK; } STDMETHODIMP Logo3CodeDLBSC::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::IBindStatusCallback::OnDataAvailable", "this=%#x, %#x, %#x, %#x, %#x", this, grfBSCF, dwSize, pformatetc, pstgmed )); HRESULT hr = S_OK; if (_pClientBSC) { hr = _pClientBSC->OnDataAvailable(grfBSCF, dwSize, pformatetc, pstgmed); } DEBUG_LEAVE(S_OK); return S_OK; } void Logo3CodeDLBSC::SetBindCtx(IBindCtx *pbc) { DEBUG_ENTER((DBG_DOWNLOAD, None, "Logo3CodeDLBSC::SetBindCtx", "this=%#x, %#x", this, pbc )); _pbc = pbc; if (_pbc) { _pbc->AddRef(); } DEBUG_LEAVE(0); } STDMETHODIMP Logo3CodeDLBSC::RecordPrecacheValue(HRESULT hr) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "Logo3CodeDLBSC::RecordPrecacheValue", "this=%#x, %#x", this, hr )); HRESULT hrRet = S_OK; DWORD lResult = 0; HKEY hkeyLogo3 = 0; HKEY hkeyVersion = 0; char achBuffer[MAX_CACHE_ENTRY_INFO_SIZE]; static const char *szAvailableVersion = "AvailableVersion"; static const char *szPrecache = "Precache"; if (_szDistUnit != NULL) { wnsprintf(achBuffer, sizeof(achBuffer)-1, "%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, _szDistUnit); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, achBuffer, 0, KEY_ALL_ACCESS, &hkeyLogo3) == ERROR_SUCCESS) { if (RegOpenKeyEx(hkeyLogo3, szAvailableVersion, 0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS) { if ((lResult = RegCreateKey(hkeyLogo3, szAvailableVersion, &hkeyVersion)) != ERROR_SUCCESS) { hrRet = HRESULT_FROM_WIN32(lResult); goto Exit; } } // record result of caching bits. HRESULT hrRecord = hr; if (FAILED(hr)) { hrRecord = ERROR_IO_INCOMPLETE; } lResult = ::RegSetValueEx(hkeyVersion, szPrecache, NULL, REG_DWORD, (unsigned char *)&hrRecord, sizeof(DWORD)); if (lResult != ERROR_SUCCESS) { hrRet = HRESULT_FROM_WIN32(lResult); goto Exit; } } } else { hrRet = E_INVALIDARG; } Exit: if (hkeyLogo3) { RegCloseKey(hkeyLogo3); } if (hkeyVersion) { RegCloseKey(hkeyVersion); } DEBUG_LEAVE(hrRet); return hrRet; } #ifdef LOGO3_SUPPORT_AUTOINSTALL void Logo3CodeDLBSC::TimeOut() { DEBUG_ENTER((DBG_DOWNLOAD, None, "Logo3CodeDLBSC::TimeOut", "this=%#x", this )); CLock lck(g_mxsCDL); // Mutex req for CDLList LISTPOSITION pos = NULL; if (WaitForSingleObjectEx(_hProc, 0, FALSE) == WAIT_OBJECT_0) { Assert(_pClientBSC); _pClientBSC->OnStopBinding(S_OK, NULL); // Remove self from code download list pos = g_CDLList.Find(this); Assert(pos); g_CDLList.RemoveAt(pos); Release(); // If no more code downloads, kill the timer if (!g_CDLList.GetCount()) { KillTimer(NULL, g_Timer); g_Timer = 0; } } DEBUG_LEAVE(0); } void CALLBACK TimeOutProc(HWND hwnd, UINT msg, UINT idEvent, DWORD dwTime) { DEBUG_ENTER((DBG_DOWNLOAD, None, "TimeOutProc", "%#x, %#x, %#x, %#x", hwnd, msg, idEvent, dwTime )); LISTPOSITION pos = NULL; Logo3CodeDLBSC *bsc = NULL; lpos = g_CDLList.GetHeadPosition(); while (lpos) { bsc = g_CDLList.GetNext(pos); Assert(bsc); bsc->TimeOut(); } DEBUG_LEAVE(0); } #endif