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.

244 lines
6.3 KiB

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