Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

649 lines
18 KiB

  1. #include "shole.h"
  2. #include "ids.h"
  3. #include "scguid.h"
  4. extern TEXT("C") const TCHAR c_szCLSID[];
  5. class CTemplateFolder : public IShellFolder, public IPersistFolder
  6. {
  7. public:
  8. CTemplateFolder();
  9. ~CTemplateFolder();
  10. protected:
  11. // IUnKnown
  12. virtual HRESULT __stdcall QueryInterface(REFIID,void **);
  13. virtual ULONG __stdcall AddRef(void);
  14. virtual ULONG __stdcall Release(void);
  15. // IShellFolder
  16. virtual HRESULT __stdcall ParseDisplayName(HWND hwndOwner,
  17. LPBC pbcReserved, LPOLESTR lpszDisplayName,
  18. ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes);
  19. virtual HRESULT __stdcall EnumObjects( THIS_ HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList);
  20. virtual HRESULT __stdcall BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved,
  21. REFIID riid, LPVOID * ppvOut);
  22. virtual HRESULT __stdcall BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved,
  23. REFIID riid, LPVOID * ppvObj);
  24. virtual HRESULT __stdcall CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
  25. virtual HRESULT __stdcall CreateViewObject (HWND hwndOwner, REFIID riid, LPVOID * ppvOut);
  26. virtual HRESULT __stdcall GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl,
  27. ULONG * rgfInOut);
  28. virtual HRESULT __stdcall GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
  29. REFIID riid, UINT * prgfInOut, LPVOID * ppvOut);
  30. virtual HRESULT __stdcall GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName);
  31. virtual HRESULT __stdcall SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,
  32. LPCOLESTR lpszName, DWORD uFlags,
  33. LPITEMIDLIST * ppidlOut);
  34. // IPersistFolder
  35. virtual HRESULT __stdcall GetClassID(LPCLSID lpClassID);
  36. virtual HRESULT __stdcall Initialize(LPCITEMIDLIST pidl);
  37. // Defview callback
  38. friend HRESULT CALLBACK DefViewCallback(
  39. LPSHELLVIEW psvOuter, LPSHELLFOLDER psf,
  40. HWND hwndOwner, UINT uMsg,
  41. WPARAM wParam, LPARAM lParam);
  42. BOOL IsMyPidl(LPCITEMIDLIST pidl)
  43. { return pidl->mkid.cb == SIZEOF(pidl->mkid.cb)+SIZEOF(CLSID); }
  44. UINT _cRef;
  45. };
  46. class CEnumTemplate : public IEnumIDList
  47. {
  48. public:
  49. CEnumTemplate();
  50. ~CEnumTemplate();
  51. protected:
  52. // IUnKnown
  53. virtual HRESULT __stdcall QueryInterface(REFIID,void **);
  54. virtual ULONG __stdcall AddRef(void);
  55. virtual ULONG __stdcall Release(void);
  56. virtual HRESULT __stdcall Next(ULONG celt,
  57. LPITEMIDLIST *rgelt,
  58. ULONG *pceltFetched);
  59. virtual HRESULT __stdcall Skip(ULONG celt);
  60. virtual HRESULT __stdcall Reset();
  61. virtual HRESULT __stdcall Clone(IEnumIDList **ppenum);
  62. UINT _cRef;
  63. UINT _iCur;
  64. HKEY _hkeyCLSID;
  65. struct {
  66. ITEMIDLIST idl;
  67. BYTE __abRest[255]; // Enough for CLSID or ProgID
  68. } _tidl;
  69. };
  70. class CTemplateUIObj : public IExtractIcon, public IDataObject
  71. {
  72. public:
  73. static HRESULT Create(REFCLSID, REFIID, LPVOID*);
  74. protected:
  75. CTemplateUIObj(REFCLSID rclsid)
  76. : _clsid(rclsid), _cRef(1)
  77. { g_cRefThisDll++; }
  78. ~CTemplateUIObj() { g_cRefThisDll--; }
  79. HRESULT _CreateInstance(IStorage* pstg);
  80. // IUnKnown
  81. virtual HRESULT __stdcall QueryInterface(REFIID,void **);
  82. virtual ULONG __stdcall AddRef(void);
  83. virtual ULONG __stdcall Release(void);
  84. // *** IExtractIcon methods ***
  85. virtual HRESULT __stdcall GetIconLocation(
  86. UINT uFlags, LPTSTR szIconFile,
  87. UINT cchMax, int * piIndex,
  88. UINT * pwFlags);
  89. virtual HRESULT __stdcall Extract(
  90. LPCTSTR pszFile, UINT nIconIndex,
  91. HICON *phiconLarge, HICON *phiconSmall,
  92. UINT nIconSize);
  93. // IDataObject
  94. virtual HRESULT __stdcall GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
  95. virtual HRESULT __stdcall GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
  96. virtual HRESULT __stdcall QueryGetData(FORMATETC *pformatetc);
  97. virtual HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut);
  98. virtual HRESULT __stdcall SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease);
  99. virtual HRESULT __stdcall EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc);
  100. virtual HRESULT __stdcall DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
  101. virtual HRESULT __stdcall DUnadvise(DWORD dwConnection);
  102. virtual HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
  103. UINT _cRef;
  104. CLSID _clsid;
  105. };
  106. CTemplateFolder::CTemplateFolder() : _cRef(1)
  107. {
  108. OleInitialize(NULL);
  109. g_cRefThisDll++;
  110. }
  111. CTemplateFolder::~CTemplateFolder()
  112. {
  113. OleUninitialize();
  114. g_cRefThisDll--;
  115. }
  116. HRESULT CTemplateFolder::QueryInterface(REFIID riid, LPVOID * ppvObj)
  117. {
  118. if (IsEqualIID(riid, IID_IShellFolder) || IsEqualIID(riid, IID_IUnknown))
  119. {
  120. *ppvObj = (IShellFolder*)this;
  121. _cRef++;
  122. return S_OK;
  123. }
  124. else if (IsEqualIID(riid, IID_IPersistFolder))
  125. {
  126. *ppvObj = (IPersistFolder*)this;
  127. _cRef++;
  128. return S_OK;
  129. }
  130. *ppvObj = NULL;
  131. return E_NOINTERFACE;
  132. }
  133. ULONG CTemplateFolder::AddRef()
  134. {
  135. _cRef++;
  136. return _cRef;
  137. }
  138. ULONG CTemplateFolder::Release()
  139. {
  140. _cRef--;
  141. if (_cRef > 0)
  142. return _cRef;
  143. delete this;
  144. return 0;
  145. }
  146. HRESULT CTemplateFolder_CreateInstnace(LPUNKNOWN * ppunk)
  147. {
  148. CTemplateFolder* ptfld = new CTemplateFolder();
  149. if (ptfld) {
  150. *ppunk = (IShellFolder *)ptfld;
  151. return S_OK;
  152. }
  153. return E_OUTOFMEMORY;
  154. }
  155. HRESULT CTemplateFolder::ParseDisplayName(HWND hwndOwner,
  156. LPBC pbcReserved, LPOLESTR lpszDisplayName,
  157. ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG *pdwAttributes)
  158. {
  159. return E_NOTIMPL;
  160. }
  161. HRESULT CTemplateFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList)
  162. {
  163. *ppenumIDList = new CEnumTemplate();
  164. return S_OK;
  165. }
  166. HRESULT CTemplateFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved,
  167. REFIID riid, LPVOID * ppvOut)
  168. {
  169. return E_NOTIMPL;
  170. }
  171. HRESULT CTemplateFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved,
  172. REFIID riid, LPVOID * ppvObj)
  173. {
  174. return E_NOTIMPL;
  175. }
  176. HRESULT CTemplateFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  177. {
  178. return E_NOTIMPL;
  179. }
  180. HRESULT CALLBACK DefViewCallback(LPSHELLVIEW psvOuter, LPSHELLFOLDER psf,
  181. HWND hwndOwner, UINT uMsg, WPARAM wParam, LPARAM lParam)
  182. {
  183. // APPCOMPAT: DefView GPF if I don't pass the callback function!
  184. // APPCOMPAT: DefView GPF if it returns S_FALSE as the default!
  185. return E_FAIL; // S_FALSE;
  186. }
  187. HRESULT CTemplateFolder::CreateViewObject (HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
  188. {
  189. if (IsEqualIID(riid, IID_IShellView))
  190. {
  191. CSFV csfv = {
  192. SIZEOF(CSFV), // cbSize
  193. this, // pshf
  194. NULL, // psvOuter
  195. NULL, // pidl
  196. 0,
  197. DefViewCallback, // pfnCallback
  198. FVM_ICON,
  199. };
  200. return SHCreateShellFolderViewEx(&csfv, (LPSHELLVIEW *)ppvOut);
  201. }
  202. return E_NOINTERFACE;
  203. }
  204. HRESULT CTemplateFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST * apidl,
  205. ULONG * rgfInOut)
  206. {
  207. UINT rgfOut = SFGAO_CANCOPY | SFGAO_HASPROPSHEET;
  208. *rgfInOut = rgfOut;
  209. return S_OK;
  210. }
  211. HRESULT CTemplateFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
  212. REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
  213. {
  214. HRESULT hres = E_INVALIDARG;
  215. if (cidl==1 && IsMyPidl(apidl[0]))
  216. {
  217. const CLSID* pclsid = (const CLSID*)&apidl[0]->mkid.abID;
  218. hres = CTemplateUIObj::Create(*pclsid, riid, ppvOut);
  219. }
  220. return hres;
  221. }
  222. HRESULT _KeyNameFromCLSID(REFCLSID rclsid, LPTSTR pszKey, UINT cchMax)
  223. {
  224. LPWSTR pwszKey;
  225. HRESULT hres = StringFromCLSID(rclsid, &pwszKey);
  226. if (FAILED(hres)) {
  227. return E_INVALIDARG;
  228. }
  229. lstrcpyn(pszKey, TEXT("CLSID\\"), cchMax);
  230. WideCharToMultiByte(CP_ACP, 0, pwszKey, -1, pszKey+6, cchMax-6, NULL, NULL);
  231. // FEATURE: Use TASK ALLOCATOR!!!
  232. LocalFree(pwszKey);
  233. return S_OK;
  234. }
  235. HRESULT CTemplateFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName)
  236. {
  237. if (!IsMyPidl(pidl)) {
  238. return E_INVALIDARG;
  239. }
  240. LPCLSID const pclsid = (LPCLSID)pidl->mkid.abID;
  241. TCHAR szKey[128];
  242. HRESULT hres = _KeyNameFromCLSID(*pclsid, szKey, ARRAYSIZE(szKey));
  243. if (FAILED(hres)) {
  244. return hres;
  245. }
  246. LONG dwSize = ARRAYSIZE(lpName->cStr);
  247. if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, lpName->cStr, &dwSize) == ERROR_SUCCESS)
  248. {
  249. lpName->uType = STRRET_CSTR;
  250. return S_OK;
  251. }
  252. return E_FAIL;
  253. }
  254. HRESULT CTemplateFolder::SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl,
  255. LPCOLESTR lpszName, DWORD uFlags,
  256. LPITEMIDLIST * ppidlOut)
  257. {
  258. return E_NOTIMPL;
  259. }
  260. HRESULT __stdcall CTemplateFolder::GetClassID(LPCLSID lpClassID)
  261. {
  262. *lpClassID = CLSID_CTemplateFolder;
  263. return S_OK;
  264. }
  265. HRESULT __stdcall CTemplateFolder::Initialize(LPCITEMIDLIST pidl)
  266. {
  267. return S_OK;
  268. }
  269. CEnumTemplate::CEnumTemplate() : _cRef(1), _iCur(0), _hkeyCLSID(NULL)
  270. {
  271. g_cRefThisDll++;
  272. }
  273. CEnumTemplate::~CEnumTemplate()
  274. {
  275. if (_hkeyCLSID) {
  276. RegCloseKey(_hkeyCLSID);
  277. }
  278. g_cRefThisDll--;
  279. }
  280. HRESULT CEnumTemplate::QueryInterface(REFIID riid, LPVOID * ppvObj)
  281. {
  282. if (IsEqualIID(riid, IID_IEnumIDList) || IsEqualIID(riid, IID_IUnknown))
  283. {
  284. *ppvObj = (IEnumIDList*)this;
  285. _cRef++;
  286. return S_OK;
  287. }
  288. *ppvObj = NULL;
  289. return E_NOINTERFACE;
  290. }
  291. ULONG CEnumTemplate::AddRef()
  292. {
  293. _cRef++;
  294. return _cRef;
  295. }
  296. ULONG CEnumTemplate::Release()
  297. {
  298. _cRef--;
  299. if (_cRef > 0)
  300. return _cRef;
  301. delete this;
  302. return 0;
  303. }
  304. HRESULT CEnumTemplate::Next(ULONG celt,
  305. LPITEMIDLIST *rgelt,
  306. ULONG *pceltFetched)
  307. {
  308. // Assume error
  309. if (pceltFetched) {
  310. *pceltFetched = 0;
  311. }
  312. if (!_hkeyCLSID)
  313. {
  314. if (RegOpenKey(HKEY_CLASSES_ROOT, c_szCLSID, &_hkeyCLSID) != ERROR_SUCCESS)
  315. {
  316. return E_FAIL;
  317. }
  318. }
  319. TCHAR szKey[40]; // enough for {CLSID}
  320. while (RegEnumKey(_hkeyCLSID, _iCur++, szKey, ARRAYSIZE(szKey)) == ERROR_SUCCESS)
  321. {
  322. TCHAR szInsertable[128]; // enough for "{CLSID}/Insertable"
  323. wsprintf(szInsertable, TEXT("%s\\Insertable"), szKey);
  324. HKEY hkeyT;
  325. if (RegOpenKey(_hkeyCLSID, szInsertable, &hkeyT) == ERROR_SUCCESS)
  326. {
  327. RegCloseKey(hkeyT);
  328. CLSID clsid;
  329. WCHAR wszKey[40];
  330. MultiByteToWideChar(CP_ACP, 0, szKey, -1, wszKey, ARRAYSIZE(wszKey));
  331. HRESULT hres = CLSIDFromString(wszKey, &clsid);
  332. if (SUCCEEDED(hres))
  333. {
  334. _tidl.idl.mkid.cb = SIZEOF(_tidl.idl.mkid.cb) + SIZEOF(clsid);
  335. memcpy(_tidl.idl.mkid.abID, &clsid, SIZEOF(clsid));
  336. LPITEMIDLIST pidl = _ILNext(&_tidl.idl);
  337. pidl->mkid.cb = 0; // Terminator
  338. rgelt[0] = ILClone(&_tidl.idl);
  339. *pceltFetched = 1;
  340. return S_OK;
  341. }
  342. }
  343. }
  344. return S_FALSE; // no more element
  345. }
  346. HRESULT CEnumTemplate::Skip(ULONG celt)
  347. {
  348. return E_NOTIMPL;
  349. }
  350. HRESULT CEnumTemplate::Reset()
  351. {
  352. return E_NOTIMPL;
  353. }
  354. HRESULT CEnumTemplate::Clone(IEnumIDList **ppenum)
  355. {
  356. return E_NOTIMPL;
  357. }
  358. //==========================================================================
  359. // CTemplateUIObj members (IUnknown override)
  360. //==========================================================================
  361. HRESULT CTemplateUIObj::QueryInterface(REFIID riid, LPVOID * ppvObj)
  362. {
  363. if (IsEqualIID(riid, IID_IExtractIcon) || IsEqualIID(riid, IID_IUnknown))
  364. {
  365. *ppvObj = (IExtractIcon*)this;
  366. _cRef++;
  367. return S_OK;
  368. }
  369. else if (IsEqualIID(riid, IID_IDataObject))
  370. {
  371. *ppvObj = (IDataObject*)this;
  372. _cRef++;
  373. return S_OK;
  374. }
  375. *ppvObj = NULL;
  376. return E_NOINTERFACE;
  377. }
  378. ULONG CTemplateUIObj::AddRef()
  379. {
  380. _cRef++;
  381. return _cRef;
  382. }
  383. ULONG CTemplateUIObj::Release()
  384. {
  385. _cRef--;
  386. if (_cRef > 0)
  387. return _cRef;
  388. delete this;
  389. return 0;
  390. }
  391. //
  392. // NOTES: This logic MUST be identical to the one in the shell.
  393. //
  394. inline int _ParseIconLocation(LPTSTR pszIconFile)
  395. {
  396. int iIndex = 0;
  397. LPTSTR pszComma = StrChr(pszIconFile, TEXT(','));
  398. if (pszComma) {
  399. *pszComma++ = 0; // terminate the icon file name.
  400. iIndex = StrToInt(pszComma);
  401. }
  402. PathRemoveBlanks(pszIconFile);
  403. return iIndex;
  404. }
  405. //==========================================================================
  406. // CTemplateUIObj members (IExtractIcon override)
  407. //==========================================================================
  408. HRESULT CTemplateUIObj::GetIconLocation(
  409. UINT uFlags, LPTSTR szIconFile,
  410. UINT cchMax, int * piIndex,
  411. UINT * pwFlags)
  412. {
  413. TCHAR szKey[128];
  414. HRESULT hres = _KeyNameFromCLSID(_clsid, szKey, ARRAYSIZE(szKey));
  415. if (SUCCEEDED(hres))
  416. {
  417. lstrcat(szKey, TEXT("\\DefaultIcon")); // FEATURE: lstrcatn?
  418. TCHAR szValue[MAX_PATH+40];
  419. LONG dwSize = ARRAYSIZE(szValue);
  420. if (RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &dwSize) == ERROR_SUCCESS)
  421. {
  422. *pwFlags = GIL_PERCLASS;
  423. *piIndex = _ParseIconLocation(szValue);
  424. lstrcpyn(szIconFile, szValue, cchMax);
  425. hres = S_OK;
  426. }
  427. }
  428. return hres;
  429. }
  430. HRESULT CTemplateUIObj::Extract(
  431. LPCTSTR pszFile, UINT nIconIndex,
  432. HICON *phiconLarge, HICON *phiconSmall,
  433. UINT nIconSize)
  434. {
  435. return S_FALSE;
  436. }
  437. HRESULT CTemplateUIObj::Create(REFCLSID rclsid, REFIID riid, LPVOID* ppvOut)
  438. {
  439. CTemplateUIObj *pti = new CTemplateUIObj(rclsid);
  440. if (pti) {
  441. pti->QueryInterface(riid, ppvOut);
  442. pti->Release();
  443. return S_OK;
  444. }
  445. *ppvOut=NULL;
  446. return E_OUTOFMEMORY;
  447. }
  448. //==========================================================================
  449. // CTemplateUIObj members (IDataObject override)
  450. //==========================================================================
  451. HRESULT CTemplateUIObj::_CreateInstance(IStorage* pstg)
  452. {
  453. HRESULT hres;
  454. IPersistStorage* pps = NULL;
  455. hres = OleCreate(_clsid, IID_IPersistStorage, OLERENDER_DRAW,
  456. NULL, NULL, pstg, (LPVOID*)&pps);
  457. DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI OleCreate returned (%x)"), hres);
  458. if (SUCCEEDED(hres))
  459. {
  460. hres = OleSave(pps, pstg, TRUE);
  461. DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI OleSave returned (%x)"), hres);
  462. pps->HandsOffStorage();
  463. pps->Release();
  464. if (SUCCEEDED(hres))
  465. {
  466. hres = pstg->Commit(STGC_OVERWRITE);
  467. DebugMsg(DM_TRACE, TEXT("so TR - TUO:CI pstg->Commit returned (%x)"), hres);
  468. }
  469. }
  470. return hres;
  471. }
  472. HRESULT CTemplateUIObj::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  473. {
  474. HRESULT hres = DATA_E_FORMATETC;
  475. pmedium->pUnkForRelease = NULL;
  476. pmedium->pstg = NULL;
  477. //
  478. // NOTES: We should avoid calling _OpenStorage if we don't support
  479. // the format.
  480. //
  481. if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT
  482. && pformatetcIn->tymed == TYMED_ISTORAGE)
  483. {
  484. IStorage* pstg = NULL;
  485. hres = StgCreateDocfile(NULL, STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstg);
  486. DebugMsg(DM_TRACE, TEXT("so TR - TUO:GD StgCreateDocfile returned (%x)"), hres);
  487. if (SUCCEEDED(hres))
  488. {
  489. hres = _CreateInstance(pstg);
  490. if (SUCCEEDED(hres)) {
  491. pmedium->tymed = TYMED_ISTORAGE;
  492. pmedium->pstg = pstg;
  493. } else {
  494. pstg->Release();
  495. }
  496. }
  497. }
  498. return hres;
  499. }
  500. HRESULT CTemplateUIObj::GetDataHere(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  501. {
  502. HRESULT hres = DATA_E_FORMATETC;
  503. if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT
  504. && pformatetcIn->tymed == TYMED_ISTORAGE && pmedium->tymed == TYMED_ISTORAGE)
  505. {
  506. hres = _CreateInstance(pmedium->pstg);
  507. }
  508. return hres;
  509. }
  510. HRESULT CTemplateUIObj::QueryGetData(LPFORMATETC pformatetcIn)
  511. {
  512. if (pformatetcIn->cfFormat == CF_EMBEDDEDOBJECT
  513. && pformatetcIn->tymed == TYMED_ISTORAGE)
  514. {
  515. return S_OK;
  516. }
  517. return DATA_E_FORMATETC;
  518. }
  519. HRESULT CTemplateUIObj::GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut)
  520. {
  521. //
  522. // This is the simplest implemtation. It means we always return
  523. // the data in the format requested.
  524. //
  525. return ResultFromScode(DATA_S_SAMEFORMATETC);
  526. }
  527. HRESULT CTemplateUIObj::SetData(LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease)
  528. {
  529. return E_FAIL;
  530. }
  531. HRESULT CTemplateUIObj::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc)
  532. {
  533. static FORMATETC s_afmt[] = { CF_EMBEDDEDOBJECT };
  534. return SHCreateStdEnumFmtEtc(ARRAYSIZE(s_afmt), s_afmt, ppenumFormatEtc);
  535. }
  536. HRESULT CTemplateUIObj::DAdvise(FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection)
  537. {
  538. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  539. }
  540. HRESULT CTemplateUIObj::DUnadvise(DWORD dwConnection)
  541. {
  542. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  543. }
  544. HRESULT CTemplateUIObj::EnumDAdvise(LPENUMSTATDATA * ppenumAdvise)
  545. {
  546. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  547. }