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.

243 lines
6.3 KiB

  1. //
  2. // isfmenu.cpp
  3. //
  4. // callback for chevron drop-down menu for isfbands
  5. //
  6. #include "shellprv.h"
  7. #include "isfmenu.h"
  8. #include "legacy.h"
  9. #include "util.h"
  10. // *** IUnknown methods ***
  11. STDMETHODIMP CISFMenuCallback::QueryInterface (REFIID riid, LPVOID * ppvObj)
  12. {
  13. static const QITAB qit[] =
  14. {
  15. QITABENT(CISFMenuCallback, IShellMenuCallback),
  16. QITABENT(CISFMenuCallback, IObjectWithSite),
  17. { 0 },
  18. };
  19. return QISearch(this, qit, riid, ppvObj);
  20. }
  21. STDMETHODIMP_(ULONG) CISFMenuCallback::AddRef ()
  22. {
  23. return ++_cRef;
  24. }
  25. STDMETHODIMP_(ULONG) CISFMenuCallback::Release()
  26. {
  27. ASSERT(_cRef > 0);
  28. _cRef--;
  29. if( _cRef > 0)
  30. return _cRef;
  31. delete this;
  32. return 0;
  33. }
  34. BOOL CISFMenuCallback::_IsVisible(LPITEMIDLIST pidl)
  35. {
  36. if (_poct) {
  37. VARIANTARG v;
  38. v.vt = VT_INT_PTR;
  39. v.byref = pidl;
  40. HRESULT hr = _poct->Exec(&CGID_ISFBand, ISFBID_ISITEMVISIBLE, 0, &v, NULL);
  41. return (hr == S_OK);
  42. }
  43. return FALSE;
  44. }
  45. HRESULT IUnknown_SeekToZero(IUnknown* punk)
  46. {
  47. HRESULT hres = E_FAIL;
  48. IStream* pstm;
  49. if (punk && SUCCEEDED(punk->QueryInterface(IID_IStream, (void**)&pstm)))
  50. {
  51. // We need to seek to the beginning of the stream here. We don't do this in
  52. // the menubands because it's rude: They should not seek to the beginning
  53. // because there may be information that needs to be saved after them.
  54. //Set the seek pointer at the beginning.
  55. const LARGE_INTEGER li0 = {0};
  56. hres = pstm->Seek(li0, STREAM_SEEK_SET, NULL);
  57. pstm->Release();
  58. }
  59. return hres;
  60. }
  61. HRESULT CISFMenuCallback::_GetObject(LPSMDATA psmd, REFIID riid, void** ppvObj)
  62. {
  63. HRESULT hres = S_FALSE;
  64. *ppvObj = NULL;
  65. if (IsEqualIID(riid, IID_IStream))
  66. {
  67. if (_pidl && psmd->pidlFolder && psmd->pidlItem)
  68. {
  69. // Verify that the Cascading menuband is ONLY asking for this folder.
  70. // because if there is a sub menu, It's going to ask again with the
  71. // pidl of that folder, which we don't have the Stream for, and we
  72. // can hose things pretty good if we indescriminatly hand out order streams
  73. LPITEMIDLIST pidlFull = ILCombine(psmd->pidlFolder, psmd->pidlItem);
  74. if (pidlFull)
  75. {
  76. if (_poct && ILIsEqual(pidlFull, _pidl))
  77. {
  78. VARIANTARG v = {0};
  79. v.vt = VT_UNKNOWN;
  80. hres = _poct->Exec(&CGID_ISFBand, ISFBID_GETORDERSTREAM, 0, NULL, &v);
  81. if (SUCCEEDED(hres))
  82. {
  83. IUnknown_SeekToZero(v.punkVal);
  84. hres = v.punkVal->QueryInterface(riid, ppvObj);
  85. v.punkVal->Release();
  86. }
  87. }
  88. ILFree(pidlFull);
  89. }
  90. }
  91. }
  92. return hres;
  93. }
  94. HRESULT CISFMenuCallback::_SetObject(LPSMDATA psmd, REFIID riid, void** ppvObj)
  95. {
  96. HRESULT hres = E_FAIL;
  97. if (IsEqualIID(riid, IID_IStream))
  98. {
  99. if (_pidl && psmd->pidlFolder && psmd->pidlItem)
  100. {
  101. // Verify that the Cascading menuband is ONLY asking for this folder.
  102. // because if there is a sub menu, It's going to ask again with the
  103. // pidl of that folder, which we don't have the Stream for, and we
  104. // can hose things pretty good if we indescriminatly hand out order streams
  105. LPITEMIDLIST pidlFull = ILCombine(psmd->pidlFolder, psmd->pidlItem);
  106. if (pidlFull)
  107. {
  108. if (_poct && ILIsEqual(pidlFull, _pidl))
  109. {
  110. ASSERT(ppvObj);
  111. VARIANTARG v;
  112. v.vt = VT_UNKNOWN;
  113. v.punkVal = *(IUnknown**)ppvObj;
  114. IUnknown_SeekToZero(*(IUnknown**)ppvObj);
  115. hres = _poct->Exec(&CGID_ISFBand, ISFBID_SETORDERSTREAM, 0, &v, NULL);
  116. }
  117. ILFree(pidlFull);
  118. }
  119. }
  120. }
  121. return hres;
  122. }
  123. HRESULT CISFMenuCallback::_GetSFInfo(LPSMDATA psmd, PSMINFO psminfo)
  124. {
  125. // We only want to filter pidls if:
  126. // 1) It's at the root of the links chevron menu
  127. // 2) It's _IS_ visible in the links bar. We don't want to show links
  128. // in this menu that are visible.
  129. if (psmd->uIdAncestor == ANCESTORDEFAULT &&
  130. (psminfo->dwMask & SMIM_FLAGS) &&
  131. _IsVisible(psmd->pidlItem))
  132. {
  133. // not obscured on the subject isfband; exclude from menu
  134. psminfo->dwFlags |= SMIF_HIDDEN;
  135. }
  136. return S_OK;
  137. }
  138. // *** IShellMenuCallback methods ***
  139. STDMETHODIMP CISFMenuCallback::CallbackSM(LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  140. {
  141. HRESULT hr = S_FALSE;
  142. switch (uMsg)
  143. {
  144. case SMC_SFEXEC:
  145. hr = SHNavigateToFavorite(psmd->psf, psmd->pidlItem, _punkSite, SBSP_DEFBROWSER | SBSP_DEFMODE);
  146. break;
  147. case SMC_GETSFINFO:
  148. hr = _GetSFInfo(psmd, (PSMINFO)lParam);
  149. break;
  150. case SMC_GETSFOBJECT:
  151. hr = _GetObject(psmd, *((GUID*)wParam), (void**)lParam);
  152. break;
  153. case SMC_SETSFOBJECT:
  154. hr = _SetObject(psmd, *((GUID*)wParam), (void**)lParam);
  155. break;
  156. }
  157. return hr;
  158. }
  159. // *** IObjectWithSite methods ***
  160. STDMETHODIMP CISFMenuCallback::SetSite(IUnknown* punkSite)
  161. {
  162. if (punkSite != _punkSite)
  163. IUnknown_Set(&_punkSite, punkSite);
  164. return S_OK;
  165. }
  166. HRESULT CISFMenuCallback::Initialize(IUnknown* punk)
  167. {
  168. HRESULT hr = E_FAIL;
  169. if (punk)
  170. hr = punk->QueryInterface(IID_IOleCommandTarget, (PVOID*)&_poct);
  171. IShellFolderBand* psfb;
  172. hr = punk->QueryInterface(IID_IShellFolderBand, (PVOID*)&psfb);
  173. if (SUCCEEDED(hr))
  174. {
  175. BANDINFOSFB bi;
  176. bi.dwMask = ISFB_MASK_IDLIST | ISFB_MASK_SHELLFOLDER;
  177. hr = psfb->GetBandInfoSFB(&bi);
  178. _pidl = bi.pidl;
  179. if (bi.psf)
  180. bi.psf->Release();
  181. psfb->Release();
  182. }
  183. return hr;
  184. }
  185. CISFMenuCallback::CISFMenuCallback() : _cRef(1)
  186. {
  187. }
  188. CISFMenuCallback::~CISFMenuCallback()
  189. {
  190. ASSERT(_cRef == 0);
  191. ILFree(_pidl);
  192. ATOMICRELEASE(_poct);
  193. }