You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
921 lines
24 KiB
921 lines
24 KiB
#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;
|
|
}
|
|
|
|
|