|
|
#include "private.h"
#include "subitem.h"
#include "subsmgrp.h"
#include "helper.h"
#include "offl_cpp.h" // Yech. Pidl stuff.
const TCHAR c_szSubscriptionInfoValue[] = TEXT("~SubsInfo");
#define c_wszSubscriptionInfoValue c_szSubscriptionInfoValue
// pragmas are for compatibility with the notification manager
// registry data structures which were not pack 8
#pragma pack(push, RegVariantBlob, 1)
//#pragma pack(8)
struct NT32PACKAGE { unsigned _int16 vt; /* VARTYPE *//* unsigned short int */ unsigned _int16 wReserved1; /* WORD *//* unsigned short int */ unsigned _int16 wReserved2; /* WORD *//* unsigned short int */ unsigned _int16 wReserved3; /* WORD *//* unsigned short int */
_int64 llVal; /* LONGLONG *//* __int64 */ };
// Q: What's going on here?
// A: Not a whole lot.
// We used to store a variant in the registry. Unfortunately, variants are
// 16 bytes on Win32 (8 byte header + 8 bytes of data)
// 24 bytes on Win64 (8 byte header + 16 bytes of data)
// Unfortunately, Win64 webcheck and Win32 webcheck both read from
// the same registry location, i.e. the same blob, and won't understand one another.
// Thus, boom! At least, for BSTRs that are stored inline
// Fortunately, we care only about only the first 16 bytes on both platforms.
// Ergo, it's sufficient to store only the top half of the Win64 variant.
struct SimpleVariantBlob { NT32PACKAGE var; };
struct BSTRVariantBlob : public SimpleVariantBlob { DWORD dwSize; // WCHAR wsz[]; // Variable length string
};
struct OldBSTRVariantBlob { DWORD dwSize; VARIANT var; };
struct SignatureSimpleBlob { DWORD dwSignature; SimpleVariantBlob svb; };
struct SignatureBSTRBlob { DWORD dwSignature; BSTRVariantBlob bvb; };
#pragma pack(pop, RegVariantBlob)
#define BLOB_SIGNATURE 0x4b434f4d
// We need fStream to indicate when we're upgrading IE4-style streams-of-blobs. (IE6 24398)
HRESULT BlobToVariant(BYTE *pData, DWORD cbData, VARIANT *pVar, DWORD *pcbUsed, BOOL fStream) { HRESULT hr = S_OK; SimpleVariantBlob *pBlob = (SimpleVariantBlob *)pData;
ASSERT(NULL != pBlob); ASSERT(cbData >= sizeof(SimpleVariantBlob)); ASSERT(NULL != pVar);
if ((NULL != pBlob) && (cbData >= sizeof(SimpleVariantBlob)) && (NULL != pVar)) { memcpy(pVar, &pBlob->var, sizeof(NT32PACKAGE));
switch (pVar->vt) { case VT_I4: // LONG
case VT_UI1: // BYTE
case VT_I2: // SHORT
case VT_R4: // FLOAT
case VT_R8: // DOUBLE
case VT_BOOL: // VARIANT_BOOL
case VT_ERROR: // SCODE
case VT_CY: // CY
case VT_DATE: // DATE
case VT_I1: // CHAR
case VT_UI2: // USHORT
case VT_UI4: // ULONG
case VT_INT: // INT
case VT_UINT: // UINT
if (pcbUsed) { *pcbUsed = sizeof(SimpleVariantBlob); } break;
case VT_BSTR: // BSTR
hr = E_UNEXPECTED;
ASSERT(cbData >= sizeof(BSTRVariantBlob));
if (cbData >= sizeof(BSTRVariantBlob)) { BSTRVariantBlob *pbstrBlob = (BSTRVariantBlob *)pData; DWORD dwSize = pbstrBlob->dwSize;
#ifdef WIN64
ASSERT((cbData==(sizeof(BSTRVariantBlob) + dwSize)) || (cbData==(sizeof(OldBSTRVariantBlob) + dwSize))); #else
ASSERT((cbData==(sizeof(BSTRVariantBlob) + dwSize)) || (fStream && (cbData>=(sizeof(BSTRVariantBlob) + dwSize))));
#endif
if ((cbData==(sizeof(BSTRVariantBlob) + dwSize)) || (fStream && (cbData>=(sizeof(BSTRVariantBlob) + dwSize)))) { pVar->bstrVal = SysAllocStringByteLen(NULL, dwSize);
if (NULL != pVar->bstrVal) { if (pcbUsed) { *pcbUsed = sizeof(BSTRVariantBlob) + pbstrBlob->dwSize; } memcpy(pVar->bstrVal, ((BYTE *)pbstrBlob) + (FIELD_OFFSET(BSTRVariantBlob, dwSize) + sizeof(dwSize)), dwSize); hr = S_OK; } else { hr = E_OUTOFMEMORY; } } } if (FAILED(hr)) { pVar->vt = VT_EMPTY; } break;
default: hr = E_NOTIMPL; break; } } else { hr = E_UNEXPECTED; }
return hr; }
HRESULT SignatureBlobToVariant(BYTE *pData, DWORD cbData, VARIANT *pVar) { HRESULT hr; SignatureSimpleBlob *pBlob = (SignatureSimpleBlob *)pData;
ASSERT(NULL != pBlob); ASSERT(cbData >= sizeof(SignatureSimpleBlob)); ASSERT(NULL != pVar); ASSERT(BLOB_SIGNATURE == pBlob->dwSignature);
if ((NULL != pBlob) && (cbData >= sizeof(SignatureSimpleBlob)) && (NULL != pVar) && (BLOB_SIGNATURE == pBlob->dwSignature)) { hr = BlobToVariant((BYTE *)&pBlob->svb, cbData - (FIELD_OFFSET(SignatureSimpleBlob, svb)), pVar, NULL); } else { hr = E_UNEXPECTED; }
return hr; }
HRESULT VariantToSignatureBlob(const VARIANT *pVar, BYTE **ppData, DWORD *pdwSize) { HRESULT hr;
ASSERT(NULL != pVar); ASSERT(NULL != ppData); ASSERT(NULL != pdwSize);
if ((NULL != pVar) && (NULL != ppData) && (NULL != pdwSize)) { DWORD dwSize; DWORD dwBstrLen = 0;
hr = S_OK; switch (pVar->vt) { case VT_I4: // LONG
case VT_UI1: // BYTE
case VT_I2: // SHORT
case VT_R4: // FLOAT
case VT_R8: // DOUBLE
case VT_BOOL: // VARIANT_BOOL
case VT_ERROR: // SCODE
case VT_CY: // CY
case VT_DATE: // DATE
case VT_I1: // CHAR
case VT_UI2: // USHORT
case VT_UI4: // ULONG
case VT_INT: // INT
case VT_UINT: // UINT
dwSize = sizeof(SignatureSimpleBlob); break;
case VT_BSTR: // BSTR
if (NULL != pVar->bstrVal) dwBstrLen = SysStringByteLen(pVar->bstrVal); dwSize = sizeof(SignatureBSTRBlob) + dwBstrLen; break; default: hr = E_NOTIMPL; dwSize = 0; break; }
if (SUCCEEDED(hr)) { SignatureSimpleBlob *pSignatureBlob = (SignatureSimpleBlob *)new BYTE[dwSize];
if (NULL != pSignatureBlob) { *ppData = (BYTE *)pSignatureBlob; *pdwSize = dwSize; pSignatureBlob->dwSignature = BLOB_SIGNATURE;
switch (pVar->vt) { case VT_I4: // LONG
case VT_UI1: // BYTE
case VT_I2: // SHORT
case VT_R4: // FLOAT
case VT_R8: // DOUBLE
case VT_BOOL: // VARIANT_BOOL
case VT_ERROR: // SCODE
case VT_CY: // CY
case VT_DATE: // DATE
case VT_I1: // CHAR
case VT_UI2: // USHORT
case VT_UI4: // ULONG
case VT_INT: // INT
case VT_UINT: // UINT
{ SimpleVariantBlob *pBlob = &pSignatureBlob->svb;
memcpy(&pBlob->var, pVar, sizeof(NT32PACKAGE)); break; }
case VT_BSTR: // BSTR
{ BSTRVariantBlob *pbstrBlob = &((SignatureBSTRBlob *)pSignatureBlob)->bvb; memcpy(&pbstrBlob->var, pVar, sizeof(NT32PACKAGE)); pbstrBlob->dwSize = dwBstrLen; memcpy(((BYTE *)pbstrBlob) + (FIELD_OFFSET(BSTRVariantBlob, dwSize) + sizeof(dwSize)), pVar->bstrVal, dwBstrLen); break; } default: ASSERT(0); // Default case should have been eliminated!
break; } } else { hr = E_OUTOFMEMORY; } } } else { hr = E_INVALIDARG; }
return hr; }
CEnumItemProperties::CEnumItemProperties() { ASSERT(0 == m_nCurrent); ASSERT(0 == m_nCount); ASSERT(NULL == m_pItemProps);
m_cRef = 1;
DllAddRef(); }
CEnumItemProperties::~CEnumItemProperties() { if (NULL != m_pItemProps) { for (ULONG i = 0; i < m_nCount; i++) { VariantClear(&m_pItemProps[i].variantValue); if (NULL != m_pItemProps[i].pwszName) { CoTaskMemFree(m_pItemProps[i].pwszName); } } delete [] m_pItemProps; } DllRelease(); }
HRESULT CEnumItemProperties::Initialize(const SUBSCRIPTIONCOOKIE *pCookie, ISubscriptionItem *psi) { HRESULT hr = E_FAIL; HKEY hkey;
ASSERT(NULL != pCookie);
if (OpenItemKey(pCookie, FALSE, KEY_READ, &hkey)) { DWORD dwMaxValNameSize; DWORD dwMaxDataSize; DWORD dwCount;
if (RegQueryInfoKey(hkey, NULL, // address of buffer for class string
NULL, // address of size of class string buffer
NULL, // reserved
NULL, // 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
&dwCount, // address of buffer for number of value entries
&dwMaxValNameSize, // address of buffer for longest value name length
&dwMaxDataSize, // 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) { // This allocates enough for Password as well
m_pItemProps = new ITEMPROP[dwCount];
dwMaxValNameSize++; // Need room for NULL
// alloca candidates:
TCHAR *pszValName = new TCHAR[dwMaxValNameSize]; BYTE *pData = new BYTE[dwMaxDataSize]; if ((NULL != m_pItemProps) && (NULL != pData) && (NULL != pszValName) ) { hr = S_OK;
for (ULONG i = 0; i < dwCount; i++) { DWORD dwType; DWORD dwSize = dwMaxDataSize; DWORD dwNameSize = dwMaxValNameSize;
if (SHEnumValue(hkey, i, pszValName, &dwNameSize, &dwType, pData, &dwSize) != ERROR_SUCCESS) { hr = E_UNEXPECTED; break; }
// Skip the default value and our subscription info structure
if ((NULL == *pszValName) || (0 == StrCmp(pszValName, c_szSubscriptionInfoValue)) ) { continue; }
if (dwType != REG_BINARY) { hr = E_UNEXPECTED; break; }
hr = SignatureBlobToVariant(pData, dwSize, &m_pItemProps[m_nCount].variantValue); if (SUCCEEDED(hr)) { WCHAR *pwszName; pwszName = pszValName;
ULONG ulSize = (lstrlenW(pwszName) + 1) * sizeof(WCHAR); m_pItemProps[m_nCount].pwszName = (WCHAR *)CoTaskMemAlloc(ulSize); if (NULL != m_pItemProps[m_nCount].pwszName) { StrCpyNW(m_pItemProps[m_nCount].pwszName, pwszName, ulSize / sizeof(WCHAR)); } else { hr = E_OUTOFMEMORY; break; } m_nCount++; } else { break; } }
if (SUCCEEDED(ReadPassword(psi, &m_pItemProps[m_nCount].variantValue.bstrVal))) { ULONG ulSize = sizeof(L"Password"); m_pItemProps[m_nCount].pwszName = (WCHAR *)CoTaskMemAlloc(ulSize);
if (NULL != m_pItemProps[m_nCount].pwszName) { StrCpyNW(m_pItemProps[m_nCount].pwszName, L"Password", ulSize / sizeof(WCHAR)); m_pItemProps[m_nCount].variantValue.vt = VT_BSTR; m_nCount++; } else { SysFreeString(m_pItemProps[m_nCount].variantValue.bstrVal); } } } else { hr = E_OUTOFMEMORY; } SAFEDELETE(pszValName); SAFEDELETE(pData); } RegCloseKey(hkey); } return hr; }
// IUnknown members
STDMETHODIMP CEnumItemProperties::QueryInterface(REFIID riid, void **ppv) { HRESULT hr;
if (NULL == ppv) { return E_INVALIDARG; }
if ((IID_IUnknown == riid) || (IID_IEnumItemProperties == riid)) { *ppv = (IEnumItemProperties *)this; AddRef(); hr = S_OK; } else { *ppv = NULL; hr = E_NOINTERFACE; } return hr; }
STDMETHODIMP_(ULONG) CEnumItemProperties::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) CEnumItemProperties::Release() { if (--m_cRef == 0) { delete this; return 0; }
return m_cRef; }
HRESULT CEnumItemProperties::CopyItem(ITEMPROP *pip, WCHAR *pwszName, VARIANT *pVar) { HRESULT hr;
ASSERT(NULL != pwszName); if (NULL != pwszName) { ULONG cb = (lstrlenW(pwszName) + 1) * sizeof(WCHAR);
pip->pwszName = (WCHAR *)CoTaskMemAlloc(cb); if (NULL != pip->pwszName) { StrCpyNW(pip->pwszName, pwszName, cb /sizeof(WCHAR)); pip->variantValue.vt = VT_EMPTY; // is this a good idea?
hr = VariantCopy(&pip->variantValue, pVar); } else { hr = E_OUTOFMEMORY; } } else { hr = E_UNEXPECTED; }
return hr; }
HRESULT CEnumItemProperties::CopyRange(ULONG nStart, ULONG nCount, ITEMPROP *ppip, ULONG *pnCopied) { HRESULT hr = S_OK; ULONG n = 0; ULONG i;
ASSERT((NULL != ppip) && (NULL != pnCopied)); for (i = nStart; (S_OK == hr) && (i < m_nCount) && (n < nCount); i++, n++) { hr = CopyItem(&ppip[n], m_pItemProps[i].pwszName, &m_pItemProps[i].variantValue); }
*pnCopied = n;
if (SUCCEEDED(hr)) { hr = (n == nCount) ? S_OK : S_FALSE; } return hr; }
// IEnumItemProperties
STDMETHODIMP CEnumItemProperties::Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ITEMPROP *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 CEnumItemProperties::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 CEnumItemProperties::Reset() { m_nCurrent = 0;
return S_OK; }
STDMETHODIMP CEnumItemProperties::Clone( /* [out] */ IEnumItemProperties **ppenum) { HRESULT hr = E_OUTOFMEMORY;
*ppenum = NULL;
CEnumItemProperties *peip = new CEnumItemProperties;
if (NULL != peip) { peip->m_pItemProps = new ITEMPROP[m_nCount];
if (NULL != peip->m_pItemProps) { ULONG nFetched;
hr = E_FAIL;
peip->m_nCount = m_nCount; hr = CopyRange(0, m_nCount, peip->m_pItemProps, &nFetched);
if (SUCCEEDED(hr)) { ASSERT(m_nCount == nFetched);
if (m_nCount == nFetched) { hr = peip->QueryInterface(IID_IEnumItemProperties, (void **)ppenum); } } } peip->Release(); } return hr; }
STDMETHODIMP CEnumItemProperties::GetCount( /* [out] */ ULONG *pnCount) { if (NULL == pnCount) { return E_INVALIDARG; }
*pnCount = m_nCount;
return S_OK; }
CSubscriptionItem::CSubscriptionItem(const SUBSCRIPTIONCOOKIE *pCookie, HKEY hkey) { ASSERT(NULL != pCookie); ASSERT(0 == m_dwFlags);
m_cRef = 1;
if (NULL != pCookie) { m_Cookie = *pCookie; }
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
if ((hkey != NULL) && SUCCEEDED(Read(hkey, c_wszSubscriptionInfoValue, (BYTE *)&sii, sizeof(SUBSCRIPTIONITEMINFO))))
{ m_dwFlags = sii.dwFlags; }
DllAddRef(); }
CSubscriptionItem::~CSubscriptionItem() { if (m_dwFlags & SI_TEMPORARY) { TCHAR szKey[MAX_PATH];
if (ItemKeyNameFromCookie(&m_Cookie, szKey, ARRAYSIZE(szKey))) { SHDeleteKey(HKEY_CURRENT_USER, szKey); } } DllRelease(); }
HRESULT CSubscriptionItem::Read(HKEY hkeyIn, const WCHAR *pwszValueName, BYTE *pData, DWORD dwDataSize) { HRESULT hr = E_FAIL; HKEY hkey = hkeyIn;
ASSERT((NULL != pwszValueName) && (NULL != pData) && (0 != dwDataSize));
if ((NULL != hkey) || OpenItemKey(&m_Cookie, FALSE, KEY_READ, &hkey)) { DWORD dwType; DWORD dwSize = dwDataSize;
if ((RegQueryValueExW(hkey, pwszValueName, NULL, &dwType, pData, &dwSize) == ERROR_SUCCESS) && (dwSize == dwDataSize) && (REG_BINARY == dwType)) { hr = S_OK; } if (NULL == hkeyIn) { RegCloseKey(hkey); } } return hr; }
HRESULT CSubscriptionItem::ReadWithAlloc(HKEY hkeyIn, const WCHAR *pwszValueName, BYTE **ppData, DWORD *pdwDataSize) { HRESULT hr = E_FAIL; HKEY hkey = hkeyIn;
ASSERT((NULL != pwszValueName) && (NULL != ppData) && (NULL != pdwDataSize));
if ((NULL != hkey) || OpenItemKey(&m_Cookie, FALSE, KEY_READ, &hkey)) { DWORD dwType; DWORD dwSize = 0;
if (RegQueryValueExW(hkey, pwszValueName, NULL, &dwType, NULL, &dwSize) == ERROR_SUCCESS) { BYTE *pData = new BYTE[dwSize]; *pdwDataSize = dwSize;
if (NULL != pData) { if ((RegQueryValueExW(hkey, pwszValueName, NULL, &dwType, pData, pdwDataSize) == ERROR_SUCCESS) && (dwSize == *pdwDataSize) && (REG_BINARY == dwType)) { *ppData = pData; hr = S_OK; } else { delete [] pData; } } else { hr = E_OUTOFMEMORY; } } if (NULL == hkeyIn) { RegCloseKey(hkey); } } return hr; }
HRESULT CSubscriptionItem::Write(HKEY hkeyIn, const WCHAR *pwszValueName, BYTE *pData, DWORD dwDataSize) { HRESULT hr = E_FAIL; HKEY hkey = hkeyIn;
ASSERT((NULL != pwszValueName) && (NULL != pData) && (0 != dwDataSize));
if ((NULL != hkey) || OpenItemKey(&m_Cookie, FALSE, KEY_WRITE, &hkey)) { if (RegSetValueExW(hkey, pwszValueName, 0, REG_BINARY, pData, dwDataSize) == ERROR_SUCCESS) { hr = S_OK; } if (NULL == hkeyIn) { RegCloseKey(hkey); } } return hr; }
STDMETHODIMP CSubscriptionItem::QueryInterface(REFIID riid, void **ppv) { HRESULT hr;
if (NULL == ppv) { return E_INVALIDARG; }
if ((IID_IUnknown == riid) || (IID_ISubscriptionItem == riid)) { *ppv = (ISubscriptionItem *)this; AddRef(); hr = S_OK; } else { *ppv = NULL; hr = E_NOINTERFACE; } return hr; }
STDMETHODIMP_(ULONG) CSubscriptionItem::AddRef() { return ++m_cRef; }
STDMETHODIMP_(ULONG) CSubscriptionItem::Release() { if (--m_cRef == 0) { delete this; return 0; }
return m_cRef; }
STDMETHODIMP CSubscriptionItem::GetCookie(SUBSCRIPTIONCOOKIE *pCookie) { if (NULL == pCookie) { return E_INVALIDARG; }
*pCookie = m_Cookie;
return S_OK; }
STDMETHODIMP CSubscriptionItem::GetSubscriptionItemInfo( /* [out] */ SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo) { HRESULT hr;
if ((NULL == pSubscriptionItemInfo) || (pSubscriptionItemInfo->cbSize < sizeof(SUBSCRIPTIONITEMINFO))) { return E_INVALIDARG; }
hr = Read(NULL, c_wszSubscriptionInfoValue, (BYTE *)pSubscriptionItemInfo, sizeof(SUBSCRIPTIONITEMINFO));
ASSERT(sizeof(SUBSCRIPTIONITEMINFO) == pSubscriptionItemInfo->cbSize); if (SUCCEEDED(hr) && (sizeof(SUBSCRIPTIONITEMINFO) != pSubscriptionItemInfo->cbSize)) { hr = E_UNEXPECTED; }
return hr; }
STDMETHODIMP CSubscriptionItem::SetSubscriptionItemInfo( /* [in] */ const SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo) { if ((NULL == pSubscriptionItemInfo) || (pSubscriptionItemInfo->cbSize < sizeof(SUBSCRIPTIONITEMINFO))) { return E_INVALIDARG; }
m_dwFlags = pSubscriptionItemInfo->dwFlags; return Write(NULL, c_wszSubscriptionInfoValue, (BYTE *)pSubscriptionItemInfo, sizeof(SUBSCRIPTIONITEMINFO)); }
STDMETHODIMP CSubscriptionItem::ReadProperties( ULONG nCount, /* [size_is][in] */ const LPCWSTR rgwszName[], /* [size_is][out] */ VARIANT rgValue[]) { HRESULT hr = S_OK; if ((0 == nCount) || (NULL == rgwszName) || (NULL == rgValue)) { return E_INVALIDARG; }
HKEY hkey;
if (OpenItemKey(&m_Cookie, FALSE, KEY_READ, &hkey)) { for (ULONG i = 0; (i < nCount) && (S_OK == hr); i++) { BYTE *pData; DWORD dwDataSize;
if (StrCmpIW(rgwszName[i], c_szPropPassword) == 0) { if (SUCCEEDED(ReadPassword(this, &rgValue[i].bstrVal))) { rgValue[i].vt = VT_BSTR; } else { rgValue[i].vt = VT_EMPTY; } } else { HRESULT hrRead = ReadWithAlloc(hkey, rgwszName[i], &pData, &dwDataSize);
if (SUCCEEDED(hrRead)) { hr = SignatureBlobToVariant(pData, dwDataSize, &rgValue[i]); delete [] pData; } else { rgValue[i].vt = VT_EMPTY; } } } RegCloseKey(hkey); } else { hr = E_FAIL; }
return hr; }
STDMETHODIMP CSubscriptionItem::WriteProperties( ULONG nCount, /* [size_is][in] */ const LPCWSTR rgwszName[], /* [size_is][in] */ const VARIANT rgValue[]) { HRESULT hr = S_OK; if ((0 == nCount) || (NULL == rgwszName) || (NULL == rgValue)) { return E_INVALIDARG; }
HKEY hkey;
if (OpenItemKey(&m_Cookie, FALSE, KEY_WRITE, &hkey)) { for (ULONG i = 0; (i < nCount) && (S_OK == hr); i++) { if (rgValue[i].vt == VT_EMPTY) { // We don't actually care if this fails since it is
// meant to delete the property anyhow
RegDeleteValueW(hkey, rgwszName[i]); } else { BYTE *pData; DWORD dwDataSize;
// Special case the name property for easy viewing
if ((VT_BSTR == rgValue[i].vt) && (StrCmpIW(rgwszName[i], c_szPropName) == 0)) { RegSetValueExW(hkey, NULL, 0, REG_SZ, (LPBYTE)rgValue[i].bstrVal, (lstrlenW(rgValue[i].bstrVal) + 1) * sizeof(WCHAR)); }
if (StrCmpIW(rgwszName[i], c_szPropPassword) == 0) { if (VT_BSTR == rgValue[i].vt) { hr = WritePassword(this, rgValue[i].bstrVal); } else { hr = E_INVALIDARG; } } else { hr = VariantToSignatureBlob(&rgValue[i], &pData, &dwDataSize);
if (SUCCEEDED(hr)) { hr = Write(hkey, rgwszName[i], pData, dwDataSize); delete [] pData; } } } } RegCloseKey(hkey); } else { hr = E_FAIL; }
return hr; }
STDMETHODIMP CSubscriptionItem::EnumProperties( /* [out] */ IEnumItemProperties **ppEnumItemProperties) { HRESULT hr;
if (NULL == ppEnumItemProperties) { return E_INVALIDARG; } CEnumItemProperties *peip = new CEnumItemProperties;
*ppEnumItemProperties = NULL;
if (NULL != peip) { hr = peip->Initialize(&m_Cookie, this); if (SUCCEEDED(hr)) { hr = peip->QueryInterface(IID_IEnumItemProperties, (void **)ppEnumItemProperties); } peip->Release(); } else { hr = E_OUTOFMEMORY; } return hr; }
STDMETHODIMP CSubscriptionItem::NotifyChanged() { HRESULT hr;
// Notify the shell folder of the updated item
// This is SOMEWHAT inefficient... why do we need 1000 properties for a pidl?
// Why do we copy them around? Why why why?
OOEBuf ooeBuf; LPMYPIDL newPidl = NULL; DWORD dwSize = 0;
memset(&ooeBuf, 0, sizeof(ooeBuf));
hr = LoadWithCookie(NULL, &ooeBuf, &dwSize, &m_Cookie);
if (SUCCEEDED(hr)) { newPidl = COfflineFolderEnum::NewPidl(dwSize); if (newPidl) { CopyToMyPooe(&ooeBuf, &(newPidl->ooe)); _GenerateEvent(SHCNE_UPDATEITEM, (LPITEMIDLIST)newPidl, NULL); COfflineFolderEnum::FreePidl(newPidl); } }
return hr; }
|