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.

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