Leaked source code of windows server 2003
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.

1601 lines
40 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: cpuiele.cpp
  8. //
  9. // This module contains the following classes:
  10. //
  11. // CCplUiElement
  12. // CCplUiCommand
  13. // CCplUiCommandOnPidl
  14. //
  15. // CCplUiElement is an implementation of IUIElement. This provides
  16. // the necessary display information for use in the shell's webview
  17. // implementation. The class also implements ICpUiElementInfo which
  18. // is similar to IUIElement but provides the display information in
  19. // a more 'final' form than a "<module>,<resource>" format.
  20. // The ICpUiElementInfo interface is used internally by the Control Panel
  21. // implementation.
  22. //
  23. // CCplUiCommand is an implementation of IUICommand. As with IUIElement,
  24. // this provides the necessary functions for communicating with webview
  25. // as a 'command' object (i.e. selectable 'link'). Also as with the
  26. // previous class, CCplUiCommand implements an internal version of
  27. // the public interface. ICplUiCommand provides two things:
  28. // 1. A method to invoke a context menu.
  29. // 2. An invocation method that accepts a site pointer. This site
  30. // pointer is passed along to an 'action' object that may need
  31. // access to the shell browser to perform it's function. It
  32. // obtains access to the shell browser through this site ptr.
  33. //
  34. // CCplUiCommandOnPidl is another implementation of IUICommand that
  35. // wraps a shell item ID list. It is used to represent the CPL
  36. // applet items in a category view.
  37. //
  38. //--------------------------------------------------------------------------
  39. #include "shellprv.h"
  40. #include "cpviewp.h"
  41. #include "cpguids.h"
  42. #include "cpuiele.h"
  43. #include "cputil.h"
  44. #include "contextmenu.h"
  45. #include "prop.h"
  46. namespace CPL {
  47. //-----------------------------------------------------------------------------
  48. // CCplUiElement
  49. //-----------------------------------------------------------------------------
  50. class CCplUiElement : public IUIElement,
  51. public ICpUiElementInfo
  52. {
  53. public:
  54. //
  55. // IUnknown
  56. //
  57. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  58. STDMETHOD_(ULONG, AddRef)(void);
  59. STDMETHOD_(ULONG, Release)(void);
  60. //
  61. // IUIElement (used by shell webview)
  62. //
  63. STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName);
  64. STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon);
  65. STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip);
  66. //
  67. // ICpUiElementInfo (used internally by Control Panel)
  68. //
  69. STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon);
  70. STDMETHOD(LoadName)(LPWSTR *ppszName);
  71. STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip);
  72. static HRESULT CreateInstance(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, REFIID riid, void **ppvOut);
  73. protected:
  74. CCplUiElement(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon);
  75. CCplUiElement(void);
  76. virtual CCplUiElement::~CCplUiElement(void);
  77. private:
  78. LONG m_cRef;
  79. LPCWSTR m_pszName;
  80. LPCWSTR m_pszInfotip;
  81. LPCWSTR m_pszIcon;
  82. HRESULT _GetResourceString(LPCWSTR pszItem, LPWSTR *ppsz);
  83. HRESULT _GetIconResource(LPWSTR *ppsz);
  84. HRESULT _GetNameResource(LPWSTR *ppsz);
  85. HRESULT _GetInfotipResource(LPWSTR *ppsz);
  86. };
  87. CCplUiElement::CCplUiElement(
  88. LPCWSTR pszName,
  89. LPCWSTR pszInfotip, // NULL == No Info Tip
  90. LPCWSTR pszIcon
  91. ) : m_cRef(1),
  92. m_pszName(pszName),
  93. m_pszInfotip(pszInfotip),
  94. m_pszIcon(pszIcon)
  95. {
  96. ASSERT(IS_INTRESOURCE(m_pszName) || !IsBadStringPtr(m_pszName, UINT_PTR(-1)));
  97. ASSERT((NULL == pszInfotip) || IS_INTRESOURCE(m_pszInfotip) || !IsBadStringPtr(m_pszInfotip, UINT_PTR(-1)));
  98. ASSERT(IS_INTRESOURCE(m_pszIcon) || !IsBadStringPtr(m_pszIcon, UINT_PTR(-1)));
  99. }
  100. CCplUiElement::CCplUiElement(
  101. void
  102. ) : m_cRef(1),
  103. m_pszName(NULL),
  104. m_pszInfotip(NULL),
  105. m_pszIcon(NULL)
  106. {
  107. TraceMsg(TF_LIFE, "CCplUiElement::CCplUiElement, this = 0x%x", this);
  108. }
  109. CCplUiElement::~CCplUiElement(
  110. void
  111. )
  112. {
  113. TraceMsg(TF_LIFE, "CCplUiElement::~CCplUiElement, this = 0x%x", this);
  114. //
  115. // Note that the member string pointers contain either a resource ID
  116. // or a pointer to constant memory.
  117. // Therefore, we do not try to free them.
  118. //
  119. }
  120. HRESULT
  121. CCplUiElement::CreateInstance( // [static]
  122. LPCWSTR pszName,
  123. LPCWSTR pszInfotip,
  124. LPCWSTR pszIcon,
  125. REFIID riid,
  126. void **ppvOut
  127. )
  128. {
  129. ASSERT(NULL != ppvOut);
  130. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  131. *ppvOut = NULL;
  132. HRESULT hr = E_OUTOFMEMORY;
  133. CCplUiElement *pe = new CCplUiElement(pszName, pszInfotip, pszIcon);
  134. if (NULL != pe)
  135. {
  136. hr = pe->QueryInterface(riid, ppvOut);
  137. pe->Release();
  138. }
  139. return THR(hr);
  140. }
  141. STDMETHODIMP
  142. CCplUiElement::QueryInterface(
  143. REFIID riid,
  144. void **ppv
  145. )
  146. {
  147. ASSERT(NULL != ppv);
  148. ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
  149. static const QITAB qit[] = {
  150. QITABENT(CCplUiElement, IUIElement),
  151. QITABENT(CCplUiElement, ICpUiElementInfo),
  152. { 0 },
  153. };
  154. HRESULT hr = QISearch(this, qit, riid, ppv);
  155. return E_NOINTERFACE == hr ? hr : THR(hr);
  156. }
  157. STDMETHODIMP_(ULONG)
  158. CCplUiElement::AddRef(
  159. void
  160. )
  161. {
  162. return InterlockedIncrement(&m_cRef);
  163. }
  164. STDMETHODIMP_(ULONG)
  165. CCplUiElement::Release(
  166. void
  167. )
  168. {
  169. ASSERT( 0 != m_cRef );
  170. ULONG cRef = InterlockedDecrement(&m_cRef);
  171. if ( 0 == cRef )
  172. {
  173. delete this;
  174. }
  175. return cRef;
  176. }
  177. STDMETHODIMP
  178. CCplUiElement::get_Name(
  179. IShellItemArray *psiItemArray,
  180. LPWSTR *ppszName
  181. )
  182. {
  183. UNREFERENCED_PARAMETER(psiItemArray);
  184. HRESULT hr = LoadName(ppszName);
  185. return THR(hr);
  186. }
  187. STDMETHODIMP
  188. CCplUiElement::get_Icon(
  189. IShellItemArray *psiItemArray,
  190. LPWSTR *ppszIcon
  191. )
  192. {
  193. UNREFERENCED_PARAMETER(psiItemArray);
  194. HRESULT hr = _GetIconResource(ppszIcon);
  195. return THR(hr);
  196. }
  197. STDMETHODIMP
  198. CCplUiElement::get_Tooltip(
  199. IShellItemArray *psiItemArray,
  200. LPWSTR *ppszInfotip
  201. )
  202. {
  203. UNREFERENCED_PARAMETER(psiItemArray);
  204. HRESULT hr = THR(LoadTooltip(ppszInfotip));
  205. if (S_FALSE == hr)
  206. {
  207. //
  208. // Tooltips are optional but we need to return a failure
  209. // code to tell webview that we don't have one.
  210. //
  211. hr = E_FAIL;
  212. }
  213. return hr;
  214. }
  215. STDMETHODIMP
  216. CCplUiElement::LoadIcon(
  217. eCPIMGSIZE eSize,
  218. HICON *phIcon
  219. )
  220. {
  221. *phIcon = NULL;
  222. LPWSTR pszResource;
  223. HRESULT hr = _GetIconResource(&pszResource);
  224. if (SUCCEEDED(hr))
  225. {
  226. hr = CPL::LoadIconFromResource(pszResource, eSize, phIcon);
  227. CoTaskMemFree(pszResource);
  228. }
  229. return THR(hr);
  230. }
  231. STDMETHODIMP
  232. CCplUiElement::LoadName(
  233. LPWSTR *ppszName
  234. )
  235. {
  236. LPWSTR pszResource;
  237. HRESULT hr = _GetNameResource(&pszResource);
  238. if (SUCCEEDED(hr))
  239. {
  240. hr = CPL::LoadStringFromResource(pszResource, ppszName);
  241. CoTaskMemFree(pszResource);
  242. }
  243. return THR(hr);
  244. }
  245. STDMETHODIMP
  246. CCplUiElement::LoadTooltip(
  247. LPWSTR *ppszTooltip
  248. )
  249. {
  250. LPWSTR pszResource;
  251. HRESULT hr = _GetInfotipResource(&pszResource);
  252. if (S_OK == hr)
  253. {
  254. hr = CPL::LoadStringFromResource(pszResource, ppszTooltip);
  255. CoTaskMemFree(pszResource);
  256. }
  257. return THR(hr);
  258. }
  259. HRESULT
  260. CCplUiElement::_GetIconResource(
  261. LPWSTR *ppsz
  262. )
  263. {
  264. HRESULT hr = _GetResourceString(m_pszIcon, ppsz);
  265. return THR(hr);
  266. }
  267. HRESULT
  268. CCplUiElement::_GetNameResource(
  269. LPWSTR *ppsz
  270. )
  271. {
  272. HRESULT hr = _GetResourceString(m_pszName, ppsz);
  273. return THR(hr);
  274. }
  275. //
  276. // Returns S_FALSE if tooltip text is not provided.
  277. // Tooltips are optional. For example, the "learn about"
  278. // tasks in Control Panel's web view pane do not have tooltip
  279. // text.
  280. //
  281. HRESULT
  282. CCplUiElement::_GetInfotipResource(
  283. LPWSTR *ppsz
  284. )
  285. {
  286. HRESULT hr = S_FALSE;
  287. if (NULL != m_pszInfotip)
  288. {
  289. hr = _GetResourceString(m_pszInfotip, ppsz);
  290. }
  291. return THR(hr);
  292. }
  293. //
  294. // On successful return, caller must free returned string using
  295. // CoTaskMemFree.
  296. //
  297. HRESULT
  298. CCplUiElement::_GetResourceString(
  299. LPCWSTR pszItem,
  300. LPWSTR *ppsz
  301. )
  302. {
  303. ASSERT(NULL != ppsz);
  304. ASSERT(!IsBadWritePtr(ppsz, sizeof(*ppsz)));
  305. *ppsz = NULL;
  306. HRESULT hr = E_FAIL;
  307. if (IS_INTRESOURCE(pszItem))
  308. {
  309. //
  310. // pszItem is a resource identifier integer. Create a resource
  311. // ID string "<module>,<-i>" for the resource.
  312. //
  313. WCHAR szModule[MAX_PATH];
  314. if (GetModuleFileNameW(HINST_THISDLL, szModule, ARRAYSIZE(szModule)))
  315. {
  316. const size_t cchResource = lstrlenW(szModule) + 15;
  317. *ppsz = (LPWSTR)CoTaskMemAlloc(cchResource * sizeof(WCHAR));
  318. if (NULL != *ppsz)
  319. {
  320. //
  321. // Precede the resource ID with a minus sign so that it will be
  322. // treated as a resource ID and not an index.
  323. //
  324. hr = StringCchPrintfW(*ppsz, cchResource, L"%s,-%u", szModule, PtrToUint(pszItem));
  325. }
  326. else
  327. {
  328. hr = E_OUTOFMEMORY;
  329. }
  330. }
  331. else
  332. {
  333. hr = ResultFromLastError();
  334. }
  335. }
  336. else
  337. {
  338. //
  339. // pszItem is a text string. Assume it's in the form of
  340. // "<module>,<-i>". Simply duplicate it.
  341. //
  342. ASSERT(!IsBadStringPtr(pszItem, UINT_PTR(-1)));
  343. hr = SHStrDup(pszItem, ppsz);
  344. }
  345. return THR(hr);
  346. }
  347. //-----------------------------------------------------------------------------
  348. // CCplUiCommand
  349. //-----------------------------------------------------------------------------
  350. class CCplUiCommand : public CObjectWithSite,
  351. public CCplUiElement,
  352. public IUICommand,
  353. public ICpUiCommand
  354. {
  355. public:
  356. //
  357. // IUnknown
  358. //
  359. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  360. STDMETHOD_(ULONG, AddRef)(void)
  361. { return CCplUiElement::AddRef(); }
  362. STDMETHOD_(ULONG, Release)(void)
  363. { return CCplUiElement::Release(); }
  364. //
  365. // IUICommand
  366. //
  367. STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName)
  368. { return CCplUiElement::get_Name(psiItemArray, ppszName); }
  369. STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon)
  370. { return CCplUiElement::get_Icon(psiItemArray, ppszIcon); }
  371. STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip)
  372. { return CCplUiElement::get_Tooltip(psiItemArray, ppszInfotip); }
  373. STDMETHOD(get_CanonicalName)(GUID *pguidCommandName);
  374. STDMETHOD(get_State)(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState);
  375. STDMETHOD(Invoke)(IShellItemArray *psiItemArray, IBindCtx *pbc);
  376. //
  377. // ICpUiCommand
  378. //
  379. STDMETHOD(InvokeContextMenu)(HWND hwndParent, const POINT *ppt);
  380. STDMETHOD(Invoke)(HWND hwndParent, IUnknown *punkSite);
  381. STDMETHOD(GetDataObject)(IDataObject **ppdtobj);
  382. //
  383. // ICpUiElementInfo
  384. //
  385. STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon)
  386. { return CCplUiElement::LoadIcon(eSize, phIcon); }
  387. STDMETHOD(LoadName)(LPWSTR *ppszName)
  388. { return CCplUiElement::LoadName(ppszName); }
  389. STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip)
  390. { return CCplUiElement::LoadTooltip(ppszTooltip); }
  391. static HRESULT CreateInstance(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction, REFIID riid, void **ppvOut);
  392. protected:
  393. CCplUiCommand(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction);
  394. CCplUiCommand(void);
  395. ~CCplUiCommand(void);
  396. private:
  397. const IAction *m_pAction;
  398. HRESULT _IsCommandRestricted(void);
  399. };
  400. CCplUiCommand::CCplUiCommand(
  401. void
  402. ) : m_pAction(NULL)
  403. {
  404. TraceMsg(TF_LIFE, "CCplUiCommand::CCplUiCommand, this = 0x%x", this);
  405. }
  406. CCplUiCommand::CCplUiCommand(
  407. LPCWSTR pszName,
  408. LPCWSTR pszInfotip,
  409. LPCWSTR pszIcon,
  410. const IAction *pAction
  411. ) : CCplUiElement(pszName, pszInfotip, pszIcon),
  412. m_pAction(pAction)
  413. {
  414. TraceMsg(TF_LIFE, "CCplUiCommand::CCplUiCommand, this = 0x%x", this);
  415. }
  416. CCplUiCommand::~CCplUiCommand(
  417. void
  418. )
  419. {
  420. TraceMsg(TF_LIFE, "CCplUiCommand::~CCplUiCommand, this = 0x%x", this);
  421. //
  422. // Note that m_pAction is a pointer to a const object.
  423. // Therefore, we don't try to free it.
  424. //
  425. }
  426. HRESULT
  427. CCplUiCommand::CreateInstance( // [static]
  428. LPCWSTR pszName,
  429. LPCWSTR pszInfotip,
  430. LPCWSTR pszIcon,
  431. const IAction *pAction,
  432. REFIID riid,
  433. void **ppvOut
  434. )
  435. {
  436. ASSERT(NULL != ppvOut);
  437. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  438. *ppvOut = NULL;
  439. HRESULT hr = E_OUTOFMEMORY;
  440. CCplUiCommand *pc = new CCplUiCommand(pszName, pszInfotip, pszIcon, pAction);
  441. if (NULL != pc)
  442. {
  443. hr = pc->QueryInterface(riid, ppvOut);
  444. pc->Release();
  445. }
  446. return THR(hr);
  447. }
  448. STDMETHODIMP
  449. CCplUiCommand::QueryInterface(
  450. REFIID riid,
  451. void **ppv
  452. )
  453. {
  454. ASSERT(NULL != ppv);
  455. ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
  456. static const QITAB qit[] = {
  457. QITABENT(CCplUiCommand, IUICommand),
  458. QITABENT(CCplUiCommand, ICpUiElementInfo),
  459. QITABENT(CCplUiCommand, ICpUiCommand),
  460. QITABENT(CCplUiCommand, IObjectWithSite),
  461. QITABENTMULTI(CCplUiCommand, IUIElement, IUICommand),
  462. { 0 },
  463. };
  464. HRESULT hr = QISearch(this, qit, riid, ppv);
  465. return E_NOINTERFACE == hr ? hr : THR(hr);
  466. }
  467. STDMETHODIMP
  468. CCplUiCommand::get_CanonicalName(
  469. GUID *pguidCommandName
  470. )
  471. {
  472. UNREFERENCED_PARAMETER(pguidCommandName);
  473. //
  474. // This function is unimplemented. It is in IUICommand to
  475. // support generic functionality in the shell. This functionality
  476. // is not applicable to the use of IUICommand in the Control
  477. // Panel.
  478. //
  479. return E_NOTIMPL;
  480. }
  481. STDMETHODIMP
  482. CCplUiCommand::get_State(
  483. IShellItemArray *psiItemArray,
  484. BOOL fOkToBeSlow,
  485. UISTATE *puisState
  486. )
  487. {
  488. ASSERT(NULL != m_pAction);
  489. ASSERT(NULL != puisState);
  490. ASSERT(!IsBadWritePtr(puisState, sizeof(*puisState)));
  491. UNREFERENCED_PARAMETER(psiItemArray);
  492. *puisState = UIS_DISABLED; // default;
  493. //
  494. // If an action is restricted, we hide it's corresponding
  495. // UI element in the user interface.
  496. //
  497. HRESULT hr = _IsCommandRestricted();
  498. if (SUCCEEDED(hr))
  499. {
  500. switch(hr)
  501. {
  502. case S_OK:
  503. *puisState = UIS_HIDDEN;
  504. break;
  505. case S_FALSE:
  506. *puisState = UIS_ENABLED;
  507. default:
  508. break;
  509. }
  510. //
  511. // Don't propagate S_FALSE to caller.
  512. //
  513. hr = S_OK;
  514. }
  515. return THR(hr);
  516. }
  517. //
  518. // IUICommand::Invoke
  519. // This version is called by webview when the user selects an
  520. // item from a webview menu.
  521. //
  522. STDMETHODIMP
  523. CCplUiCommand::Invoke(
  524. IShellItemArray *psiItemArray,
  525. IBindCtx *pbc
  526. )
  527. {
  528. DBG_ENTER(FTF_CPANEL, "CCplUiCommand::Invoke");
  529. ASSERT(NULL != m_pAction);
  530. UNREFERENCED_PARAMETER(psiItemArray);
  531. UNREFERENCED_PARAMETER(pbc);
  532. HRESULT hr = m_pAction->Execute(NULL, _punkSite);
  533. DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommand::Invoke", hr);
  534. return THR(hr);
  535. }
  536. //
  537. // ICpUiCommand::Invoke
  538. // This version is called by CLinkElement::_OnSelected when
  539. // the user selects either a category task or a category item
  540. // in the category choice view.
  541. //
  542. STDMETHODIMP
  543. CCplUiCommand::Invoke(
  544. HWND hwndParent,
  545. IUnknown *punkSite
  546. )
  547. {
  548. ASSERT(NULL != m_pAction);
  549. HRESULT hr = m_pAction->Execute(hwndParent, punkSite);
  550. return THR(hr);
  551. }
  552. STDMETHODIMP
  553. CCplUiCommand::InvokeContextMenu(
  554. HWND hwndParent,
  555. const POINT *ppt
  556. )
  557. {
  558. //
  559. // Only commands on pidls provide a context menu.
  560. //
  561. UNREFERENCED_PARAMETER(hwndParent);
  562. UNREFERENCED_PARAMETER(ppt);
  563. return E_NOTIMPL;
  564. }
  565. STDMETHODIMP
  566. CCplUiCommand::GetDataObject(
  567. IDataObject **ppdtobj
  568. )
  569. {
  570. //
  571. // Simple UI commands don't provide a data object.
  572. //
  573. return E_NOTIMPL;
  574. }
  575. //
  576. // Returns:
  577. // S_OK = Command is restricted.
  578. // S_FALSE = Command is not restricted.
  579. //
  580. HRESULT
  581. CCplUiCommand::_IsCommandRestricted(
  582. void
  583. )
  584. {
  585. //
  586. // The ICplNamespace ptr is passed to IsRestricted in case the restriction
  587. // code needs to inspect contents of the namespace. The "Other Cpl Options"
  588. // link command uses this to determine if the "OTHER" category contains any
  589. // CPL applets or not. If it contains no applets, the link is hidden (restricted).
  590. //
  591. ICplNamespace *pns;
  592. HRESULT hr = IUnknown_QueryService(_punkSite, SID_SControlPanelView, IID_ICplNamespace, (void **)&pns);
  593. if (SUCCEEDED(hr))
  594. {
  595. hr = m_pAction->IsRestricted(pns);
  596. pns->Release();
  597. }
  598. return THR(hr);
  599. }
  600. //-----------------------------------------------------------------------------
  601. // CCplUiCommandOnPidl
  602. //-----------------------------------------------------------------------------
  603. class CCplUiCommandOnPidl : public CObjectWithSite,
  604. public IUICommand,
  605. public ICpUiCommand,
  606. public ICpUiElementInfo,
  607. public IDataObject
  608. {
  609. public:
  610. ~CCplUiCommandOnPidl(void);
  611. //
  612. // IUnknown
  613. //
  614. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  615. STDMETHOD_(ULONG, AddRef)(void);
  616. STDMETHOD_(ULONG, Release)(void);
  617. //
  618. // IUICommand
  619. //
  620. STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName);
  621. STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon);
  622. STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip);
  623. STDMETHOD(get_CanonicalName)(GUID *pguidCommandName);
  624. STDMETHOD(get_State)(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState);
  625. STDMETHOD(Invoke)(IShellItemArray *psiItemArray, IBindCtx *pbc);
  626. //
  627. // ICpUiCommand
  628. //
  629. STDMETHOD(InvokeContextMenu)(HWND hwndParent, const POINT *ppt);
  630. STDMETHOD(Invoke)(HWND hwndParent, IUnknown *punkSite);
  631. STDMETHOD(GetDataObject)(IDataObject **ppdtobj);
  632. //
  633. // ICpUiElementInfo
  634. //
  635. STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon);
  636. STDMETHOD(LoadName)(LPWSTR *ppszName);
  637. STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip);
  638. //
  639. // IDataObject
  640. //
  641. STDMETHOD(GetData)(FORMATETC *pFmtEtc, STGMEDIUM *pstm);
  642. STDMETHOD(GetDataHere)(FORMATETC *pFmtEtc, STGMEDIUM *pstm);
  643. STDMETHOD(QueryGetData)(FORMATETC *pFmtEtc);
  644. STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *pFmtEtcIn, FORMATETC *pFmtEtcOut);
  645. STDMETHOD(SetData)(FORMATETC *pFmtEtc, STGMEDIUM *pstm, BOOL fRelease);
  646. STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC *ppEnum);
  647. STDMETHOD(DAdvise)(FORMATETC *pFmtEtc, DWORD grfAdv, LPADVISESINK pAdvSink, DWORD *pdwConnection);
  648. STDMETHOD(DUnadvise)(DWORD dwConnection);
  649. STDMETHOD(EnumDAdvise)(LPENUMSTATDATA *ppEnum);
  650. static HRESULT CreateInstance(LPCITEMIDLIST pidl, REFIID riid, void **ppvOut);
  651. private:
  652. LONG m_cRef;
  653. IShellFolder *m_psf; // Cached Control Panel IShellFolder ptr.
  654. LPITEMIDLIST m_pidl; // Assumed to be relative to Control Panel.
  655. IDataObject *m_pdtobj;
  656. CCplUiCommandOnPidl(void);
  657. HRESULT _GetControlPanelFolder(IShellFolder **ppsf);
  658. HRESULT _Initialize(LPCITEMIDLIST pidl);
  659. HRESULT _GetName(LPWSTR *ppszName);
  660. HRESULT _GetInfotip(LPWSTR *ppszInfotip);
  661. HRESULT _GetIconResource(LPWSTR *ppszIcon);
  662. HRESULT _Invoke(HWND hwndParent, IUnknown *punkSite);
  663. HRESULT _GetDataObject(IDataObject **ppdtobj);
  664. };
  665. CCplUiCommandOnPidl::CCplUiCommandOnPidl(
  666. void
  667. ) : m_cRef(1),
  668. m_psf(NULL),
  669. m_pidl(NULL),
  670. m_pdtobj(NULL)
  671. {
  672. TraceMsg(TF_LIFE, "CCplUiCommandOnPidl::CCplUiCommandOnPidl, this = 0x%x", this);
  673. }
  674. CCplUiCommandOnPidl::~CCplUiCommandOnPidl(
  675. void
  676. )
  677. {
  678. TraceMsg(TF_LIFE, "CCplUiCommandOnPidl::~CCplUiCommandOnPidl, this = 0x%x", this);
  679. ATOMICRELEASE(m_psf);
  680. ATOMICRELEASE(m_pdtobj);
  681. if (NULL != m_pidl)
  682. {
  683. ILFree(m_pidl);
  684. }
  685. }
  686. HRESULT
  687. CCplUiCommandOnPidl::CreateInstance( // [static]
  688. LPCITEMIDLIST pidl,
  689. REFIID riid,
  690. void **ppvOut
  691. )
  692. {
  693. ASSERT(NULL != ppvOut);
  694. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  695. ASSERT(NULL != pidl);
  696. *ppvOut = NULL;
  697. HRESULT hr = E_OUTOFMEMORY;
  698. CCplUiCommandOnPidl *pc = new CCplUiCommandOnPidl();
  699. if (NULL != pc)
  700. {
  701. hr = pc->_Initialize(pidl);
  702. if (SUCCEEDED(hr))
  703. {
  704. hr = pc->QueryInterface(riid, ppvOut);
  705. }
  706. pc->Release();
  707. }
  708. return THR(hr);
  709. }
  710. STDMETHODIMP
  711. CCplUiCommandOnPidl::QueryInterface(
  712. REFIID riid,
  713. void **ppv
  714. )
  715. {
  716. ASSERT(NULL != ppv);
  717. ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
  718. static const QITAB qit[] = {
  719. QITABENT(CCplUiCommandOnPidl, IUICommand),
  720. QITABENT(CCplUiCommandOnPidl, ICpUiCommand),
  721. QITABENT(CCplUiCommandOnPidl, ICpUiElementInfo),
  722. QITABENT(CCplUiCommandOnPidl, IObjectWithSite),
  723. QITABENT(CCplUiCommandOnPidl, IDataObject),
  724. QITABENTMULTI(CCplUiCommandOnPidl, IUIElement, IUICommand),
  725. { 0 },
  726. };
  727. HRESULT hr = QISearch(this, qit, riid, ppv);
  728. return E_NOINTERFACE == hr ? hr : THR(hr);
  729. }
  730. STDMETHODIMP_(ULONG)
  731. CCplUiCommandOnPidl::AddRef(
  732. void
  733. )
  734. {
  735. return InterlockedIncrement(&m_cRef);
  736. }
  737. STDMETHODIMP_(ULONG)
  738. CCplUiCommandOnPidl::Release(
  739. void
  740. )
  741. {
  742. ASSERT( 0 != m_cRef );
  743. ULONG cRef = InterlockedDecrement(&m_cRef);
  744. if ( 0 == cRef )
  745. {
  746. delete this;
  747. }
  748. return cRef;
  749. }
  750. STDMETHODIMP
  751. CCplUiCommandOnPidl::get_Name(
  752. IShellItemArray *psiItemArray,
  753. LPWSTR *ppszName
  754. )
  755. {
  756. UNREFERENCED_PARAMETER(psiItemArray);
  757. HRESULT hr = _GetName(ppszName);
  758. return THR(hr);
  759. }
  760. STDMETHODIMP
  761. CCplUiCommandOnPidl::get_Icon(
  762. IShellItemArray *psiItemArray,
  763. LPWSTR *ppszIcon
  764. )
  765. {
  766. UNREFERENCED_PARAMETER(psiItemArray);
  767. HRESULT hr = _GetIconResource(ppszIcon);
  768. return THR(hr);
  769. }
  770. STDMETHODIMP
  771. CCplUiCommandOnPidl::get_Tooltip(
  772. IShellItemArray *psiItemArray,
  773. LPWSTR *ppszInfotip
  774. )
  775. {
  776. UNREFERENCED_PARAMETER(psiItemArray);
  777. HRESULT hr = _GetInfotip(ppszInfotip);
  778. return THR(hr);
  779. }
  780. STDMETHODIMP
  781. CCplUiCommandOnPidl::get_CanonicalName(
  782. GUID *pguidCommandName
  783. )
  784. {
  785. UNREFERENCED_PARAMETER(pguidCommandName);
  786. return E_NOTIMPL;
  787. }
  788. STDMETHODIMP
  789. CCplUiCommandOnPidl::get_State(
  790. IShellItemArray *psiItemArray,
  791. BOOL fOkToBeSlow,
  792. UISTATE *puisState
  793. )
  794. {
  795. ASSERT(NULL != puisState);
  796. ASSERT(!IsBadWritePtr(puisState, sizeof(*puisState)));
  797. UNREFERENCED_PARAMETER(psiItemArray);
  798. UNREFERENCED_PARAMETER(fOkToBeSlow);
  799. HRESULT hr = S_OK;
  800. *puisState = UIS_ENABLED; // default;
  801. //
  802. // We do not handle restrictions on CPL applets in the same
  803. // sense as other 'tasks' in this architecture.
  804. // CPL applets are restricted by the Control Panel folder's
  805. // item enumerator. If the folder enumerates a CPL applet
  806. // then we assume it's valid to present that applet in the
  807. // UI.
  808. //
  809. return THR(hr);
  810. }
  811. STDMETHODIMP
  812. CCplUiCommandOnPidl::Invoke(
  813. IShellItemArray *psiItemArray,
  814. IBindCtx *pbc
  815. )
  816. {
  817. DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke");
  818. UNREFERENCED_PARAMETER(psiItemArray);
  819. UNREFERENCED_PARAMETER(pbc);
  820. HRESULT hr = _Invoke(NULL, NULL);
  821. DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke", hr);
  822. return THR(hr);
  823. }
  824. //
  825. // ICpUiCommand::Invoke
  826. //
  827. STDMETHODIMP
  828. CCplUiCommandOnPidl::Invoke(
  829. HWND hwndParent,
  830. IUnknown *punkSite
  831. )
  832. {
  833. DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke");
  834. UNREFERENCED_PARAMETER(punkSite);
  835. HRESULT hr = _Invoke(hwndParent, punkSite);
  836. DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke", hr);
  837. return THR(hr);
  838. }
  839. HRESULT
  840. CCplUiCommandOnPidl::_Invoke(
  841. HWND hwndParent,
  842. IUnknown *punkSite
  843. )
  844. {
  845. DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::_Invoke");
  846. UNREFERENCED_PARAMETER(hwndParent);
  847. LPITEMIDLIST pidlCpanel;
  848. HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlCpanel);
  849. if (SUCCEEDED(hr))
  850. {
  851. LPITEMIDLIST pidl = ILCombine(pidlCpanel, m_pidl);
  852. if (FAILED(hr))
  853. {
  854. hr = E_OUTOFMEMORY;
  855. }
  856. else
  857. {
  858. bool bItemIsBrowsable = false;
  859. IUnknown *punkSiteToRelease = NULL;
  860. if (NULL == punkSite)
  861. {
  862. //
  863. // No site provided. Let's use our site.
  864. //
  865. ASSERT(NULL != _punkSite);
  866. (punkSite = punkSiteToRelease = _punkSite)->AddRef();
  867. }
  868. if (NULL != punkSite)
  869. {
  870. //
  871. // If we have a site pointer, try to browse the object in-place
  872. // if it is indeed browsable.
  873. //
  874. WCHAR szName[MAX_PATH];
  875. ULONG rgfAttrs = SFGAO_BROWSABLE | SFGAO_FOLDER;
  876. hr = SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szName, ARRAYSIZE(szName), &rgfAttrs);
  877. if (SUCCEEDED(hr))
  878. {
  879. if ((SFGAO_BROWSABLE | SFGAO_FOLDER) & rgfAttrs)
  880. {
  881. //
  882. // Browse the object in-place. This is the path taken
  883. // by things like the "Printers" folder, "Scheduled Tasks" etc.
  884. //
  885. bItemIsBrowsable = true;
  886. IShellBrowser *psb;
  887. hr = CPL::ShellBrowserFromSite(punkSite, &psb);
  888. if (SUCCEEDED(hr))
  889. {
  890. hr = CPL::BrowseIDListInPlace(pidl, psb);
  891. psb->Release();
  892. }
  893. }
  894. }
  895. }
  896. if (NULL == punkSite || !bItemIsBrowsable)
  897. {
  898. //
  899. // Either we don't have a site ptr (can't get to the browser)
  900. // or the item is not browsable. Simply execute it.
  901. // This is the path taken by conventional CPL applets like
  902. // Mouse, Power Options, Display etc.
  903. //
  904. SHELLEXECUTEINFOW sei = {
  905. sizeof(sei), // cbSize;
  906. SEE_MASK_INVOKEIDLIST, // fMask
  907. NULL, // hwnd
  908. NULL, // lpVerb
  909. NULL, // lpFile
  910. NULL, // lpParameters
  911. NULL, // lpDirectory
  912. SW_SHOWNORMAL, // nShow
  913. 0, // hInstApp
  914. pidl, // lpIDList
  915. NULL, // lpClass
  916. NULL, // hkeyClass
  917. 0, // dwHotKey
  918. NULL, // hIcon
  919. NULL // hProcess
  920. };
  921. if (!ShellExecuteExW(&sei))
  922. {
  923. hr = ResultFromLastError();
  924. }
  925. }
  926. ATOMICRELEASE(punkSiteToRelease);
  927. ILFree(pidl);
  928. }
  929. ILFree(pidlCpanel);
  930. }
  931. DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::_Invoke", hr);
  932. return THR(hr);
  933. }
  934. HRESULT
  935. CCplUiCommandOnPidl::InvokeContextMenu(
  936. HWND hwndParent,
  937. const POINT *ppt
  938. )
  939. {
  940. DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::InvokeContextMenu");
  941. ASSERT(NULL != ppt);
  942. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  943. //
  944. // First build a full pidl to the item.
  945. //
  946. LPITEMIDLIST pidlCpanel;
  947. HRESULT hr = SHGetSpecialFolderLocation(hwndParent, CSIDL_CONTROLS, &pidlCpanel);
  948. if (SUCCEEDED(hr))
  949. {
  950. LPITEMIDLIST pidlFull = ILCombine(pidlCpanel, m_pidl);
  951. if (NULL == pidlFull)
  952. {
  953. hr = E_OUTOFMEMORY;
  954. }
  955. else
  956. {
  957. //
  958. // Get the item's context menu interface from the shell.
  959. //
  960. IContextMenu *pcm;
  961. hr = SHGetUIObjectFromFullPIDL(pidlFull, hwndParent, IID_PPV_ARG(IContextMenu, &pcm));
  962. if (SUCCEEDED(hr))
  963. {
  964. ASSERT(NULL != _punkSite);
  965. IContextMenu *pcmNoDelete;
  966. hr = Create_ContextMenuWithoutVerbs(pcm, L"cut;delete", IID_PPV_ARG(IContextMenu, &pcmNoDelete));
  967. if (SUCCEEDED(hr))
  968. {
  969. hr = IUnknown_DoContextMenuPopup(_punkSite, pcmNoDelete, CMF_NORMAL, *ppt);
  970. pcmNoDelete->Release();
  971. }
  972. pcm->Release();
  973. }
  974. else
  975. {
  976. TraceMsg(TF_ERROR, "Shell item does not provide a context menu");
  977. }
  978. ILFree(pidlFull);
  979. }
  980. ILFree(pidlCpanel);
  981. }
  982. DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::InvokeContextMenu", hr);
  983. return THR(hr);
  984. }
  985. STDMETHODIMP
  986. CCplUiCommandOnPidl::GetDataObject(
  987. IDataObject **ppdtobj
  988. )
  989. {
  990. return _GetDataObject(ppdtobj);
  991. }
  992. STDMETHODIMP
  993. CCplUiCommandOnPidl::LoadIcon(
  994. eCPIMGSIZE eSize,
  995. HICON *phIcon
  996. )
  997. {
  998. IShellFolder *psf;
  999. HRESULT hr = CPL::GetControlPanelFolder(&psf);
  1000. if (SUCCEEDED(hr))
  1001. {
  1002. hr = CPL::ExtractIconFromPidl(psf, m_pidl, eSize, phIcon);
  1003. psf->Release();
  1004. }
  1005. return THR(hr);
  1006. }
  1007. STDMETHODIMP
  1008. CCplUiCommandOnPidl::LoadName(
  1009. LPWSTR *ppszName
  1010. )
  1011. {
  1012. HRESULT hr = _GetName(ppszName);
  1013. return THR(hr);
  1014. }
  1015. STDMETHODIMP
  1016. CCplUiCommandOnPidl::LoadTooltip(
  1017. LPWSTR *ppszTooltip
  1018. )
  1019. {
  1020. HRESULT hr = _GetInfotip(ppszTooltip);
  1021. return THR(hr);
  1022. }
  1023. HRESULT
  1024. CCplUiCommandOnPidl::_Initialize(
  1025. LPCITEMIDLIST pidl
  1026. )
  1027. {
  1028. ASSERT(NULL == m_pidl);
  1029. ASSERT(NULL != pidl);
  1030. HRESULT hr = E_OUTOFMEMORY;
  1031. m_pidl = ILClone(pidl);
  1032. if (NULL != m_pidl)
  1033. {
  1034. hr = S_OK;
  1035. }
  1036. return THR(hr);
  1037. }
  1038. HRESULT
  1039. CCplUiCommandOnPidl::_GetControlPanelFolder(
  1040. IShellFolder **ppsf
  1041. )
  1042. {
  1043. ASSERT(NULL != ppsf);
  1044. ASSERT(!IsBadWritePtr(ppsf, sizeof(*ppsf)));
  1045. HRESULT hr = S_OK;
  1046. if (NULL == m_psf)
  1047. {
  1048. hr = CPL::GetControlPanelFolder(&m_psf);
  1049. }
  1050. *ppsf = m_psf;
  1051. if (NULL != *ppsf)
  1052. {
  1053. (*ppsf)->AddRef();
  1054. }
  1055. return THR(hr);
  1056. }
  1057. HRESULT
  1058. CCplUiCommandOnPidl::_GetName(
  1059. LPWSTR *ppszName
  1060. )
  1061. {
  1062. ASSERT(NULL != m_pidl);
  1063. ASSERT(NULL != ppszName);
  1064. ASSERT(!IsBadWritePtr(ppszName, sizeof(*ppszName)));
  1065. *ppszName = NULL;
  1066. IShellFolder *psf;
  1067. HRESULT hr = _GetControlPanelFolder(&psf);
  1068. if (SUCCEEDED(hr))
  1069. {
  1070. STRRET strret;
  1071. hr = psf->GetDisplayNameOf(m_pidl, SHGDN_INFOLDER, &strret);
  1072. if (SUCCEEDED(hr))
  1073. {
  1074. hr = StrRetToStrW(&strret, m_pidl, ppszName);
  1075. }
  1076. psf->Release();
  1077. }
  1078. return THR(hr);
  1079. }
  1080. HRESULT
  1081. CCplUiCommandOnPidl::_GetInfotip(
  1082. LPWSTR *ppszInfotip
  1083. )
  1084. {
  1085. ASSERT(NULL != ppszInfotip);
  1086. ASSERT(!IsBadWritePtr(ppszInfotip, sizeof(*ppszInfotip)));
  1087. ASSERT(NULL != m_pidl);
  1088. *ppszInfotip = NULL;
  1089. IShellFolder *psf;
  1090. HRESULT hr = _GetControlPanelFolder(&psf);
  1091. if (SUCCEEDED(hr))
  1092. {
  1093. IShellFolder2 *psf2;
  1094. psf->QueryInterface(IID_PPV_ARG(IShellFolder2, &psf2));
  1095. if (SUCCEEDED(hr))
  1096. {
  1097. TCHAR szBuf[256];
  1098. hr = GetStringProperty(psf2, m_pidl, &SCID_Comment, szBuf, ARRAYSIZE(szBuf));
  1099. if (SUCCEEDED(hr))
  1100. {
  1101. hr = SHStrDup(szBuf, ppszInfotip);
  1102. }
  1103. psf2->Release();
  1104. }
  1105. psf->Release();
  1106. }
  1107. return THR(hr);
  1108. }
  1109. HRESULT
  1110. CCplUiCommandOnPidl::_GetIconResource(
  1111. LPWSTR *ppszIcon
  1112. )
  1113. {
  1114. ASSERT(NULL != ppszIcon);
  1115. ASSERT(!IsBadWritePtr(ppszIcon, sizeof(*ppszIcon)));
  1116. ASSERT(NULL != m_pidl);
  1117. LPWSTR pszIconPath = NULL;
  1118. IShellFolder *psf;
  1119. HRESULT hr = _GetControlPanelFolder(&psf);
  1120. if (SUCCEEDED(hr))
  1121. {
  1122. IExtractIconW* pxi;
  1123. hr = psf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&m_pidl, IID_PPV_ARG_NULL(IExtractIconW, &pxi));
  1124. if (SUCCEEDED(hr))
  1125. {
  1126. WCHAR szPath[MAX_PATH];
  1127. int iIndex;
  1128. UINT wFlags = 0;
  1129. hr = pxi->GetIconLocation(GIL_FORSHELL, szPath, ARRAYSIZE(szPath), &iIndex, &wFlags);
  1130. if (SUCCEEDED(hr))
  1131. {
  1132. const size_t cchIconPath = lstrlenW(szPath) + 15;
  1133. pszIconPath = (LPWSTR)SHAlloc(cchIconPath * sizeof(WCHAR));
  1134. if (pszIconPath)
  1135. {
  1136. hr = StringCchPrintfW(pszIconPath, cchIconPath, L"%s,%d", szPath, iIndex);
  1137. }
  1138. else
  1139. {
  1140. hr = E_OUTOFMEMORY;
  1141. }
  1142. }
  1143. pxi->Release();
  1144. }
  1145. psf->Release();
  1146. }
  1147. *ppszIcon = pszIconPath;
  1148. return THR(hr);
  1149. }
  1150. HRESULT
  1151. CCplUiCommandOnPidl::_GetDataObject(
  1152. IDataObject **ppdtobj
  1153. )
  1154. {
  1155. ASSERT(NULL != ppdtobj);
  1156. ASSERT(!IsBadWritePtr(ppdtobj, sizeof(*ppdtobj)));
  1157. HRESULT hr = S_OK;
  1158. if (NULL == m_pdtobj)
  1159. {
  1160. IShellFolder *psf;
  1161. hr = _GetControlPanelFolder(&psf);
  1162. if (SUCCEEDED(hr))
  1163. {
  1164. hr = THR(psf->GetUIObjectOf(NULL,
  1165. 1,
  1166. (LPCITEMIDLIST *)&m_pidl,
  1167. IID_PPV_ARG_NULL(IDataObject, &m_pdtobj)));
  1168. psf->Release();
  1169. }
  1170. }
  1171. if (SUCCEEDED(hr))
  1172. {
  1173. ASSERT(NULL != m_pdtobj);
  1174. (*ppdtobj = m_pdtobj)->AddRef();
  1175. }
  1176. return THR(hr);
  1177. }
  1178. STDMETHODIMP
  1179. CCplUiCommandOnPidl::GetData(
  1180. FORMATETC *pFmtEtc,
  1181. STGMEDIUM *pstm
  1182. )
  1183. {
  1184. IDataObject *pdtobj;
  1185. HRESULT hr = _GetDataObject(&pdtobj);
  1186. if (SUCCEEDED(hr))
  1187. {
  1188. hr = pdtobj->GetData(pFmtEtc, pstm);
  1189. pdtobj->Release();
  1190. }
  1191. return THR(hr);
  1192. }
  1193. STDMETHODIMP
  1194. CCplUiCommandOnPidl::GetDataHere(
  1195. FORMATETC *pFmtEtc,
  1196. STGMEDIUM *pstm
  1197. )
  1198. {
  1199. IDataObject *pdtobj;
  1200. HRESULT hr = _GetDataObject(&pdtobj);
  1201. if (SUCCEEDED(hr))
  1202. {
  1203. hr = pdtobj->GetDataHere(pFmtEtc, pstm);
  1204. pdtobj->Release();
  1205. }
  1206. return THR(hr);
  1207. }
  1208. STDMETHODIMP
  1209. CCplUiCommandOnPidl::QueryGetData(
  1210. FORMATETC *pFmtEtc
  1211. )
  1212. {
  1213. IDataObject *pdtobj;
  1214. HRESULT hr = _GetDataObject(&pdtobj);
  1215. if (SUCCEEDED(hr))
  1216. {
  1217. hr = pdtobj->QueryGetData(pFmtEtc);
  1218. pdtobj->Release();
  1219. }
  1220. return THR(hr);
  1221. }
  1222. STDMETHODIMP
  1223. CCplUiCommandOnPidl::GetCanonicalFormatEtc(
  1224. FORMATETC *pFmtEtcIn,
  1225. FORMATETC *pFmtEtcOut
  1226. )
  1227. {
  1228. IDataObject *pdtobj;
  1229. HRESULT hr = _GetDataObject(&pdtobj);
  1230. if (SUCCEEDED(hr))
  1231. {
  1232. hr = pdtobj->GetCanonicalFormatEtc(pFmtEtcIn, pFmtEtcOut);
  1233. pdtobj->Release();
  1234. }
  1235. return THR(hr);
  1236. }
  1237. STDMETHODIMP
  1238. CCplUiCommandOnPidl::SetData(
  1239. FORMATETC *pFmtEtc,
  1240. STGMEDIUM *pstm,
  1241. BOOL fRelease
  1242. )
  1243. {
  1244. IDataObject *pdtobj;
  1245. HRESULT hr = _GetDataObject(&pdtobj);
  1246. if (SUCCEEDED(hr))
  1247. {
  1248. hr = pdtobj->SetData(pFmtEtc, pstm, fRelease);
  1249. pdtobj->Release();
  1250. }
  1251. return THR(hr);
  1252. }
  1253. STDMETHODIMP
  1254. CCplUiCommandOnPidl::EnumFormatEtc(
  1255. DWORD dwDirection,
  1256. LPENUMFORMATETC *ppEnum
  1257. )
  1258. {
  1259. IDataObject *pdtobj;
  1260. HRESULT hr = _GetDataObject(&pdtobj);
  1261. if (SUCCEEDED(hr))
  1262. {
  1263. hr = pdtobj->EnumFormatEtc(dwDirection, ppEnum);
  1264. pdtobj->Release();
  1265. }
  1266. return THR(hr);
  1267. }
  1268. STDMETHODIMP
  1269. CCplUiCommandOnPidl::DAdvise(
  1270. FORMATETC *pFmtEtc,
  1271. DWORD grfAdv,
  1272. LPADVISESINK pAdvSink,
  1273. DWORD *pdwConnection
  1274. )
  1275. {
  1276. IDataObject *pdtobj;
  1277. HRESULT hr = _GetDataObject(&pdtobj);
  1278. if (SUCCEEDED(hr))
  1279. {
  1280. hr = pdtobj->DAdvise(pFmtEtc, grfAdv, pAdvSink, pdwConnection);
  1281. pdtobj->Release();
  1282. }
  1283. return THR(hr);
  1284. }
  1285. STDMETHODIMP
  1286. CCplUiCommandOnPidl::DUnadvise(
  1287. DWORD dwConnection
  1288. )
  1289. {
  1290. IDataObject *pdtobj;
  1291. HRESULT hr = _GetDataObject(&pdtobj);
  1292. if (SUCCEEDED(hr))
  1293. {
  1294. hr = pdtobj->DUnadvise(dwConnection);
  1295. pdtobj->Release();
  1296. }
  1297. return THR(hr);
  1298. }
  1299. STDMETHODIMP
  1300. CCplUiCommandOnPidl::EnumDAdvise(
  1301. LPENUMSTATDATA *ppEnum
  1302. )
  1303. {
  1304. IDataObject *pdtobj;
  1305. HRESULT hr = _GetDataObject(&pdtobj);
  1306. if (SUCCEEDED(hr))
  1307. {
  1308. hr = pdtobj->EnumDAdvise(ppEnum);
  1309. pdtobj->Release();
  1310. }
  1311. return THR(hr);
  1312. }
  1313. //-----------------------------------------------------------------------------
  1314. // Public instance generators.
  1315. //-----------------------------------------------------------------------------
  1316. HRESULT
  1317. Create_CplUiElement(
  1318. LPCWSTR pszName,
  1319. LPCWSTR pszInfotip,
  1320. LPCWSTR pszIcon,
  1321. REFIID riid,
  1322. void **ppvOut
  1323. )
  1324. {
  1325. ASSERT(NULL != ppvOut);
  1326. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  1327. return CCplUiElement::CreateInstance(pszName, pszInfotip, pszIcon, riid, ppvOut);
  1328. }
  1329. HRESULT
  1330. Create_CplUiCommand(
  1331. LPCWSTR pszName,
  1332. LPCWSTR pszInfotip,
  1333. LPCWSTR pszIcon,
  1334. const IAction *pAction,
  1335. REFIID riid,
  1336. void **ppvOut
  1337. )
  1338. {
  1339. ASSERT(NULL != ppvOut);
  1340. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  1341. return CCplUiCommand::CreateInstance(pszName, pszInfotip, pszIcon, pAction, riid, ppvOut);
  1342. }
  1343. HRESULT
  1344. Create_CplUiCommandOnPidl(
  1345. LPCITEMIDLIST pidl,
  1346. REFIID riid,
  1347. void **ppvOut
  1348. )
  1349. {
  1350. ASSERT(NULL != ppvOut);
  1351. ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
  1352. ASSERT(NULL != pidl);
  1353. HRESULT hr = CCplUiCommandOnPidl::CreateInstance(pidl, riid, ppvOut);
  1354. return THR(hr);
  1355. }
  1356. } // namespace CPL