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.

218 lines
6.4 KiB

  1. #include "precomp.hxx"
  2. #pragma hdrstop
  3. #include <cowsite.h>
  4. #include "contextmenu.h"
  5. // Context Menu Forwarding base class, desinged to delegate
  6. // to a real IContextMenu, and provide inheriting class
  7. // an easy way to override minor bits of functionality
  8. //
  9. CContextMenuForwarder::CContextMenuForwarder(IUnknown* punk) : _cRef(1)
  10. {
  11. _punk = punk;
  12. _punk->AddRef();
  13. _punk->QueryInterface(IID_PPV_ARG(IObjectWithSite, &_pows));
  14. _punk->QueryInterface(IID_PPV_ARG(IContextMenu, &_pcm));
  15. _punk->QueryInterface(IID_PPV_ARG(IContextMenu2, &_pcm2));
  16. _punk->QueryInterface(IID_PPV_ARG(IContextMenu3, &_pcm3));
  17. }
  18. CContextMenuForwarder::~CContextMenuForwarder()
  19. {
  20. if (_pows) _pows->Release();
  21. if (_pcm) _pcm->Release();
  22. if (_pcm2) _pcm2->Release();
  23. if (_pcm3) _pcm3->Release();
  24. _punk->Release();
  25. }
  26. STDMETHODIMP CContextMenuForwarder::QueryInterface(REFIID riid, void **ppv)
  27. {
  28. HRESULT hr = _punk->QueryInterface(riid, ppv);
  29. if (SUCCEEDED(hr))
  30. {
  31. IUnknown* punkTmp = (IUnknown*)(*ppv);
  32. static const QITAB qit[] = {
  33. QITABENT(CContextMenuForwarder, IObjectWithSite), // IID_IObjectWithSite
  34. QITABENT(CContextMenuForwarder, IContextMenu3), // IID_IContextMenu3
  35. QITABENTMULTI(CContextMenuForwarder, IContextMenu2, IContextMenu3), // IID_IContextMenu2
  36. QITABENTMULTI(CContextMenuForwarder, IContextMenu, IContextMenu3), // IID_IContextMenu
  37. { 0 },
  38. };
  39. HRESULT hrTmp = QISearch(this, qit, riid, ppv);
  40. if (SUCCEEDED(hrTmp))
  41. {
  42. punkTmp->Release();
  43. }
  44. else
  45. {
  46. RIPMSG(FALSE, "CContextMenuForwarder asked for an interface it doesn't support");
  47. *ppv = NULL;
  48. hr = E_NOINTERFACE;
  49. }
  50. }
  51. return hr;
  52. }
  53. STDMETHODIMP_(ULONG) CContextMenuForwarder::AddRef()
  54. {
  55. return InterlockedIncrement(&_cRef);
  56. }
  57. STDMETHODIMP_(ULONG) CContextMenuForwarder::Release()
  58. {
  59. ASSERT( 0 != _cRef );
  60. ULONG cRef = InterlockedDecrement(&_cRef);
  61. if ( 0 == cRef )
  62. {
  63. delete this;
  64. }
  65. return cRef;
  66. }
  67. // Forward everything to the given context menu,
  68. // but remove menu items with the canonical verbs
  69. // given in the semicolon-separated list of canonical verbs
  70. //
  71. class CContextMenuWithoutVerbs : CContextMenuForwarder
  72. {
  73. public:
  74. STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
  75. protected:
  76. CContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList);
  77. friend HRESULT Create_ContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList, REFIID riid, void **ppv);
  78. private:
  79. LPCWSTR _pszVerbList;
  80. };
  81. CContextMenuWithoutVerbs::CContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList) : CContextMenuForwarder(punk)
  82. {
  83. _pszVerbList = pszVerbList; // no reference - this should be a pointer to the code segment
  84. }
  85. HRESULT Create_ContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList, REFIID riid, void **ppv)
  86. {
  87. HRESULT hr = E_OUTOFMEMORY;
  88. *ppv = NULL;
  89. if (pszVerbList)
  90. {
  91. CContextMenuWithoutVerbs* p = new CContextMenuWithoutVerbs(punk, pszVerbList);
  92. if (p)
  93. {
  94. hr = p->QueryInterface(riid, ppv);
  95. p->Release();
  96. }
  97. }
  98. return hr;
  99. }
  100. HRESULT CContextMenuWithoutVerbs::QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
  101. {
  102. HRESULT hr = CContextMenuForwarder::QueryContextMenu(hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags);
  103. if (SUCCEEDED(hr))
  104. {
  105. LPCWSTR pszVerb = _pszVerbList;
  106. while (*pszVerb)
  107. {
  108. WCHAR szVerb[64];
  109. LPCWSTR pszNext = StrChrW(pszVerb, L';');
  110. if (pszNext)
  111. {
  112. size_t cch = (size_t)(pszNext - pszVerb) + 1;
  113. ASSERT(0 < cch && cch < ARRAYSIZE(szVerb)); // we should be large enough for all the canonical verbs we use
  114. StrCpyNW(szVerb, pszVerb, min(cch, ARRAYSIZE(szVerb)));
  115. pszVerb = pszNext + 1;
  116. }
  117. else
  118. {
  119. size_t cch = lstrlenW(pszVerb) + 1;
  120. ASSERT(0 < cch && cch < ARRAYSIZE(szVerb)); // we should be large enough for all the canonical verbs we use
  121. StrCpyNW(szVerb, pszVerb, min(cch, ARRAYSIZE(szVerb)));
  122. pszVerb += cch - 1; // point at NULL
  123. }
  124. ContextMenu_DeleteCommandByName(_pcm, hmenu, idCmdFirst, szVerb);
  125. }
  126. }
  127. return hr;
  128. }
  129. // Forward everything to the given context menu,
  130. // but disable popup menus
  131. //
  132. class CContextMenuWithoutPopups : CContextMenuForwarder
  133. {
  134. public:
  135. STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
  136. protected:
  137. CContextMenuWithoutPopups(IUnknown* punk) : CContextMenuForwarder(punk) {}
  138. friend HRESULT Create_ContextMenuWithoutPopups(IUnknown* punk, REFIID riid, void **ppv);
  139. };
  140. HRESULT Create_ContextMenuWithoutPopups(IUnknown* punk, REFIID riid, void **ppv)
  141. {
  142. HRESULT hr = E_OUTOFMEMORY;
  143. *ppv = NULL;
  144. CContextMenuWithoutPopups* p = new CContextMenuWithoutPopups(punk);
  145. if (p)
  146. {
  147. hr = p->QueryInterface(riid, ppv);
  148. p->Release();
  149. }
  150. return hr;
  151. }
  152. HRESULT CContextMenuWithoutPopups::QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
  153. {
  154. HRESULT hr = CContextMenuForwarder::QueryContextMenu(hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags);
  155. if (SUCCEEDED(hr))
  156. {
  157. MENUITEMINFO mii;
  158. // Disable any submenus that were just added
  159. mii.cbSize = sizeof(mii);
  160. idCmdLast = idCmdFirst + ShortFromResult(hr);
  161. for (UINT i = idCmdFirst; i < idCmdLast; i++)
  162. {
  163. mii.fMask = MIIM_STATE | MIIM_SUBMENU;
  164. if (GetMenuItemInfo(hmenu, i, FALSE, &mii)
  165. && mii.hSubMenu
  166. && (mii.fState & (MFS_DISABLED | MFS_GRAYED)) != (MFS_DISABLED | MFS_GRAYED))
  167. {
  168. mii.fMask = MIIM_STATE;
  169. mii.fState |= MFS_DISABLED | MFS_GRAYED;
  170. SetMenuItemInfo(hmenu, i, FALSE, &mii);
  171. }
  172. }
  173. }
  174. return hr;
  175. }