|
|
#include "shole.h"
#include "ids.h"
#include "scguid.h"
extern TEXT("C") const TCHAR c_szCLSID[];
class CTemplateFolder : public IShellFolder, public IPersistFolder { public: CTemplateFolder(); ~CTemplateFolder();
protected: // IUnKnown
virtual HRESULT __stdcall QueryInterface(REFIID,void **); virtual ULONG __stdcall AddRef(void); virtual ULONG __stdcall Release(void);
// IShellFolder
virtual HRESULT __stdcall ParseDisplayName(HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName, ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes);
virtual HRESULT __stdcall EnumObjects( THIS_ HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList);
virtual HRESULT __stdcall BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut); virtual HRESULT __stdcall BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvObj); virtual HRESULT __stdcall CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); virtual HRESULT __stdcall CreateViewObject (HWND hwndOwner, REFIID riid, LPVOID * ppvOut); virtual HRESULT __stdcall GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfInOut); virtual HRESULT __stdcall GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut); virtual HRESULT __stdcall GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName); virtual HRESULT __stdcall SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut);
// IPersistFolder
virtual HRESULT __stdcall GetClassID(LPCLSID lpClassID); virtual HRESULT __stdcall Initialize(LPCITEMIDLIST pidl);
// Defview callback
friend HRESULT CALLBACK DefViewCallback( LPSHELLVIEW psvOuter, LPSHELLFOLDER psf, HWND hwndOwner, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL IsMyPidl(LPCITEMIDLIST pidl) { return pidl->mkid.cb == SIZEOF(pidl->mkid.cb)+SIZEOF(CLSID); }
UINT _cRef; };
class CEnumTemplate : public IEnumIDList { public: CEnumTemplate(); ~CEnumTemplate();
protected: // IUnKnown
virtual HRESULT __stdcall QueryInterface(REFIID,void **); virtual ULONG __stdcall AddRef(void); virtual ULONG __stdcall Release(void);
virtual HRESULT __stdcall Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched); virtual HRESULT __stdcall Skip(ULONG celt); virtual HRESULT __stdcall Reset(); virtual HRESULT __stdcall Clone(IEnumIDList **ppenum);
UINT _cRef; UINT _iCur; HKEY _hkeyCLSID; struct { ITEMIDLIST idl; BYTE __abRest[255]; // Enough for CLSID or ProgID
} _tidl; };
class CTemplateUIObj : public IExtractIcon, public IDataObject { public: static HRESULT Create(REFCLSID, REFIID, LPVOID*); protected: CTemplateUIObj(REFCLSID rclsid) : _clsid(rclsid), _cRef(1) { g_cRefThisDll++; } ~CTemplateUIObj() { g_cRefThisDll--; } HRESULT _CreateInstance(IStorage* pstg);
// IUnKnown
virtual HRESULT __stdcall QueryInterface(REFIID,void **); virtual ULONG __stdcall AddRef(void); virtual ULONG __stdcall Release(void);
// *** IExtractIcon methods ***
virtual HRESULT __stdcall GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags);
virtual HRESULT __stdcall Extract( LPCTSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
// IDataObject
virtual HRESULT __stdcall GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium); virtual HRESULT __stdcall GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium); virtual HRESULT __stdcall QueryGetData(FORMATETC *pformatetc); virtual HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut); virtual HRESULT __stdcall SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease); virtual HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc); virtual HRESULT __stdcall DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); virtual HRESULT __stdcall DUnadvise(DWORD dwConnection); virtual HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
UINT _cRef; CLSID _clsid; };
CTemplateFolder::CTemplateFolder() : _cRef(1) { OleInitialize(NULL); g_cRefThisDll++; }
CTemplateFolder::~CTemplateFolder() { OleUninitialize(); g_cRefThisDll--; }
HRESULT CTemplateFolder::QueryInterface(REFIID riid, LPVOID * ppvObj) { if (IsEqualIID(riid, IID_IShellFolder) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IShellFolder*)this; _cRef++; return S_OK; } else if (IsEqualIID(riid, IID_IPersistFolder)) { *ppvObj = (IPersistFolder*)this; _cRef++; return S_OK; } *ppvObj = NULL;
return E_NOINTERFACE; }
ULONG CTemplateFolder::AddRef() { _cRef++; return _cRef; }
ULONG CTemplateFolder::Release() { _cRef--; if (_cRef > 0) return _cRef;
delete this; return 0; }
HRESULT CTemplateFolder_CreateInstnace(LPUNKNOWN * ppunk) { CTemplateFolder* ptfld = new CTemplateFolder(); if (ptfld) { *ppunk = (IShellFolder *)ptfld; return S_OK; } return E_OUTOFMEMORY; }
HRESULT CTemplateFolder::ParseDisplayName(HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName, ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes) { return E_NOTIMPL; }
HRESULT CTemplateFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList) { *ppenumIDList = new CEnumTemplate(); return S_OK; }
HRESULT CTemplateFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) { return E_NOTIMPL; }
HRESULT CTemplateFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvObj) { return E_NOTIMPL; }
HRESULT CTemplateFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { return E_NOTIMPL; }
HRESULT CALLBACK DefViewCallback(LPSHELLVIEW psvOuter, LPSHELLFOLDER psf, HWND hwndOwner, UINT uMsg, WPARAM wParam, LPARAM lParam) { // APPCOMPAT: DefView GPF if I don't pass the callback function!
// APPCOMPAT: DefView GPF if it returns S_FALSE as the default!
return E_FAIL; // S_FALSE;
}
HRESULT CTemplateFolder::CreateViewObject (HWND hwndOwner, REFIID riid, LPVOID * ppvOut) { if (IsEqualIID(riid, IID_IShellView)) { CSFV csfv = { SIZEOF(CSFV), // cbSize
this, // pshf
NULL, // psvOuter
NULL, // pidl
0, DefViewCallback, // pfnCallback
FVM_ICON, }; return SHCreateShellFolderViewEx(&csfv, (LPSHELLVIEW *)ppvOut); } return E_NOINTERFACE; }
HRESULT CTemplateFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl, ULONG * rgfInOut) { UINT rgfOut = SFGAO_CANCOPY | SFGAO_HASPROPSHEET; *rgfInOut = rgfOut; return S_OK; }
HRESULT CTemplateFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) { HRESULT hres = E_INVALIDARG; if (cidl==1 && IsMyPidl(apidl[0])) { const CLSID* pclsid = (const CLSID*)&apidl[0]->mkid.abID; hres = CTemplateUIObj::Create(*pclsid, riid, ppvOut); }
return hres; }
HRESULT _KeyNameFromCLSID(REFCLSID rclsid, LPTSTR pszKey, UINT cchMax) { LPWSTR pwszKey; HRESULT hres = StringFromCLSID(rclsid, &pwszKey); if (FAILED(hres)) { return E_INVALIDARG; }
lstrcpyn(pszKey, TEXT("CLSID\\"), cchMax); WideCharToMultiByte(CP_ACP, 0, pwszKey, -1, pszKey+6, cchMax-6, NULL, NULL);
// FEATURE: Use TASK ALLOCATOR!!!
LocalFree(pwszKey); return S_OK; }
HRESULT CTemplateFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName) { if (!IsMyPidl(pidl)) { return E_INVALIDARG; }
LPCLSID const pclsid = (LPCLSID)pidl->mkid.abID; TCHAR szKey[128]; HRESULT hres = _KeyNameFromCLSID(*pclsid, szKey, ARRAYSIZE(szKey)); if (FAILED(hres)) { return hres; }
LONG dwSize = ARRAYSIZE(lpName->cStr); if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, lpName->cStr, &dwSize) == ERROR_SUCCESS) { lpName->uType = STRRET_CSTR; return S_OK; }
return E_FAIL; }
HRESULT CTemplateFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut) { return E_NOTIMPL; }
HRESULT __stdcall CTemplateFolder::GetClassID(LPCLSID lpClassID) { *lpClassID = CLSID_CTemplateFolder; return S_OK; }
HRESULT __stdcall CTemplateFolder::Initialize(LPCITEMIDLIST pidl) { return S_OK; }
CEnumTemplate::CEnumTemplate() : _cRef(1), _iCur(0), _hkeyCLSID(NULL) { g_cRefThisDll++; }
CEnumTemplate::~CEnumTemplate() { if (_hkeyCLSID) { RegCloseKey(_hkeyCLSID); } g_cRefThisDll--; }
HRESULT CEnumTemplate::QueryInterface(REFIID riid, LPVOID * ppvObj) { if (IsEqualIID(riid, IID_IEnumIDList) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IEnumIDList*)this; _cRef++; return S_OK; } *ppvObj = NULL;
return E_NOINTERFACE; }
ULONG CEnumTemplate::AddRef() { _cRef++; return _cRef; }
ULONG CEnumTemplate::Release() { _cRef--; if (_cRef > 0) return _cRef;
delete this; return 0; }
HRESULT CEnumTemplate::Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) { // Assume error
if (pceltFetched) { *pceltFetched = 0; }
if (!_hkeyCLSID) { if (RegOpenKey(HKEY_CLASSES_ROOT, c_szCLSID, &_hkeyCLSID) != ERROR_SUCCESS) { return E_FAIL; } }
TCHAR szKey[40]; // enough for {CLSID}
while (RegEnumKey(_hkeyCLSID, _iCur++, szKey, ARRAYSIZE(szKey)) == ERROR_SUCCESS) { TCHAR szInsertable[128]; // enough for "{CLSID}/Insertable"
wsprintf(szInsertable, TEXT("%s\\Insertable"), szKey); HKEY hkeyT;
if (RegOpenKey(_hkeyCLSID, szInsertable, &hkeyT) == ERROR_SUCCESS) { RegCloseKey(hkeyT);
CLSID clsid; WCHAR wszKey[40]; MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, ARRAYSIZE(wszKey)); HRESULT hres = CLSIDFromString(wszKey, &clsid); if (SUCCEEDED(hres)) { _tidl.idl.mkid.cb = SIZEOF(_tidl.idl.mkid.cb) + SIZEOF(clsid); memcpy(_tidl.idl.mkid.abID, &clsid, SIZEOF(clsid)); LPITEMIDLIST pidl = _ILNext(&_tidl.idl); pidl->mkid.cb = 0; // Terminator
rgelt[0] = ILClone(&_tidl.idl); *pceltFetched = 1; return S_OK; } } }
return S_FALSE; // no more element
}
HRESULT CEnumTemplate::Skip(ULONG celt) { return E_NOTIMPL; }
HRESULT CEnumTemplate::Reset() { return E_NOTIMPL; }
HRESULT CEnumTemplate::Clone(IEnumIDList **ppenum) { return E_NOTIMPL; }
//==========================================================================
// CTemplateUIObj members (IUnknown override)
//==========================================================================
HRESULT CTemplateUIObj::QueryInterface(REFIID riid, LPVOID * ppvObj) { if (IsEqualIID(riid, IID_IExtractIcon) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IExtractIcon*)this; _cRef++; return S_OK; } else if (IsEqualIID(riid, IID_IDataObject)) { *ppvObj = (IDataObject*)this; _cRef++; return S_OK; } *ppvObj = NULL;
return E_NOINTERFACE; }
ULONG CTemplateUIObj::AddRef() { _cRef++; return _cRef; }
ULONG CTemplateUIObj::Release() { _cRef--; if (_cRef > 0) return _cRef;
delete this; return 0; }
//
// NOTES: This logic MUST be identical to the one in the shell.
//
inline int _ParseIconLocation(LPTSTR pszIconFile) { int iIndex = 0; LPTSTR pszComma = StrChr(pszIconFile, TEXT(','));
if (pszComma) { *pszComma++ = 0; // terminate the icon file name.
iIndex = StrToInt(pszComma); } PathRemoveBlanks(pszIconFile); return iIndex; }
//==========================================================================
// CTemplateUIObj members (IExtractIcon override)
//==========================================================================
HRESULT CTemplateUIObj::GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags) { TCHAR szKey[128]; HRESULT hres = _KeyNameFromCLSID(_clsid, szKey, ARRAYSIZE(szKey)); if (SUCCEEDED(hres)) { lstrcat(szKey, TEXT("\\DefaultIcon")); // FEATURE: lstrcatn?
TCHAR szValue[MAX_PATH+40]; LONG dwSize = ARRAYSIZE(szValue); if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &dwSize) == ERROR_SUCCESS) { *pwFlags = GIL_PERCLASS; *piIndex = _ParseIconLocation(szValue); lstrcpyn(szIconFile, szValue, cchMax); hres = S_OK; } } return hres; }
HRESULT CTemplateUIObj::Extract( LPCTSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) { return S_FALSE; }
HRESULT CTemplateUIObj::Create(REFCLSID rclsid, REFIID riid, LPVOID* ppvOut) { CTemplateUIObj *pti = new CTemplateUIObj(rclsid); if (pti) { pti->QueryInterface(riid, ppvOut); pti->Release(); return S_OK; }
*ppvOut=NULL; return E_OUTOFMEMORY; }
//==========================================================================
// CTemplateUIObj members (IDataObject override)
//==========================================================================
HRESULT CTemplateUIObj::_CreateInstance(IStorage* pstg) { HRESULT hres; IPersistStorage* pps = NULL; hres = OleCreate(_clsid, IID_IPersistStorage, OLERENDER_DRAW, NULL, NULL, pstg, (LPVOID*)&pps); DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI OleCreate returned (%x)"), hres);
if (SUCCEEDED(hres)) { hres = OleSave(pps, pstg, TRUE); DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI OleSave returned (%x)"), hres); pps->HandsOffStorage(); pps->Release();
if (SUCCEEDED(hres)) { hres = pstg->Commit(STGC_OVERWRITE); DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI pstg->Commit returned (%x)"), hres); } }
return hres; }
HRESULT CTemplateUIObj::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) { HRESULT hres = DATA_E_FORMATETC;
pmedium->pUnkForRelease = NULL; pmedium->pstg = NULL;
//
// NOTES: We should avoid calling _OpenStorage if we don't support
// the format.
//
if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE) { IStorage* pstg = NULL; hres = StgCreateDocfile(NULL, STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstg); DebugMsg(DM_TRACE, TEXT("so TR - TUO:GD StgCreateDocfile returned (%x)"), hres); if (SUCCEEDED(hres)) { hres = _CreateInstance(pstg); if (SUCCEEDED(hres)) { pmedium->tymed = TYMED_ISTORAGE; pmedium->pstg = pstg; } else { pstg->Release(); } } } return hres; }
HRESULT CTemplateUIObj::GetDataHere(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) { HRESULT hres = DATA_E_FORMATETC;
if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE && pmedium->tymed == TYMED_ISTORAGE) { hres = _CreateInstance(pmedium->pstg); }
return hres; }
HRESULT CTemplateUIObj::QueryGetData(LPFORMATETC pformatetcIn) { if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT && pformatetcIn->tymed == TYMED_ISTORAGE) { return S_OK; } return DATA_E_FORMATETC; }
HRESULT CTemplateUIObj::GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) { //
// This is the simplest implemtation. It means we always return
// the data in the format requested.
//
return ResultFromScode(DATA_S_SAMEFORMATETC); }
HRESULT CTemplateUIObj::SetData(LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease) { return E_FAIL; }
HRESULT CTemplateUIObj::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc) { static FORMATETC s_afmt[] = { CF_EMBEDDEDOBJECT }; return SHCreateStdEnumFmtEtc(ARRAYSIZE(s_afmt), s_afmt, ppenumFormatEtc); }
HRESULT CTemplateUIObj::DAdvise(FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
HRESULT CTemplateUIObj::DUnadvise(DWORD dwConnection) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
HRESULT CTemplateUIObj::EnumDAdvise(LPENUMSTATDATA * ppenumAdvise) { return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); }
|