|
|
#include "priv.h"
#include "varutil.h"
#define COMPILE_MULTIMON_STUBS
#include "multimon.h"
#define MAX_PROPERTY_SIZE 2048
// simple inline base class.
class CBasePropertyBag : public IPropertyBag, IPropertyBag2 { public: // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CBasePropertyBag, IPropertyBag), QITABENT(CBasePropertyBag, IPropertyBag2), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }
STDMETHODIMP_(ULONG) Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
// IPropertyBag
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) PURE; STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar) PURE;
// IPropertyBag2 (note, does not derive from IPropertyBag)
STDMETHODIMP Read(ULONG cProperties, PROPBAG2 *pPropBag, IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError); STDMETHODIMP Write(ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue); STDMETHODIMP CountProperties(ULONG *pcProperties); STDMETHODIMP GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2 *pPropBag, ULONG *pcProperties); STDMETHODIMP LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown *pUnkObject, IErrorLog *pErrLog);
protected: // methods
CBasePropertyBag() {} // DONT DELETE ME
CBasePropertyBag(DWORD grfMode) : _cRef(1), _grfMode(grfMode) {}
virtual ~CBasePropertyBag() {} // DONT DELETE ME
HRESULT _CanRead(void) { return STGM_WRITE != (_grfMode & (STGM_WRITE | STGM_READWRITE)) ? S_OK : E_ACCESSDENIED;}
HRESULT _CanWrite(void) { return (_grfMode & (STGM_WRITE | STGM_READWRITE)) ? S_OK : E_ACCESSDENIED;}
protected: // members
LONG _cRef; DWORD _grfMode; };
STDMETHODIMP CBasePropertyBag::Read(ULONG cProperties, PROPBAG2 *pPropBag, IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError) { return E_NOTIMPL; }
STDMETHODIMP CBasePropertyBag::Write(ULONG cProperties, PROPBAG2 *pPropBag, VARIANT *pvarValue) { return E_NOTIMPL; }
STDMETHODIMP CBasePropertyBag::CountProperties(ULONG *pcProperties) { return E_NOTIMPL; }
STDMETHODIMP CBasePropertyBag::GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2 *pPropBag, ULONG *pcProperties) { return E_NOTIMPL; }
STDMETHODIMP CBasePropertyBag::LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown *pUnkObject, IErrorLog *pErrLog) { return E_NOTIMPL; }
//
// Ini file property bag implementation
//
class CIniPropertyBag : public CBasePropertyBag {
public: // IPropertyBag
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar);
protected: // methods
CIniPropertyBag(DWORD grfMode) : CBasePropertyBag(grfMode) {} virtual ~CIniPropertyBag(); HRESULT _Init(LPCWSTR pszFile, LPCWSTR pszSection); HRESULT _GetSectionAndName(LPCWSTR pszProp, LPWSTR pszSection, UINT cchSec, LPWSTR pszName, UINT cchName);
protected: // members
LPWSTR _pszFile; LPWSTR _pszSection;
friend HRESULT SHCreatePropertyBagOnProfileSection(LPCWSTR pszFile, LPCWSTR pszSection, DWORD grfMode, REFIID riid, void **ppv); };
CIniPropertyBag::~CIniPropertyBag() { LocalFree(_pszFile); // accepts NULL
LocalFree(_pszSection); // accepts NULL
}
HRESULT CIniPropertyBag::_Init(LPCWSTR pszFile, LPCWSTR pszSection) { HRESULT hr = E_OUTOFMEMORY;
_pszFile = StrDupW(pszFile); if (_pszFile) { if (pszSection) { _pszSection = StrDupW(pszSection); if (_pszSection) hr = S_OK; } else { hr = S_OK; } }
return hr; }
// support the <section name>.<prop name> scheme
HRESULT CIniPropertyBag::_GetSectionAndName(LPCWSTR pszProp, LPWSTR pszSection, UINT cchSec, LPWSTR pszName, UINT cchName) { HRESULT hr; LPCWSTR pszSlash = StrChrW(pszProp, L'\\'); if (pszSlash) { StrCpyNW(pszSection, pszProp, min((UINT)(pszSlash - pszProp) + 1, cchSec)); StrCpyNW(pszName, pszSlash + 1, cchName); hr = S_OK; } else if (_pszSection) { StrCpyNW(pszSection, _pszSection, cchSec); StrCpyNW(pszName, pszProp, cchName); hr = S_OK; } else { hr = E_INVALIDARG; } return hr; }
// only supports strings. use VariantChangeType() to suppor others
HRESULT CIniPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pvar, IErrorLog *pErrorLog) { VARTYPE vtDesired = pvar->vt;
VariantInit(pvar);
HRESULT hr = _CanRead(); if (SUCCEEDED(hr)) { WCHAR szSec[64], szName[64]; hr = _GetSectionAndName(pszPropName, szSec, ARRAYSIZE(szSec), szName, ARRAYSIZE(szName)); if (SUCCEEDED(hr)) { WCHAR sz[MAX_PROPERTY_SIZE]; if (SHGetIniStringUTF7W(szSec, szName, sz, ARRAYSIZE(sz), _pszFile)) { pvar->bstrVal = SysAllocString(sz); if (pvar->bstrVal) { pvar->vt = VT_BSTR;
hr = VariantChangeTypeForRead(pvar, vtDesired); } else { hr = E_OUTOFMEMORY; } } else { hr = E_FAIL; } } } return hr; }
// only writes as strings to the INI file, we use VariantChangeType() to morp the types.
HRESULT CIniPropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pvar) { HRESULT hr = _CanWrite(); if (SUCCEEDED(hr)) { LPCWSTR psz = pvar->vt == VT_EMPTY ? NULL : pvar->bstrVal; VARIANT var = { 0 }; if ((pvar->vt != VT_EMPTY) && (pvar->vt != VT_BSTR)) { hr = VariantChangeType(&var, pvar, 0, VT_BSTR); if (SUCCEEDED(hr)) psz = var.bstrVal; }
if (SUCCEEDED(hr)) { WCHAR szSec[64], szName[64]; hr = _GetSectionAndName(pszPropName, szSec, ARRAYSIZE(szSec), szName, ARRAYSIZE(szName)); if (SUCCEEDED(hr)) { if (!SHSetIniStringUTF7W(szSec, szName, psz, _pszFile)) { hr = E_FAIL; } else { SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW, _pszFile, NULL); } } }
VariantClear(&var); } return hr; }
HRESULT SHCreatePropertyBagOnProfileSection(LPCWSTR pszFile, LPCWSTR pszSection, DWORD grfMode, REFIID riid, void **ppv) { if (grfMode & STGM_CREATE) { // we need to touch this file first
HANDLE h = CreateFileW(pszFile, 0, FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL); if (INVALID_HANDLE_VALUE != h) { WCHAR szFolder[MAX_PATH]; StrCpyNW(szFolder, pszFile, ARRAYSIZE(szFolder)); if (PathRemoveFileSpecW(szFolder)) { PathMakeSystemFolderW(szFolder); } CloseHandle(h); } }
if (PathFileExistsAndAttributesW(pszFile, NULL)) { CIniPropertyBag *pbag = new CIniPropertyBag(grfMode); if (pbag) { HRESULT hr = pbag->_Init(pszFile, pszSection); if (SUCCEEDED(hr)) hr = pbag->QueryInterface(riid, ppv); pbag->Release();
return hr; } }
*ppv = NULL; return E_OUTOFMEMORY; }
//
// Registry property bag implementation
//
class CRegPropertyBag : public CBasePropertyBag { public: // IPropertyBag
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar);
protected: // methods
CRegPropertyBag(DWORD grfMode); virtual ~CRegPropertyBag(); HRESULT _Init(HKEY hk, LPCWSTR pszSubKey); friend HRESULT SHCreatePropertyBagOnRegKey(HKEY hk, LPCWSTR pszSubKey, DWORD grfMode, REFIID riid, void **ppv);
private: HRESULT _ReadDword(LPCOLESTR pszPropName, VARIANT *pvar); HRESULT _ReadString(LPCOLESTR pszPropName, VARIANT *pvar, DWORD cb); HRESULT _ReadStream(VARIANT* pvar, BYTE* pBuff, DWORD cb); HRESULT _ReadBinary(LPCOLESTR pszPropName, VARIANT* pvar, VARTYPE vt, DWORD cb); HRESULT _GetStreamSize(IStream* pstm, DWORD* pcb); HRESULT _CopyStreamIntoBuff(IStream* pstm, BYTE* pBuff, DWORD cb); HRESULT _WriteStream(LPCOLESTR pszPropName, IStream* pstm);
protected: // members
HKEY _hk;
friend HRESULT SHCreatePropertyBagOnRegKey(HKEY hk, LPCWSTR pszSubKey, DWORD grfMode, REFIID riid, void **ppv); };
CRegPropertyBag::CRegPropertyBag(DWORD grfMode) : CBasePropertyBag(grfMode) { ASSERT(NULL == _hk); }
CRegPropertyBag::~CRegPropertyBag() { if (_hk) RegCloseKey(_hk); }
HRESULT CRegPropertyBag::_Init(HKEY hk, LPCWSTR pszSubKey) { DWORD err; REGSAM sam = 0;
if (SUCCEEDED(_CanRead())) sam |= KEY_READ;
if (SUCCEEDED(_CanWrite())) sam |= KEY_WRITE;
if (_grfMode & STGM_CREATE) err = RegCreateKeyExW(hk, pszSubKey, 0, NULL, 0, sam, NULL, &_hk, NULL); else err = RegOpenKeyExW(hk, pszSubKey, 0, sam, &_hk);
return HRESULT_FROM_WIN32(err); }
HRESULT CRegPropertyBag::_ReadDword(LPCOLESTR pszPropName, VARIANT *pvar) { HRESULT hr;
DWORD dwType; DWORD cb = sizeof(pvar->lVal);
if (NOERROR == SHGetValueW(_hk, NULL, pszPropName, &dwType, &pvar->lVal, &cb)) { ASSERT(REG_DWORD == dwType); pvar->vt = VT_UI4; hr = S_OK; } else { hr = E_FAIL; }
return hr; }
HRESULT CRegPropertyBag::_ReadString(LPCOLESTR pszPropName, VARIANT *pvar, DWORD cb) { HRESULT hr;
DWORD dwType; pvar->bstrVal = SysAllocStringByteLen(NULL, cb);
if (pvar->bstrVal) { pvar->vt = VT_BSTR;
if (NOERROR == SHGetValueW(_hk, NULL, pszPropName, &dwType, pvar->bstrVal, &cb)) { hr = S_OK; } else { VariantClear(pvar); hr = E_FAIL; } } else { hr = E_OUTOFMEMORY; }
return hr; }
HRESULT CRegPropertyBag::_ReadStream(VARIANT* pvar, BYTE* pBuff, DWORD cb) { HRESULT hr;
pvar->punkVal = SHCreateMemStream(pBuff, cb);
if (pvar->punkVal) { pvar->vt = VT_UNKNOWN; hr = S_OK; } else { hr = E_OUTOFMEMORY; }
return hr; }
HRESULT CRegPropertyBag::_ReadBinary(LPCOLESTR pszPropName, VARIANT* pvar, VARTYPE vt, DWORD cb) { HRESULT hr;
switch(vt) { case VT_UNKNOWN: hr = E_FAIL; if (EVAL(cb >= sizeof(GUID))) { BYTE* pBuff = static_cast<BYTE*>(LocalAlloc(LPTR, cb)); if (pBuff) { DWORD dwType; if (NOERROR == SHGetValueW(_hk, NULL, pszPropName, &dwType, pBuff, &cb)) { GUID* pguid = (GUID*)pBuff;
if (IsEqualGUID(GUID_NULL, *pguid)) { // it's our non-cocreatable IStream implementation
hr = _ReadStream(pvar, pBuff + sizeof(GUID), cb - sizeof(GUID)); } else { ASSERTMSG(FALSE, "We don't support writing other types of objects yet."); } }
LocalFree(pBuff); } } break;
default: hr = E_FAIL; break; }
return hr; }
HRESULT CRegPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pvar, IErrorLog *pErrorLog) { HRESULT hr = _CanRead();
if (SUCCEEDED(hr)) { VARTYPE vtDesired = pvar->vt; VariantInit(pvar);
DWORD dwType; DWORD cb;
if (NOERROR == SHGetValueW(_hk, NULL, pszPropName, &dwType, NULL, &cb)) { switch(dwType) { case REG_DWORD: hr = _ReadDword(pszPropName, pvar); break;
case REG_SZ: hr = _ReadString(pszPropName, pvar, cb); break;
case REG_BINARY: hr = _ReadBinary(pszPropName, pvar, vtDesired, cb); break;
default: hr = E_FAIL; break; }
if (SUCCEEDED(hr)) { hr = VariantChangeTypeForRead(pvar, vtDesired); } } else { hr = E_FAIL; } }
if (FAILED(hr)) VariantInit(pvar);
return hr; }
HRESULT CRegPropertyBag::_GetStreamSize(IStream* pstm, DWORD* pcb) { HRESULT hr;
*pcb = 0;
ULARGE_INTEGER uli; hr = IStream_Size(pstm, &uli);
if (SUCCEEDED(hr)) { if (0 == uli.HighPart) { *pcb = uli.LowPart; } else { hr = E_FAIL; } }
return hr; }
HRESULT CRegPropertyBag::_CopyStreamIntoBuff(IStream* pstm, BYTE* pBuff, DWORD cb) { HRESULT hr;
hr = IStream_Reset(pstm);
if (SUCCEEDED(hr)) { hr = IStream_Read(pstm, pBuff, cb); }
return hr; }
HRESULT CRegPropertyBag::_WriteStream(LPCOLESTR pszPropName, IStream* pstm) { HRESULT hr; DWORD cb;
hr = _GetStreamSize(pstm, &cb);
if (SUCCEEDED(hr) && cb) { BYTE* pBuff = static_cast<BYTE*>(LocalAlloc(LPTR, cb + sizeof(GUID)));
if (pBuff) { // we're using a NULL GUID to mean our own IStream implementation
hr = _CopyStreamIntoBuff(pstm, pBuff + sizeof(GUID), cb);
if (SUCCEEDED(hr)) { if (NOERROR != SHSetValueW(_hk, NULL, pszPropName, REG_BINARY, pBuff, cb + sizeof(GUID))) { hr = E_FAIL; } }
LocalFree(pBuff); } else { hr = E_OUTOFMEMORY; } }
return hr; }
HRESULT CRegPropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pvar) { HRESULT hr = _CanWrite(); if (SUCCEEDED(hr)) { VARIANT var = { 0 };
switch(pvar->vt) { case VT_EMPTY: SHDeleteValueW(_hk, NULL, pszPropName); break;
case VT_I1: case VT_I2: case VT_I4: case VT_INT: case VT_UI1: case VT_UI2: case VT_UI4: case VT_UINT: case VT_BOOL: hr = VariantChangeType(&var, pvar, 0, VT_UI4); if (SUCCEEDED(hr)) { if (NOERROR != SHSetValueW(_hk, NULL, pszPropName, REG_DWORD, &var.lVal, sizeof(var.lVal))) { hr = E_FAIL; } } break;
case VT_UNKNOWN: IStream* pstm; hr = pvar->punkVal->QueryInterface(IID_PPV_ARG(IStream, &pstm)); if (SUCCEEDED(hr)) { hr = _WriteStream(pszPropName, pstm); pstm->Release(); } else { TraceMsg(TF_WARNING, "CRegPropertyBag::Write: Someone is trying to write an object we don't know how to save"); } break;
default: hr = VariantChangeType(&var, pvar, 0, VT_BSTR); if (SUCCEEDED(hr)) { if (NOERROR != SHSetValueW(_hk, NULL, pszPropName, REG_SZ, var.bstrVal, CbFromCchW(lstrlenW(var.bstrVal) + 1))) { hr = E_FAIL; } VariantClear(&var); } break; } } return hr; }
HRESULT SHCreatePropertyBagOnRegKey(HKEY hk, LPCWSTR pszSubKey, DWORD grfMode, REFIID riid, void **ppv) { HRESULT hr; CRegPropertyBag *pbag = new CRegPropertyBag(grfMode); if (pbag) { hr = pbag->_Init(hk, pszSubKey);
if (SUCCEEDED(hr)) hr = pbag->QueryInterface(riid, ppv);
pbag->Release(); } else { *ppv = NULL; hr = E_OUTOFMEMORY; }
return hr; }
//
// Memory property bag implementation
//
typedef struct { LPWSTR pszPropName; VARIANT variant; } PBAGENTRY, * LPPBAGENTRY;
class CMemPropertyBag : public CBasePropertyBag { public: // IPropertyBag
STDMETHOD(Read)(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); STDMETHOD(Write)(LPCOLESTR pszPropName, VARIANT *pVar);
protected: // methods
CMemPropertyBag(DWORD grfMode) : CBasePropertyBag(grfMode) {} ~CMemPropertyBag(); HRESULT _Find(LPCOLESTR pszPropName, PBAGENTRY **pppbe, BOOL fCreate);
friend HRESULT SHCreatePropertyBagOnMemory(DWORD grfMode, REFIID riid, void **ppv);
protected: // members
HDSA _hdsaProperties; };
INT _FreePropBagCB(LPVOID pData, LPVOID lParam) { LPPBAGENTRY ppbe = (LPPBAGENTRY)pData; Str_SetPtrW(&ppbe->pszPropName, NULL); VariantClear(&ppbe->variant); return 1; }
CMemPropertyBag::~CMemPropertyBag() { if (_hdsaProperties) DSA_DestroyCallback(_hdsaProperties, _FreePropBagCB, NULL); }
//
// manange the list of propeties in the property bag
//
HRESULT CMemPropertyBag::_Find(LPCOLESTR pszPropName, PBAGENTRY **pppbe, BOOL fCreate) { int i; PBAGENTRY pbe = { 0 };
*pppbe = NULL;
// look up the property in the DSA
// PERF: change to a DPA and sort accordingly for better perf (daviddv 110798)
for ( i = 0 ; _hdsaProperties && (i < DSA_GetItemCount(_hdsaProperties)) ; i++ ) { LPPBAGENTRY ppbe = (LPPBAGENTRY)DSA_GetItemPtr(_hdsaProperties, i); if ( !StrCmpIW(pszPropName, ppbe->pszPropName) ) { *pppbe = ppbe; return S_OK; } }
// no entry found, should we create one?
if ( !fCreate ) return E_FAIL;
// yes, so lets check to see if we have a DSA yet.
if ( !_hdsaProperties ) _hdsaProperties = DSA_Create(SIZEOF(PBAGENTRY), 4); if ( !_hdsaProperties ) return E_OUTOFMEMORY;
// we have the DSA so lets fill the record we want to put into it
if ( !Str_SetPtrW(&pbe.pszPropName, pszPropName) ) return E_OUTOFMEMORY;
VariantInit(&pbe.variant);
// append it to the DSA we are using
i = DSA_AppendItem(_hdsaProperties, &pbe); if ( -1 == i ) { Str_SetPtrW(&pbe.pszPropName, NULL); return E_OUTOFMEMORY; } *pppbe = (LPPBAGENTRY)DSA_GetItemPtr(_hdsaProperties, i);
return S_OK; }
//
// IPropertyBag methods
//
STDMETHODIMP CMemPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pv, IErrorLog *pErrorLog) { VARTYPE vtDesired = pv->vt;
VariantInit(pv);
HRESULT hr = _CanRead(); if (SUCCEEDED(hr)) { hr = (pszPropName && pv) ? S_OK : E_INVALIDARG;
if (SUCCEEDED(hr)) { LPPBAGENTRY ppbe; hr = _Find(pszPropName, &ppbe, FALSE); if (SUCCEEDED(hr)) { hr = VariantCopy(pv, &ppbe->variant); if (SUCCEEDED(hr)) hr = VariantChangeTypeForRead(pv, vtDesired); } } } return hr; }
STDMETHODIMP CMemPropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pv) { HRESULT hr = _CanWrite(); if (SUCCEEDED(hr)) { hr = (pszPropName && pv) ? S_OK : E_INVALIDARG; if (SUCCEEDED(hr)) { LPPBAGENTRY ppbe; hr = _Find(pszPropName, &ppbe, TRUE); if (SUCCEEDED(hr)) { hr = VariantCopy(&ppbe->variant, pv); } } }
return hr; }
//
// Exported function for creating a IPropertyBag (or variant of) object.
//
STDAPI SHCreatePropertyBagOnMemory(DWORD grfMode, REFIID riid, void **ppv) { CMemPropertyBag *ppb = new CMemPropertyBag(grfMode); if (ppb) { HRESULT hres = ppb->QueryInterface(riid, ppv); ppb->Release();
return hres; } *ppv = NULL; return E_OUTOFMEMORY; }
//
// Property bag helper functions
//
STDAPI SHPropertyBag_ReadType(IPropertyBag *ppb, LPCWSTR pszPropName, VARIANT *pv, VARTYPE vt) { VariantInit(pv); pv->vt = vt;
HRESULT hr = ppb->Read(pszPropName, pv, NULL); if (SUCCEEDED(hr)) { if (vt != pv->vt && vt != VT_EMPTY) { TraceMsg(TF_WARNING, "SHPropertyBag_ReadType found an IPropertyBag that did not return the correct data!"); }
// Our IPropertyBag implementations have been buggy in the past, cover up for them
hr = VariantChangeTypeForRead(pv, vt); } else { // don't break the caller by returning a bogus VARIANT struct
VariantInit(pv); }
return hr; }
STDAPI SHPropertyBag_ReadBSTR(IPropertyBag *ppb, LPCWSTR pszPropName, BSTR* pbstr) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadBSTR caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadBSTR caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(pbstr, *pbstr), "SHPropertyBag_ReadBSTR caller passed bad pbstr");
HRESULT hr;
if (ppb && pszPropName && pbstr) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_BSTR); if (SUCCEEDED(hr)) *pbstr = va.bstrVal; else *pbstr = NULL; } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadStr(IPropertyBag* ppb, LPCWSTR pszPropName, LPWSTR psz, int cch) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadStr caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadStr caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_BUFFER(psz, *psz, cch), "SHPropertyBag_ReadStr caller passed bad psz and cch");
HRESULT hr;
if (ppb && pszPropName && psz) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_BSTR); if (SUCCEEDED(hr)) { StrCpyNW(psz, va.bstrVal, cch); VariantClear(&va); hr = S_OK; } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteStr(IPropertyBag* ppb, LPCWSTR pszPropName, LPCWSTR psz) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteStr caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteStr caller passed bad pszPropName"); RIPMSG(NULL == psz || IS_VALID_STRING_PTRW(psz, -1), "SHPropertyBag_WriteStr caller passed bad psz");
HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.bstrVal = SysAllocString(psz);
if (va.bstrVal) { va.vt = VT_BSTR; hr = ppb->Write(pszPropName, &va); SysFreeString(va.bstrVal); } else { hr = E_OUTOFMEMORY; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadInt(IPropertyBag* ppb, LPCWSTR pszPropName, int* piResult) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadInt caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadInt caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(piResult, *piResult), "SHPropertyBag_ReadInt caller passed bad piResult");
HRESULT hr;
if (ppb && pszPropName && piResult) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_I4); if (SUCCEEDED(hr)) { *piResult = va.ulVal; // VT_I4 has nothing to VariantClear
} } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteInt(IPropertyBag* ppb, LPCWSTR pszPropName, int i) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteInt caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteInt caller passed bad pszPropName");
HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_I4; va.lVal = i; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadSHORT(IPropertyBag* ppb, LPCWSTR pszPropName, SHORT* psh) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadSHORT caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadSHORT caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(psh, *psh), "SHPropertyBag_ReadSHORT caller passed bad psh");
HRESULT hr;
if (ppb && pszPropName && psh) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_UI2); if (SUCCEEDED(hr)) { *psh = va.iVal; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteSHORT(IPropertyBag* ppb, LPCWSTR pszPropName, SHORT sh) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteSHORT caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteSHORT caller passed bad pszPropName"); HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_UI2; va.iVal = sh; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadLONG(IPropertyBag* ppb, LPCWSTR pszPropName, LONG* pl) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadLONG caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadLONG caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(pl, *pl), "SHPropertyBag_ReadLONG caller passed bad pl");
HRESULT hr;
if (ppb && pszPropName && pl) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_I4); if (SUCCEEDED(hr)) { *pl = va.ulVal; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteLONG(IPropertyBag* ppb, LPCWSTR pszPropName, LONG l) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteLONG caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteLONG caller passed bad pszPropName");
HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_I4; va.lVal = l; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadDWORD(IPropertyBag* ppb, LPCWSTR pszPropName, DWORD* pdw) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadDWORD caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadDWORD caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(pdw, *pdw), "SHPropertyBag_ReadInt caller passed bad pdw");
HRESULT hr;
if (ppb && pszPropName && pdw) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_UI4); if (SUCCEEDED(hr)) { *pdw = va.ulVal; // VT_UI4 has nothing to VariantClear
} } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteDWORD(IPropertyBag* ppb, LPCWSTR pszPropName, DWORD dw) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteDWORD caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteDWORD caller passed bad pszPropName"); HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_UI4; va.ulVal = dw; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
// This shipped on Whistler Beta 1. It's exported by ordinal.
STDAPI_(BOOL) SHPropertyBag_ReadBOOLOld(IPropertyBag *ppb, LPCWSTR pwzPropName, BOOL fResult) { VARIANT va; HRESULT hr = SHPropertyBag_ReadType(ppb, pwzPropName, &va, VT_BOOL); if (SUCCEEDED(hr)) { fResult = (va.boolVal == VARIANT_TRUE); // VT_BOOL has nothing to VariantClear
} return fResult; }
STDAPI SHPropertyBag_ReadBOOL(IPropertyBag* ppb, LPCWSTR pszPropName, BOOL* pfResult) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadBOOL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadBOOL caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(pfResult, *pfResult), "SHPropertyBag_ReadBOOL caller passed bad pfResult");
HRESULT hr;
if (ppb && pszPropName && pfResult) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_BOOL); if (SUCCEEDED(hr)) { *pfResult = (va.boolVal == VARIANT_TRUE); } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteBOOL(IPropertyBag* ppb, LPCWSTR pszPropName, BOOL fValue) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteBOOL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteBOOL caller passed bad pszPropName");
HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_BOOL; va.boolVal = fValue ? VARIANT_TRUE : VARIANT_FALSE; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadGUID(IPropertyBag* ppb, LPCWSTR pszPropName, GUID* pguid) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadGUID caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadGUID caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(pguid, *pguid), "SHPropertyBag_ReadGUID caller passed bad pguid");
HRESULT hr;
if (ppb && pszPropName && pguid) { VARIANT var; hr = SHPropertyBag_ReadType(ppb, pszPropName, &var, VT_EMPTY); if (SUCCEEDED(hr)) { if (var.vt == (VT_ARRAY | VT_UI1)) // some code has been writing GUIDs as array's of bytes
{ hr = VariantToGUID(&var, pguid) ? S_OK : E_FAIL; } else if (var.vt == VT_BSTR) { hr = GUIDFromStringW(var.bstrVal, pguid) ? S_OK : E_FAIL; } VariantClear(&var); } } else { hr = E_INVALIDARG; }
return hr; } STDAPI SHPropertyBag_WriteGUID(IPropertyBag *ppb, LPCWSTR pszPropName, const GUID *pguid) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteGUID caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteGUID caller passed bad pszPropName"); RIPMSG(IS_VALID_READ_PTR(pguid, *pguid), "SHPropertyBag_WriteGUID caller passed bad pguid");
HRESULT hr;
if (ppb && pszPropName && pguid) { WCHAR sz[64]; SHStringFromGUIDW(*pguid, sz, ARRAYSIZE(sz)); hr = SHPropertyBag_WriteStr(ppb, pszPropName, sz); // assumes null terminator
} else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadPOINTL(IPropertyBag* ppb, LPCWSTR pszPropName, POINTL* ppt) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadPOINTL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadPOINTL caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(ppt, *ppt), "SHPropertyBag_ReadPOINTL caller passed bad ppt");
HRESULT hr;
if (ppb && pszPropName && ppt) { WCHAR szProp[MAX_PATH]; RIP(lstrlenW(pszPropName) < ARRAYSIZE(szProp) - 2); StrCpyNW(szProp, pszPropName, ARRAYSIZE(szProp)); UINT cch = lstrlenW(szProp);
if (ARRAYSIZE(szProp) - cch >= 3) { StrCpyNW(szProp + cch, L".x", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &ppt->x);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".y", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &ppt->y); } } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WritePOINTL(IPropertyBag* ppb, LPCWSTR pszPropName, const POINTL* ppt) { RIPMSG(NULL != ppb, "SHPropertyBag_WritePOINTL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WritePOINTL caller passed bad pszPropName"); RIPMSG(IS_VALID_READ_PTR(ppt, *ppt), "SHPropertyBag_WritePOINTL caller passed bad ppt");
HRESULT hr;
if (ppb && pszPropName && ppt) { WCHAR szProp[MAX_PATH]; RIP(lstrlenW(pszPropName) < ARRAYSIZE(szProp) - 2); StrCpyNW(szProp, pszPropName, ARRAYSIZE(szProp)); UINT cch = lstrlenW(szProp);
if (ARRAYSIZE(szProp) - cch >= 3) { StrCpyNW(szProp + cch, L".x", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, ppt->x);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".y", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, ppt->y);
if (FAILED(hr)) { StrCpyNW(szProp + cch, L".x", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_Delete(ppb, szProp); } } } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadPOINTS(IPropertyBag* ppb, LPCWSTR pszPropName, POINTS* ppt) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadPOINTS caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadPOINTS caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(ppt, *ppt), "SHPropertyBag_ReadPOINTS caller passed bad ppt");
HRESULT hr;
if (ppb && pszPropName && ppt) { POINTL ptL; hr = SHPropertyBag_ReadPOINTL(ppb, pszPropName, &ptL);
if (SUCCEEDED(hr)) { ppt->x = static_cast<SHORT>(ptL.x); ppt->y = static_cast<SHORT>(ptL.y); } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WritePOINTS(IPropertyBag* ppb, LPCWSTR pszPropName, const POINTS* ppt) { RIPMSG(NULL != ppb, "SHPropertyBag_WritePOINTS caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WritePOINTS caller passed bad pszPropName"); RIPMSG(IS_VALID_READ_PTR(ppt, *ppt), "SHPropertyBag_WritePOINTS caller passed bad ppt");
HRESULT hr;
if (ppb && pszPropName && ppt) { POINTL ptL; ptL.x = ppt->x; ptL.y = ppt->y;
hr = SHPropertyBag_WritePOINTL(ppb, pszPropName, &ptL); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadRECTL(IPropertyBag* ppb, LPCWSTR pszPropName, RECTL* prc) { RIPMSG(NULL != ppb, "SHPropertyBag_ReadRECTL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_ReadRECTL caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(prc, *prc), "SHPropertyBag_ReadRECTL caller passed bad prc");
HRESULT hr;
if (ppb && pszPropName && prc) { WCHAR szProp[MAX_PATH]; RIP(lstrlenW(pszPropName) < ARRAYSIZE(szProp) - 7); StrCpyNW(szProp, pszPropName, ARRAYSIZE(szProp)); UINT cch = lstrlenW(szProp);
if (ARRAYSIZE(szProp) - cch >= 8) { StrCpyNW(szProp + cch, L".left", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &prc->left);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".top", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &prc->top);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".right", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &prc->right);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".bottom", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_ReadLONG(ppb, szProp, &prc->bottom); } } } } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteRECTL(IPropertyBag* ppb, LPCWSTR pszPropName, const RECTL* prc) { RIPMSG(NULL != ppb, "SHPropertyBag_WriteRECTL caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_WriteRECTL caller passed bad pszPropName"); RIPMSG(IS_VALID_READ_PTR(prc, *prc), "SHPropertyBag_WriteRECTL caller passed bad prc");
HRESULT hr;
if (ppb && pszPropName && prc) { WCHAR szProp[MAX_PATH]; RIP(lstrlenW(pszPropName) < ARRAYSIZE(szProp) - 7); StrCpyNW(szProp, pszPropName, ARRAYSIZE(szProp)); UINT cch = lstrlenW(szProp);
if (ARRAYSIZE(szProp) - cch >= 8) { StrCpyNW(szProp + cch, L".left", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, prc->left);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".top", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, prc->top);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".right", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, prc->right);
if (SUCCEEDED(hr)) { StrCpyNW(szProp + cch, L".bottom", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_WriteLONG(ppb, szProp, prc->bottom);
if (FAILED(hr)) { StrCpyNW(szProp + cch, L".right", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_Delete(ppb, szProp); } }
if (FAILED(hr)) { StrCpyNW(szProp + cch, L".top", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_Delete(ppb, szProp); } }
if (FAILED(hr)) { StrCpyNW(szProp + cch, L".left", ARRAYSIZE(szProp) - cch); hr = SHPropertyBag_Delete(ppb, szProp); } } } else { hr = E_FAIL; } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_ReadStream(IPropertyBag* ppb, LPCWSTR pszPropName, IStream** ppstm) { RIPMSG(NULL != ppb, "SHPropertyBag_GetSTREAM caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_GetSTREAM caller passed bad pszPropName"); RIPMSG(IS_VALID_WRITE_PTR(ppstm, *ppstm), "SHPropertyBag_GetSTREAM caller passed bad ppstm");
HRESULT hr;
if (ppb && pszPropName && ppstm) { VARIANT va; hr = SHPropertyBag_ReadType(ppb, pszPropName, &va, VT_UNKNOWN);
if (SUCCEEDED(hr)) { hr = va.punkVal->QueryInterface(IID_PPV_ARG(IStream, ppstm)); va.punkVal->Release(); } } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_WriteStream(IPropertyBag* ppb, LPCWSTR pszPropName, IStream* pstm) { RIPMSG(NULL != ppb, "SHPropertyBag_GetSTREAM caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_GetSTREAM caller passed bad pszPropName"); RIPMSG(NULL != pstm, "SHPropertyBag_GetSTREAM caller passed bad pstm");
HRESULT hr;
if (ppb && pszPropName && pstm) { VARIANT va; va.vt = VT_UNKNOWN; va.punkVal = pstm; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
STDAPI SHPropertyBag_Delete(IPropertyBag* ppb, LPCWSTR pszPropName) { RIPMSG(NULL != ppb, "SHPropertyBag_GetSTREAM caller passed bad ppb"); RIPMSG(IS_VALID_STRING_PTRW(pszPropName, -1), "SHPropertyBag_GetSTREAM caller passed bad pszPropName");
HRESULT hr;
if (ppb && pszPropName) { VARIANT va; va.vt = VT_EMPTY; hr = ppb->Write(pszPropName, &va); } else { hr = E_INVALIDARG; }
return hr; }
class CDesktopUpgradePropertyBag : public CBasePropertyBag { public: // IPropertyBag
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar);
protected: CDesktopUpgradePropertyBag() : CBasePropertyBag(STGM_READ) {} ~CDesktopUpgradePropertyBag() {} friend HRESULT SHGetDesktopUpgradePropertyBag(REFIID riid, void** ppv);
private: HRESULT _ReadFlags(VARIANT* pVar); HRESULT _ReadItemPositions(VARIANT* pVar); IStream* _GetOldDesktopViewStream(void); IStream* _NewStreamFromOld(IStream* pstmOld); BOOL _AlreadyUpgraded(HKEY hk); void _MarkAsUpgraded(HKEY hk); };
HRESULT CDesktopUpgradePropertyBag::_ReadFlags(VARIANT* pVar) { HRESULT hr;
FOLDERSETTINGS fs; DWORD cb = sizeof(fs);
if (NOERROR == SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\DeskView"), TEXT("Settings"), NULL, (BYTE *)&fs, &cb) && cb >= sizeof(fs)) { pVar->uintVal = fs.fFlags | FWF_DESKTOP | FWF_NOCLIENTEDGE; pVar->vt = VT_UINT; hr = S_OK; } else { hr = E_FAIL; }
return hr; }
typedef struct { WORD wSig; BYTE bDontCare[12]; WORD cbPosOffset; }OLDVS_STREAMHEADER;
#define OLDVS_STREAMHEADERSIG 28 // sizeof(WIN95HEADER)
IStream* CDesktopUpgradePropertyBag::_NewStreamFromOld(IStream* pstmOld) { IStream* pstmNew = NULL;
OLDVS_STREAMHEADER ovssh;
if (SUCCEEDED(IStream_Read(pstmOld, &ovssh, sizeof(ovssh))) && OLDVS_STREAMHEADERSIG == ovssh.wSig) { LARGE_INTEGER liPos; liPos.QuadPart = ovssh.cbPosOffset - sizeof(ovssh);
if (SUCCEEDED(pstmOld->Seek(liPos, STREAM_SEEK_CUR, NULL))) { ULARGE_INTEGER uliSize;
if (SUCCEEDED(IStream_Size(pstmOld, &uliSize))) { pstmNew = SHCreateMemStream(NULL, 0);
if (pstmNew) { uliSize.QuadPart -= ovssh.cbPosOffset;
if (SUCCEEDED(pstmOld->CopyTo(pstmNew, uliSize, NULL, NULL))) { IStream_Reset(pstmNew); } else { pstmNew->Release(); pstmNew = NULL; } } } } }
return pstmNew; }
BOOL CDesktopUpgradePropertyBag::_AlreadyUpgraded(HKEY hk) { DWORD dwUpgrade; DWORD cbUpgrade = sizeof(dwUpgrade); DWORD dwType;
return (ERROR_SUCCESS == SHGetValueW(hk, NULL, L"Upgrade", &dwType, &dwUpgrade, &cbUpgrade)); }
void CDesktopUpgradePropertyBag::_MarkAsUpgraded(HKEY hk) { DWORD dwVal = 1; SHSetValueW(hk, NULL, L"Upgrade", REG_DWORD, &dwVal, sizeof(dwVal)); }
IStream* CDesktopUpgradePropertyBag::_GetOldDesktopViewStream() { IStream* pstmRet = NULL;
HKEY hk = SHGetShellKey(SHELLKEY_HKCU_EXPLORER, L"Streams\\Desktop", FALSE); if (hk) { if (!_AlreadyUpgraded(hk)) { pstmRet = SHOpenRegStream2W(hk, NULL, L"ViewView2", STGM_READ);
if (NULL != pstmRet) { ULARGE_INTEGER uliSize; if (SUCCEEDED(IStream_Size(pstmRet, &uliSize)) && 0 == uliSize.QuadPart) { pstmRet->Release(); pstmRet = NULL; } }
if (NULL == pstmRet) pstmRet = SHOpenRegStream2W(hk, NULL, L"ViewView", STGM_READ);
_MarkAsUpgraded(hk); } RegCloseKey(hk); }
return pstmRet; }
HRESULT CDesktopUpgradePropertyBag::_ReadItemPositions(VARIANT* pVar) { HRESULT hr = E_FAIL;
IStream* pstmOld = _GetOldDesktopViewStream(); if (pstmOld) { IStream* pstmNew = _NewStreamFromOld(pstmOld); if (pstmNew) { pVar->punkVal = pstmNew; pVar->vt = VT_UNKNOWN; hr = S_OK; }
pstmOld->Release(); }
return hr; }
HRESULT CDesktopUpgradePropertyBag::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog *pErrorLog) { HRESULT hr;
VARTYPE vtDesired = pVar->vt;
if (0 == StrCmpW(VS_PROPSTR_FFLAGS, pszPropName)) { hr = _ReadFlags(pVar); } else if (0 == StrCmpNW(VS_PROPSTR_ITEMPOS, pszPropName, ARRAYSIZE(VS_PROPSTR_ITEMPOS) - 1)) { hr = _ReadItemPositions(pVar); } else { hr = E_FAIL; }
if (SUCCEEDED(hr)) { hr = VariantChangeTypeForRead(pVar, vtDesired); } else { VariantInit(pVar); }
return hr; }
HRESULT CDesktopUpgradePropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pVar) { return E_NOTIMPL; }
HRESULT SHGetDesktopUpgradePropertyBag(REFIID riid, void** ppv) { HRESULT hr;
*ppv = NULL;
CDesktopUpgradePropertyBag* pbag = new CDesktopUpgradePropertyBag();
if (pbag) { hr = pbag->QueryInterface(riid, ppv); pbag->Release(); } else { hr = E_OUTOFMEMORY; }
return hr; }
class CViewStatePropertyBag : public CBasePropertyBag { public: // IPropertyBag
STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar);
protected: CViewStatePropertyBag(void); virtual ~CViewStatePropertyBag(); HRESULT _Init(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags); BOOL _IsSameBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags); friend HRESULT SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, REFIID riid, void** ppv); friend HRESULT GetCachedViewStatePropertyBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, REFIID riid, void** ppv);
private: HRESULT _CreateBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, DWORD grfMode, REFIID riid, void** ppv); HRESULT _CreateUpgradeBag(REFIID riid, void** ppv);
BOOL _CanAccessPidlBag(void); BOOL _EnsurePidlBag(DWORD grfMode, REFIID riid); HRESULT _ReadPidlBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _CanAccessUpgradeBag(void); BOOL _EnsureUpgradeBag(DWORD grfMode, REFIID riid); HRESULT _ReadUpgradeBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _CanAccessInheritBag(void); BOOL _EnsureInheritBag(DWORD grfMode, REFIID riid); HRESULT _ReadInheritBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _CanAccessUserDefaultsBag(void); BOOL _EnsureUserDefaultsBag(DWORD grfMode, REFIID riid); HRESULT _ReadUserDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _CanAccessFolderDefaultsBag(void); BOOL _EnsureFolderDefaultsBag(DWORD grfMode, REFIID riid); HRESULT _ReadFolderDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _CanAccessGlobalDefaultsBag(void); BOOL _EnsureGlobalDefaultsBag(DWORD grfMode, REFIID riid); HRESULT _ReadGlobalDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog); BOOL _EnsureReadBag(DWORD grfMode, REFIID riid); BOOL _EnsureWriteBag(DWORD grfMode, REFIID riid); HRESULT _GetRegKey(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, DWORD grfMode, HKEY hk, LPWSTR pszKey, UINT cch); DWORD _GetMRUSize(HKEY hk); HRESULT _GetMRUSlots(LPCITEMIDLIST pidl, DWORD grfMode, HKEY hk, DWORD adwSlot[], DWORD dwcSlots, DWORD* pdwFetched); HRESULT _GetMRUSlot(LPCITEMIDLIST pidl, DWORD grfMode, HKEY hk, DWORD* pdwSlot); HKEY _GetHKey(DWORD dwFlags); void _ResetTryAgainFlag(); HRESULT _FindNearestInheritBag(REFIID riid, void** ppv); void _PruneMRUTree(void); BOOL _IsSamePidl(LPCITEMIDLIST pidl); BOOL _IsSystemFolder(void);
private: LPITEMIDLIST _pidl; LPWSTR _pszBagName; DWORD _dwFlags; IPropertyBag* _ppbPidl; IPropertyBag* _ppbUpgrade; IPropertyBag* _ppbInherit; IPropertyBag* _ppbUserDefaults; IPropertyBag* _ppbFolderDefaults; IPropertyBag* _ppbGlobalDefaults; IPropertyBag* _ppbRead; IPropertyBag* _ppbWrite;
BOOL _fTriedPidlBag; BOOL _fTriedUpgradeBag; BOOL _fTriedInheritBag; BOOL _fTriedUserDefaultsBag; BOOL _fTriedFolderDefaultsBag; BOOL _fTriedGlobalDefaultsBag; BOOL _fTriedReadBag; BOOL _fTriedWriteBag; };
CViewStatePropertyBag::CViewStatePropertyBag() : CBasePropertyBag(STGM_READ) { ASSERT(NULL == _pidl); ASSERT(NULL == _pszBagName); ASSERT( 0 == _dwFlags); ASSERT(NULL == _ppbPidl); ASSERT(NULL == _ppbUpgrade); ASSERT(NULL == _ppbInherit); ASSERT(NULL == _ppbUserDefaults); ASSERT(NULL == _ppbFolderDefaults); ASSERT(NULL == _ppbGlobalDefaults); ASSERT(NULL == _ppbRead); ASSERT(NULL == _ppbWrite); }
CViewStatePropertyBag::~CViewStatePropertyBag() { if (_pidl) ILFree(_pidl);
if (_pszBagName) LocalFree(_pszBagName);
if (_ppbPidl) _ppbPidl->Release();
if (_ppbUpgrade) _ppbUpgrade->Release();
if (_ppbInherit) _ppbInherit->Release();
if (_ppbUserDefaults) _ppbUserDefaults->Release();
if (_ppbFolderDefaults) _ppbFolderDefaults->Release();
if (_ppbGlobalDefaults) _ppbGlobalDefaults->Release();
if (_ppbRead) _ppbRead->Release();
if (_ppbWrite) _ppbWrite->Release(); }
HKEY CViewStatePropertyBag::_GetHKey(DWORD dwFlags) { HKEY hkRet;
if ((dwFlags & SHGVSPB_PERUSER) || (dwFlags & SHGVSPB_INHERIT)) { if (!(_dwFlags & SHGVSPB_ROAM) || !(dwFlags & SHGVSPB_PERFOLDER)) { hkRet = SHGetShellKey(SHELLKEY_HKCU_SHELLNOROAM, NULL, TRUE); } else { hkRet = SHGetShellKey(SHELLKEY_HKCU_SHELL, NULL, TRUE); } } else { hkRet = SHGetShellKey(SHELLKEY_HKLM_SHELL, NULL, TRUE); }
return hkRet; }
DWORD CViewStatePropertyBag::_GetMRUSize(HKEY hk) { DWORD dwMRUSize; DWORD dwSize = sizeof(dwMRUSize);
if (NOERROR != SHGetValueW(hk, NULL, L"BagMRU Size", NULL, &dwMRUSize, &dwSize)) { dwMRUSize = 400; // default size.
}
return dwMRUSize; }
HRESULT CViewStatePropertyBag::_GetMRUSlots(LPCITEMIDLIST pidl, DWORD grfMode, HKEY hk, DWORD adwSlots[], DWORD cSlots, DWORD* pdwFetched) { HRESULT hr;
IMruPidlList *pmru; hr = CoCreateInstance(CLSID_MruPidlList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMruPidlList, &pmru));
if (SUCCEEDED(hr)) { hr = pmru->InitList(_GetMRUSize(hk), hk, L"BagMRU");
if (SUCCEEDED(hr)) { hr = pmru->QueryPidl(pidl, cSlots, adwSlots, pdwFetched);
if (S_OK == hr || (grfMode & (STGM_WRITE | STGM_READWRITE))) { hr = pmru->UsePidl(pidl, &adwSlots[0]); } else if (1 == cSlots) // return S_FALSE for cSlots > 1 if parent slots exist.
{ hr = E_FAIL; } }
pmru->Release(); }
return hr; }
HRESULT CViewStatePropertyBag::_GetMRUSlot(LPCITEMIDLIST pidl, DWORD grfMode, HKEY hk, DWORD* pdwSlot) { DWORD dwFetched;
return _GetMRUSlots(pidl, grfMode, hk, pdwSlot, 1, &dwFetched); }
HRESULT CViewStatePropertyBag::_GetRegKey(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, DWORD grfMode, HKEY hk, LPWSTR pszKey, UINT cch) { HRESULT hr = S_OK;
if ((dwFlags & SHGVSPB_PERFOLDER) || (dwFlags & SHGVSPB_INHERIT)) { DWORD dwSlot; hr = _GetMRUSlot(pidl, grfMode, hk, &dwSlot);
if (SUCCEEDED(hr)) { if (!(dwFlags & SHGVSPB_INHERIT)) { wnsprintfW(pszKey, cch, L"Bags\\%d\\%s", dwSlot, pszBagName); } else { wnsprintfW(pszKey, cch, L"Bags\\%d\\%s\\Inherit", dwSlot, pszBagName); } } } else { wnsprintfW(pszKey, cch, L"Bags\\AllFolders\\%s", pszBagName); }
return hr; }
HRESULT CViewStatePropertyBag::_Init(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags) { HRESULT hr = E_OUTOFMEMORY;
if (pidl) { _pidl = ILClone(pidl); }
_pszBagName = StrDupW(pszBagName);
if (_pszBagName) { _dwFlags = dwFlags; hr = S_OK; }
return hr; }
BOOL CViewStatePropertyBag::_IsSamePidl(LPCITEMIDLIST pidl) { return (((pidl == NULL) && (_pidl == NULL)) || ((pidl != NULL) && (_pidl != NULL) && ILIsEqual(pidl, _pidl))); } BOOL CViewStatePropertyBag::_IsSameBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags) { return dwFlags == _dwFlags && 0 == StrCmpW(pszBagName, _pszBagName) && _IsSamePidl(pidl); }
HRESULT CViewStatePropertyBag::_CreateBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, DWORD grfMode, REFIID riid, void** ppv) { HRESULT hr;
DWORD grfMode2 = grfMode | ((grfMode & (STGM_WRITE | STGM_READWRITE)) ? STGM_CREATE : 0);
if (!(dwFlags & SHGVSPB_ALLUSERS) || !(dwFlags & SHGVSPB_PERFOLDER)) { HKEY hk = _GetHKey(dwFlags);
if (hk) { WCHAR szRegSubKey[64]; hr = _GetRegKey(pidl, pszBagName, dwFlags, grfMode2, hk, szRegSubKey, ARRAYSIZE(szRegSubKey));
if (SUCCEEDED(hr)) { hr = SHCreatePropertyBagOnRegKey(hk, szRegSubKey, grfMode2, riid, ppv); }
RegCloseKey(hk); } else { hr = E_FAIL; } } else { IBindCtx* pbctx; hr = BindCtx_CreateWithMode(grfMode2, &pbctx);
if (SUCCEEDED(hr)) { // can't use - causes link problems.
// hr = SHBindToObjectEx(NULL, _pidl, pbctx, riid, ppv);
IShellFolder* psf; hr = SHGetDesktopFolder(&psf);
if (SUCCEEDED(hr)) { hr = psf->BindToObject(_pidl, pbctx, riid, ppv);
if (SUCCEEDED(hr) && NULL == *ppv) hr = E_FAIL;
psf->Release(); }
pbctx->Release(); } }
return hr; }
HRESULT CViewStatePropertyBag::_CreateUpgradeBag(REFIID riid, void** ppv) { return SHGetDesktopUpgradePropertyBag(riid, ppv); }
BOOL CViewStatePropertyBag::_CanAccessPidlBag() { return (_dwFlags & SHGVSPB_PERUSER) && (_dwFlags & SHGVSPB_PERFOLDER); }
BOOL CViewStatePropertyBag::_EnsurePidlBag(DWORD grfMode, REFIID riid) { if (!_ppbPidl && !_fTriedPidlBag && _CanAccessPidlBag()) { _fTriedPidlBag = TRUE; _CreateBag(_pidl, _pszBagName, (SHGVSPB_PERUSER | SHGVSPB_PERFOLDER), grfMode, riid, (void**)&_ppbPidl); }
return NULL != _ppbPidl; }
HRESULT CViewStatePropertyBag::_ReadPidlBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsurePidlBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbPidl->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
BOOL CViewStatePropertyBag::_CanAccessUpgradeBag() { // only upgrade desktop for now.
return 0 == StrCmpW(_pszBagName, VS_BAGSTR_DESKTOP); }
BOOL CViewStatePropertyBag::_EnsureUpgradeBag(DWORD grfMode, REFIID riid) { if (!_ppbUpgrade && !_fTriedUpgradeBag && _CanAccessUpgradeBag()) { _fTriedUpgradeBag = TRUE;
_CreateUpgradeBag(riid, (void**)&_ppbUpgrade); }
return NULL != _ppbUpgrade; }
HRESULT CViewStatePropertyBag::_ReadUpgradeBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsureUpgradeBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbUpgrade->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
HRESULT CViewStatePropertyBag::_FindNearestInheritBag(REFIID riid, void** ppv) { HRESULT hr = E_FAIL;
*ppv = NULL;
HKEY hk = _GetHKey(SHGVSPB_INHERIT); if (hk) { DWORD aParentSlots[64]; DWORD dwFetched;
if (SUCCEEDED(_GetMRUSlots(_pidl, STGM_READ, hk, aParentSlots, ARRAYSIZE(aParentSlots), &dwFetched))) { for (DWORD i = 0; i < dwFetched && FAILED(hr); i++) { WCHAR szRegSubKey[64]; wnsprintfW(szRegSubKey, ARRAYSIZE(szRegSubKey), L"Bags\\%d\\%s\\Inherit", aParentSlots[i], _pszBagName);
hr = SHCreatePropertyBagOnRegKey(hk, szRegSubKey, STGM_READ, riid, ppv); } }
RegCloseKey(hk); }
return hr; }
BOOL CViewStatePropertyBag::_CanAccessInheritBag() { return _CanAccessPidlBag() || (_dwFlags & SHGVSPB_INHERIT); }
BOOL CViewStatePropertyBag::_EnsureInheritBag(DWORD grfMode, REFIID riid) { if (!_ppbInherit && !_fTriedInheritBag && _CanAccessInheritBag()) { _fTriedInheritBag = TRUE; _FindNearestInheritBag(riid, (void**)&_ppbInherit); }
return NULL != _ppbInherit; }
HRESULT CViewStatePropertyBag::_ReadInheritBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsureInheritBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbInherit->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
BOOL CViewStatePropertyBag::_CanAccessUserDefaultsBag() { return _CanAccessPidlBag() || ((_dwFlags & SHGVSPB_PERUSER) && (_dwFlags & SHGVSPB_ALLFOLDERS)); }
BOOL CViewStatePropertyBag::_EnsureUserDefaultsBag(DWORD grfMode, REFIID riid) { if (!_ppbUserDefaults && !_fTriedUserDefaultsBag && _CanAccessUserDefaultsBag()) { _fTriedUserDefaultsBag = TRUE; _CreateBag(NULL, _pszBagName, SHGVSPB_PERUSER | SHGVSPB_ALLFOLDERS, grfMode, riid, (void**)&_ppbUserDefaults); }
return NULL != _ppbUserDefaults; }
HRESULT CViewStatePropertyBag::_ReadUserDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsureUserDefaultsBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbUserDefaults->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
BOOL CViewStatePropertyBag::_CanAccessFolderDefaultsBag() { return _CanAccessUserDefaultsBag() || ((_dwFlags & SHGVSPB_ALLUSERS) && (_dwFlags & SHGVSPB_PERFOLDER)); }
BOOL CViewStatePropertyBag::_IsSystemFolder() { BOOL fRet = FALSE; LPCITEMIDLIST pidlLast; IShellFolder* psf; if (SUCCEEDED(SHBindToParent(_pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast))) { WIN32_FIND_DATAW fd; if (SUCCEEDED(SHGetDataFromIDListW(psf, pidlLast, SHGDFIL_FINDDATA, &fd, sizeof(fd)))) { fRet = PathIsSystemFolder(NULL, fd.dwFileAttributes); }
psf->Release(); } return fRet; }
BOOL CViewStatePropertyBag::_EnsureFolderDefaultsBag(DWORD grfMode, REFIID riid) { if (!_ppbFolderDefaults && !_fTriedFolderDefaultsBag && _CanAccessFolderDefaultsBag()) { _fTriedFolderDefaultsBag = TRUE;
// PERF: Use the desktop.ini only if the folder is a system folder.
if (_IsSystemFolder()) { _CreateBag(_pidl, _pszBagName, SHGVSPB_ALLUSERS | SHGVSPB_PERFOLDER, grfMode, riid, (void**)&_ppbFolderDefaults); } }
return NULL != _ppbFolderDefaults; }
HRESULT CViewStatePropertyBag::_ReadFolderDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsureFolderDefaultsBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbFolderDefaults->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
BOOL CViewStatePropertyBag::_CanAccessGlobalDefaultsBag() { return _CanAccessFolderDefaultsBag() || ((_dwFlags & SHGVSPB_ALLUSERS) && (_dwFlags & SHGVSPB_ALLFOLDERS)); }
BOOL CViewStatePropertyBag::_EnsureGlobalDefaultsBag(DWORD grfMode, REFIID riid) { if (!_ppbGlobalDefaults && !_fTriedGlobalDefaultsBag && _CanAccessGlobalDefaultsBag()) { _fTriedGlobalDefaultsBag = TRUE; _CreateBag(NULL, _pszBagName, SHGVSPB_ALLUSERS | SHGVSPB_ALLFOLDERS, grfMode, riid, (void**)&_ppbGlobalDefaults); }
return NULL != _ppbGlobalDefaults; }
HRESULT CViewStatePropertyBag::_ReadGlobalDefaultsBag(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if (_EnsureGlobalDefaultsBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbGlobalDefaults->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; }
return hr; }
BOOL CViewStatePropertyBag::_EnsureReadBag(DWORD grfMode, REFIID riid) { if (!_ppbRead && !_fTriedReadBag) { _fTriedReadBag = TRUE; _CreateBag(_pidl, _pszBagName, _dwFlags, grfMode, riid, (void**)&_ppbRead); }
return NULL != _ppbRead; }
HRESULT CViewStatePropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr;
if ((_dwFlags & SHGVSPB_NOAUTODEFAULTS) || (_dwFlags & SHGVSPB_INHERIT)) { if (_EnsureReadBag(STGM_READ, IID_IPropertyBag)) { hr = _ppbRead->Read(pszPropName, pVar, pErrorLog); } else { hr = E_FAIL; } } else { hr = _ReadPidlBag(pszPropName, pVar, pErrorLog); // per user per folder
if (FAILED(hr)) { hr = _ReadInheritBag(pszPropName, pVar, pErrorLog);
if (FAILED(hr)) { hr = _ReadUpgradeBag(pszPropName, pVar, pErrorLog); // (legacy per user per folder)
if (FAILED(hr)) { hr = _ReadUserDefaultsBag(pszPropName, pVar, pErrorLog); // per user all folders
if (FAILED(hr)) { hr = _ReadFolderDefaultsBag(pszPropName, pVar, pErrorLog); // per folder all users
if (FAILED(hr)) { hr = _ReadGlobalDefaultsBag(pszPropName, pVar, pErrorLog); // all folders all users
} } } } } }
return hr; }
void CViewStatePropertyBag::_PruneMRUTree() { HKEY hk = _GetHKey(SHGVSPB_INHERIT);
if (hk) { IMruPidlList *pmru; HRESULT hr = CoCreateInstance(CLSID_MruPidlList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMruPidlList, &pmru));
if (SUCCEEDED(hr)) { hr = pmru->InitList(200, hk, L"BagMRU");
if (SUCCEEDED(hr)) { pmru->PruneKids(_pidl); }
pmru->Release(); }
RegCloseKey(hk); } }
void CViewStatePropertyBag::_ResetTryAgainFlag() { if (_dwFlags & SHGVSPB_NOAUTODEFAULTS) { _fTriedReadBag = FALSE; } else { if ((_dwFlags & SHGVSPB_PERUSER) && (_dwFlags & SHGVSPB_PERFOLDER)) { _fTriedPidlBag = FALSE; } else if (_dwFlags & SHGVSPB_INHERIT) { _fTriedInheritBag = FALSE; } else if ((_dwFlags & SHGVSPB_PERUSER) && (_dwFlags & SHGVSPB_ALLFOLDERS)) { _fTriedUserDefaultsBag = FALSE; } else if ((_dwFlags & SHGVSPB_ALLUSERS) && (_dwFlags & SHGVSPB_PERFOLDER)) { _fTriedFolderDefaultsBag = FALSE; } else if ((_dwFlags & SHGVSPB_ALLUSERS) && (_dwFlags & SHGVSPB_ALLFOLDERS)) { _fTriedGlobalDefaultsBag = FALSE; } } }
BOOL CViewStatePropertyBag::_EnsureWriteBag(DWORD grfMode, REFIID riid) { if (!_ppbWrite && !_fTriedWriteBag) { _fTriedWriteBag = TRUE; _CreateBag(_pidl, _pszBagName, _dwFlags, grfMode, riid, (void**)&_ppbWrite); if (_ppbWrite) { _ResetTryAgainFlag();
if (SHGVSPB_INHERIT & _dwFlags) { _PruneMRUTree(); } } }
return NULL != _ppbWrite; }
HRESULT CViewStatePropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pVar) { HRESULT hr;
if (_EnsureWriteBag(STGM_WRITE, IID_IPropertyBag)) { hr = _ppbWrite->Write(pszPropName, pVar); } else { hr = E_FAIL; }
return hr; }
#ifdef DEBUG
void IS_VALID_SHGVSPB_PARAMS(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, REFIID riid, void** ppv) { RIP((NULL == pidl && (dwFlags & SHGVSPB_ALLFOLDERS)) || (IsValidPIDL(pidl) && ((SHGVSPB_PERFOLDER & dwFlags) || (SHGVSPB_INHERIT & dwFlags)))); RIP(pszBagName); RIP(SHGVSPB_PERUSER == (dwFlags & (SHGVSPB_PERUSER | SHGVSPB_ALLUSERS | SHGVSPB_INHERIT)) || SHGVSPB_ALLUSERS == (dwFlags & (SHGVSPB_PERUSER | SHGVSPB_ALLUSERS | SHGVSPB_INHERIT)) || SHGVSPB_INHERIT == (dwFlags & (SHGVSPB_PERUSER | SHGVSPB_ALLUSERS | SHGVSPB_INHERIT))); RIP(SHGVSPB_PERFOLDER == (dwFlags & (SHGVSPB_PERFOLDER | SHGVSPB_ALLFOLDERS | SHGVSPB_INHERIT)) || SHGVSPB_ALLFOLDERS == (dwFlags & (SHGVSPB_PERFOLDER | SHGVSPB_ALLFOLDERS | SHGVSPB_INHERIT)) || SHGVSPB_INHERIT == (dwFlags & (SHGVSPB_PERFOLDER | SHGVSPB_ALLFOLDERS | SHGVSPB_INHERIT))); RIP(riid == IID_IPropertyBag || riid == IID_IUnknown); RIP(NULL != ppv); }
#else
#define IS_VALID_SHGVSPB_PARAMS(a, b, c, d, e)
#endif
// Cache the last bag accessed.
CViewStatePropertyBag* g_pCachedBag = NULL;
EXTERN_C void FreeViewStatePropertyBagCache() { ENTERCRITICAL; { if (g_pCachedBag) { g_pCachedBag->Release(); g_pCachedBag = NULL; } } LEAVECRITICAL; }
BOOL SHIsRemovableDrive(LPCITEMIDLIST pidl) { BOOL fRet = FALSE; LPCITEMIDLIST pidlLast; IShellFolder* psf; if (SUCCEEDED(SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast))) { STRRET str; if (SUCCEEDED(psf->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &str))) { WCHAR szPath[MAX_PATH]; if (SUCCEEDED(StrRetToBufW(&str, pidlLast, szPath, ARRAYSIZE(szPath)))) { int iDrive = PathGetDriveNumberW(szPath); if (iDrive != -1) { int iDriveType = RealDriveType(iDrive, FALSE);
fRet = (DRIVE_REMOVABLE == iDriveType || DRIVE_CDROM == iDriveType); } } }
psf->Release(); } return fRet; }
STDAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPCWSTR pszBagName, DWORD dwFlags, REFIID riid, void** ppv) { IS_VALID_SHGVSPB_PARAMS(pidl, pszBagName, dwFlags, riid, ppv);
HRESULT hr;
*ppv = NULL;
ENTERCRITICAL; { if (g_pCachedBag && g_pCachedBag->_IsSameBag(pidl, pszBagName, dwFlags)) { hr = S_OK; } else { if (!SHIsRemovableDrive(pidl)) { CViewStatePropertyBag* pBag = new CViewStatePropertyBag();
if (pBag) { hr = pBag->_Init(pidl, pszBagName, dwFlags);
if (SUCCEEDED(hr)) { if (g_pCachedBag) g_pCachedBag->Release();
g_pCachedBag = pBag; } else { pBag->Release(); } } else { hr = E_OUTOFMEMORY; } } else { hr = E_FAIL; // don't save property bags for removable drives.
} }
if (SUCCEEDED(hr)) { hr = g_pCachedBag->QueryInterface(riid, ppv); } } LEAVECRITICAL;
return hr; }
ULONG SHGetPerScreenResName(WCHAR* pszRes, ULONG cch, DWORD dwVersion) { RIPMSG(IS_VALID_WRITE_BUFFER(pszRes, *pszRes, cch), "SHGetPerScreenResName caller passed bad pszRes or cch");
ULONG uRet;
if (0 == dwVersion) { HDC hdc = GetDC(NULL); int x = GetDeviceCaps(hdc, HORZRES); int y = GetDeviceCaps(hdc, VERTRES); ReleaseDC(NULL, hdc);
int n = GetSystemMetrics(SM_CMONITORS);
int cchLen = wnsprintfW(pszRes, cch, L"%dx%d(%d)", x, y, n);
uRet = (cchLen > 0) ? cchLen : 0; } else { uRet = 0; }
return uRet; }
|