|
|
#include "shole.h"
#include "ids.h"
#include "scguid.h"
#ifdef FEATURE_SHELLEXTENSION
extern "C" const TCHAR c_szCLSID[];
class CTemplateFolder : public IShellFolder, public IPersistFolder { public: CTemplateFolder(); ~CTemplateFolder(); inline BOOL ConstructedSuccessfully() { return _hdpaMap != NULL; }
// 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);
protected: // Defview callback
friend HRESULT CALLBACK DefViewCallback( LPSHELLVIEW psvOuter, LPSHELLFOLDER psf, HWND hwndOwner, UINT uMsg, WPARAM wParam, LPARAM lParam); HRESULT GetDetailsOfDVM(UINT ici, DETAILSINFO *pdi);
BOOL IsMyPidl(LPCITEMIDLIST pidl) { return (pidl->mkid.abID[0] == 'S' && pidl->mkid.abID[1] == 'N'); }
UINT _cRef;
//
// To speed up name lookups, we cache the mapping between CLSIDs and
// display names. We cannot persist this mapping because it won't
// survive localization or ANSI/UNICODE interop.
//
typedef struct { CLSID clsid; TCHAR achName[MAX_PATH]; } CLSIDMAP, *PCLSIDMAP;
HDPA _hdpaMap;
HRESULT GetNameOf(LPCITEMIDLIST pidl, LPCTSTR *ppsz); };
class CEnumTemplate : public IEnumIDList { public: CEnumTemplate(DWORD grfFlags); ~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; const DWORD _grfFlags; UINT _iCur; HKEY _hkeyCLSID; };
//
// For Win95/NT interop, our PIDLs are always UNICODE.
// Use explicit packing for Win32/64 interop.
#include <pshpack1.h>
typedef struct _TIDL { USHORT cb; // This matches SHITEMID
BYTE abID[2]; // This matches SHITEMID
CLSID clsid; } TIDL; typedef const UNALIGNED TIDL *PTIDL;
//
// This is the TIDL constructor -- it has the cbZero at the end.
//
typedef struct _TIDLCONS { TIDL tidl; USHORT cbZero; } TIDLCONS;
#include <poppack.h>
class CTemplateUIObj : public IExtractIcon, public IDataObject, public IContextMenu { public: static HRESULT Create(REFCLSID, REFIID, LPVOID*); protected: CTemplateUIObj(REFCLSID rclsid) : _clsid(rclsid), _cRef(1) { DllAddRef(); } ~CTemplateUIObj() { DllRelease(); } 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);
// IContextMenu
virtual HRESULT __stdcall QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
virtual HRESULT __stdcall InvokeCommand( LPCMINVOKECOMMANDINFO lpici);
virtual HRESULT __stdcall GetCommandString( UINT idCmd, UINT uType, UINT * pwReserved, LPSTR pszName, UINT cchMax);
UINT _cRef; CLSID _clsid; };
CTemplateFolder::CTemplateFolder() : _cRef(1) { _hdpaMap = DPA_Create(10); OleInitialize(NULL); DllAddRef(); }
CTemplateFolder::~CTemplateFolder() { if (_hdpaMap) { for (int i = DPA_GetPtrCount(_hdpaMap) - 1; i >= 0; i--) { PCLSIDMAP pmap = (PCLSIDMAP)DPA_FastGetPtr(_hdpaMap, i); LocalFree(pmap); } DPA_Destroy(_hdpaMap); }
OleUninitialize(); DllRelease(); }
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_CreateInstance(LPUNKNOWN * ppunk) { *ppunk = NULL;
CTemplateFolder* ptfld = new CTemplateFolder(); if (ptfld) { if (ptfld->ConstructedSuccessfully()) { *ppunk = (IShellFolder *)ptfld; return S_OK; } ptfld->Release(); } 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(grfFlags); return *ppenumIDList ? S_OK : E_OUTOFMEMORY; }
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; }
//
// If the name is in the cache, celebrate our good fortune and return it.
// Else, go get the name from the registry and cache it for later.
//
HRESULT CTemplateFolder::GetNameOf(LPCITEMIDLIST pidl, LPCTSTR *ppsz) { if (!IsMyPidl(pidl)) return E_INVALIDARG;
HRESULT hres; PTIDL ptidl = (PTIDL)pidl; CLSIDMAP map; map.clsid = ptidl->clsid; // Align the CLSID
PCLSIDMAP pmap; for (int i = DPA_GetPtrCount(_hdpaMap) - 1; i >= 0; i--) { pmap = (PCLSIDMAP)DPA_FastGetPtr(_hdpaMap, i); if (IsEqualGUID(pmap->clsid, map.clsid)) { *ppsz = pmap->achName; return S_OK; } }
//
// Not in cache -- go find it in the registry
//
TCHAR szKey[GUIDSTR_MAX + 6]; _KeyNameFromCLSID(map.clsid, szKey, ARRAYSIZE(szKey)); LONG dwSize = ARRAYSIZE(map.achName); LONG lError = RegQueryValue(HKEY_CLASSES_ROOT, szKey, map.achName, &dwSize); if (lError == ERROR_SUCCESS) { UINT cb = FIELD_OFFSET(CLSIDMAP, achName[lstrlen(map.achName)+1]); pmap = (PCLSIDMAP)LocalAlloc(LMEM_FIXED, cb); if (pmap) { CopyMemory(pmap, &map, cb); if (DPA_AppendPtr(_hdpaMap, pmap) >= 0) { *ppsz = pmap->achName; hres = S_OK; } else { LocalFree(pmap); hres = E_OUTOFMEMORY; } } else { hres = E_OUTOFMEMORY; } } else { hres = HRESULT_FROM_WIN32(lError); }
return hres;
}
HRESULT CTemplateFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { LPCTSTR psz1, psz2; HRESULT hres;
hres = GetNameOf(pidl1, &psz1); if (SUCCEEDED(hres)) { hres = GetNameOf(pidl2, &psz2); if (SUCCEEDED(hres)) { hres = ResultFromShort(lstrcmpi(psz1, psz2)); } } return hres; }
HRESULT CTemplateFolder::GetDetailsOfDVM(UINT ici, DETAILSINFO *pdi) { HRESULT hres;
switch (ici) { case 0: if (pdi->pidl) { hres = GetDisplayNameOf(pdi->pidl, SHGDN_NORMAL, &pdi->str); } else { pdi->fmt = LVCFMT_LEFT; pdi->cxChar = 30; pdi->str.uType = STRRET_CSTR; lstrcpyA(pdi->str.cStr, "Name"); hres = S_OK; } break;
default: hres = E_NOTIMPL; break; } return hres; }
HRESULT CALLBACK DefViewCallback(LPSHELLVIEW psvOuter, LPSHELLFOLDER psf, HWND hwndOwner, UINT uMsg, WPARAM wParam, LPARAM lParam) { // DefView GPF if I don't pass the callback function!
// DebugMsg(DM_TRACE, "sc TR - DefViewCallBack %d,%x,%x", uMsg, wParam, lParam);
switch(uMsg) { case DVM_WINDOWDESTROY: DebugMsg(DM_TRACE, TEXT("sc TR - DefViewCallBack Calling OleFlushClipboard")); OleFlushClipboard(); return S_OK; case DVM_GETDETAILSOF: return ((CTemplateFolder*)psf)->GetDetailsOfDVM((UINT)wParam, (DETAILSINFO*)lParam); } // 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) { if (cidl==1) { UINT rgfOut = SFGAO_CANCOPY /* | SFGAO_HASPROPSHEET */; *rgfInOut &= rgfOut; } else { *rgfInOut = 0; } 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])) { PTIDL ptidl = (PTIDL)apidl[0]; hres = CTemplateUIObj::Create(ptidl->clsid, riid, ppvOut); }
return hres; }
HRESULT _KeyNameFromCLSID(REFCLSID rclsid, LPTSTR pszKey, UINT cchMax) { ASSERT(cchMax - 6 >= GUIDSTR_MAX); lstrcpyn(pszKey, TEXT("CLSID\\"), cchMax); SHStringFromGUID(rclsid, pszKey + 6, cchMax - 6); return S_OK; }
HRESULT CTemplateFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName) { LPCTSTR psz; HRESULT hres;
hres = GetNameOf(pidl, &psz); if (SUCCEEDED(hres)) { #ifdef UNICODE
lpName->uType = STRRET_WSTR; hres = SHStrDupW(psz, &lpName->pOleStr); #else
lstrcpyn(lpName->cStr, psz, ARRAYSIZE(lpName->cStr)); hres = S_OK; #endif
} return hres; }
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(DWORD grfFlags) : _cRef(1), _grfFlags(grfFlags), _iCur(0), _hkeyCLSID(NULL) { DllAddRef(); }
CEnumTemplate::~CEnumTemplate() { if (_hkeyCLSID) { RegCloseKey(_hkeyCLSID); } DllRelease(); }
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 (!(_grfFlags & SHCONTF_NONFOLDERS)) { return S_FALSE; }
if (!_hkeyCLSID) { if (RegOpenKey(HKEY_CLASSES_ROOT, c_szCLSID, &_hkeyCLSID) != ERROR_SUCCESS) { return E_FAIL; } }
TCHAR szKeyBuf[128]; // enough for {CLSID} or "ProgId/XXX"
// Subtract 64 to allow room for the goo we append later on
while (RegEnumKey(HKEY_CLASSES_ROOT, _iCur++, szKeyBuf, ARRAYSIZE(szKeyBuf) - 64) == ERROR_SUCCESS) { TCHAR szT[128]; LONG dwRead; int cchKey = lstrlen(szKeyBuf);
// Check for \NotInsertable.
lstrcpy(szKeyBuf+cchKey, TEXT("\\NotInsertable")); dwRead = ARRAYSIZE(szT); if (RegQueryValue(HKEY_CLASSES_ROOT, szKeyBuf, szT, &dwRead) == ERROR_SUCCESS) { continue; }
BOOL fInsertable = FALSE; //
// Let's stop supporting OLE1 servers anymore.
//
#if 0
lstrcpy(szKeyBuf+cchKey, TEXT("\\protocol\\StdFileEditing\\server")); dwRead = ARRAYSIZE(szT); if (RegQueryValue(HKEY_CLASSES_ROOT, szKeyBuf, szT, &dwRead) == ERROR_SUCCESS) { fInsertable = TRUE; } else #endif
{ lstrcpy(szKeyBuf+cchKey, TEXT("\\Insertable")); dwRead = ARRAYSIZE(szT); if (RegQueryValue(HKEY_CLASSES_ROOT, szKeyBuf, szT, &dwRead) == ERROR_SUCCESS) { fInsertable = TRUE; } }
if (fInsertable) { lstrcpy(szKeyBuf+cchKey, TEXT("\\CLSID")); dwRead = ARRAYSIZE(szT); if (RegQueryValue(HKEY_CLASSES_ROOT, szKeyBuf, szT, &dwRead) == ERROR_SUCCESS) { TIDLCONS tidlCons; CLSID clsid; // Aligned version
tidlCons.tidl.cb = sizeof(TIDL); tidlCons.tidl.abID[0] = 'S'; tidlCons.tidl.abID[1] = 'N';
if (GUIDFromString(szT, &clsid)) { tidlCons.tidl.clsid = clsid; tidlCons.cbZero = 0; rgelt[0] = ILClone((LPITEMIDLIST)&tidlCons); *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; } else if (IsEqualIID(riid, IID_IContextMenu)) { *ppvObj = (IContextMenu*)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.
//
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)
//==========================================================================
//
// szClass -- Specifies either CLSID\{CLSID} or ProgID
//
HRESULT _GetDefaultIcon(LPCTSTR szClass, LPTSTR szIconFile, UINT cchMax, int *piIndex) { TCHAR szKey[256]; wsprintf(szKey, TEXT("%s\\DefaultIcon"), szClass); TCHAR szValue[MAX_PATH+40]; LONG dwSize = ARRAYSIZE(szValue); if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &dwSize) == ERROR_SUCCESS) { *piIndex = _ParseIconLocation(szValue); lstrcpyn(szIconFile, szValue, cchMax); return S_OK; } return E_FAIL; }
HRESULT CTemplateUIObj::GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags) { *pwFlags = GIL_PERCLASS; // Always per-class
TCHAR szKey[128]; HRESULT hres = _KeyNameFromCLSID(_clsid, szKey, ARRAYSIZE(szKey)); if (SUCCEEDED(hres)) { //
// First, look at "CLSID\{CLSID}\DefautlIcon"
//
hres = _GetDefaultIcon(szKey, szIconFile, cchMax, piIndex); if (FAILED(hres)) { //
// Then, look at "ProgID\DefaultIcon" to work-around a bug
// of "Wave Sound".
//
lstrcat(szKey, TEXT("\\ProgID")); TCHAR szValue[MAX_PATH+40]; LONG dwSize = ARRAYSIZE(szValue); if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &dwSize) == ERROR_SUCCESS) { hres = _GetDefaultIcon(szValue, szIconFile, cchMax, piIndex); } } } 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); HRESULT hres; if (pti) { hres = pti->QueryInterface(riid, ppvOut); pti->Release(); return hres; }
*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(); } } } else if (pformatetcIn->cfFormat == CF_OBJECTDESCRIPTOR && pformatetcIn->tymed == TYMED_HGLOBAL) { DebugMsg(DM_TRACE, TEXT("so TR - TUO:GD cfFormat==CF_OBJECTDESCRIPTOR"));
static WCHAR szUserTypeName[] = L"Foo"; // REARCHITECT: this code is really miss, and might end up returning Foo
static WCHAR szSrcOfCopy[] = L"Bar"; UINT cbUserTypeName = sizeof(szUserTypeName); UINT cbSrcOfCopy = sizeof(szSrcOfCopy); pmedium->hGlobal = GlobalAlloc(GPTR, sizeof(OBJECTDESCRIPTOR)+cbUserTypeName+cbSrcOfCopy); if (pmedium->hGlobal) { OBJECTDESCRIPTOR* podsc = (OBJECTDESCRIPTOR*)pmedium->hGlobal; podsc->cbSize = sizeof(OBJECTDESCRIPTOR); podsc->clsid = _clsid; podsc->dwDrawAspect = 0; // The source does not draw the object
// podsc->sizel = { 0, 0 }; // The source does not draw the object
// podsc->pointl = { 0, 0 };
podsc->dwStatus = 0; // FEATURE: read it from registry! CLSID/MiscStatus
podsc->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR); podsc->dwSrcOfCopy = sizeof(OBJECTDESCRIPTOR)+cbUserTypeName; LPBYTE pbT = (LPBYTE)(podsc+1); lstrcpyW((LPWSTR)pbT, szUserTypeName); lstrcpyW((LPWSTR)(pbT+cbUserTypeName), szSrcOfCopy); Assert(pbT == ((LPBYTE)podsc)+podsc->dwFullUserTypeName); Assert(pbT+cbUserTypeName == ((LPBYTE)podsc)+podsc->dwSrcOfCopy);
pmedium->tymed = TYMED_HGLOBAL; hres = S_OK; } else { hres = E_OUTOFMEMORY; } } 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; } else if (pformatetcIn->cfFormat == CF_OBJECTDESCRIPTOR && pformatetcIn->tymed == TYMED_HGLOBAL) { 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[] = { { (CLIPFORMAT)CF_EMBEDDEDOBJECT }, {(CLIPFORMAT)CF_OBJECTDESCRIPTOR} }; 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); }
#define TIDC_INVALID -1
#define TIDC_COPY 0
#define TIDC_MAX 1
HRESULT CTemplateUIObj::QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { DebugMsg(DM_TRACE, TEXT("sc TR - CTUI::QCM called (uFlags=%x)"), uFlags);
//
// REVIEW: Checking CMF_DVFILE is subtle, need to be documented clearly!
//
if (!(uFlags & (CMF_VERBSONLY|CMF_DVFILE))) { MENUITEMINFO mii = { sizeof(MENUITEMINFO), MIIM_STATE|MIIM_ID|MIIM_TYPE, MFT_STRING, MFS_DEFAULT, idCmdFirst+TIDC_COPY, NULL, NULL, NULL, 0, TEXT("&Copy"), // FEATURE: Support NLS, the Copy operation might have a different name in other languages
5 }; InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); } return ResultFromShort(TIDC_MAX); }
HRESULT CTemplateUIObj::InvokeCommand( LPCMINVOKECOMMANDINFO lpici) { HRESULT hres; DebugMsg(DM_TRACE, TEXT("sc TR - CTUI::IC called (%x)"), lpici->lpVerb); int idCmd = TIDC_INVALID;
if (HIWORD(lpici->lpVerb)) { if (lstrcmpiA(lpici->lpVerb, "copy") == 0) { idCmd = TIDC_COPY; } } else { idCmd = LOWORD(lpici->lpVerb); }
switch(idCmd) { case TIDC_COPY: hres = OleSetClipboard(this); break;
default: hres = E_INVALIDARG; break; }
return hres; }
HRESULT CTemplateUIObj::GetCommandString( UINT idCmd, UINT uType, UINT * pwReserved, LPSTR pszName, UINT cchMax) { DebugMsg(DM_TRACE, TEXT("sc TR - CTUI::GCS called (%d, %x)"), idCmd, uType); return E_NOTIMPL; }
#endif // FEATURE_SHELLEXTENSION
|