Source code of Windows XP (NT5)
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.

830 lines
22 KiB

  1. #include "cabinet.h"
  2. #include "rcids.h"
  3. #include <shguidp.h>
  4. #include <lmcons.h>
  5. #include "bandsite.h"
  6. #include "shellp.h"
  7. #include "shdguid.h"
  8. #include <regstr.h>
  9. #include "startmnu.h"
  10. #include "trayp.h" // for WMTRAY_*
  11. #include "tray.h"
  12. #include "util.h"
  13. HMENU GetStaticStartMenu(BOOL fEdit);
  14. // *** IUnknown methods ***
  15. STDMETHODIMP CStartMenuHost::QueryInterface (REFIID riid, LPVOID * ppvObj)
  16. {
  17. static const QITAB qit[] =
  18. {
  19. QITABENTMULTI(CStartMenuHost, IOleWindow, IMenuPopup),
  20. QITABENTMULTI(CStartMenuHost, IDeskBarClient, IMenuPopup),
  21. QITABENT(CStartMenuHost, IMenuPopup),
  22. QITABENT(CStartMenuHost, ITrayPriv),
  23. QITABENT(CStartMenuHost, IShellService),
  24. QITABENT(CStartMenuHost, IServiceProvider),
  25. QITABENT(CStartMenuHost, IOleCommandTarget),
  26. QITABENT(CStartMenuHost, IWinEventHandler),
  27. { 0 },
  28. };
  29. return QISearch(this, qit, riid, ppvObj);
  30. }
  31. STDMETHODIMP_(ULONG) CStartMenuHost::AddRef ()
  32. {
  33. return ++_cRef;
  34. }
  35. STDMETHODIMP_(ULONG) CStartMenuHost::Release()
  36. {
  37. ASSERT(_cRef > 0);
  38. _cRef--;
  39. if( _cRef > 0)
  40. return _cRef;
  41. delete this;
  42. return 0;
  43. }
  44. /*----------------------------------------------------------
  45. Purpose: ITrayPriv::ExecItem method
  46. */
  47. STDMETHODIMP CStartMenuHost::ExecItem (IShellFolder* psf, LPCITEMIDLIST pidl)
  48. {
  49. // ShellExecute will display errors (if any). No need
  50. // to show errors here.
  51. return SHInvokeDefaultCommand(v_hwndTray, psf, pidl);
  52. }
  53. /*----------------------------------------------------------
  54. Purpose: ITrayPriv::GetFindCM method
  55. */
  56. STDMETHODIMP CStartMenuHost::GetFindCM(HMENU hmenu, UINT idFirst, UINT idLast, IContextMenu** ppcmFind)
  57. {
  58. *ppcmFind = SHFind_InitMenuPopup(hmenu, v_hwndTray, TRAY_IDM_FINDFIRST, TRAY_IDM_FINDLAST);
  59. if(*ppcmFind)
  60. return NOERROR;
  61. else
  62. return E_FAIL;
  63. }
  64. /*----------------------------------------------------------
  65. Purpose: ITrayPriv::GetStaticStartMenu method
  66. */
  67. STDMETHODIMP CStartMenuHost::GetStaticStartMenu(HMENU* phmenu)
  68. {
  69. *phmenu = ::GetStaticStartMenu(TRUE);
  70. if(*phmenu)
  71. return NOERROR;
  72. else
  73. return E_FAIL;
  74. }
  75. // *** IServiceProvider ***
  76. STDMETHODIMP CStartMenuHost::QueryService (REFGUID guidService, REFIID riid, void ** ppvObject)
  77. {
  78. if(IsEqualGUID(guidService,SID_SMenuPopup))
  79. return QueryInterface(riid,ppvObject);
  80. else
  81. return E_NOINTERFACE;
  82. }
  83. // *** IShellService ***
  84. STDMETHODIMP CStartMenuHost::SetOwner (struct IUnknown* punkOwner)
  85. {
  86. return E_NOTIMPL;
  87. }
  88. // *** IOleWindow methods ***
  89. STDMETHODIMP CStartMenuHost::GetWindow(HWND * lphwnd)
  90. {
  91. *lphwnd = v_hwndTray;
  92. return NOERROR;
  93. }
  94. /*----------------------------------------------------------
  95. Purpose: IMenuPopup::Popup method
  96. */
  97. STDMETHODIMP CStartMenuHost::Popup(POINTL *ppt, RECTL *prcExclude, DWORD dwFlags)
  98. {
  99. return E_NOTIMPL;
  100. }
  101. /*----------------------------------------------------------
  102. Purpose: IMenuPopup::OnSelect method
  103. */
  104. STDMETHODIMP CStartMenuHost::OnSelect(DWORD dwSelectType)
  105. {
  106. return NOERROR;
  107. }
  108. /*----------------------------------------------------------
  109. Purpose: IMenuPopup::SetSubMenu method
  110. */
  111. STDMETHODIMP CStartMenuHost::SetSubMenu(IMenuPopup* pmp, BOOL fSet)
  112. {
  113. if (!fSet)
  114. {
  115. Tray_OnStartMenuDismissed();
  116. }
  117. return NOERROR;
  118. }
  119. // *** IOleCommandTarget ***
  120. STDMETHODIMP CStartMenuHost::QueryStatus (const GUID * pguidCmdGroup,
  121. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  122. {
  123. return E_NOTIMPL;
  124. }
  125. STDMETHODIMP CStartMenuHost::Exec (const GUID * pguidCmdGroup,
  126. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  127. {
  128. if (IsEqualGUID(CGID_MENUDESKBAR,*pguidCmdGroup))
  129. {
  130. switch (nCmdID)
  131. {
  132. case MBCID_GETSIDE:
  133. pvarargOut->vt = VT_I4;
  134. pvarargOut->lVal = MENUBAR_TOP;
  135. break;
  136. default:
  137. break;
  138. }
  139. }
  140. return NOERROR;
  141. }
  142. // *** IWinEventHandler ***
  143. STDMETHODIMP CStartMenuHost::OnWinEvent(HWND h, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  144. {
  145. //Forward events to the tray winproc?
  146. return E_NOTIMPL;
  147. }
  148. STDMETHODIMP CStartMenuHost::IsWindowOwner(HWND hwnd)
  149. {
  150. return E_NOTIMPL;
  151. }
  152. CStartMenuHost::CStartMenuHost() : _cRef(1)
  153. {
  154. }
  155. HRESULT StartMenuHost_Create(IMenuPopup** ppmp, IMenuBand** ppmb)
  156. {
  157. HRESULT hres = E_OUTOFMEMORY;
  158. IMenuPopup * pmp = NULL;
  159. IMenuBand * pmb = NULL;
  160. CStartMenuHost *psmh = new CStartMenuHost();
  161. if (psmh)
  162. {
  163. hres = CoCreateInstance(CLSID_StartMenuBar, NULL, CLSCTX_INPROC_SERVER,
  164. IID_IMenuPopup, (LPVOID*)&pmp);
  165. if (SUCCEEDED(hres))
  166. {
  167. IObjectWithSite* pows;
  168. hres = pmp->QueryInterface(IID_IObjectWithSite, (void**)&pows);
  169. if(SUCCEEDED(hres))
  170. {
  171. IInitializeObject* pio;
  172. pows->SetSite(SAFECAST(psmh, ITrayPriv*));
  173. hres = pmp->QueryInterface(IID_IInitializeObject, (void**)&pio);
  174. if(SUCCEEDED(hres))
  175. {
  176. hres = pio->Initialize();
  177. pio->Release();
  178. }
  179. if (SUCCEEDED(hres))
  180. {
  181. IUnknown* punk;
  182. hres = pmp->GetClient(&punk);
  183. if (SUCCEEDED(hres))
  184. {
  185. IBandSite* pbs;
  186. hres = punk->QueryInterface(IID_IBandSite, (void**)&pbs);
  187. if(SUCCEEDED(hres))
  188. {
  189. DWORD dwBandID;
  190. pbs->EnumBands(0, &dwBandID);
  191. hres = pbs->GetBandObject(dwBandID, IID_IMenuBand, (void**)&pmb);
  192. pbs->Release();
  193. // Don't release pmb
  194. }
  195. punk->Release();
  196. }
  197. }
  198. if (FAILED(hres))
  199. pows->SetSite(NULL);
  200. pows->Release();
  201. }
  202. // Don't release pmp
  203. }
  204. psmh->Release();
  205. }
  206. if (FAILED(hres))
  207. {
  208. ATOMICRELEASE(pmp);
  209. ATOMICRELEASE(pmb);
  210. }
  211. *ppmp = pmp;
  212. *ppmb = pmb;
  213. return hres;
  214. }
  215. HRESULT IMenuPopup_SetIconSize(IMenuPopup* pmp,DWORD iIcon)
  216. {
  217. IBanneredBar* pbb;
  218. if (pmp == NULL)
  219. return E_FAIL;
  220. HRESULT hres = pmp->QueryInterface(IID_IBanneredBar,(void**)&pbb);
  221. if (SUCCEEDED(hres))
  222. {
  223. pbb->SetIconSize(iIcon);
  224. pbb->Release();
  225. }
  226. return hres;
  227. }
  228. void CreateInitialMFU(BOOL fReset);
  229. //
  230. // "Delayed per-user install".
  231. //
  232. // StartMenuInit is the value that tells us what version of the shell
  233. // this user has seen most recently.
  234. //
  235. // missing = has never run explorer before, or pre-IE4
  236. // 1 = IE4 or later
  237. // 2 = XP or later
  238. //
  239. void HandleFirstTime()
  240. {
  241. DWORD dwStartMenuInit = 0;
  242. DWORD cb = sizeof(dwStartMenuInit);
  243. SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_ADVANCED, TEXT("StartMenuInit"), NULL, &dwStartMenuInit, &cb);
  244. if (dwStartMenuInit < 2)
  245. {
  246. DWORD dwValue;
  247. switch (dwStartMenuInit)
  248. {
  249. case 0: // Upgrade from 0 to latest
  250. {
  251. // If this is the first boot of the shell for this user, then we need to see if it's an upgrade.
  252. // If it is, then we need set the Logoff option. PM Decision to have a different
  253. // look for upgraded machines...
  254. TCHAR szPath[MAX_PATH];
  255. TCHAR szPathExplorer[MAX_PATH];
  256. DWORD cbSize = ARRAYSIZE(szPath);
  257. DWORD dwType;
  258. // Is this an upgrade (Does WindowsUpdate\UpdateURL Exist?)
  259. PathCombine(szPathExplorer, REGSTR_PATH_EXPLORER, TEXT("WindowsUpdate"));
  260. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, szPathExplorer, TEXT("UpdateURL"),
  261. &dwType, szPath, &cbSize) &&
  262. szPath[0] != TEXT('\0'))
  263. {
  264. // Yes; Then write the option out to the registry.
  265. dwValue = 1;
  266. SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_ADVANCED, TEXT("StartMenuLogoff"), REG_DWORD, &dwValue, sizeof(DWORD));
  267. }
  268. }
  269. // FALL THROUGH
  270. case 1: // Upgrade from 1 to latest
  271. // User has never seen XP before.
  272. // PMs in certain groups insist on getting free advertising
  273. // even on upgrades, so we do it.
  274. CreateInitialMFU(dwStartMenuInit == 0);
  275. // FALL THROUGH
  276. default:
  277. break;
  278. }
  279. // If AuditInProgress is set; that means that we are in the
  280. // OEM sysprep stage and not running as an end user, in which
  281. // case don't set the flag saying "don't do this again" because
  282. // we do want to do this again when the retail end user logs
  283. // on for the first time.
  284. //
  285. // (We need to do all this work even in Audit mode so the OEM
  286. // gets a warm fuzzy feeling.)
  287. if (!SHRegGetBoolUSValue(TEXT("System\\Setup"), TEXT("AuditinProgress"), TRUE, FALSE))
  288. {
  289. // Mark this so that we know we've been launched once.
  290. dwValue = 2;
  291. SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_ADVANCED, TEXT("StartMenuInit"), REG_DWORD, &dwValue, sizeof(DWORD));
  292. }
  293. }
  294. }
  295. BOOL GetLogonUserName(LPTSTR pszUsername, DWORD* pcchUsername)
  296. {
  297. BOOL fSuccess = FALSE;
  298. HKEY hkeyExplorer = NULL;
  299. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER, 0, KEY_QUERY_VALUE, &hkeyExplorer))
  300. {
  301. DWORD dwType;
  302. DWORD dwSize = (*pcchUsername) * sizeof(TCHAR);
  303. if (ERROR_SUCCESS == RegQueryValueEx(hkeyExplorer, TEXT("Logon User Name"), 0, &dwType,
  304. (LPBYTE) pszUsername, &dwSize))
  305. {
  306. if ((REG_SZ == dwType) && (*pszUsername))
  307. {
  308. fSuccess = TRUE;
  309. }
  310. }
  311. RegCloseKey(hkeyExplorer);
  312. }
  313. // Fall back on GetUserName if the Logon User Name isn't set.
  314. if (!fSuccess)
  315. {
  316. fSuccess = GetUserName(pszUsername, pcchUsername);
  317. if (fSuccess)
  318. {
  319. CharUpperBuff(pszUsername, 1);
  320. }
  321. }
  322. return fSuccess;
  323. }
  324. BOOL IsNetConnectInstalled()
  325. {
  326. #ifdef WINNT
  327. return TRUE; // Always installed
  328. #else
  329. HKEY hkey = NULL;
  330. BOOL fInstalled = FALSE;
  331. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\")
  332. TEXT("CurrentVersion\\Setup\\OptionalComponents\\RNA"), 0, KEY_QUERY_VALUE, &hkey))
  333. {
  334. DWORD dwType;
  335. TCHAR sz[MAX_PATH];
  336. DWORD dwSize = ARRAYSIZE(sz);
  337. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("Installed"), 0, &dwType,
  338. (LPBYTE) &sz, &dwSize))
  339. {
  340. if (dwType == REG_SZ &&
  341. sz[0] == TEXT('1'))
  342. {
  343. fInstalled = TRUE;
  344. }
  345. }
  346. RegCloseKey(hkey);
  347. }
  348. return fInstalled;
  349. #endif
  350. }
  351. BOOL _ShowStartMenuLogoff()
  352. {
  353. // We want the Logoff menu on the start menu if:
  354. // These MUST both be true
  355. // 1) It's not restricted
  356. // 2) We have Logged On.
  357. // Any of these three.
  358. // 3) We've Upgraded from IE4
  359. // 4) The user has specified that it should be present
  360. // 5) It's been "Restricted" On.
  361. // Behavior also depends on whether we are a remote session or not (dsheldon):
  362. // Remote session: Logoff brings up shutdown dialog
  363. // Console session: Logoff directly does logoff
  364. DWORD dwRest = SHRestricted(REST_STARTMENULOGOFF);
  365. SHELLSTATE ss = {0};
  366. SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE); // if the new start menu is on, always show logoff
  367. BOOL fUserWantsLogoff = ss.fStartPanelOn || GetExplorerUserSetting(HKEY_CURRENT_USER, TEXT("Advanced"), TEXT("StartMenuLogoff")) > 0;
  368. BOOL fAdminWantsLogoff = (BOOL)(dwRest == 2) || SHRestricted(REST_FORCESTARTMENULOGOFF);
  369. BOOL fIsFriendlyUIActive = IsOS(OS_FRIENDLYLOGONUI);
  370. if ((dwRest != 1 && (GetSystemMetrics(SM_NETWORK) & RNC_LOGON) != 0) &&
  371. ( fUserWantsLogoff || fAdminWantsLogoff || fIsFriendlyUIActive))
  372. {
  373. return TRUE;
  374. }
  375. else
  376. {
  377. return FALSE;
  378. }
  379. }
  380. BOOL _ShowStartMenuEject()
  381. {
  382. if(SHRestricted(REST_NOSMEJECTPC)) //Is there a policy restriction?
  383. return FALSE;
  384. // CanShowEject Queries the user's permission to eject,
  385. // IsEjectAllowed queries the hardware.
  386. return SHTestTokenPrivilege(NULL, SE_UNDOCK_NAME) &&
  387. IsEjectAllowed(FALSE) &&
  388. !GetSystemMetrics(SM_REMOTESESSION);
  389. }
  390. BOOL _ShowStartMenuRun()
  391. {
  392. return !IsRestrictedOrUserSetting(HKEY_CURRENT_USER, REST_NORUN, TEXT("Advanced"), TEXT("StartMenuRun"), ROUS_KEYALLOWS | ROUS_DEFAULTALLOW);
  393. }
  394. BOOL _ShowStartMenuHelp()
  395. {
  396. return !IsRestrictedOrUserSetting(HKEY_CURRENT_USER, REST_NOSMHELP, TEXT("Advanced"), TEXT("NoStartMenuHelp"), ROUS_KEYRESTRICTS | ROUS_DEFAULTALLOW);
  397. }
  398. BOOL _ShowStartMenuShutdown()
  399. {
  400. return !SHRestricted(REST_NOCLOSE) &&
  401. !GetSystemMetrics(SM_REMOTESESSION) &&
  402. (!IsOS(OS_FRIENDLYLOGONUI) || SHTestTokenPrivilege(NULL, SE_SHUTDOWN_NAME));
  403. // if friendly logon is active, then don't show shutdown unless they have privileges, since shutdown "only" shuts you down.
  404. // if they're not using friendly logon ui, then shutdown also contains options to log you off/hibernate, so show it...
  405. }
  406. // If remote and not disabled by administrator then show "Disconnect".
  407. BOOL _ShowStartMenuDisconnect()
  408. {
  409. return GetSystemMetrics(SM_REMOTESESSION) && !SHRestricted(REST_NODISCONNECT);
  410. }
  411. BOOL _ShowStartMenuSearch()
  412. {
  413. return !SHRestricted(REST_NOFIND);
  414. }
  415. HMENU GetStaticStartMenu(BOOL fEdit)
  416. {
  417. #ifdef WINNT // hydra adds two more items
  418. #define CITEMSMISSING 4
  419. #else
  420. #define CITEMSMISSING 3
  421. #endif
  422. HMENU hStartMenu = LoadMenuPopup(MAKEINTRESOURCE(MENU_START));
  423. // If no editing requested, then we're done, lickity-split
  424. if (!fEdit)
  425. return hStartMenu;
  426. HMENU hmenu;
  427. UINT iSep2ItemsMissing = 0;
  428. //
  429. // Default to the Win95/NT4 version of the Settings menu.
  430. //
  431. // Restictions
  432. if (!_ShowStartMenuRun())
  433. {
  434. DeleteMenu(hStartMenu, IDM_FILERUN, MF_BYCOMMAND);
  435. }
  436. if (!_ShowStartMenuHelp())
  437. {
  438. DeleteMenu(hStartMenu, IDM_HELPSEARCH, MF_BYCOMMAND);
  439. }
  440. if (IsRestrictedOrUserSetting(HKEY_LOCAL_MACHINE, REST_NOCSC, TEXT("Advanced"), TEXT("StartMenuSyncAll"), ROUS_KEYALLOWS | ROUS_DEFAULTRESTRICT))
  441. {
  442. DeleteMenu(hStartMenu, IDM_CSC, MF_BYCOMMAND);
  443. iSep2ItemsMissing++;
  444. }
  445. BOOL fIsFriendlyUIActive = IsOS(OS_FRIENDLYLOGONUI);
  446. if (_ShowStartMenuLogoff())
  447. {
  448. UINT idMenuRenameToLogoff = IDM_LOGOFF;
  449. TCHAR szUserName[200];
  450. TCHAR szTemp[256];
  451. TCHAR szMenuText[256];
  452. DWORD dwSize = ARRAYSIZE(szUserName);
  453. MENUITEMINFO mii;
  454. mii.cbSize = sizeof(MENUITEMINFO);
  455. mii.dwTypeData = szTemp;
  456. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_STATE | MIIM_DATA;
  457. mii.cch = ARRAYSIZE(szTemp);
  458. mii.hSubMenu = NULL;
  459. mii.fType = MFT_SEPARATOR; // to avoid ramdom result.
  460. mii.dwItemData = 0;
  461. GetMenuItemInfo(hStartMenu,idMenuRenameToLogoff,MF_BYCOMMAND,&mii);
  462. if (GetLogonUserName(szUserName, &dwSize))
  463. {
  464. if (fIsFriendlyUIActive)
  465. {
  466. dwSize = ARRAYSIZE(szUserName);
  467. if (FAILED(SHGetUserDisplayName(szUserName, &dwSize)))
  468. {
  469. dwSize = ARRAYSIZE(szUserName);
  470. GetLogonUserName(szUserName, &dwSize);
  471. }
  472. }
  473. wsprintf (szMenuText,szTemp, szUserName);
  474. }
  475. else if (!LoadString(hinstCabinet, IDS_LOGOFFNOUSER,
  476. szMenuText, ARRAYSIZE(szMenuText)))
  477. {
  478. // mem error, use the current string.
  479. szUserName[0] = 0;
  480. wsprintf(szMenuText, szTemp, szUserName);
  481. }
  482. mii.dwTypeData = szMenuText;
  483. mii.cch = ARRAYSIZE(szMenuText);
  484. SetMenuItemInfo(hStartMenu,idMenuRenameToLogoff,MF_BYCOMMAND,&mii);
  485. }
  486. else
  487. {
  488. DeleteMenu(hStartMenu, IDM_LOGOFF, MF_BYCOMMAND);
  489. iSep2ItemsMissing++;
  490. }
  491. // If restricted, then user cannot shut down at all.
  492. // If friendly UI is active change "Shut Down..." to "Turn Off Computer..."
  493. if (!_ShowStartMenuShutdown())
  494. {
  495. DeleteMenu(hStartMenu, IDM_EXITWIN, MF_BYCOMMAND);
  496. iSep2ItemsMissing++;
  497. }
  498. else if (fIsFriendlyUIActive)
  499. {
  500. // If the user has the SE_SHUTDOWN_NAME privilege
  501. // then rename the menu item.
  502. if (SHTestTokenPrivilege(NULL, SE_SHUTDOWN_NAME) && !GetSystemMetrics(SM_REMOTESESSION))
  503. {
  504. MENUITEMINFO mii;
  505. TCHAR szMenuText[256];
  506. (int)LoadString(hinstCabinet, IDS_TURNOFFCOMPUTER, szMenuText, ARRAYSIZE(szMenuText));
  507. ZeroMemory(&mii, sizeof(mii));
  508. mii.cbSize = sizeof(mii);
  509. mii.fMask = MIIM_TYPE;
  510. mii.fType = MFT_STRING;
  511. mii.dwTypeData = szMenuText;
  512. mii.cch = ARRAYSIZE(szMenuText);
  513. TBOOL(SetMenuItemInfo(hStartMenu, IDM_EXITWIN, FALSE, &mii));
  514. }
  515. // Otherwise delete the menu item.
  516. else
  517. {
  518. DeleteMenu(hStartMenu, IDM_EXITWIN, MF_BYCOMMAND);
  519. iSep2ItemsMissing++;
  520. }
  521. }
  522. if (!_ShowStartMenuDisconnect())
  523. {
  524. DeleteMenu(hStartMenu, IDM_MU_DISCONNECT, MF_BYCOMMAND);
  525. iSep2ItemsMissing++;
  526. }
  527. if (iSep2ItemsMissing == CITEMSMISSING)
  528. {
  529. DeleteMenu(hStartMenu, IDM_SEP2, MF_BYCOMMAND);
  530. }
  531. if (!_ShowStartMenuEject())
  532. {
  533. DeleteMenu(hStartMenu, IDM_EJECTPC, MF_BYCOMMAND);
  534. }
  535. // Setting stuff.
  536. hmenu = SHGetMenuFromID(hStartMenu, IDM_SETTINGS);
  537. if (hmenu)
  538. {
  539. int iMissingSettings = 0;
  540. #ifdef WINNT // hydra menu items
  541. #define CITEMS_SETTINGS 5 // Number of items in settings menu
  542. #else
  543. #define CITEMS_SETTINGS 4 // Number of items in settings menu
  544. #endif
  545. if (SHRestricted(REST_NOSETTASKBAR))
  546. {
  547. DeleteMenu(hStartMenu, IDM_TRAYPROPERTIES, MF_BYCOMMAND);
  548. iMissingSettings++;
  549. }
  550. if (SHRestricted(REST_NOSETFOLDERS) || SHRestricted(REST_NOCONTROLPANEL))
  551. {
  552. DeleteMenu(hStartMenu, IDM_CONTROLS, MF_BYCOMMAND);
  553. // For the separator that now on top
  554. DeleteMenu(hmenu, 0, MF_BYPOSITION);
  555. iMissingSettings++;
  556. }
  557. if (SHRestricted(REST_NOSETFOLDERS))
  558. {
  559. DeleteMenu(hStartMenu, IDM_PRINTERS, MF_BYCOMMAND);
  560. iMissingSettings++;
  561. }
  562. if (SHRestricted(REST_NOSETFOLDERS) || SHRestricted(REST_NONETWORKCONNECTIONS) ||
  563. !IsNetConnectInstalled())
  564. {
  565. DeleteMenu(hStartMenu, IDM_NETCONNECT, MF_BYCOMMAND);
  566. iMissingSettings++;
  567. }
  568. #ifdef WINNT // hydra menu items
  569. if (!SHGetMachineInfo(GMI_TSCLIENT) || SHRestricted(REST_NOSECURITY))
  570. {
  571. DeleteMenu(hStartMenu, IDM_MU_SECURITY, MF_BYCOMMAND);
  572. iMissingSettings++;
  573. }
  574. #endif
  575. // Are all the items missing?
  576. if (iMissingSettings == CITEMS_SETTINGS)
  577. {
  578. // Yes; don't bother showing the menu at all
  579. DeleteMenu(hStartMenu, IDM_SETTINGS, MF_BYCOMMAND);
  580. }
  581. }
  582. else
  583. {
  584. DebugMsg(DM_ERROR, TEXT("c.fm_rui: Settings menu couldn't be found. Restricted items may not have been removed."));
  585. }
  586. // Find menu.
  587. if (!_ShowStartMenuSearch())
  588. {
  589. DeleteMenu(hStartMenu, IDM_MENU_FIND, MF_BYCOMMAND);
  590. }
  591. // Documents menu.
  592. if (SHRestricted(REST_NORECENTDOCSMENU))
  593. {
  594. DeleteMenu(hStartMenu, IDM_RECENT, MF_BYCOMMAND);
  595. }
  596. // Favorites menu.
  597. if (IsRestrictedOrUserSetting(HKEY_CURRENT_USER, REST_NOFAVORITESMENU, TEXT("Advanced"), TEXT("StartMenuFavorites"), ROUS_KEYALLOWS | ROUS_DEFAULTRESTRICT))
  598. {
  599. DeleteMenu(hStartMenu, IDM_FAVORITES, MF_BYCOMMAND);
  600. }
  601. return hStartMenu;
  602. }
  603. //
  604. // CHotKey class
  605. //
  606. // constructor
  607. CHotKey::CHotKey() : _cRef(1)
  608. {
  609. }
  610. STDMETHODIMP CHotKey::QueryInterface(REFIID riid, LPVOID * ppvObj)
  611. {
  612. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IShellHotKey))
  613. {
  614. *ppvObj = SAFECAST(this, IShellHotKey *);
  615. }
  616. else
  617. {
  618. *ppvObj = NULL;
  619. return E_NOINTERFACE;
  620. }
  621. AddRef();
  622. return NOERROR;
  623. }
  624. STDMETHODIMP_(ULONG) CHotKey::AddRef()
  625. {
  626. return ++_cRef;
  627. }
  628. STDMETHODIMP_(ULONG) CHotKey::Release()
  629. {
  630. ASSERT(_cRef > 0);
  631. _cRef--;
  632. if( _cRef > 0)
  633. return _cRef;
  634. delete this;
  635. return 0;
  636. }
  637. HRESULT Tray_RegisterHotKey(WORD wHotkey, LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidl)
  638. {
  639. if (wHotkey)
  640. {
  641. int i = c_tray.HotkeyAdd(wHotkey, (LPITEMIDLIST)pidlParent, (LPITEMIDLIST)pidl, TRUE);
  642. if (i != -1)
  643. {
  644. // Register in the context of the tray's thread.
  645. PostMessage(v_hwndTray, WMTRAY_REGISTERHOTKEY, i, 0);
  646. }
  647. }
  648. return S_OK;
  649. }
  650. /*----------------------------------------------------------
  651. Purpose: IShellHotKey::RegisterHotKey method
  652. */
  653. STDMETHODIMP CHotKey::RegisterHotKey(IShellFolder * psf, LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidl)
  654. {
  655. WORD wHotkey;
  656. HRESULT hr = S_OK;
  657. wHotkey = _GetHotkeyFromFolderItem(psf, pidl);
  658. if (wHotkey)
  659. {
  660. hr = ::Tray_RegisterHotKey(wHotkey, pidlParent, pidl);
  661. }
  662. return hr;
  663. }
  664. STDAPI CHotKey_Create(IShellHotKey ** ppshk)
  665. {
  666. HRESULT hres = E_OUTOFMEMORY;
  667. CHotKey * photkey = new CHotKey;
  668. if (photkey)
  669. {
  670. hres = S_OK;
  671. }
  672. *ppshk = SAFECAST(photkey, IShellHotKey *);
  673. return hres;
  674. }