|
|
#include "private.h"
#include "subsmgrp.h"
#include "subitem.h"
// Contains implementations of IEnumSubscription and ISubscriptionMgr2
HRESULT SubscriptionItemFromCookie(BOOL fCreateNew, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie, ISubscriptionItem **ppSubscriptionItem);
HRESULT DoGetItemFromURL(LPCTSTR pszURL, ISubscriptionItem **ppSubscriptionItem) { HRESULT hr; SUBSCRIPTIONCOOKIE cookie;
if ((NULL == pszURL) || (NULL == ppSubscriptionItem)) { return E_INVALIDARG; }
hr = ReadCookieFromInetDB(pszURL, &cookie); if (SUCCEEDED(hr)) { hr = SubscriptionItemFromCookie(FALSE, &cookie, ppSubscriptionItem); }
return hr; }
HRESULT DoGetItemFromURLW(LPCWSTR pwszURL, ISubscriptionItem **ppSubscriptionItem) { TCHAR szURL[INTERNET_MAX_URL_LENGTH];
if ((NULL == pwszURL) || (NULL == ppSubscriptionItem)) { return E_INVALIDARG; }
StrCpyN(szURL, pwszURL, ARRAYSIZE(szURL));
return DoGetItemFromURL(szURL, ppSubscriptionItem); }
HRESULT DoAbortItems( /* [in] */ DWORD dwNumCookies, /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies) { HRESULT hr;
if ((0 == dwNumCookies) || (NULL == pCookies)) { return E_INVALIDARG; }
ISubscriptionThrottler *pst;
hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_ISubscriptionThrottler, (void **)&pst);
if (SUCCEEDED(hr)) { hr = pst->AbortItems(dwNumCookies, pCookies); pst->Release(); } else { hr = S_FALSE; }
return hr; }
HRESULT DoCreateSubscriptionItem( /* [in] */ const SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo, /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { HRESULT hr; ISubscriptionItem *psi;
if ((NULL == pSubscriptionItemInfo) || (NULL == pNewCookie) || (NULL == ppSubscriptionItem)) { return E_INVALIDARG; }
*ppSubscriptionItem = NULL;
CreateCookie(pNewCookie);
hr = SubscriptionItemFromCookie(TRUE, pNewCookie, &psi);
if (SUCCEEDED(hr)) { ASSERT(NULL != psi);
hr = psi->SetSubscriptionItemInfo(pSubscriptionItemInfo); if (SUCCEEDED(hr)) { *ppSubscriptionItem = psi; } else { // Don't leak or leave slop hanging around
psi->Release(); DoDeleteSubscriptionItem(pNewCookie, FALSE); } }
return hr; }
HRESULT DoCloneSubscriptionItem( /* [in] */ ISubscriptionItem *pSubscriptionItem, /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { HRESULT hr; SUBSCRIPTIONCOOKIE NewCookie;
if ((NULL == pSubscriptionItem) || (NULL == ppSubscriptionItem)) { return E_INVALIDARG; }
IEnumItemProperties *peip; SUBSCRIPTIONITEMINFO sii;
*ppSubscriptionItem = NULL;
// First get existing subscription details
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO); hr = pSubscriptionItem->GetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr)) { ISubscriptionItem *psi;
// Mark as temp and create a new subscription item
sii.dwFlags |= SI_TEMPORARY;
hr = DoCreateSubscriptionItem(&sii, &NewCookie, &psi);
if (SUCCEEDED(hr)) { if (pNewCookie) *pNewCookie = NewCookie;
// Get properties from existing item
hr = pSubscriptionItem->EnumProperties(&peip); if (SUCCEEDED(hr)) { ULONG count; ASSERT(NULL != peip);
hr = peip->GetCount(&count);
if (SUCCEEDED(hr)) { ITEMPROP *pProps = new ITEMPROP[count]; LPWSTR *pNames = new LPWSTR[count]; VARIANT *pVars = new VARIANT[count];
if ((NULL != pProps) && (NULL != pNames) && (NULL != pVars)) { hr = peip->Next(count, pProps, &count);
if (SUCCEEDED(hr)) { ULONG i;
for (i = 0; i < count; i++) { pNames[i] = pProps[i].pwszName; pVars[i] = pProps[i].variantValue; }
hr = psi->WriteProperties(count, pNames, pVars);
// clean up from enum
for (i = 0; i < count; i++) { if (pProps[i].pwszName) { CoTaskMemFree(pProps[i].pwszName); } VariantClear(&pProps[i].variantValue); } } } else { hr = E_OUTOFMEMORY; }
SAFEDELETE(pProps); SAFEDELETE(pNames); SAFEDELETE(pVars); } peip->Release(); }
if (SUCCEEDED(hr)) { *ppSubscriptionItem = psi; } else { psi->Release(); } } } return hr; }
HRESULT DoDeleteSubscriptionItem( /* [in] */ const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua, /* [in] */ BOOL fAbortItem) { HRESULT hr; TCHAR szKey[MAX_PATH]; SUBSCRIPTIONCOOKIE cookie_buf; SUBSCRIPTIONCOOKIE *pCookie;
//
// Make an aligned copy of pCookie_ua and set a pointer to it.
//
if (pCookie_ua != NULL) { cookie_buf = *pCookie_ua; pCookie = &cookie_buf; } else { pCookie = NULL; }
if (NULL == pCookie) { return E_INVALIDARG; }
if (fAbortItem) { DoAbortItems(1, pCookie); }
if (ItemKeyNameFromCookie(pCookie, szKey, ARRAYSIZE(szKey))) { // Notify the agent that it is about to get deleted.
ISubscriptionItem *pItem=NULL; if (SUCCEEDED(SubscriptionItemFromCookie(FALSE, pCookie, &pItem))) { SUBSCRIPTIONITEMINFO sii = { sizeof(SUBSCRIPTIONITEMINFO) };
if (SUCCEEDED(pItem->GetSubscriptionItemInfo(&sii))) { ASSERT(!(sii.dwFlags & SI_TEMPORARY));
ISubscriptionAgentControl *psac=NULL;
if (SUCCEEDED( CoCreateInstance(sii.clsidAgent, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionAgentControl, (void**)&psac))) { psac->SubscriptionControl(pItem, SUBSCRIPTION_AGENT_DELETE); psac->Release(); }
FireSubscriptionEvent(SUBSNOTF_DELETE, pCookie);
if (GUID_NULL != sii.ScheduleGroup) { ISyncScheduleMgr *pSyncScheduleMgr; hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr)) { pSyncScheduleMgr->RemoveSchedule(&sii.ScheduleGroup); pSyncScheduleMgr->Release(); } } }
pItem->Release(); }
hr = (SHDeleteKey(HKEY_CURRENT_USER, szKey) == ERROR_SUCCESS) ? S_OK : E_FAIL; } else { TraceMsg(TF_ALWAYS, "Failed to delete subscription item."); hr = E_FAIL; }
return hr; }
HRESULT AddUpdateSubscription(SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua, SUBSCRIPTIONITEMINFO *psii, LPCWSTR pwszURL, ULONG nProps, const LPWSTR rgwszName[], VARIANT rgValue[]) { HRESULT hr = S_OK; SUBSCRIPTIONCOOKIE cookie_buf; SUBSCRIPTIONCOOKIE *pCookie;
//
// Make an aligned copy of pCookie_ua and set a pointer to it.
//
cookie_buf = *pCookie_ua; pCookie = &cookie_buf; ASSERT((0 == nProps) || ((NULL != rgwszName) && (NULL != rgValue)));
TCHAR szURL[INTERNET_MAX_URL_LENGTH]; ISubscriptionItem *psi = NULL; SUBSCRIPTIONCOOKIE cookie;
StrCpyNW(szURL, pwszURL, ARRAYSIZE(szURL));
// Try and get the cookie from the inet db otherwise
// create a new one.
if (*pCookie == CLSID_NULL) { CreateCookie(&cookie); } else { cookie = *pCookie; } // Update the inet db
WriteCookieToInetDB(szURL, &cookie, FALSE); hr = SubscriptionItemFromCookie(TRUE, &cookie, &psi);
if (SUCCEEDED(hr)) { hr = psi->SetSubscriptionItemInfo(psii); if (SUCCEEDED(hr) && (nProps > 0)) { ASSERT(NULL != psi);
hr = psi->WriteProperties(nProps, rgwszName, rgValue); } psi->Release();
if (FAILED(hr)) { DoDeleteSubscriptionItem(&cookie, TRUE); } }
*pCookie_ua = cookie_buf;
return hr; }
HRESULT SubscriptionItemFromCookie(BOOL fCreateNew, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua, ISubscriptionItem **ppSubscriptionItem) { HRESULT hr; SUBSCRIPTIONCOOKIE cookie_buf; SUBSCRIPTIONCOOKIE *pCookie;
//
// Make an aligned copy of pCookie_ua and set a pointer to it.
//
if (pCookie_ua != NULL) { cookie_buf = *pCookie_ua; pCookie = &cookie_buf; } else { pCookie = NULL; }
ASSERT((NULL != pCookie) && (NULL != ppSubscriptionItem));
HKEY hkey; if (OpenItemKey(pCookie, fCreateNew ? TRUE : FALSE, KEY_READ | KEY_WRITE, &hkey)) { *ppSubscriptionItem = new CSubscriptionItem(pCookie, hkey); if (NULL != *ppSubscriptionItem) { hr = S_OK; } else { hr = E_OUTOFMEMORY; } RegCloseKey(hkey); } else { *ppSubscriptionItem = NULL; hr = E_FAIL; } return hr; }
BOOL ItemKeyNameFromCookie(const SUBSCRIPTIONCOOKIE *pCookie, TCHAR *pszKeyName, DWORD cchKeyName) { WCHAR wszGuid[GUIDSTR_MAX];
ASSERT((NULL != pCookie) && (NULL != pszKeyName) && (cchKeyName >= ARRAYSIZE(WEBCHECK_REGKEY_STORE) + GUIDSTR_MAX));
if (StringFromGUID2(*pCookie, wszGuid, ARRAYSIZE(wszGuid))) { wnsprintfW(pszKeyName, cchKeyName, L"%s\\%s", c_szRegKeyStore, wszGuid); return TRUE; }
return FALSE; }
BOOL OpenItemKey(const SUBSCRIPTIONCOOKIE *pCookie, BOOL fCreateNew, REGSAM samDesired, HKEY *phkey) { TCHAR szKeyName[MAX_PATH];
ASSERT((NULL != pCookie) && (NULL != phkey));
if (ItemKeyNameFromCookie(pCookie, szKeyName, ARRAYSIZE(szKeyName))) { if (fCreateNew) { DWORD dwDisposition; return RegCreateKeyEx(HKEY_CURRENT_USER, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, phkey, &dwDisposition) == ERROR_SUCCESS; } else { return RegOpenKeyEx(HKEY_CURRENT_USER, szKeyName, 0, samDesired, phkey) == ERROR_SUCCESS; } }
return FALSE; }
// ISubscriptionMgr2 members
STDMETHODIMP CSubscriptionMgr::GetItemFromURL( /* [in] */ LPCWSTR pwszURL, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { return DoGetItemFromURLW(pwszURL, ppSubscriptionItem); }
STDMETHODIMP CSubscriptionMgr::GetItemFromCookie( /* [in] */ const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { if ((NULL == pSubscriptionCookie) || (NULL == ppSubscriptionItem)) { return E_INVALIDARG; }
return SubscriptionItemFromCookie(FALSE, pSubscriptionCookie, ppSubscriptionItem); }
STDMETHODIMP CSubscriptionMgr::GetSubscriptionRunState( /* [in] */ DWORD dwNumCookies, /* [in] */ const SUBSCRIPTIONCOOKIE *pSubscriptionCookies, /* [out] */ DWORD *pdwRunState) { HRESULT hr; if ((0 == dwNumCookies) || (NULL == pSubscriptionCookies) || (NULL == pdwRunState)) { return E_INVALIDARG; }
ISubscriptionThrottler *pst;
hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_ISubscriptionThrottler, (void **)&pst);
if (SUCCEEDED(hr)) { hr = pst->GetSubscriptionRunState(dwNumCookies, pSubscriptionCookies, pdwRunState); pst->Release(); } else { // Couldn't connect to a running throttler so assume nothing
// is running.
for (DWORD i = 0; i < dwNumCookies; i++) { *pdwRunState++ = 0; }
hr = S_FALSE; }
return hr; }
STDMETHODIMP CSubscriptionMgr::EnumSubscriptions( /* [in] */ DWORD dwFlags, /* [out] */ IEnumSubscription **ppEnumSubscriptions) { HRESULT hr;
if ((dwFlags & ~SUBSMGRENUM_MASK) || (NULL == ppEnumSubscriptions)) { return E_INVALIDARG; } CEnumSubscription *pes = new CEnumSubscription;
*ppEnumSubscriptions = NULL;
if (NULL != pes) { hr = pes->Initialize(dwFlags); if (SUCCEEDED(hr)) { hr = pes->QueryInterface(IID_IEnumSubscription, (void **)ppEnumSubscriptions); } pes->Release(); } else { hr = E_OUTOFMEMORY; } return hr; }
STDMETHODIMP CSubscriptionMgr::UpdateItems( /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwNumCookies, /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies) { HRESULT hr;
if ((dwFlags & ~SUBSMGRUPDATE_MASK) || (0 == dwNumCookies) || (NULL == pCookies)) { return E_INVALIDARG; }
//
// Fail if restrictions are in place.
// FEATURE: Should we have a flag parameter to override this?
//
if (SHRestricted2W(REST_NoManualUpdates, NULL, 0)) { SGMessageBox(NULL, IDS_RESTRICTED, MB_OK); return E_ACCESSDENIED; }
ISyncMgrSynchronizeInvoke *pSyncMgrInvoke; hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, IID_ISyncMgrSynchronizeInvoke, (void **)&pSyncMgrInvoke);
if (SUCCEEDED(hr)) { DWORD dwInvokeFlags = SYNCMGRINVOKE_STARTSYNC;
if (dwFlags & SUBSMGRUPDATE_MINIMIZE) { dwInvokeFlags |= SYNCMGRINVOKE_MINIMIZED; } hr = pSyncMgrInvoke->UpdateItems(dwInvokeFlags, CLSID_WebCheckOfflineSync, dwNumCookies * sizeof(SUBSCRIPTIONCOOKIE), (const BYTE *)pCookies); pSyncMgrInvoke->Release(); } return hr; }
STDMETHODIMP CSubscriptionMgr::AbortItems( /* [in] */ DWORD dwNumCookies, /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies) { return DoAbortItems(dwNumCookies, pCookies); }
STDMETHODIMP CSubscriptionMgr::AbortAll() { HRESULT hr;
ISubscriptionThrottler *pst;
hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_ISubscriptionThrottler, (void **)&pst);
if (SUCCEEDED(hr)) { hr = pst->AbortAll(); pst->Release(); } else { hr = S_FALSE; }
return hr; }
// ISubscriptionMgrPriv
STDMETHODIMP CSubscriptionMgr::CreateSubscriptionItem( /* [in] */ const SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo, /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { return DoCreateSubscriptionItem(pSubscriptionItemInfo, pNewCookie, ppSubscriptionItem); }
STDMETHODIMP CSubscriptionMgr::CloneSubscriptionItem( /* [in] */ ISubscriptionItem *pSubscriptionItem, /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie, /* [out] */ ISubscriptionItem **ppSubscriptionItem) { return DoCloneSubscriptionItem(pSubscriptionItem, pNewCookie, ppSubscriptionItem); }
STDMETHODIMP CSubscriptionMgr::DeleteSubscriptionItem( /* [in] */ const SUBSCRIPTIONCOOKIE *pCookie) { return DoDeleteSubscriptionItem(pCookie, TRUE); }
// ** CEnumSubscription **
CEnumSubscription::CEnumSubscription() { ASSERT(NULL == m_pCookies); ASSERT(0 == m_nCurrent); ASSERT(0 == m_nCount);
m_cRef = 1;
DllAddRef(); }
CEnumSubscription::~CEnumSubscription() { if (NULL != m_pCookies) { delete [] m_pCookies; }
DllRelease(); }
HRESULT CEnumSubscription::Initialize(DWORD dwFlags) { HRESULT hr = E_FAIL; HKEY hkey = NULL; DWORD dwDisposition;
ASSERT(0 == m_nCount);
if (RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegKeyStore, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS) { DWORD nCount;
if (RegQueryInfoKey(hkey, NULL, // address of buffer for class string
NULL, // address of size of class string buffer
NULL, // reserved
&nCount, // address of buffer for number of subkeys
NULL, // address of buffer for longest subkey name length
NULL, // address of buffer for longest class string length
NULL, // address of buffer for number of value entries
NULL, // address of buffer for longest value name length
NULL, // address of buffer for longest value data length
NULL, // address of buffer for security descriptor length
NULL // address of buffer for last write time
) == ERROR_SUCCESS) { SUBSCRIPTIONCOOKIE Cookie; m_pCookies = new SUBSCRIPTIONCOOKIE[nCount]; if (NULL != m_pCookies) { TCHAR szKeyName[GUIDSTR_MAX];
hr = S_OK;
for (ULONG i = 0; (i < nCount) && (S_OK == hr); i++) { if (RegEnumKey(hkey, i, szKeyName, ARRAYSIZE(szKeyName)) == ERROR_SUCCESS) { HRESULT hrConvert; hrConvert = CLSIDFromString(szKeyName, &Cookie);
if (SUCCEEDED(hrConvert)) { ISubscriptionItem *psi;
m_pCookies[m_nCount] = Cookie;
hr = SubscriptionItemFromCookie(FALSE, &Cookie, &psi); if (SUCCEEDED(hr)) { SUBSCRIPTIONITEMINFO sii; sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO); if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii))) { // Only count this if it's not a temporary
// or the caller asked for temporary items.
if ((!(sii.dwFlags & SI_TEMPORARY)) || (dwFlags & SUBSMGRENUM_TEMP)) { m_nCount++; } } psi->Release(); } } } } } else { hr = E_OUTOFMEMORY; } } RegCloseKey(hkey); }
return hr; }
// IUnknown members
STDMETHODIMP CEnumSubscription::QueryInterface(REFIID riid, void **ppv) { HRESULT hr;
if (NULL == ppv) { return E_INVALIDARG; }
if ((IID_IUnknown == riid) || (IID_IEnumSubscription == riid)) { *ppv = (IEnumSubscription *)this; AddRef(); hr = S_OK; } else { *ppv = NULL; hr = E_NOINTERFACE; } return hr; }
STDMETHODIMP_(ULONG) CEnumSubscription::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) CEnumSubscription::Release() { if (--m_cRef == 0) { delete this; return 0; }
return m_cRef; }
HRESULT CEnumSubscription::CopyRange(ULONG nStart, ULONG nCount, SUBSCRIPTIONCOOKIE *pCookies, ULONG *pnCopied) { ULONG nCopied = 0;
ASSERT((NULL != pCookies) && (NULL != pnCopied));
if (m_nCurrent < m_nCount) { ULONG nRemaining = m_nCount - m_nCurrent; nCopied = min(nRemaining, nCount); memcpy(pCookies, m_pCookies + m_nCurrent, nCopied * sizeof(SUBSCRIPTIONCOOKIE)); } *pnCopied = nCopied;
return (nCopied == nCount) ? S_OK : S_FALSE; }
// IEnumSubscription
STDMETHODIMP CEnumSubscription::Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ SUBSCRIPTIONCOOKIE *rgelt, /* [out] */ ULONG *pceltFetched) { HRESULT hr;
if ((0 == celt) || ((celt > 1) && (NULL == pceltFetched)) || (NULL == rgelt)) { return E_INVALIDARG; }
DWORD nFetched;
hr = CopyRange(m_nCurrent, celt, rgelt, &nFetched);
m_nCurrent += nFetched;
if (pceltFetched) { *pceltFetched = nFetched; }
return hr; }
STDMETHODIMP CEnumSubscription::Skip( /* [in] */ ULONG celt) { HRESULT hr; m_nCurrent += celt;
if (m_nCurrent > (m_nCount - 1)) { m_nCurrent = m_nCount; // Passed the last one
hr = S_FALSE; } else { hr = S_OK; } return hr; }
STDMETHODIMP CEnumSubscription::Reset() { m_nCurrent = 0;
return S_OK; }
STDMETHODIMP CEnumSubscription::Clone( /* [out] */ IEnumSubscription **ppenum) { HRESULT hr = E_OUTOFMEMORY;
*ppenum = NULL;
CEnumSubscription *pes = new CEnumSubscription;
if (NULL != pes) { pes->m_pCookies = new SUBSCRIPTIONCOOKIE[m_nCount];
if (NULL != pes->m_pCookies) { ULONG nFetched;
hr = E_FAIL;
pes->m_nCount = m_nCount; CopyRange(0, m_nCount, pes->m_pCookies, &nFetched);
ASSERT(m_nCount == nFetched);
if (m_nCount == nFetched) { hr = pes->QueryInterface(IID_IEnumSubscription, (void **)ppenum); } } pes->Release(); } return hr; }
STDMETHODIMP CEnumSubscription::GetCount( /* [out] */ ULONG *pnCount) { if (NULL == pnCount) { return E_INVALIDARG; }
*pnCount = m_nCount;
return S_OK; }
|