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.

509 lines
14 KiB

  1. #include "shellprv.h"
  2. #include "defview.h"
  3. #include "defviewp.h"
  4. #include "contextmenu.h"
  5. #include "ids.h"
  6. #include "unicpp\deskhtm.h"
  7. class CThumbnailMenu : public IContextMenu3,
  8. public CComObjectRoot,
  9. public IObjectWithSite
  10. {
  11. public:
  12. BEGIN_COM_MAP(CThumbnailMenu)
  13. COM_INTERFACE_ENTRY_IID(IID_IContextMenu3,IContextMenu3)
  14. COM_INTERFACE_ENTRY_IID(IID_IContextMenu2,IContextMenu2)
  15. COM_INTERFACE_ENTRY_IID(IID_IContextMenu,IContextMenu)
  16. COM_INTERFACE_ENTRY(IObjectWithSite)
  17. END_COM_MAP()
  18. DECLARE_NOT_AGGREGATABLE(CThumbnailMenu)
  19. CThumbnailMenu();
  20. ~CThumbnailMenu();
  21. HRESULT Init(CDefView* pView, LPCITEMIDLIST * apidl, UINT cidl);
  22. STDMETHOD(QueryContextMenu)(HMENU hmenu,
  23. UINT indexMenu,
  24. UINT idCmdFirst,
  25. UINT idCmdLast,
  26. UINT uFlags);
  27. STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
  28. STDMETHOD(GetCommandString)(UINT_PTR idCmd,
  29. UINT uType,
  30. UINT * pwReserved,
  31. LPSTR pszName,
  32. UINT cchMax);
  33. STDMETHOD(HandleMenuMsg)(UINT uMsg,
  34. WPARAM wParam,
  35. LPARAM lParam);
  36. STDMETHOD(HandleMenuMsg2)(UINT uMsg,
  37. WPARAM wParam,
  38. LPARAM lParam,
  39. LRESULT* plRes);
  40. STDMETHOD(SetSite)(IUnknown *punkSite);
  41. STDMETHOD(GetSite)(REFIID riid, void **ppvSite);
  42. protected:
  43. LPCITEMIDLIST * _apidl;
  44. UINT _cidl;
  45. IContextMenu *_pMenu;
  46. IContextMenu2 *_pMenu2;
  47. BOOL _fCaptureAvail;
  48. UINT _wID;
  49. CDefView* _pView;
  50. };
  51. HRESULT CDefView::_CreateSelectionContextMenu(REFIID riid, void** ppv)
  52. {
  53. *ppv = NULL;
  54. HRESULT hr = E_OUTOFMEMORY;
  55. if (_IsImageMode() && !_IsOwnerData())
  56. {
  57. LPCITEMIDLIST* apidl;
  58. UINT cidl;
  59. _GetItemObjects(&apidl, SVGIO_SELECTION, &cidl);
  60. if (apidl)
  61. {
  62. // get the context menu interface for the object ....
  63. CComObject<CThumbnailMenu> * pMenuTmp = new CComObject<CThumbnailMenu>;
  64. if (pMenuTmp)
  65. {
  66. pMenuTmp->AddRef(); // ATL is strange, start with zero ref
  67. hr = pMenuTmp->Init(this, apidl, cidl);
  68. if (SUCCEEDED(hr))
  69. hr = pMenuTmp->QueryInterface(riid, ppv);
  70. pMenuTmp->Release();
  71. }
  72. LocalFree((HLOCAL)apidl);
  73. }
  74. }
  75. else
  76. {
  77. hr = GetItemObject(SVGIO_SELECTION, riid, ppv);
  78. }
  79. ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && !*ppv));
  80. return hr;
  81. }
  82. LPCITEMIDLIST * DuplicateIDArray(LPCITEMIDLIST * apidl, UINT cidl)
  83. {
  84. LPCITEMIDLIST * apidlNew = (LPCITEMIDLIST *) LocalAlloc(LPTR, cidl * sizeof(LPCITEMIDLIST));
  85. if (apidlNew)
  86. {
  87. CopyMemory(apidlNew, apidl, cidl * sizeof(LPCITEMIDLIST));
  88. }
  89. return apidlNew;
  90. }
  91. CThumbnailMenu::CThumbnailMenu()
  92. {
  93. _pMenu = NULL;
  94. _pMenu2 = NULL;
  95. _pView = NULL;
  96. _apidl = NULL;
  97. _cidl = NULL;
  98. _fCaptureAvail = FALSE;
  99. _wID = -1;
  100. }
  101. CThumbnailMenu::~CThumbnailMenu()
  102. {
  103. if (_pMenu)
  104. {
  105. _pMenu->Release();
  106. }
  107. if (_pMenu2)
  108. {
  109. _pMenu2->Release();
  110. }
  111. if (_pView)
  112. {
  113. _pView->Release();
  114. }
  115. if (_apidl)
  116. {
  117. LocalFree(_apidl);
  118. }
  119. }
  120. HRESULT CThumbnailMenu::Init(CDefView*pView, LPCITEMIDLIST *apidl, UINT cidl)
  121. {
  122. if (cidl == 0)
  123. return E_INVALIDARG;
  124. // duplicate the array that holds the pointers ..
  125. _apidl = DuplicateIDArray(apidl, cidl);
  126. _cidl = cidl;
  127. if (_apidl == NULL)
  128. {
  129. _cidl = 0;
  130. return E_OUTOFMEMORY;
  131. }
  132. _pView = pView;
  133. pView->AddRef();
  134. // scan the pidl array and check for Extractors ...
  135. for (int i = 0; i < (int) _cidl; i++)
  136. {
  137. IExtractImage *pExtract;
  138. HRESULT hr = pView->_pshf->GetUIObjectOf(pView->_hwndView, 1, &_apidl[i], IID_PPV_ARG_NULL(IExtractImage, &pExtract));
  139. if (SUCCEEDED(hr))
  140. {
  141. WCHAR szPath[MAX_PATH];
  142. DWORD dwFlags = 0;
  143. SIZE rgThumbSize;
  144. pView->_GetThumbnailSize(&rgThumbSize);
  145. hr = pExtract->GetLocation(szPath, ARRAYSIZE(szPath), NULL, &rgThumbSize, pView->_dwRecClrDepth, &dwFlags);
  146. pExtract->Release();
  147. if (dwFlags & (IEIFLAG_CACHE | IEIFLAG_REFRESH))
  148. {
  149. _fCaptureAvail = TRUE;
  150. break;
  151. }
  152. }
  153. else
  154. {
  155. // blank it out so we don't bother trying it if the user choses the command
  156. _apidl[i] = NULL;
  157. }
  158. }
  159. HRESULT hr = pView->_pshf->GetUIObjectOf(pView->_hwndMain, cidl, apidl,
  160. IID_PPV_ARG_NULL(IContextMenu, & _pMenu));
  161. if (SUCCEEDED(hr))
  162. {
  163. _pMenu->QueryInterface(IID_PPV_ARG(IContextMenu2, &_pMenu2));
  164. }
  165. return hr;
  166. }
  167. STDMETHODIMP CThumbnailMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu,
  168. UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  169. {
  170. ASSERT(_pMenu != NULL);
  171. // generate the proper menu
  172. HRESULT hr = _pMenu->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
  173. if (SUCCEEDED(hr) && _fCaptureAvail)
  174. {
  175. // find the first separator and insert the menu text after it....
  176. int cMenuSize = GetMenuItemCount(hmenu);
  177. for (int iIndex = 0; iIndex < cMenuSize; iIndex ++)
  178. {
  179. WCHAR szText[80];
  180. MENUITEMINFOW mii = {0};
  181. mii.cbSize = sizeof(mii);
  182. mii.fMask = MIIM_TYPE;
  183. mii.fType = 0;
  184. mii.dwTypeData = szText;
  185. mii.cch = ARRAYSIZE(szText);
  186. GetMenuItemInfo(hmenu, iIndex, TRUE, &mii);
  187. if (mii.fType & MFT_SEPARATOR)
  188. {
  189. szText[0] = 0;
  190. LoadString(HINST_THISDLL, IDS_CREATETHUMBNAIL, szText, ARRAYSIZE(szText));
  191. mii.fMask = MIIM_ID | MIIM_TYPE;
  192. mii.fType = MFT_STRING;
  193. mii.dwTypeData = szText;
  194. mii.cch = 0;
  195. // assuming 0 is the first id, therefore the next one = the count they returned
  196. _wID = HRESULT_CODE(hr);
  197. mii.wID = idCmdFirst + _wID;
  198. InsertMenuItem(hmenu, iIndex, TRUE, &mii);
  199. // we used an extra ID.
  200. hr++;
  201. break;
  202. }
  203. }
  204. }
  205. return hr;
  206. }
  207. STDMETHODIMP CThumbnailMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  208. {
  209. HRESULT hr = E_FAIL;
  210. ASSERT(_pMenu != NULL);
  211. if (pici->lpVerb != IntToPtr_(LPCSTR, _wID))
  212. {
  213. hr = _pMenu->InvokeCommand(pici);
  214. }
  215. else
  216. {
  217. // capture thumbnails .....
  218. for (UINT i = 0; i < _cidl; i++)
  219. {
  220. if (_apidl[i])
  221. {
  222. UINT uiImage;
  223. _pView->ExtractItem(&uiImage, -1, _apidl[i], TRUE, TRUE, PRIORITY_P5);
  224. }
  225. }
  226. }
  227. return hr;
  228. }
  229. STDMETHODIMP CThumbnailMenu::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwRes, LPSTR pszName, UINT cchMax)
  230. {
  231. if (cchMax)
  232. pszName[0] = 0;
  233. if (!IS_INTRESOURCE(idCmd))
  234. {
  235. // it is really a text verb ...
  236. LPSTR pszCommand = (LPSTR) idCmd;
  237. if (lstrcmpA(pszCommand, "CaptureThumbnail") == 0)
  238. {
  239. return S_OK;
  240. }
  241. }
  242. else
  243. {
  244. if (idCmd == _wID)
  245. {
  246. // it is ours ...
  247. switch(uType)
  248. {
  249. case GCS_VERB:
  250. StrCpyN((LPWSTR) pszName, TEXT("CaptureThumbnail"), cchMax);
  251. break;
  252. case GCS_HELPTEXT:
  253. LoadString(HINST_THISDLL, IDS_CREATETHUMBNAILHELP, (LPWSTR) pszName, cchMax);
  254. break;
  255. case GCS_VALIDATE:
  256. break;
  257. default:
  258. return E_INVALIDARG;
  259. }
  260. return S_OK;
  261. }
  262. }
  263. return _pMenu->GetCommandString(idCmd, uType, pwRes, pszName, cchMax);
  264. }
  265. STDMETHODIMP CThumbnailMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plRes)
  266. {
  267. HRESULT hr = E_NOTIMPL;
  268. if (uMsg == WM_MENUCHAR)
  269. {
  270. hr = SHForwardContextMenuMsg(_pMenu2, uMsg, wParam, lParam, plRes, FALSE);
  271. }
  272. else
  273. {
  274. hr = HandleMenuMsg(uMsg, wParam, lParam);
  275. if (plRes)
  276. *plRes = 0;
  277. }
  278. return hr;
  279. }
  280. STDMETHODIMP CThumbnailMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  281. {
  282. if (_pMenu2 == NULL)
  283. {
  284. return E_NOTIMPL;
  285. }
  286. switch (uMsg)
  287. {
  288. case WM_DRAWITEM:
  289. {
  290. DRAWITEMSTRUCT * pdi = (DRAWITEMSTRUCT *)lParam;
  291. if (pdi->CtlType == ODT_MENU && pdi->itemID == _wID)
  292. {
  293. return E_NOTIMPL;
  294. }
  295. }
  296. break;
  297. case WM_MEASUREITEM:
  298. {
  299. MEASUREITEMSTRUCT *pmi = (MEASUREITEMSTRUCT *)lParam;
  300. if (pmi->CtlType == ODT_MENU && pmi->itemID == _wID)
  301. {
  302. return E_NOTIMPL;
  303. }
  304. }
  305. break;
  306. }
  307. return _pMenu2->HandleMenuMsg(uMsg, wParam, lParam);
  308. }
  309. HRESULT CThumbnailMenu::SetSite(IUnknown *punkSite)
  310. {
  311. IUnknown_SetSite(_pMenu, punkSite);
  312. return S_OK;
  313. }
  314. HRESULT CThumbnailMenu::GetSite(REFIID riid, void **ppvSite)
  315. {
  316. return IUnknown_GetSite(_pMenu, riid, ppvSite);
  317. }
  318. // Create defview's POPUP_SFV_BACKGROUND menu
  319. HRESULT CDefView::_Create_BackgrndHMENU(BOOL fViewMenuOnly, REFIID riid, void **ppv)
  320. {
  321. HRESULT hr = E_OUTOFMEMORY;
  322. *ppv = NULL;
  323. HMENU hmContext = SHLoadPopupMenu(HINST_THISDLL, POPUP_SFV_BACKGROUND);
  324. if (hmContext)
  325. {
  326. // HACK: we are only initializing the Paste command, so we don't
  327. // need any attributes
  328. Def_InitEditCommands(0, hmContext, SFVIDM_FIRST, _pdtgtBack,
  329. DIEC_BACKGROUNDCONTEXT);
  330. InitViewMenu(hmContext);
  331. // Do a whole lot of desktop-only stuff for the actual desktop
  332. if (_IsDesktop() && IsDesktopBrowser(_psb))
  333. {
  334. // We only want LargeIcons on the real desktop
  335. // so we remove the View menu
  336. DeleteMenu(hmContext, SFVIDM_MENU_VIEW, MF_BYCOMMAND);
  337. // No Choose Columns either
  338. DeleteMenu(hmContext, SFVIDM_VIEW_COLSETTINGS, MF_BYCOMMAND);
  339. // Only put on ActiveDesktop menu item if it isn't restricted.
  340. if (SHRestricted(REST_FORCEACTIVEDESKTOPON) ||
  341. (!PolicyNoActiveDesktop() &&
  342. !SHRestricted(REST_CLASSICSHELL) &&
  343. !SHRestricted(REST_NOACTIVEDESKTOPCHANGES)))
  344. {
  345. HMENU hmenuAD;
  346. // Load the menu and make the appropriate modifications
  347. if (hmenuAD = SHLoadMenuPopup(HINST_THISDLL, POPUP_SFV_BACKGROUND_AD))
  348. {
  349. MENUITEMINFO mii = {0};
  350. mii.cbSize = sizeof(mii);
  351. mii.fMask = MIIM_SUBMENU;
  352. if (GetMenuItemInfo(hmContext, SFVIDM_MENU_ARRANGE, FALSE, &mii))
  353. {
  354. // Get the present settings regarding HTML on desktop
  355. SHELLSTATE ss;
  356. SHGetSetSettings(&ss, SSF_DESKTOPHTML | SSF_HIDEICONS, FALSE);
  357. if (!ss.fHideIcons)
  358. CheckMenuItem(hmenuAD, SFVIDM_DESKTOPHTML_ICONS, MF_BYCOMMAND | MF_CHECKED);
  359. if (GetDesktopFlags() & COMPONENTS_LOCKED)
  360. CheckMenuItem(hmenuAD, SFVIDM_DESKTOPHTML_LOCK, MF_BYCOMMAND | MF_CHECKED);
  361. // Hide the desktop cleanup wizard item if we're not allowed to run it
  362. // (user is guest or policy forbids it)
  363. if (IsOS(OS_ANYSERVER) || IsUserAGuest() || SHRestricted(REST_NODESKTOPCLEANUP))
  364. {
  365. DeleteMenu(hmenuAD, SFVIDM_DESKTOPHTML_WIZARD, MF_BYCOMMAND);
  366. }
  367. Shell_MergeMenus(mii.hSubMenu, hmenuAD, (UINT)-1, 0, (UINT)-1, MM_ADDSEPARATOR);
  368. }
  369. DestroyMenu(hmenuAD);
  370. }
  371. }
  372. }
  373. if (fViewMenuOnly)
  374. {
  375. MENUITEMINFO mii = {0};
  376. mii.cbSize = sizeof(mii);
  377. mii.fMask = MIIM_SUBMENU;
  378. GetMenuItemInfo(hmContext, SFVIDM_MENU_VIEW, MF_BYCOMMAND, &mii);
  379. HMENU hmenuView = mii.hSubMenu;
  380. RemoveMenu(hmContext, SFVIDM_MENU_VIEW, MF_BYCOMMAND);
  381. DestroyMenu(hmContext);
  382. hmContext = hmenuView;
  383. }
  384. hr = Create_ContextMenuOnHMENU(hmContext, _hwndView, riid, ppv);
  385. }
  386. return hr;
  387. }
  388. // Create defview's actual background context menu, an array of:
  389. // defview's POPUP_SFV_BACKGROUND and
  390. // the IShellFolder's CreateViewObject(IID_IContextMenu)
  391. //
  392. HRESULT CDefView::_CBackgrndMenu_CreateInstance(REFIID riid, void **ppv)
  393. {
  394. HRESULT hr = E_OUTOFMEMORY;
  395. *ppv = NULL;
  396. IContextMenu* pcmMenu;
  397. hr = _Create_BackgrndHMENU(FALSE, IID_PPV_ARG(IContextMenu, &pcmMenu));
  398. if (SUCCEEDED(hr))
  399. {
  400. IContextMenu* pcmView;
  401. if (SUCCEEDED(_pshf->CreateViewObject(_hwndMain, IID_PPV_ARG(IContextMenu, &pcmView))))
  402. {
  403. IContextMenu* rgpcm[2] = {pcmMenu, pcmView};
  404. hr = Create_ContextMenuOnContextMenuArray(rgpcm, ARRAYSIZE(rgpcm), riid, ppv);
  405. pcmView->Release();
  406. }
  407. else
  408. {
  409. // Compat - RNAUI fails the CreateViewObject and they rely on simply having the default stuff...
  410. //
  411. hr = pcmMenu->QueryInterface(riid, ppv);
  412. }
  413. pcmMenu->Release();
  414. }
  415. return hr;
  416. }