#include #include #include #include "..\\inc\\urlint.h" #include "..\\inc\\wcheckcb.h" #include "..\\inc\\debug.h" #include "..\\download\\cdl.h" #include "Status.h" // {5DFE9E81-46E4-11d0-94E8-00AA0059CE02} const CLSID CLSID_ControlRefreshCallback = { 0x5dfe9e81, 0x46e4, 0x11d0, 0x94, 0xe8, 0x0, 0xaa, 0x0, 0x59, 0xce, 0x2 }; const static TCHAR *g_pszUpdateInfo = TEXT("UpdateInfo"); const static TCHAR *g_pszNewControlInCache = TEXT("NewControlInCache"); #define CLSID_MAX_LENGTH 50 #define CONTENT_MAX_LENGTH 1024 /****************************************************************************** Constructor, Destructor and helper methods ******************************************************************************/ CControlRefreshCallback::CControlRefreshCallback() { DllAddRef(); m_cRef = 1; m_clsidCtrl = CLSID_NULL; m_wszURL[0] = '\0'; } CControlRefreshCallback::~CControlRefreshCallback() { Assert(m_cRef == 0); DllRelease(); } // Give this object information such as the clsid and url of the control // it's dealing with STDMETHODIMP CControlRefreshCallback::SetInfo( REFCLSID rclsidControl, LPCWSTR lpwszURL) { m_clsidCtrl = rclsidControl; // copy wide strings #ifdef UNICODE lstrcpyW(m_wszURL, lpwszURL); // only works in Win32 mode // fails on Win95 #else INT i = 0; for(; lpwszURL[i]; i++) m_wszURL[i] = lpwszURL[i]; m_wszURL[i] = '\0'; #endif Assert(lstrlenW(m_wszURL) == lstrlenW(lpwszURL)); return S_OK; } /* HRESULT CControlRefreshCallback::UpdateControlInCacheFlag( SCODE scReason) const { // update flag in registry so that IE initiates a new // download when the control is visited. LONG lResult = ERROR_SUCCESS; TCHAR szKey[MAX_PATH]; LPOLESTR pwcsClsid = NULL; BOOL fChanged = (scReason == S_OK); lstrcpy(szKey, TEXT("CLSID\\")); if (SUCCEEDED(::StringFromCLSID(m_clsidCtrl, &pwcsClsid))) { HKEY hKey = NULL; int nLen = lstrlen(szKey); if (WideCharToMultiByte( CP_ACP, 0, pwcsClsid, -1, szKey + nLen, MAX_PATH - nLen, NULL, NULL) > 0) { lstrcat(szKey, "\\"); lstrcat(szKey, g_pszUpdateInfo); lResult = RegOpenKeyEx( HKEY_CLASSES_ROOT, szKey, 0, KEY_ALL_ACCESS, &hKey); if (lResult == ERROR_SUCCESS) { DWORD dwKeySet = 0; DWORD dwSize = sizeof(DWORD); lResult = RegQueryValueEx( hKey, g_pszNewControlInCache, NULL, NULL, (LPBYTE)&dwKeySet, &dwSize); if (lResult != ERROR_SUCCESS || (dwKeySet == 0 && fChanged)) { dwKeySet = (fChanged ? 1 : 0); lResult = RegSetValueEx( hKey, g_pszNewControlInCache, 0, REG_DWORD, (LPBYTE)&dwKeySet, sizeof(DWORD)); } RegCloseKey(hKey); } } delete pwcsClsid; } return (lResult == ERROR_SUCCESS ? S_OK : HRESULT_FROM_WIN32(lResult)); } */ HRESULT CControlRefreshCallback::DownloadControl() const { HRESULT hr = S_OK; CSilentCodeDLSink *pscdls = NULL; LPBC pbc = NULL; Assert(lstrlenW(m_wszURL) > 0); Assert(m_clsidCtrl != CLSID_NULL); pscdls = new CSilentCodeDLSink; if (pscdls == NULL) { hr = E_OUTOFMEMORY; goto Exit; } hr = CreateBindCtx(0, &pbc); if (SUCCEEDED(hr)) hr = RegisterBindStatusCallback(pbc, pscdls, NULL, 0); if (FAILED(hr)) goto Exit; hr = AsyncGetClassBits( m_clsidCtrl, NULL, NULL, (DWORD)-1, (DWORD)-1, m_wszURL, pbc, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, NULL, IID_IClassFactory, 0); if (hr == MK_S_ASYNCHRONOUS) hr = pscdls->WaitTillNotified(); RevokeBindStatusCallback(pbc, pscdls); Exit: if (pbc) pbc->Release(); if (pscdls) pscdls->Release(); return hr; } /****************************************************************************** IUnknown Methods ******************************************************************************/ STDMETHODIMP CControlRefreshCallback::QueryInterface( REFIID iid, void** ppvObject) { *ppvObject = NULL; if (iid == IID_IUnknown) { *ppvObject = (void*)this; } else if (iid == IID_IPersistStream) { *ppvObject = (void*)(IPersistStream*)this; } else if (iid == IID_IWebCheckAdviseSink) { *ppvObject = (void*)(IWebCheckAdviseSink*)this; } if (*ppvObject) { ((LPUNKNOWN)*ppvObject)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CControlRefreshCallback::AddRef() { return ++m_cRef; } STDMETHODIMP_(ULONG) CControlRefreshCallback::Release() { if (--m_cRef) return m_cRef; delete this; return 0; } /****************************************************************************** IPersistStream Methods ******************************************************************************/ STDMETHODIMP CControlRefreshCallback::GetClassID(CLSID* pClsssID) { *pClsssID = CLSID_ControlRefreshCallback; return S_OK; } STDMETHODIMP CControlRefreshCallback::IsDirty(void) { Assert(m_clsidCtrl != CLSID_NULL); return (m_clsidCtrl != CLSID_NULL ? S_OK : S_FALSE); } STDMETHODIMP CControlRefreshCallback::Load(IStream* pStm) { DWORD dwLen = 0; ULONG cb = sizeof(CLSID); ULONG cbRead = 0; pStm->Read((void*)&m_clsidCtrl, cb, &cbRead); Assert(cb == cbRead); if (cb != cbRead) goto Exit; cb = sizeof(DWORD); cbRead = 0; pStm->Read((void*)&dwLen, cb, &cbRead); Assert(cb == cbRead); if (cb != cbRead) goto Exit; cb = dwLen * sizeof(WCHAR); cbRead = 0; pStm->Read((void*)&m_wszURL, cb, &cbRead); Assert(cb == cbRead); Assert((DWORD)lstrlenW(m_wszURL) == dwLen - 1); Exit: return (cbRead == cb ? S_OK : E_FAIL); } STDMETHODIMP CControlRefreshCallback::Save(IStream* pStm, BOOL fClearDirty) { DWORD dwLen = lstrlenW(m_wszURL) + 1; // add 1 for NULL char ULONG cb = sizeof(CLSID); ULONG cbSaved = 0; pStm->Write((void*)&m_clsidCtrl, cb, &cbSaved); Assert(cb == cbSaved); if (cb != cbSaved) goto Exit; cb = sizeof(DWORD); cbSaved = 0; pStm->Write((void*)&dwLen, cb, &cbSaved); Assert(cb == cbSaved); if (cb != cbSaved) goto Exit; cb = dwLen * sizeof(WCHAR); cbSaved = 0; pStm->Write((void*)m_wszURL, cb, &cbSaved); Assert(cb == cbSaved); Exit: return (cbSaved == cb ? S_OK : E_FAIL); } STDMETHODIMP CControlRefreshCallback::GetSizeMax(ULARGE_INTEGER* pcbSize) { pcbSize->QuadPart = sizeof(CLSID) + sizeof(DWORD) + sizeof(m_wszURL); return S_OK; } /****************************************************************************** IWebCheckAdviseSink Methods ******************************************************************************/ STDMETHODIMP CControlRefreshCallback::UpdateBegin( long lCookie, SCODE scReason, BSTR lpURL) { return S_OK; } // scReason -- S_OK means changed, S_FALSE means no changes STDMETHODIMP CControlRefreshCallback::UpdateEnd( long lCookie, SCODE scReason) { Assert(m_clsidCtrl != CLSID_NULL); LONG lResult = ERROR_SUCCESS; if (scReason == S_OK) { DownloadControl(); // UpdateControlInCacheFlag(scReason); } return S_OK; } STDMETHODIMP CControlRefreshCallback::UpdateProgress( long lCookie, long lCurrent, long lMax) { return S_OK; }