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.

2703 lines
86 KiB

  1. //---------------------------------------------------------------------------
  2. // This file contains Taskbar and Start Menu property sheet code
  3. //---------------------------------------------------------------------------
  4. #include "cabinet.h"
  5. #include "rcids.h"
  6. #include "util.h"
  7. #include <help.h> // help ids
  8. #include <regstr.h>
  9. #include <atlstuff.h>
  10. #include "dlg.h"
  11. #include "tray.h"
  12. #include "traycmn.h"
  13. #include "startmnu.h"
  14. #include "desktop2.h"
  15. #include "uemapp.h"
  16. #define GROUPID_CURRENTITEMS 5
  17. #define GROUPID_PASTITEMS 6
  18. #define MAX_PROGS_ALLOWED 30
  19. const static DWORD aInitStartMenuHelpIDs[] = {
  20. IDC_NO_HELP_1, NO_HELP,
  21. IDC_NO_HELP_2, NO_HELP,
  22. IDC_NO_HELP_3, NO_HELP,
  23. IDC_NO_HELP_4, NO_HELP,
  24. IDC_GROUPBOX, IDH_COMM_GROUPBOX,
  25. IDC_GROUPBOX_2, IDH_MENUCONFIG_CLEAR,
  26. IDC_GROUPBOX_3, IDH_COMM_GROUPBOX,
  27. IDC_ADDSHORTCUT, IDH_TRAY_ADD_PROGRAM,
  28. IDC_DELSHORTCUT, IDH_TRAY_REMOVE_PROGRAM,
  29. IDC_EXPLOREMENUS, IDH_TRAY_ADVANCED,
  30. IDC_KILLDOCUMENTS, IDH_MENUCONFIG_CLEAR,
  31. IDC_RESORT, IDH_TRAY_RESORT_BUTTON,
  32. IDC_STARTMENUSETTINGSTEXT, IDH_TRAY_START_MENU_SETTINGS,
  33. 0, 0
  34. };
  35. const static DWORD aTaskOptionsHelpIDs[] = { // Context Help IDs
  36. IDC_TASKBARAPPEARANCE,IDH_TASKBAR_OPTIONS_BITMAP,
  37. IDC_NOTIFYAPPEARANCE, IDH_TASKBAR_OPTIONS_BITMAP,
  38. IDC_TRAYOPTAUTOHIDE, IDH_TRAY_TASKBAR_AUTOHIDE,
  39. IDC_TRAYOPTSHOWCLOCK, IDH_TRAY_SHOW_CLOCK,
  40. IDC_TRAYOPTONTOP, IDH_TRAY_TASKBAR_ONTOP,
  41. IDC_LOCKTASKBAR, IDH_TRAY_ENABLEMOVERESIZE,
  42. IDC_GROUPITEMS, IDH_TRAY_GROUPING,
  43. IDC_NOTIFYMAN, IDH_TRAY_HIDE_ICONS,
  44. IDC_CUSTOMIZE, IDH_TRAY_CUSTOMIZE_ICONS,
  45. IDC_QUICKLAUNCH, IDH_TRAY_QUICKLAUNCH,
  46. 0, 0
  47. };
  48. const static DWORD aNotifyOptionsHelpIDs[] = { // Context Help IDs
  49. IDC_NOTIFY_TEXT, NO_HELP,
  50. IDC_NOTIFY_TEXT2, NO_HELP,
  51. IDC_COMBO_ACTION, NO_HELP,
  52. IDC_NOTIFY_ITEMS, NO_HELP,
  53. IDB_NOTIFY_RESTOREDEFAULTS, IDH_TRAY_RESTOREDEFBUTTON,
  54. 0, 0
  55. };
  56. const static DWORD aStartTabHelpIDs[] = {
  57. IDC_STARTMENUPREVIEW, IDH_START_PREVIEW,
  58. IDC_NEWSCHOOL, IDH_START_SELECTPERSONAL,
  59. IDC_OLDSCHOOL, IDH_START_SELECTCLASSIC,
  60. IDC_NEWSTARTCUSTOMIZE, IDH_START_CUSTOMIZEPERSONAL,
  61. IDC_OLDSTARTCUSTOMIZE, IDH_START_CUSTOMIZECLASSIC,
  62. 0, 0
  63. };
  64. const static DWORD aStartCustGeneralTabHelpIDs[] = {
  65. IDC_SPCUST_ICONLARGE, IDH_START_SPCUST_LARGE,
  66. IDC_SPCUST_ICONSMALL, IDH_START_SPCUST_SMALL,
  67. IDC_SPCUST_LARGE, IDH_START_SPCUST_LARGE,
  68. IDC_SPCUST_SMALL, IDH_START_SPCUST_SMALL,
  69. IDC_SPCUST_MINPROGS, IDH_START_SPCUST_MINPROGS,
  70. IDC_SPCUST_MINPROGS_ARROW, IDH_START_SPCUST_MINPROGS,
  71. IDB_SPCUST_CLEARPROG, IDH_START_SPCUST_CLEARPROG,
  72. IDC_SPCUST_INTERNET, IDH_START_SPCUST_INTERNET,
  73. IDC_SPCUST_INTERNETCB, IDH_START_SPCUST_INTERNETCB,
  74. IDC_SPCUST_EMAIL, IDH_START_SPCUST_EMAIL,
  75. IDC_SPCUST_EMAILCB, IDH_START_SPCUST_EMAILCB,
  76. 0, 0
  77. };
  78. const static DWORD aStartCustAdvancedTabHelpIDs[] = {
  79. IDC_SPCUST_HOVEROPEN, IDH_START_SPCUST_HOVEROPEN,
  80. IDC_SPCUST_NOTIFYNEW, IDH_START_SPCUST_NOTIFYNEW,
  81. IDC_STARTMENUSETTINGS, IDH_START_STARTMENUSETTINGS,
  82. IDC_SPCUST_RECENT_GROUPBOX, NO_HELP,
  83. IDC_SPCUST_RECENT_TEXT, NO_HELP,
  84. IDC_SPCUST_RECENT, IDH_START_SPCUST_RECENT,
  85. IDB_SPCUST_CLEARDOCS, IDH_START_SPCUST_CLEARDOCS,
  86. 0, 0
  87. };
  88. #define REGSTR_VAL_LARGEICONSTEMP TEXT("Start_LargeIcons")
  89. #define REGSTR_VAL_ADMINTOOLSTEMP TEXT("Start_AdminToolsTemp")
  90. void SetDlgItemBitmap(HWND hDlg, int idStatic, int iResource);
  91. void SetDlgItemIcon(HWND hDlg, int idStatic, HICON hi);
  92. void SetProgramIcon(HWND hDlg, int idLarge, int idSmall);
  93. void _TaskbarOptionsUpdateDisplay(HWND hDlg);
  94. void _TaskbarOptionsSizeControls(HWND hDlg);
  95. void _TaskbarOptionsDestroyBitmaps(HWND hDlg);
  96. BOOL_PTR WINAPI AdvancedOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  97. typedef struct
  98. {
  99. HWND hwndTree;
  100. IRegTreeOptions *pTO;
  101. } SMADVANCED;
  102. void SendPSMChanged(HWND hDlg)
  103. {
  104. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  105. }
  106. class CPinHelper
  107. {
  108. public:
  109. CPinHelper();
  110. ~CPinHelper();
  111. void Save(BOOL bShowEmail, BOOL bShowBrowser);
  112. void GetPinInfo(BOOL *pbPinBrowser, BOOL *pbPinEmail);
  113. private:
  114. void SavePinInfo(LPCITEMIDLIST pidlVictim, BOOL bOld, BOOL bNew);
  115. LPITEMIDLIST _pidlBrowser;
  116. LPITEMIDLIST _pidlEmail;
  117. IStartMenuPin *_psmp;
  118. };
  119. CPinHelper::CPinHelper()
  120. {
  121. _pidlBrowser = ILCreateFromPath(TEXT("shell:::{2559a1f4-21d7-11d4-bdaf-00c04f60b9f0}"));
  122. _pidlEmail = ILCreateFromPath(TEXT("shell:::{2559a1f5-21d7-11d4-bdaf-00c04f60b9f0}"));
  123. CoCreateInstance(CLSID_StartMenuPin, NULL, CLSCTX_INPROC_SERVER,
  124. IID_PPV_ARG(IStartMenuPin, &_psmp));
  125. }
  126. CPinHelper::~CPinHelper()
  127. {
  128. ILFree(_pidlBrowser);
  129. ILFree(_pidlEmail);
  130. ATOMICRELEASE(_psmp);
  131. }
  132. void CPinHelper::GetPinInfo(BOOL *pbPinBrowser, BOOL *pbPinEmail)
  133. {
  134. *pbPinBrowser = FALSE;
  135. *pbPinEmail = FALSE;
  136. if (_psmp)
  137. {
  138. IEnumIDList *peidl;
  139. if (SUCCEEDED(_psmp->EnumObjects(&peidl)))
  140. {
  141. LPITEMIDLIST pidl;
  142. while (peidl->Next(1, &pidl, NULL) == S_OK)
  143. {
  144. if (ILIsEqual(pidl, _pidlBrowser)) *pbPinBrowser = TRUE;
  145. if (ILIsEqual(pidl, _pidlEmail)) *pbPinEmail = TRUE;
  146. ILFree(pidl);
  147. }
  148. peidl->Release();
  149. }
  150. }
  151. }
  152. void CPinHelper::SavePinInfo(LPCITEMIDLIST pidlVictim, BOOL bOld, BOOL bNew)
  153. {
  154. ASSERT(bOld == TRUE || bOld == FALSE);
  155. ASSERT(bNew == TRUE || bNew == FALSE);
  156. if (pidlVictim && _psmp && bOld != bNew)
  157. {
  158. if (bNew)
  159. {
  160. _psmp->Modify(NULL, pidlVictim);
  161. _psmp->Modify(pidlVictim, SMPIN_POS(0));
  162. }
  163. else
  164. {
  165. _psmp->Modify(pidlVictim, NULL);
  166. }
  167. }
  168. }
  169. void CPinHelper::Save(BOOL bShowEmail, BOOL bShowBrowser)
  170. {
  171. // Get old settings
  172. BOOL bShowBrowserOld, bShowEmailOld;
  173. GetPinInfo(&bShowBrowserOld, &bShowEmailOld);
  174. //
  175. // Do in reverse order because we insert at the top of the list.
  176. //
  177. SavePinInfo(_pidlEmail, bShowEmailOld, bShowEmail);
  178. SavePinInfo(_pidlBrowser, bShowBrowserOld, bShowBrowser);
  179. }
  180. class ATL_NO_VTABLE CNotificationsDlg :
  181. public CComObjectRootEx<CComSingleThreadModel>,
  182. public CDialogImpl<CNotificationsDlg>,
  183. public INotificationCB
  184. {
  185. public:
  186. CNotificationsDlg()
  187. {
  188. _pTrayNotify = NULL;
  189. _fItemChanged = FALSE;
  190. _hPlaceholderIcon = NULL;
  191. _nIndex = -1;
  192. _fComboBoxActive = FALSE;
  193. };
  194. virtual ~CNotificationsDlg()
  195. {
  196. if (_pTrayNotify)
  197. {
  198. _pTrayNotify->Release();
  199. _pTrayNotify = NULL;
  200. }
  201. };
  202. DECLARE_NOT_AGGREGATABLE(CNotificationsDlg)
  203. BEGIN_COM_MAP(CNotificationsDlg)
  204. COM_INTERFACE_ENTRY(INotificationCB)
  205. END_COM_MAP()
  206. enum {IDD = DLG_NOTIFY};
  207. BEGIN_MSG_MAP_EX(CNotificationsDlg)
  208. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  209. MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
  210. MESSAGE_HANDLER(WM_HELP, OnHelp)
  211. NOTIFY_HANDLER_EX(IDC_NOTIFY_ITEMS, LVN_ITEMCHANGED, OnItemChanged)
  212. NOTIFY_HANDLER_EX(IDC_NOTIFY_ITEMS, LVN_ENDSCROLL, OnEndScroll)
  213. NOTIFY_CODE_HANDLER(HDN_ITEMCHANGED, OnHeaderItemChanged)
  214. COMMAND_HANDLER_EX(IDC_COMBO_ACTION, CBN_SELENDOK, OnComboSelEnd)
  215. COMMAND_ID_HANDLER_EX(IDB_NOTIFY_RESTOREDEFAULTS, OnRestoreDefaults)
  216. COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd)
  217. END_MSG_MAP()
  218. //*** INotificationCB ***
  219. STDMETHODIMP Notify(DWORD dwMessage, LPNOTIFYITEM pNotifyItem);
  220. //*** Message Callbacks ***
  221. LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  222. LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  223. LRESULT OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  224. LRESULT OnItemChanged(LPNMHDR pnmh);
  225. LRESULT OnEndScroll(LPNMHDR pnmh);
  226. LRESULT OnHeaderItemChanged(WPARAM wParam, LPNMHDR pnmh, LPARAM lParam);
  227. LRESULT OnComboSelEnd(UINT uMsg, UINT uID , HWND hwnd);
  228. LRESULT OnRestoreDefaults(UINT uMsg, UINT uID , HWND hwnd);
  229. LRESULT OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  230. static LRESULT CALLBACK s_ListViewSubClassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  231. LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  232. static LRESULT CALLBACK s_ComboBoxSubClassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  233. LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  234. //*** Other ***
  235. void ApplyChanges(void);
  236. private:
  237. HRESULT _AddItem(CNotificationItem& ni, int iIndex);
  238. void _ShowComboBox();
  239. int _GetCurSel();
  240. void _LoadAndSetLVItemText(UINT uResourceID, DWORD nRow, DWORD nCol);
  241. CSimpleArray<CNotificationItem> _saItems; //copy of the data, initialized by user
  242. BOOL _fItemChanged;
  243. ITrayNotify* _pTrayNotify;
  244. int _nPrevIndex;
  245. HWND _hwndCombo;
  246. HWND _hwndListView;
  247. RECT _rcOldPos;
  248. HICON _hPlaceholderIcon;
  249. BOOL _fComboBoxActive;
  250. int _nIndex;
  251. };
  252. HRESULT CNotificationsDlg::_AddItem(CNotificationItem& ni, int iIndex)
  253. {
  254. HIMAGELIST himl = ListView_GetImageList(_hwndListView, LVSIL_SMALL);
  255. BOOL fInsert = FALSE;
  256. LV_ITEM lvitem = {0};
  257. int iImage = -1;
  258. if (!ni.hIcon)
  259. {
  260. if (!_hPlaceholderIcon)
  261. {
  262. _hPlaceholderIcon = (HICON)LoadImage(hinstCabinet,
  263. MAKEINTRESOURCE(ICO_TRAYPROP_PLACEHOLDER), IMAGE_ICON,
  264. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  265. LR_LOADMAP3DCOLORS);
  266. }
  267. if (_hPlaceholderIcon)
  268. ni.hIcon = CopyIcon(_hPlaceholderIcon);
  269. }
  270. if (iIndex == -1)
  271. {
  272. iIndex = _saItems.GetSize();
  273. iImage = ImageList_AddIcon(himl, ni.hIcon);
  274. fInsert = TRUE;
  275. }
  276. else
  277. {
  278. lvitem.mask = LVIF_IMAGE;
  279. lvitem.iItem = iIndex;
  280. lvitem.iSubItem = 0;
  281. ListView_GetItem(_hwndListView, &lvitem);
  282. ImageList_ReplaceIcon(himl, lvitem.iImage, ni.hIcon);
  283. iImage = lvitem.iImage;
  284. fInsert = FALSE;
  285. }
  286. if (!ni.pszIconText || ni.pszIconText[0] == 0)
  287. {
  288. TCHAR szTemp[MAX_PATH];
  289. if (LoadString(hinstCabinet, IDS_NOTITLE, szTemp, ARRAYSIZE(szTemp)))
  290. ni.SetIconText(szTemp);
  291. // ni.m_strText.LoadString(IDS_NOTITLE);
  292. }
  293. else
  294. // Replace '\n' with ' '
  295. {
  296. LPTSTR pszTemp = NULL;
  297. while (NULL != (pszTemp = StrChr(ni.pszIconText, TEXT('\n'))))
  298. {
  299. *pszTemp = TEXT(' ');
  300. }
  301. }
  302. lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_GROUPID;
  303. lvitem.iItem = iIndex;
  304. lvitem.iSubItem = 0;
  305. lvitem.pszText = ni.pszIconText;
  306. lvitem.iImage = iImage;
  307. lvitem.iGroupId = (ni.hWnd == NULL) ? GROUPID_PASTITEMS : GROUPID_CURRENTITEMS;
  308. if (fInsert)
  309. ListView_InsertItem(_hwndListView, &lvitem);
  310. else
  311. ListView_SetItem(_hwndListView, &lvitem);
  312. lvitem.mask = LVIF_TEXT;
  313. lvitem.iItem = iIndex;
  314. lvitem.iSubItem = 1;
  315. CString str;
  316. str.LoadString(IDS_NOTIFY_FIRST + ni.dwUserPref);
  317. lvitem.pszText = (LPTSTR)(LPCTSTR)str;
  318. ListView_SetItem(_hwndListView, &lvitem);
  319. if (fInsert)
  320. {
  321. _saItems.Add(ni);
  322. }
  323. else
  324. {
  325. _saItems[iIndex] = ni;
  326. }
  327. return S_OK;
  328. }
  329. HRESULT CNotificationsDlg::Notify(DWORD dwMessage, NOTIFYITEM * pNotifyItem)
  330. {
  331. if (!pNotifyItem || (!pNotifyItem->hWnd && !pNotifyItem->pszExeName))
  332. return E_INVALIDARG;
  333. ASSERT(pNotifyItem);
  334. CNotificationItem ni = *pNotifyItem;
  335. switch (dwMessage)
  336. {
  337. case NIM_ADD:
  338. case NIM_MODIFY:
  339. {
  340. // We never need to modify a Past Item
  341. for (int i = 0; (i < _saItems.GetSize() && ni.hWnd); i++)
  342. {
  343. // If the Item is already in the list just update it
  344. if (_saItems[i] == ni)
  345. {
  346. return _AddItem(ni, i);
  347. }
  348. }
  349. // If it is not in the list add it
  350. return _AddItem(ni, -1);
  351. }
  352. break;
  353. case NIM_DELETE:
  354. {
  355. for (int i = 0; (i < _saItems.GetSize()); i++)
  356. {
  357. if (_saItems[i] == ni)
  358. {
  359. _saItems.RemoveAt(i);
  360. ListView_DeleteItem(_hwndListView, i);
  361. _ShowComboBox();
  362. return S_OK;
  363. }
  364. }
  365. break;
  366. }
  367. }
  368. return E_INVALIDARG;
  369. }
  370. LRESULT CNotificationsDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  371. {
  372. _hwndListView = GetDlgItem(IDC_NOTIFY_ITEMS);
  373. _nPrevIndex = -2;
  374. _rcOldPos.top = -500;
  375. CImageList il;
  376. int iSize = GetSystemMetrics(SM_CXSMICON);
  377. // found in security review -- not a security problem, but this doesnt do jack (?)
  378. // ::Create allocates a new CImageList, should this call initialize()?
  379. il.Create(iSize, iSize, SHGetImageListFlags(_hwndListView), _saItems.GetSize(), 4);
  380. if (il)
  381. {
  382. CString str;
  383. //list view control holding all the items
  384. ListView_SetExtendedListViewStyle(_hwndListView, LVS_EX_FULLROWSELECT);
  385. ListView_EnableGroupView(_hwndListView, TRUE);
  386. static const struct {
  387. int ids;
  388. int idGroup;
  389. } groupData[] = {{ IDS_NOTIFY_CURRENTITEMS, GROUPID_CURRENTITEMS },
  390. { IDS_NOTIFY_PASTITEMS, GROUPID_PASTITEMS }};
  391. for (int i = 0; i < ARRAYSIZE(groupData); i++)
  392. {
  393. str.LoadString(groupData[i].ids);
  394. LVGROUP lvgrp = { sizeof(LVGROUP) };
  395. lvgrp.mask = LVGF_HEADER | LVGF_GROUPID;
  396. lvgrp.pszHeader = (LPTSTR)(LPCTSTR)str;
  397. lvgrp.cchHeader = lstrlen(lvgrp.pszHeader);
  398. lvgrp.iGroupId = groupData[i].idGroup;
  399. SendMessage(_hwndListView, LVM_INSERTGROUP, -1, (LPARAM)&lvgrp);
  400. }
  401. //Split width of columns 3/5, 2/5
  402. RECT rc;
  403. ::GetClientRect(_hwndListView, &rc);
  404. int width = rc.right - rc.left - GetSystemMetrics(SM_CXHSCROLL);
  405. int width0 = 3*width/5;
  406. int width1 = width-width0;
  407. LV_COLUMN lvcol = {0};
  408. lvcol.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
  409. str.LoadString(IDS_NOTIFYNAME);
  410. lvcol.pszText = (LPTSTR)(LPCTSTR)str;
  411. lvcol.cx = width0;
  412. lvcol.iSubItem = 0;
  413. ListView_InsertColumn(_hwndListView, 0, &lvcol);
  414. str.LoadString(IDS_BEHAVIOR);
  415. lvcol.pszText = (LPTSTR)(LPCTSTR)str;
  416. lvcol.cx = width1;
  417. lvcol.iSubItem = 1;
  418. ListView_InsertColumn(_hwndListView, 1, &lvcol);
  419. il.SetBkColor(GetSysColor(COLOR_WINDOW));
  420. ListView_SetImageList(_hwndListView, il, LVSIL_SMALL);
  421. il.Detach();
  422. _hwndCombo = GetDlgItem(IDC_COMBO_ACTION);
  423. // make sure combo box uses same font as list view
  424. ::SendMessage(_hwndCombo, WM_SETFONT, (WPARAM)::SendMessage(_hwndListView, WM_GETFONT, 0, 0), MAKELPARAM(TRUE, 0));
  425. for (int i = IDS_NOTIFY_FIRST; i < IDS_NOTIFY_LAST; i++)
  426. {
  427. CString strTemp;
  428. strTemp.LoadString(i);
  429. ComboBox_AddString(_hwndCombo, strTemp);
  430. }
  431. ::SetParent(_hwndCombo, _hwndListView);
  432. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  433. ::SetWindowPos(_hwndCombo, hwndHeader, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW);
  434. ::SetWindowSubclass(_hwndListView, s_ListViewSubClassWndProc, 0,
  435. reinterpret_cast<DWORD_PTR>(this));
  436. ::SetWindowSubclass(_hwndCombo, s_ComboBoxSubClassWndProc, 0,
  437. reinterpret_cast<DWORD_PTR>(this));
  438. }
  439. _saItems.RemoveAll();
  440. if (_pTrayNotify)
  441. {
  442. _pTrayNotify->Release();
  443. _pTrayNotify = NULL;
  444. }
  445. // localserver for tray notify
  446. if (SUCCEEDED(CoCreateInstance(CLSID_TrayNotify, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(ITrayNotify, &_pTrayNotify))))
  447. {
  448. INotificationCB* pCB;
  449. if (SUCCEEDED(QueryInterface(IID_PPV_ARG(INotificationCB, &pCB))))
  450. {
  451. _pTrayNotify->RegisterCallback(pCB);
  452. pCB->Release();
  453. }
  454. }
  455. // Set the selected and focused state to the first item
  456. // ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  457. bHandled = TRUE;
  458. return 0;
  459. }
  460. LRESULT CNotificationsDlg::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  461. {
  462. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aNotifyOptionsHelpIDs);
  463. bHandled = TRUE;
  464. return 0;
  465. }
  466. LRESULT CNotificationsDlg::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  467. {
  468. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aNotifyOptionsHelpIDs);
  469. bHandled = TRUE;
  470. return 0;
  471. }
  472. LRESULT CNotificationsDlg::OnItemChanged(LPNMHDR pnmh)
  473. {
  474. _ShowComboBox();
  475. return 0;
  476. }
  477. LRESULT CNotificationsDlg::OnEndScroll(LPNMHDR pnmh)
  478. {
  479. _ShowComboBox();
  480. return 0;
  481. }
  482. LRESULT CNotificationsDlg::OnHeaderItemChanged(WPARAM wParam, LPNMHDR pnmh, LPARAM lParam)
  483. {
  484. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  485. if (pnmh->hwndFrom == hwndHeader)
  486. {
  487. _ShowComboBox();
  488. }
  489. return 0;
  490. }
  491. int CNotificationsDlg::_GetCurSel()
  492. {
  493. return (int)::SendMessage(_hwndListView, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
  494. }
  495. void CNotificationsDlg::_LoadAndSetLVItemText(UINT uResourceID, DWORD nRow, DWORD nCol)
  496. {
  497. CString str;
  498. str.LoadString(uResourceID);
  499. ListView_SetItemText(_hwndListView, nRow, nCol, (LPTSTR)(LPCTSTR)str);
  500. }
  501. LRESULT CNotificationsDlg::OnComboSelEnd(UINT uMsg, UINT uID ,HWND hwnd)
  502. {
  503. int nCurIndex = _fComboBoxActive ? _nIndex : _GetCurSel();
  504. if (nCurIndex != -1)
  505. {
  506. DWORD dwUserPref = ComboBox_GetCurSel(_hwndCombo);
  507. if (dwUserPref != _saItems[nCurIndex].dwUserPref)
  508. {
  509. _fItemChanged = TRUE;
  510. _saItems[nCurIndex].dwUserPref = dwUserPref;
  511. _LoadAndSetLVItemText(IDS_NOTIFY_FIRST + dwUserPref, nCurIndex, 1);
  512. }
  513. }
  514. return 0;
  515. }
  516. LRESULT CNotificationsDlg::OnRestoreDefaults(UINT uMsg, UINT uID , HWND hwnd)
  517. {
  518. for (int i=0;i<_saItems.GetSize();i++)
  519. {
  520. if (_saItems[i].dwUserPref != TNUP_AUTOMATIC)
  521. {
  522. _fItemChanged = TRUE;
  523. _saItems[i].dwUserPref = TNUP_AUTOMATIC;
  524. _LoadAndSetLVItemText(IDS_AUTOMATIC, i, 1);
  525. }
  526. }
  527. return 0;
  528. }
  529. LRESULT CNotificationsDlg::OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  530. {
  531. if (wID == IDOK)
  532. {
  533. ApplyChanges();
  534. }
  535. if (_hPlaceholderIcon)
  536. {
  537. DestroyIcon(_hPlaceholderIcon);
  538. _hPlaceholderIcon = NULL;
  539. }
  540. _saItems.RemoveAll();
  541. if (_hwndListView)
  542. {
  543. RemoveWindowSubclass(_hwndListView, s_ListViewSubClassWndProc, 0);
  544. }
  545. if (_hwndCombo)
  546. {
  547. RemoveWindowSubclass(_hwndCombo, s_ComboBoxSubClassWndProc, 0);
  548. }
  549. if (_pTrayNotify)
  550. {
  551. _pTrayNotify->RegisterCallback(NULL);
  552. }
  553. bHandled = TRUE;
  554. ::EndDialog(m_hWnd, wID);
  555. return 0;
  556. }
  557. LRESULT CALLBACK CNotificationsDlg::s_ListViewSubClassWndProc( HWND hwnd, UINT uMsg,
  558. WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
  559. {
  560. CNotificationsDlg * pNotificationsDlg = reinterpret_cast<CNotificationsDlg*>(dwRefData);
  561. AssertMsg((pNotificationsDlg != NULL), TEXT("pNotificationsDlg SHOULD NOT be NULL."));
  562. switch (uMsg)
  563. {
  564. case WM_KEYDOWN:
  565. {
  566. if (wParam == VK_RIGHT && !pNotificationsDlg->_fComboBoxActive)
  567. {
  568. int nIndex = pNotificationsDlg->_GetCurSel();
  569. if (nIndex != -1)
  570. {
  571. pNotificationsDlg->_nIndex = nIndex;
  572. pNotificationsDlg->_fComboBoxActive = TRUE;
  573. ::SetFocus(pNotificationsDlg->_hwndCombo);
  574. }
  575. return 0;
  576. }
  577. }
  578. break;
  579. }
  580. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  581. }
  582. LRESULT CALLBACK CNotificationsDlg::s_ComboBoxSubClassWndProc( HWND hwnd, UINT uMsg,
  583. WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
  584. {
  585. CNotificationsDlg * pNotificationsDlg = reinterpret_cast<CNotificationsDlg*>(dwRefData);
  586. AssertMsg((pNotificationsDlg != NULL), TEXT("pNotificationsDlg SHOULD NOT be NULL."));
  587. switch (uMsg)
  588. {
  589. case WM_KEYDOWN:
  590. {
  591. if (pNotificationsDlg->_fComboBoxActive)
  592. {
  593. if (wParam == VK_LEFT)
  594. {
  595. pNotificationsDlg->_fComboBoxActive = FALSE;
  596. pNotificationsDlg->_nIndex = 0;
  597. ::SetFocus(pNotificationsDlg->_hwndListView);
  598. return 0;
  599. }
  600. else if (wParam == VK_RIGHT)
  601. {
  602. // Disable selection in combo on right button
  603. return 0;
  604. }
  605. }
  606. }
  607. break;
  608. case WM_KILLFOCUS:
  609. {
  610. if (pNotificationsDlg->_fComboBoxActive)
  611. {
  612. pNotificationsDlg->_fComboBoxActive = FALSE;
  613. pNotificationsDlg->_nIndex = 0;
  614. }
  615. }
  616. break;
  617. }
  618. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  619. }
  620. void CNotificationsDlg::ApplyChanges(void)
  621. {
  622. if (!_fItemChanged)
  623. return;
  624. if (_pTrayNotify)
  625. {
  626. for (int i = 0; i < _saItems.GetSize(); i++)
  627. {
  628. _pTrayNotify->SetPreference(&_saItems[i]);
  629. }
  630. }
  631. }
  632. void CNotificationsDlg::_ShowComboBox(void)
  633. {
  634. int nCurIndex = _GetCurSel();
  635. if (!_fComboBoxActive && nCurIndex == -1)
  636. {
  637. ::ShowWindow(_hwndCombo, SW_HIDE);
  638. }
  639. else if (nCurIndex != -1)
  640. {
  641. RECT rcListView;
  642. ::GetClientRect(_hwndListView, &rcListView);
  643. RECT rc;
  644. ListView_GetItemRect(_hwndListView, nCurIndex, &rc, LVIR_BOUNDS);
  645. RECT rcHeader;
  646. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  647. Header_GetItemRect(hwndHeader, 1, &rcHeader);
  648. rc.left = rcHeader.left;
  649. rc.right = rcHeader.right;
  650. if (!EqualRect(&_rcOldPos, &rc))
  651. {
  652. _rcOldPos = rc;
  653. ::MoveWindow(_hwndCombo, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
  654. }
  655. if (!::IsWindowVisible(_hwndCombo))
  656. {
  657. ::ShowWindow(_hwndCombo, SW_SHOW);
  658. ComboBox_SetCurSel(_hwndCombo, _saItems[nCurIndex].dwUserPref);
  659. }
  660. }
  661. }
  662. //This is the property sheet for all of the task bar stuff
  663. class CTaskBarPropertySheet : public CPropertySheetImpl<CTaskBarPropertySheet>
  664. {
  665. public:
  666. CTaskBarPropertySheet(UINT nStartPage, HWND hwndParent, DWORD dwFlags) :
  667. CPropertySheetImpl<CTaskBarPropertySheet>((LPCTSTR)NULL, nStartPage, hwndParent),
  668. _dwFlags(dwFlags)
  669. {
  670. LoadString(hinstCabinet, IDS_STARTMENUANDTASKBAR, szPath, ARRAYSIZE(szPath));
  671. SetTitle(szPath);
  672. HPROPSHEETPAGE hpage;
  673. PROPSHEETPAGE psp;
  674. psp.dwSize = sizeof(psp);
  675. psp.dwFlags = PSP_DEFAULT;
  676. psp.hInstance = hinstCabinet;
  677. //taskbar page
  678. psp.pszTemplate = MAKEINTRESOURCE(DLG_TRAY_OPTIONS);
  679. psp.pfnDlgProc = s_TaskbarOptionsDlgProc;
  680. psp.lParam = (LPARAM) this;
  681. hpage = CreatePropertySheetPage(&psp);
  682. if (hpage)
  683. AddPage(hpage);
  684. //start page
  685. psp.pszTemplate = MAKEINTRESOURCE(DLG_START);
  686. psp.pfnDlgProc = s_StartMenuDlgProc;
  687. psp.lParam = (LPARAM) this;
  688. hpage = CreatePropertySheetPage(&psp);
  689. if (hpage)
  690. AddPage(hpage);
  691. _pDlgNotify = new CComObject<CNotificationsDlg>;
  692. if (_pDlgNotify)
  693. {
  694. _pDlgNotify->AddRef();
  695. }
  696. }
  697. ~CTaskBarPropertySheet()
  698. {
  699. ATOMICRELEASE(_pDlgNotify);
  700. }
  701. // We aren't handling any messages special, so we just make an empty map
  702. DECLARE_EMPTY_MSG_MAP()
  703. private:
  704. // dlgproc's for the various pages
  705. static BOOL_PTR s_TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  706. static BOOL_PTR s_StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  707. BOOL_PTR TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  708. BOOL_PTR StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  709. void _ApplyTaskbarOptionsFromDialog(HWND hDlg);
  710. void _ApplyStartOptionsFromDialog(HWND hDlg);
  711. // for the old style customize dialog
  712. SMADVANCED _Adv;
  713. //need to keep storage for the title until the property sheet is created
  714. TCHAR szPath[MAX_PATH];
  715. CComObject<CNotificationsDlg>* _pDlgNotify;
  716. DWORD _dwFlags;
  717. };
  718. //
  719. // RegSaveDefaultClient
  720. //
  721. void RegSaveDefaultClient(HWND hwndCB, LPCTSTR pszPath)
  722. {
  723. int iSelected = ComboBox_GetCurSel(hwndCB);
  724. if (iSelected >= 0)
  725. {
  726. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, iSelected);
  727. if (pszKey)
  728. {
  729. if (SHSetValue(HKEY_CURRENT_USER, pszPath, NULL, REG_SZ, pszKey, sizeof(TCHAR) * (1 + lstrlen(pszKey))) == ERROR_SUCCESS)
  730. {
  731. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)pszPath);
  732. }
  733. }
  734. }
  735. }
  736. BOOL RegGetDefaultClient(HWND hwndCB, HKEY hkRoot, LPCTSTR pszPath)
  737. {
  738. TCHAR szCurrent[MAX_PATH];
  739. LONG cb = sizeof(szCurrent);
  740. if (RegQueryValue(hkRoot, pszPath, szCurrent, &cb) != ERROR_SUCCESS ||
  741. szCurrent[0] == TEXT('\0'))
  742. {
  743. return FALSE;
  744. }
  745. // Now make sure the selected client exists
  746. int i = ComboBox_GetCount(hwndCB);
  747. while (--i >= 0)
  748. {
  749. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, i);
  750. // Use StrCmpIC so we don't get faked out by Hungarian locale...
  751. if (pszKey && StrCmpIC(pszKey, szCurrent) == 0)
  752. {
  753. ComboBox_SetCurSel(hwndCB, i);
  754. return TRUE;
  755. }
  756. }
  757. return FALSE;
  758. }
  759. void RegPopulateComboBox(HWND hwndCB, LPCTSTR pszPath)
  760. {
  761. TCHAR szFriendlyName [MAX_PATH];
  762. TCHAR szKeyName [MAX_PATH];
  763. DWORD i; // Index counter
  764. HKEY hkeyProtocol;
  765. // See if the clients key even exists...
  766. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszPath, 0, KEY_READ, &hkeyProtocol) != ERROR_SUCCESS)
  767. return;
  768. // populate the dropdown
  769. for(i=0; // always start with 0
  770. ERROR_SUCCESS==RegEnumKey(hkeyProtocol, i, szKeyName, ARRAYSIZE(szKeyName));
  771. i++) // get next entry
  772. {
  773. // get the friendly name of the client
  774. if (SUCCEEDED(SHLoadLegacyRegUIString(hkeyProtocol, szKeyName, szFriendlyName, ARRAYSIZE(szFriendlyName))))
  775. {
  776. // save its key name so we can find it later
  777. LPTSTR pszKeyName = StrDup(szKeyName);
  778. if (pszKeyName)
  779. {
  780. // add name to dropdown
  781. int iAdded = ComboBox_AddString(hwndCB, szFriendlyName);
  782. if (iAdded >= 0)
  783. {
  784. ComboBox_SetItemData(hwndCB, iAdded, pszKeyName);
  785. }
  786. else
  787. {
  788. LocalFree(pszKeyName);
  789. }
  790. }
  791. }
  792. }
  793. RegCloseKey(hkeyProtocol);
  794. // Do this after populating the dropdown because we need to look into
  795. // the dropdown to see if the current value is valid or not
  796. //
  797. // First try HKCU; then try HKLM...
  798. //
  799. if (!RegGetDefaultClient(hwndCB, HKEY_CURRENT_USER, pszPath))
  800. {
  801. RegGetDefaultClient(hwndCB, HKEY_LOCAL_MACHINE, pszPath);
  802. }
  803. }
  804. void RegClearClientComboBox(HWND hDlg, UINT idc)
  805. {
  806. HWND hwndCB = GetDlgItem(hDlg, idc);
  807. int i = ComboBox_GetCount(hwndCB);
  808. while (--i >= 0)
  809. {
  810. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, i);
  811. LocalFree(pszKey);
  812. }
  813. }
  814. void HandleClearButtonClick(HWND hwndClear);
  815. void SetDocButton(HWND hDlg, int id);
  816. //This is the property sheet for the "Customize Simple Start Menu" dlg
  817. class CCustomizeSPPropSheet : public CPropertySheetImpl<CCustomizeSPPropSheet>
  818. {
  819. public:
  820. CCustomizeSPPropSheet(HWND hwndParent) :
  821. CPropertySheetImpl<CCustomizeSPPropSheet>((LPCTSTR)NULL, 0, hwndParent)
  822. , _fInsideInit(FALSE)
  823. {
  824. HPROPSHEETPAGE hpage;
  825. PROPSHEETPAGE psp;
  826. // We are heap-allocated so these should be pre-initialized properly
  827. ASSERT(_bDirtyTree == FALSE);
  828. ASSERT(_prto == NULL);
  829. ASSERT(_pph == NULL);
  830. LoadString(hinstCabinet, IDS_SPCUST_TITLE, _szTitle, ARRAYSIZE(_szTitle));
  831. SetTitle(_szTitle);
  832. m_psh.dwFlags |= PSH_NOAPPLYNOW;
  833. psp.dwSize = sizeof(psp);
  834. psp.dwFlags = PSP_DEFAULT;
  835. psp.hInstance = hinstCabinet;
  836. //General page
  837. psp.pszTemplate = MAKEINTRESOURCE(DLG_PAGE_SMGENERAL);
  838. psp.pfnDlgProc = s_GeneralTabDlgProc;
  839. psp.lParam = (LPARAM) this;
  840. hpage = CreatePropertySheetPage(&psp);
  841. if (hpage)
  842. AddPage(hpage);
  843. //Advanced page
  844. psp.pszTemplate = MAKEINTRESOURCE(DLG_PAGE_SMADVANCED);
  845. psp.pfnDlgProc = s_AdvancedTabDlgProc;
  846. psp.lParam = (LPARAM) this;
  847. hpage = CreatePropertySheetPage(&psp);
  848. if (hpage)
  849. AddPage(hpage);
  850. };
  851. ~CCustomizeSPPropSheet()
  852. {
  853. ASSERT(!_prto); // should be gone by now
  854. if (_pph)
  855. delete _pph;
  856. }
  857. private:
  858. // dlgproc's for the various pages
  859. static BOOL_PTR s_GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  860. static BOOL_PTR s_AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  861. BOOL_PTR GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  862. BOOL_PTR AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  863. BOOL GeneralTabInit(HWND hDlg);
  864. BOOL AdvancedTabInit(HWND hDlg);
  865. BOOL OnCommand(UINT id, UINT code, HWND hwndCtl, HWND hwndDlg); // shared command handler
  866. BOOL OnGeneralApply(HWND hwndDlg);
  867. BOOL_PTR OnAdvancedNotify(HWND hwndDlg, NMHDR * pnm);
  868. BOOL_PTR OnAdvancedHelp(HWND hDlg, HELPINFO *phi);
  869. void _InitMagicEntries();
  870. void _SaveMagicEntries();
  871. //helpers
  872. DWORD _ReadStartPageSetting(LPCTSTR pszVal, DWORD dwDefault)
  873. {
  874. DWORD dw, cb=sizeof(dw), dwType;
  875. SHRegGetUSValue(REGSTR_PATH_STARTPANE_SETTINGS, pszVal, &dwType, &dw, &cb, FALSE, &dwDefault, sizeof(dwDefault));
  876. return dw; // since we passed a default value, above fn will return our default on failure
  877. }
  878. BOOL _ReadStartPageCUSetting(LPCTSTR pszVal, DWORD *pdw) // returns TRUE/FALSE for present under CU or not, actual value in pdw
  879. {
  880. DWORD cb=sizeof(*pdw), dwType;
  881. return NO_ERROR == SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal, &dwType, pdw, &cb);
  882. }
  883. BOOL _WriteStartPageSetting(LPCTSTR pszVal, DWORD dwVal)
  884. {
  885. return SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal, REG_DWORD, &dwVal, sizeof(dwVal)) == NO_ERROR;
  886. }
  887. BOOL _ClearStartPageSetting(LPCTSTR pszVal)
  888. {
  889. return SHDeleteValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal) == NO_ERROR;
  890. }
  891. // State
  892. BOOL _bLargeIcons;
  893. IRegTreeOptions *_prto;
  894. // Dirty Flags
  895. BOOL _bDirtyTree; // to avoid saving the tree if we don't need to
  896. BOOL _bDirtyClients; // to avoid saving the clients if we don't need to
  897. BOOL _bDirtyPinList; // to avoid re-persisting the pin list (and possibly changing the order)
  898. BOOL _bCustNetPlaces; // Did the user previously have net places customized?
  899. BOOL _bCustNetConn; // Did the user previously have net connections customized?
  900. // random bits
  901. CPinHelper *_pph;
  902. TCHAR _szTitle[80]; // needed for the propsheet title...
  903. // We need this to take care of initialization!
  904. BOOL _fInsideInit;
  905. };
  906. BOOL_PTR CCustomizeSPPropSheet::s_GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  907. {
  908. CCustomizeSPPropSheet* self = NULL;
  909. if (uMsg == WM_INITDIALOG)
  910. {
  911. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  912. self = (CCustomizeSPPropSheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  913. }
  914. else
  915. {
  916. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  917. if (psp)
  918. self = (CCustomizeSPPropSheet*)psp->lParam;
  919. }
  920. if (self)
  921. {
  922. return self->GeneralTabDlgProc(hDlg, uMsg, wParam, lParam);
  923. }
  924. else
  925. {
  926. return FALSE;
  927. }
  928. }
  929. BOOL_PTR CCustomizeSPPropSheet::s_AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  930. {
  931. CCustomizeSPPropSheet* self = NULL;
  932. if (uMsg == WM_INITDIALOG)
  933. {
  934. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  935. self = (CCustomizeSPPropSheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  936. }
  937. else
  938. {
  939. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  940. if (psp)
  941. self = (CCustomizeSPPropSheet*)psp->lParam;
  942. }
  943. if (self)
  944. {
  945. return self->AdvancedTabDlgProc(hDlg, uMsg, wParam, lParam);
  946. }
  947. else
  948. {
  949. return FALSE;
  950. }
  951. }
  952. BOOL_PTR CCustomizeSPPropSheet::GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  953. {
  954. switch (uMsg)
  955. {
  956. case WM_INITDIALOG:
  957. return GeneralTabInit(hDlg);
  958. case WM_COMMAND:
  959. return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND) lParam, hDlg);
  960. case WM_DESTROY:
  961. {
  962. SetDlgItemIcon(hDlg, IDC_SPCUST_ICONSMALL, NULL);
  963. SetDlgItemIcon(hDlg, IDC_SPCUST_ICONLARGE, NULL);
  964. RegClearClientComboBox(hDlg, IDC_SPCUST_EMAILCB);
  965. RegClearClientComboBox(hDlg, IDC_SPCUST_INTERNETCB);
  966. break;
  967. }
  968. case WM_NOTIFY:
  969. switch (((NMHDR*)lParam)->code)
  970. {
  971. case PSN_APPLY:
  972. return OnGeneralApply(hDlg);
  973. }
  974. break;
  975. case WM_HELP:
  976. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aStartCustGeneralTabHelpIDs);
  977. break;
  978. case WM_CONTEXTMENU:
  979. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartCustGeneralTabHelpIDs);
  980. break;
  981. }
  982. return FALSE;
  983. }
  984. BOOL CCustomizeSPPropSheet::GeneralTabInit(HWND hDlg)
  985. {
  986. _fInsideInit = TRUE; //We are getting inside initilization!
  987. ::SendMessage(::GetDlgItem(hDlg, IDC_SPCUST_MINPROGS_ARROW), UDM_SETRANGE, 0, (LPARAM)MAKELONG(MAX_PROGS_ALLOWED, 0));
  988. // set up icon size
  989. _bLargeIcons = _ReadStartPageSetting(REGSTR_VAL_DV2_LARGEICONS, /*bDefault*/ TRUE);
  990. ::CheckDlgButton(hDlg, IDC_SPCUST_LARGE, _bLargeIcons);
  991. ::CheckDlgButton(hDlg, IDC_SPCUST_SMALL, !_bLargeIcons);
  992. SetProgramIcon(hDlg, IDC_SPCUST_ICONLARGE, IDC_SPCUST_ICONSMALL);
  993. // Set up the Number of programs dropdown
  994. DWORD dwMinMFU = _ReadStartPageSetting(REGSTR_VAL_DV2_MINMFU, REGSTR_VAL_DV2_MINMFU_DEFAULT);
  995. ::SetDlgItemInt(hDlg, IDC_SPCUST_MINPROGS, dwMinMFU, FALSE);
  996. // Set up internet, email checkboxes and comboboxes
  997. BOOL bInternet=FALSE, bMail=FALSE;
  998. RegPopulateComboBox(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), TEXT("SOFTWARE\\Clients\\mail"));
  999. RegPopulateComboBox(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), TEXT("SOFTWARE\\Clients\\StartMenuInternet"));
  1000. // if this fails, its not fatal, we just won't be able to persist the pin info
  1001. _pph = new CPinHelper();
  1002. if (_pph)
  1003. {
  1004. _pph->GetPinInfo(&bInternet, &bMail);
  1005. }
  1006. ::CheckDlgButton(hDlg, IDC_SPCUST_INTERNET, bInternet);
  1007. ::CheckDlgButton(hDlg, IDC_SPCUST_EMAIL, bMail);
  1008. ::EnableWindow(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), bInternet);
  1009. ::EnableWindow(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), bMail);
  1010. _fInsideInit = FALSE; //We are done initializing.
  1011. return TRUE;
  1012. }
  1013. // Temp until the new UEM code gets in...
  1014. void ClearUEMData()
  1015. {
  1016. HKEY hk;
  1017. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\UserAssist\\{75048700-EF1F-11D0-9888-006097DEACF9}\\Count"),
  1018. 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE,
  1019. &hk))
  1020. {
  1021. int cValues;
  1022. if (ERROR_SUCCESS == RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD*) &cValues, NULL, NULL, NULL, NULL))
  1023. {
  1024. while (cValues >= 0)
  1025. {
  1026. TCHAR szValue[MAX_PATH];
  1027. DWORD cch = ARRAYSIZE(szValue);
  1028. DWORD cbData;
  1029. if (ERROR_SUCCESS != RegEnumValue(hk, --cValues, szValue, &cch, NULL, NULL, NULL, &cbData))
  1030. break;
  1031. // don't nuke the session value
  1032. if (cbData > 8)
  1033. RegDeleteValue(hk, szValue);
  1034. }
  1035. #ifdef DEBUG
  1036. RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD*) &cValues, NULL, NULL, NULL, NULL);
  1037. ASSERT(cValues == 1); // the session info value should still exist
  1038. #endif
  1039. }
  1040. RegCloseKey(hk);
  1041. // Set the "Apps installed prior to this point are not interesting"
  1042. // to the current time. Since we deleted all the usages, we have to
  1043. // do something to prevent all the user's apps from being redetected
  1044. // as "newly installed and not yet run".
  1045. FILETIME ftNow;
  1046. GetSystemTimeAsFileTime(&ftNow);
  1047. SHRegSetUSValue(DV2_REGPATH, DV2_SYSTEM_START_TIME, REG_BINARY,
  1048. &ftNow, sizeof(ftNow), SHREGSET_FORCE_HKCU);
  1049. // Start a new session - this kick-starts anybody who is listening
  1050. // to UEM events to tell them their cache is invalid
  1051. UEMFireEvent(&UEMIID_SHELL, UEME_CTLSESSION, UEMF_XEVENT, TRUE, -1);
  1052. }
  1053. }
  1054. void AdjustNumOfProgsOnStartMenu(HWND hwndDlg, UINT Id)
  1055. {
  1056. BOOL fTranslated;
  1057. int iNumOfProgs = (int)GetDlgItemInt(hwndDlg, Id, &fTranslated, FALSE);
  1058. int iNewNumOfProgs = min(max(iNumOfProgs, 0), MAX_PROGS_ALLOWED);
  1059. if((iNumOfProgs != iNewNumOfProgs) || (!fTranslated))
  1060. {
  1061. SetDlgItemInt(hwndDlg, Id, (UINT)iNewNumOfProgs, FALSE);
  1062. SendPSMChanged(hwndDlg);
  1063. }
  1064. }
  1065. // NOTE - shared WM_COMMAND handler
  1066. //
  1067. BOOL CCustomizeSPPropSheet::OnCommand(UINT id, UINT code, HWND hwndCtl, HWND hwndDlg)
  1068. {
  1069. switch (id)
  1070. {
  1071. ////// General Tab Controls
  1072. case IDC_SPCUST_LARGE:
  1073. case IDC_SPCUST_SMALL:
  1074. _bLargeIcons = (id == IDC_SPCUST_LARGE);
  1075. SendPSMChanged(hwndDlg);
  1076. return FALSE;
  1077. case IDC_SPCUST_MINPROGS:
  1078. if(code == EN_KILLFOCUS)
  1079. AdjustNumOfProgsOnStartMenu(hwndDlg, id);
  1080. else
  1081. {
  1082. if ((_fInsideInit == FALSE) && (code == EN_CHANGE))
  1083. SendPSMChanged(hwndDlg);
  1084. }
  1085. return FALSE;
  1086. case IDB_SPCUST_CLEARPROG:
  1087. ClearUEMData();
  1088. return FALSE;
  1089. case IDC_SPCUST_INTERNET:
  1090. case IDC_SPCUST_EMAIL:
  1091. COMPILETIME_ASSERT(IDC_SPCUST_INTERNETCB == IDC_SPCUST_INTERNET+1);
  1092. COMPILETIME_ASSERT(IDC_SPCUST_EMAILCB == IDC_SPCUST_EMAIL+1);
  1093. ::EnableWindow(::GetDlgItem(hwndDlg, id+1), ::IsDlgButtonChecked(hwndDlg, id));
  1094. _bDirtyPinList = TRUE;
  1095. SendPSMChanged(hwndDlg);
  1096. return FALSE;
  1097. case IDC_SPCUST_INTERNETCB:
  1098. case IDC_SPCUST_EMAILCB:
  1099. if (code == CBN_SELCHANGE)
  1100. {
  1101. _bDirtyClients = TRUE;
  1102. SendPSMChanged(hwndDlg);
  1103. }
  1104. return FALSE;
  1105. ////// Advanced Tab Controls
  1106. case IDC_SPCUST_RECENT:
  1107. SendPSMChanged(hwndDlg);
  1108. return FALSE;
  1109. case IDB_SPCUST_CLEARDOCS:
  1110. HandleClearButtonClick(hwndCtl);
  1111. return FALSE;
  1112. case IDC_SPCUST_HOVEROPEN:
  1113. case IDC_SPCUST_NOTIFYNEW:
  1114. SendPSMChanged(hwndDlg);
  1115. return FALSE;
  1116. break;
  1117. }
  1118. return TRUE;
  1119. }
  1120. BOOL CCustomizeSPPropSheet::OnGeneralApply(HWND hDlg)
  1121. {
  1122. TraceMsg(TF_ALWAYS, "cspps.General apply", _bDirtyTree);
  1123. _WriteStartPageSetting(REGSTR_VAL_DV2_LARGEICONS, _bLargeIcons);
  1124. if (_pph && _bDirtyPinList)
  1125. {
  1126. BOOL bInternet = ::IsDlgButtonChecked(hDlg, IDC_SPCUST_INTERNET);
  1127. BOOL bMail = ::IsDlgButtonChecked(hDlg, IDC_SPCUST_EMAIL);
  1128. _pph->Save(bMail, bInternet);
  1129. }
  1130. if (_bDirtyClients)
  1131. {
  1132. // persist Internet, Mail comboboxes
  1133. RegSaveDefaultClient(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), TEXT("Software\\Clients\\mail"));
  1134. RegSaveDefaultClient(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), TEXT("SOFTWARE\\Clients\\StartMenuInternet"));
  1135. }
  1136. BOOL bTranslated;
  1137. DWORD dwMinMFU = ::GetDlgItemInt(hDlg, IDC_SPCUST_MINPROGS, &bTranslated, FALSE);
  1138. if (EVAL(bTranslated))
  1139. {
  1140. dwMinMFU = min(max(dwMinMFU, 0), MAX_PROGS_ALLOWED);
  1141. _WriteStartPageSetting(REGSTR_VAL_DV2_MINMFU, dwMinMFU);
  1142. }
  1143. return TRUE;
  1144. }
  1145. BOOL_PTR CCustomizeSPPropSheet::OnAdvancedNotify(HWND hwndDlg, NMHDR * pnm)
  1146. {
  1147. ::SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, 0); // handled
  1148. switch (pnm->code)
  1149. {
  1150. case PSN_APPLY:
  1151. TraceMsg(TF_ALWAYS, "cspps.Advanced apply - _bDirtyTree=%d", _bDirtyTree);
  1152. if (_bDirtyTree)
  1153. {
  1154. _prto->WalkTree(WALK_TREE_SAVE);
  1155. }
  1156. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWRECDOCS, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_RECENT) ? 2 : 0); // 2 so that it cascades
  1157. _WriteStartPageSetting(REGSTR_VAL_DV2_AUTOCASCADE, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_HOVEROPEN));
  1158. _WriteStartPageSetting(REGSTR_VAL_DV2_NOTIFYNEW, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_NOTIFYNEW));
  1159. // fall through to PSN_RESET case...
  1160. case PSN_RESET:
  1161. _SaveMagicEntries(); // this must be called on both cancel and apply, so that it cleans up properly...
  1162. // must release prto before the treeview goes away!
  1163. _prto->WalkTree(WALK_TREE_DELETE);
  1164. ATOMICRELEASE(_prto);
  1165. break;
  1166. case TVN_KEYDOWN:
  1167. {
  1168. TV_KEYDOWN *pnmtv = (TV_KEYDOWN*)pnm;
  1169. if (pnmtv->wVKey == VK_SPACE)
  1170. {
  1171. HWND hwndTree = ::GetDlgItem(hwndDlg, IDC_STARTMENUSETTINGS);
  1172. _prto->ToggleItem((HTREEITEM)SendMessage(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L));
  1173. _bDirtyTree = TRUE;
  1174. SendPSMChanged(hwndDlg);
  1175. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); // eat the key
  1176. }
  1177. break;
  1178. }
  1179. case NM_CLICK:
  1180. case NM_DBLCLK:
  1181. // is this click in our tree?
  1182. if ( pnm->idFrom == IDC_STARTMENUSETTINGS )
  1183. {
  1184. HWND hwndTree = ::GetDlgItem(hwndDlg, IDC_STARTMENUSETTINGS);
  1185. TV_HITTESTINFO ht;
  1186. DWORD dwPos = GetMessagePos(); // get where we were hit
  1187. ht.pt.x = GET_X_LPARAM(dwPos);
  1188. ht.pt.y = GET_Y_LPARAM(dwPos);
  1189. ::ScreenToClient(hwndTree, &ht.pt); // translate it to our window
  1190. // retrieve the item hit
  1191. HTREEITEM hti = TreeView_HitTest(hwndTree, &ht);
  1192. if (hti)
  1193. {
  1194. _prto->ToggleItem(hti);
  1195. _bDirtyTree = TRUE;
  1196. SendPSMChanged(hwndDlg);
  1197. }
  1198. }
  1199. break;
  1200. // no help yet- needs ids/text from UA
  1201. #if 0
  1202. case NM_RCLICK: // right mouse click
  1203. if (pnm->hwndFrom == hwndTree)
  1204. {
  1205. _DoTreeHelp(pAdv, (WPARAM)pnm->hwndFrom);
  1206. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); // eat the click
  1207. return TRUE;
  1208. }
  1209. break;
  1210. #endif
  1211. }
  1212. return TRUE;
  1213. }
  1214. BOOL_PTR CCustomizeSPPropSheet::OnAdvancedHelp(HWND hDlg, HELPINFO *phi)
  1215. {
  1216. if (phi->iCtrlId != IDC_STARTMENUSETTINGS)
  1217. {
  1218. ::WinHelp((HWND)(phi->hItemHandle), NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aStartCustAdvancedTabHelpIDs);
  1219. }
  1220. else
  1221. {
  1222. HTREEITEM hItem;
  1223. HWND hwndTree = ::GetDlgItem(hDlg, IDC_STARTMENUSETTINGS);
  1224. //Is this help invoked throught F1 key
  1225. if (GetAsyncKeyState(VK_F1) < 0)
  1226. {
  1227. // Yes. WE need to give help for the currently selected item
  1228. hItem = TreeView_GetSelection(hwndTree);
  1229. }
  1230. else
  1231. {
  1232. //No, We need to give help for the item at the cursor position
  1233. TV_HITTESTINFO ht;
  1234. ht.pt = phi->MousePos;
  1235. ::ScreenToClient(hwndTree, &ht.pt); // Translate it to our window
  1236. hItem = TreeView_HitTest(hwndTree, &ht);
  1237. }
  1238. if (hItem)
  1239. _prto->ShowHelp(hItem, HELP_WM_HELP);
  1240. }
  1241. return TRUE;
  1242. }
  1243. BOOL_PTR CCustomizeSPPropSheet::AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1244. {
  1245. switch (uMsg)
  1246. {
  1247. case WM_INITDIALOG:
  1248. return AdvancedTabInit(hDlg);
  1249. case WM_COMMAND:
  1250. return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND) lParam, hDlg);
  1251. case WM_NOTIFY:
  1252. return OnAdvancedNotify(hDlg, (NMHDR*)lParam);
  1253. case WM_HELP:
  1254. return OnAdvancedHelp(hDlg, (HELPINFO*) lParam);
  1255. break;
  1256. case WM_CONTEXTMENU:
  1257. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartCustAdvancedTabHelpIDs);
  1258. break;
  1259. }
  1260. return FALSE;
  1261. }
  1262. int DefaultNetConValue()
  1263. {
  1264. return ShouldShowConnectTo() ? 2 : 0; // default to menu-style (2)
  1265. }
  1266. int DefaultNetPlacesValue()
  1267. {
  1268. return ShouldShowNetPlaces() ? 1 : 0; // default to link -style (1)
  1269. }
  1270. // These two "magic" functions maintain the proper behavior of the network places and network connections settings
  1271. // which, by default, turn on when there are n or more items in the folder. But they can also be customized by the
  1272. // user to force them on or off.
  1273. void CCustomizeSPPropSheet::_InitMagicEntries()
  1274. {
  1275. BOOL bNewNetPlaces;
  1276. BOOL bNewNetConn;
  1277. _bCustNetPlaces = _ReadStartPageCUSetting(REGSTR_VAL_DV2_SHOWNETPL, (DWORD*) &bNewNetPlaces);
  1278. _bCustNetConn = _ReadStartPageCUSetting(REGSTR_VAL_DV2_SHOWNETCONN, (DWORD*) &bNewNetConn);
  1279. // if the user didn't previously customize these settings, then use the auto-magic setting
  1280. if (!_bCustNetPlaces)
  1281. bNewNetPlaces = DefaultNetPlacesValue();
  1282. if (!_bCustNetConn)
  1283. bNewNetConn = DefaultNetConValue();
  1284. // Write it out, so the rgtreeoption control will reflect either the user's customization, or the magic value
  1285. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL, bNewNetPlaces);
  1286. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN, bNewNetConn);
  1287. // for the admin tools radio buttons:
  1288. // 0 = don't show anywhere
  1289. // 1 = display in all programs (StartMenuAdminTools = 1, Start_AdminToolsRoot = 0)
  1290. // 2 = display in all programs and root (StartMenuAdminTools = 1, Start_AdminToolsRoot = 2)
  1291. int iAdminToolsTemp = _ReadStartPageSetting(REGSTR_VAL_DV2_ADMINTOOLSROOT, FALSE) ? 2 :
  1292. (_ReadStartPageSetting(TEXT("StartMenuAdminTools"), FALSE) ? 1 : 0);
  1293. _WriteStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP, iAdminToolsTemp);
  1294. }
  1295. void CCustomizeSPPropSheet::_SaveMagicEntries()
  1296. {
  1297. BOOL bNewNetPlaces = _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL, FALSE);
  1298. BOOL bNewNetConn = _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN, FALSE);
  1299. // if the user previously had it customized, then we don't need to clear it since it will either
  1300. // contain the original value we loaded in _InitMagicEntries, or the updated value if the user changed it.
  1301. // if it wasn't originally customized, then we need to clear it if the tree isn't even dirty, or the current value is the magic value we loaded
  1302. if (!_bCustNetPlaces && (!_bDirtyTree || bNewNetPlaces == DefaultNetPlacesValue()))
  1303. _ClearStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL);
  1304. if (!_bCustNetConn && (!_bDirtyTree || bNewNetConn == DefaultNetConValue()))
  1305. _ClearStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN);
  1306. if (_bDirtyTree)
  1307. {
  1308. // see comment above for how this should work
  1309. int iAdminToolsTemp = _ReadStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP, FALSE);
  1310. int iATRoot = 0;
  1311. int iATPrograms = 0;
  1312. if (iAdminToolsTemp >= 1)
  1313. {
  1314. iATPrograms = 1;
  1315. if (iAdminToolsTemp == 2)
  1316. {
  1317. iATRoot = 2;
  1318. }
  1319. }
  1320. _WriteStartPageSetting(REGSTR_VAL_DV2_ADMINTOOLSROOT, iATRoot);
  1321. _WriteStartPageSetting(TEXT("StartMenuAdminTools"), iATPrograms);
  1322. }
  1323. _ClearStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP);
  1324. }
  1325. BOOL CCustomizeSPPropSheet::AdvancedTabInit(HWND hDlg)
  1326. {
  1327. if (SUCCEEDED(CoCreateInstance(CLSID_CRegTreeOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IRegTreeOptions, &_prto))))
  1328. {
  1329. HRESULT hr;
  1330. HWND hwndTV = ::GetDlgItem(hDlg, IDC_STARTMENUSETTINGS);
  1331. // Compute the magic entries before we init the RegTreeOptions
  1332. // (so we will have correct information for him!)
  1333. _InitMagicEntries();
  1334. // HACKHACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE
  1335. #undef TEXT
  1336. #define TEXT(s) s
  1337. hr = _prto->InitTree(hwndTV, HKEY_LOCAL_MACHINE, REGSTR_PATH_SMADVANCED "\\StartPanel", NULL);
  1338. #undef TEXT
  1339. #define TEXT(s) __TEXT(s)
  1340. TreeView_SelectSetFirstVisible(hwndTV, TreeView_GetRoot(hwndTV));
  1341. ::CheckDlgButton(hDlg, IDC_SPCUST_RECENT, _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWRECDOCS, IsOS(OS_PERSONAL) ? FALSE : TRUE));
  1342. ::CheckDlgButton(hDlg, IDC_SPCUST_HOVEROPEN,_ReadStartPageSetting(REGSTR_VAL_DV2_AUTOCASCADE, TRUE));
  1343. ::CheckDlgButton(hDlg, IDC_SPCUST_NOTIFYNEW,_ReadStartPageSetting(REGSTR_VAL_DV2_NOTIFYNEW, TRUE));
  1344. if(SHRestricted(REST_NORECENTDOCSMENU))
  1345. {
  1346. //Since this policy is present, hide all the relevant controls
  1347. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT_GROUPBOX), FALSE);// Group box
  1348. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT_TEXT), FALSE); // Description Text.
  1349. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT), FALSE); // Check box
  1350. ::ShowWindow(::GetDlgItem(hDlg, IDB_SPCUST_CLEARDOCS), FALSE); // Clear button.
  1351. }
  1352. SetDocButton(hDlg, IDB_SPCUST_CLEARDOCS);
  1353. return TRUE;
  1354. }
  1355. return FALSE;
  1356. }
  1357. BOOL_PTR CTaskBarPropertySheet::s_TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1358. {
  1359. CTaskBarPropertySheet* self = NULL;
  1360. if (uMsg == WM_INITDIALOG)
  1361. {
  1362. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1363. self = (CTaskBarPropertySheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  1364. }
  1365. else
  1366. {
  1367. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  1368. if (psp)
  1369. self = (CTaskBarPropertySheet*)psp->lParam;
  1370. }
  1371. BOOL_PTR fValue = FALSE;
  1372. if (self)
  1373. {
  1374. self->TaskbarOptionsDlgProc(hDlg, uMsg, wParam, lParam);
  1375. }
  1376. return fValue;
  1377. }
  1378. void _TaskbarOptions_OnInitDialog(HWND hDlg)
  1379. {
  1380. TRAYVIEWOPTS tvo;
  1381. c_tray.GetTrayViewOpts(&tvo);
  1382. CheckDlgButton(hDlg, IDC_QUICKLAUNCH, tvo.fShowQuickLaunch);
  1383. CheckDlgButton(hDlg, IDC_TRAYOPTONTOP, tvo.fAlwaysOnTop);
  1384. CheckDlgButton(hDlg, IDC_TRAYOPTAUTOHIDE, (tvo.uAutoHide & AH_ON));
  1385. CheckDlgButton(hDlg, IDC_TRAYOPTSHOWCLOCK, !tvo.fHideClock);
  1386. if (SHRestricted(REST_HIDECLOCK))
  1387. {
  1388. EnableWindow(GetDlgItem(hDlg, IDC_TRAYOPTSHOWCLOCK), FALSE);
  1389. }
  1390. if (SHRestricted(REST_NOTOOLBARSONTASKBAR))
  1391. {
  1392. EnableWindow(GetDlgItem(hDlg, IDC_QUICKLAUNCH), FALSE);
  1393. }
  1394. // Restriction- either the tray is disabled by policy, or the "smart" auto tray
  1395. // is disabled by policy
  1396. if (tvo.fNoTrayItemsDisplayPolicyEnabled || tvo.fNoAutoTrayPolicyEnabled)
  1397. {
  1398. EnableWindow(GetDlgItem(hDlg, IDC_NOTIFYMAN), FALSE);
  1399. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), FALSE);
  1400. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NOTIFY), FALSE);
  1401. }
  1402. else
  1403. {
  1404. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), tvo.fAutoTrayEnabledByUser);
  1405. CheckDlgButton(hDlg, IDC_NOTIFYMAN, tvo.fAutoTrayEnabledByUser);
  1406. }
  1407. CheckDlgButton(hDlg, IDC_LOCKTASKBAR, !_IsSizeMoveEnabled());
  1408. BOOL fEnable = !_IsSizeMoveRestricted();
  1409. EnableWindow(GetDlgItem(hDlg, IDC_LOCKTASKBAR), fEnable);
  1410. if (SHRestricted(REST_NOTASKGROUPING))
  1411. {
  1412. // If there is a restriction of any kine, hide the window
  1413. ShowWindow(GetDlgItem(hDlg, IDC_GROUPITEMS), FALSE);
  1414. }
  1415. else if (SHRegGetBoolUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarGlomming"),
  1416. FALSE, TRUE))
  1417. {
  1418. CheckDlgButton(hDlg, IDC_GROUPITEMS, TRUE);
  1419. }
  1420. _TaskbarOptionsSizeControls(hDlg);
  1421. _TaskbarOptionsUpdateDisplay(hDlg);
  1422. }
  1423. BOOL_PTR CTaskBarPropertySheet::TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1424. {
  1425. INSTRUMENT_WNDPROC(SHCNFI_TRAYVIEWOPTIONS_DLGPROC, hDlg, uMsg, wParam, lParam);
  1426. switch (uMsg)
  1427. {
  1428. case WM_COMMAND:
  1429. if (GET_WM_COMMAND_ID(wParam, lParam) == IDC_CUSTOMIZE)
  1430. {
  1431. if (_pDlgNotify)
  1432. {
  1433. _pDlgNotify->DoModal();
  1434. }
  1435. }
  1436. _TaskbarOptionsUpdateDisplay(hDlg);
  1437. SendPSMChanged(hDlg);
  1438. break;
  1439. case WM_INITDIALOG:
  1440. _TaskbarOptions_OnInitDialog(hDlg);
  1441. if (_dwFlags & TPF_INVOKECUSTOMIZE)
  1442. {
  1443. ::PostMessage(hDlg, WM_COMMAND, IDC_CUSTOMIZE, 0);
  1444. }
  1445. break;
  1446. case WM_SYSCOLORCHANGE:
  1447. _TaskbarOptionsUpdateDisplay(hDlg);
  1448. return TRUE;
  1449. case WM_DESTROY:
  1450. _TaskbarOptionsDestroyBitmaps(hDlg);
  1451. break;
  1452. case WM_NOTIFY:
  1453. switch (((NMHDR *)lParam)->code)
  1454. {
  1455. case PSN_APPLY:
  1456. // save settings here
  1457. _ApplyTaskbarOptionsFromDialog(hDlg);
  1458. return TRUE;
  1459. case PSN_KILLACTIVE:
  1460. case PSN_SETACTIVE:
  1461. return TRUE;
  1462. }
  1463. break;
  1464. case WM_HELP:
  1465. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aTaskOptionsHelpIDs);
  1466. break;
  1467. case WM_CONTEXTMENU:
  1468. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aTaskOptionsHelpIDs);
  1469. break;
  1470. }
  1471. return FALSE;
  1472. }
  1473. void _StartOptions_OnInitDialog(HWND hDlg)
  1474. {
  1475. // If StartPanel UI is turned off, then this check box should not show up!
  1476. if (SHRestricted(REST_NOSTARTPANEL))
  1477. {
  1478. //If the restriction exists, then hide this check box.
  1479. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSCHOOL), FALSE);
  1480. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSCHOOLDESCRIPTION), FALSE);
  1481. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSTARTCUSTOMIZE), FALSE);
  1482. // And the only thing you can do is check the OldSchool button
  1483. CheckDlgButton(hDlg, IDC_OLDSCHOOL, TRUE);
  1484. // TODO - PM's need to figure out what to do in the case where new start menu is restricted
  1485. // or not available. This propsheet page is rather pointless in that case...
  1486. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW, IDB_STARTPREVIEWCLASSIC);
  1487. }
  1488. else
  1489. {
  1490. SHELLSTATE ss = {0};
  1491. SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE);
  1492. CheckDlgButton(hDlg, IDC_NEWSCHOOL, BOOLIFY(ss.fStartPanelOn));
  1493. CheckDlgButton(hDlg, IDC_OLDSCHOOL, !BOOLIFY(ss.fStartPanelOn));
  1494. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW,
  1495. ss.fStartPanelOn ? IDB_STARTPREVIEWNEW : IDB_STARTPREVIEWCLASSIC);
  1496. // disable "customize" for the style thats off.
  1497. EnableWindow(GetDlgItem(hDlg, ss.fStartPanelOn ? IDC_OLDSTARTCUSTOMIZE : IDC_NEWSTARTCUSTOMIZE), FALSE);
  1498. }
  1499. }
  1500. // On destroy, clean up the bitmaps we loaded so we don't leak them
  1501. void _StartOptions_OnDestroy(HWND hDlg)
  1502. {
  1503. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW, 0);
  1504. }
  1505. BOOL_PTR CTaskBarPropertySheet::s_StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1506. {
  1507. CTaskBarPropertySheet* self = NULL;
  1508. if (uMsg == WM_INITDIALOG)
  1509. {
  1510. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1511. self = (CTaskBarPropertySheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  1512. }
  1513. else
  1514. {
  1515. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  1516. if (psp)
  1517. self = (CTaskBarPropertySheet*)psp->lParam;
  1518. }
  1519. BOOL_PTR fValue = FALSE;
  1520. if (self)
  1521. {
  1522. self->StartMenuDlgProc(hDlg, uMsg, wParam, lParam);
  1523. }
  1524. return fValue;
  1525. }
  1526. BOOL_PTR CTaskBarPropertySheet::StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1527. {
  1528. switch (uMsg)
  1529. {
  1530. case WM_COMMAND:
  1531. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1532. {
  1533. case IDC_NEWSCHOOL:
  1534. case IDC_OLDSCHOOL:
  1535. if (HIWORD(wParam) == BN_CLICKED)
  1536. {
  1537. ::EnableWindow(::GetDlgItem(hDlg, IDC_NEWSTARTCUSTOMIZE), GET_WM_COMMAND_ID(wParam, lParam) == IDC_NEWSCHOOL);
  1538. ::EnableWindow(::GetDlgItem(hDlg, IDC_OLDSTARTCUSTOMIZE), GET_WM_COMMAND_ID(wParam, lParam) == IDC_OLDSCHOOL);
  1539. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW,
  1540. GET_WM_COMMAND_ID(wParam, lParam) == IDC_NEWSCHOOL ? IDB_STARTPREVIEWNEW : IDB_STARTPREVIEWCLASSIC);
  1541. SendPSMChanged(hDlg);
  1542. }
  1543. break;
  1544. case IDC_NEWSTARTCUSTOMIZE:
  1545. {
  1546. CCustomizeSPPropSheet *pps = new CCustomizeSPPropSheet(hDlg);
  1547. if (pps)
  1548. {
  1549. if (pps->DoModal() == IDOK)
  1550. {
  1551. // if anything changed, let the propsheet know
  1552. SendPSMChanged(hDlg);
  1553. }
  1554. delete pps;
  1555. }
  1556. break;
  1557. }
  1558. case IDC_OLDSTARTCUSTOMIZE:
  1559. {
  1560. if (FAILED(CoCreateInstance(CLSID_CRegTreeOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IRegTreeOptions, &_Adv.pTO))))
  1561. {
  1562. TraceMsg(TF_WARNING, "ctbps failed to create CRegTreeOptions");
  1563. break;
  1564. }
  1565. if (DialogBoxParam(hinstCabinet, MAKEINTRESOURCE(DLG_STARTMENU_CONFIG), hDlg, AdvancedOptDlgProc, (LPARAM)&_Adv))
  1566. {
  1567. // if anything changed, let the propsheet know
  1568. SendPSMChanged(hDlg);
  1569. }
  1570. break;
  1571. }
  1572. }
  1573. break;
  1574. case WM_INITDIALOG:
  1575. _StartOptions_OnInitDialog(hDlg);
  1576. break;
  1577. case WM_DESTROY:
  1578. _StartOptions_OnDestroy(hDlg);
  1579. break;
  1580. case WM_NOTIFY:
  1581. switch (((NMHDR *)lParam)->code)
  1582. {
  1583. case PSN_APPLY:
  1584. // save settings here
  1585. _ApplyStartOptionsFromDialog(hDlg);
  1586. return TRUE;
  1587. case PSN_KILLACTIVE:
  1588. case PSN_SETACTIVE:
  1589. return TRUE;
  1590. }
  1591. break;
  1592. case WM_HELP:
  1593. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aStartTabHelpIDs);
  1594. break;
  1595. case WM_CONTEXTMENU:
  1596. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartTabHelpIDs);
  1597. break;
  1598. }
  1599. return FALSE;
  1600. }
  1601. void _UpdateNotifySetting(BOOL fNotifySetting)
  1602. {
  1603. ITrayNotify * pTrayNotify = NULL;
  1604. // localserver for tray notify
  1605. if (SUCCEEDED(CoCreateInstance(CLSID_TrayNotify, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(ITrayNotify, &pTrayNotify))))
  1606. {
  1607. pTrayNotify->EnableAutoTray(fNotifySetting);
  1608. pTrayNotify->Release();
  1609. }
  1610. }
  1611. void CTaskBarPropertySheet ::_ApplyTaskbarOptionsFromDialog(HWND hDlg)
  1612. {
  1613. // We need to get the Cabinet structure from the property sheet info.
  1614. // First check for Always on Top
  1615. BOOL fAlwaysOnTop = ::IsDlgButtonChecked(hDlg, IDC_TRAYOPTONTOP);
  1616. c_tray._UpdateAlwaysOnTop(fAlwaysOnTop);
  1617. // And change the Autohide state
  1618. BOOL fAutoHide = ::IsDlgButtonChecked(hDlg, IDC_TRAYOPTAUTOHIDE);
  1619. LONG lRet = c_tray._SetAutoHideState(fAutoHide);
  1620. TRAYVIEWOPTS tvo;
  1621. c_tray.GetTrayViewOpts(&tvo);
  1622. if (!HIWORD(lRet) && fAutoHide)
  1623. {
  1624. // we tried and failed.
  1625. if (!(tvo.uAutoHide & AH_ON))
  1626. {
  1627. ::CheckDlgButton(hDlg, IDC_TRAYOPTAUTOHIDE, FALSE);
  1628. _TaskbarOptionsUpdateDisplay(hDlg);
  1629. }
  1630. }
  1631. BOOL fChanged = LOWORD(lRet);
  1632. if (fChanged)
  1633. c_tray._AppBarNotifyAll(NULL, ABN_STATECHANGE, NULL, 0);
  1634. // show/hide the clock
  1635. tvo.fHideClock = !::IsDlgButtonChecked(hDlg, IDC_TRAYOPTSHOWCLOCK);
  1636. if (!tvo.fNoTrayItemsDisplayPolicyEnabled && !tvo.fNoAutoTrayPolicyEnabled)
  1637. {
  1638. BOOL fNotifySetting = ::IsDlgButtonChecked(hDlg, IDC_NOTIFYMAN);
  1639. if (tvo.fAutoTrayEnabledByUser != fNotifySetting)
  1640. {
  1641. tvo.fAutoTrayEnabledByUser = fNotifySetting;
  1642. _UpdateNotifySetting(fNotifySetting);
  1643. }
  1644. }
  1645. tvo.fShowQuickLaunch = ::IsDlgButtonChecked(hDlg, IDC_QUICKLAUNCH);
  1646. c_tray.SetTrayViewOpts(&tvo);
  1647. SendMessage(c_tray.GetTrayNotifyHWND(), TNM_HIDECLOCK, 0, tvo.fHideClock);
  1648. c_tray.SizeWindows();
  1649. // Update registry for locked taskbar
  1650. DWORD dwEnableSizeMove = !::IsDlgButtonChecked(hDlg, IDC_LOCKTASKBAR);
  1651. SHRegSetUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarSizeMove"),
  1652. REG_DWORD, &dwEnableSizeMove, sizeof(DWORD), SHREGSET_FORCE_HKCU);
  1653. //Update registry for grouping behavior
  1654. DWORD dwGlom = ::IsDlgButtonChecked(hDlg, IDC_GROUPITEMS);
  1655. SHRegSetUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarGlomming"),
  1656. REG_DWORD, &dwGlom, sizeof(DWORD), SHREGSET_FORCE_HKCU);
  1657. ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)TEXT("TraySettings"), SMTO_NOTIMEOUTIFNOTHUNG, 1000, NULL);
  1658. }
  1659. void CTaskBarPropertySheet::_ApplyStartOptionsFromDialog(HWND hDlg)
  1660. {
  1661. if (!SHRestricted(REST_NOSTARTPANEL))
  1662. {
  1663. //Get the current state of the check box
  1664. BOOL fStartPanelOn = BOOLIFY(::IsDlgButtonChecked(hDlg, IDC_NEWSCHOOL));
  1665. SHELLSTATE ss = {0};
  1666. //See if Startpage is currently on or off.
  1667. SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE);
  1668. //Check if the check box has been toggled
  1669. if (fStartPanelOn != BOOLIFY(ss.fStartPanelOn))
  1670. {
  1671. // Toggle the setting
  1672. ss.fStartPanelOn = fStartPanelOn;
  1673. SHGetSetSettings(&ss, SSF_STARTPANELON, TRUE);
  1674. //Tell the desktop window so it can add/remove the desktop icons
  1675. ::PostMessage(v_hwndDesktop, DTM_STARTPAGEONOFF, 0, 0);
  1676. }
  1677. // Tell the Start Menu to rebuild itself now that we changed it
  1678. // (This part is unconditional since the user may have merely
  1679. // changed a setting with the Start Menu)
  1680. ::PostMessage(v_hwndTray, SBM_REBUILDMENU, 0, 0);
  1681. }
  1682. }
  1683. //---------------------------------------------------------------------------
  1684. void _TaskbarOptionsDestroyBitmaps(HWND hDlg)
  1685. {
  1686. SetDlgItemBitmap(hDlg, IDC_TASKBARAPPEARANCE, 0);
  1687. SetDlgItemBitmap(hDlg, IDC_NOTIFYAPPEARANCE, 0);
  1688. }
  1689. typedef struct
  1690. {
  1691. int idc;
  1692. int iAdd;
  1693. }
  1694. CONTROLBITMAP;
  1695. int _TaskbarPickBitmap(HWND hDlg, int iBmpBase, const CONTROLBITMAP* pca, int cca)
  1696. {
  1697. for (int i = 0; i < cca; i++)
  1698. {
  1699. if (!IsDlgButtonChecked(hDlg, pca[i].idc))
  1700. {
  1701. iBmpBase += pca[i].iAdd;
  1702. }
  1703. }
  1704. return iBmpBase;
  1705. }
  1706. void _TaskbarOptionsUpdateDisplay(HWND hDlg)
  1707. {
  1708. static const CONTROLBITMAP c_caTaskbar[] =
  1709. {
  1710. { IDC_LOCKTASKBAR, 1 },
  1711. { IDC_GROUPITEMS, 2 },
  1712. { IDC_QUICKLAUNCH, 4 },
  1713. };
  1714. static const CONTROLBITMAP c_caNotify[] =
  1715. {
  1716. { IDC_TRAYOPTSHOWCLOCK, 1 },
  1717. { IDC_NOTIFYMAN, 2 },
  1718. };
  1719. //
  1720. // top preview
  1721. //
  1722. int iBmp;
  1723. if (IsDlgButtonChecked(hDlg, IDC_TRAYOPTAUTOHIDE))
  1724. {
  1725. iBmp = IDB_TAAUTOHIDE;
  1726. }
  1727. else
  1728. {
  1729. iBmp = _TaskbarPickBitmap(hDlg, IDB_TAQLLOCKGROUP, c_caTaskbar, ARRAYSIZE(c_caTaskbar));
  1730. }
  1731. SetDlgItemBitmap(hDlg, IDC_TASKBARAPPEARANCE, iBmp);
  1732. //
  1733. // bottom preview
  1734. //
  1735. iBmp = _TaskbarPickBitmap(hDlg, IDB_NACLOCKCLEAN, c_caNotify, ARRAYSIZE(c_caNotify));
  1736. SetDlgItemBitmap(hDlg, IDC_NOTIFYAPPEARANCE, iBmp);
  1737. //
  1738. // customize button
  1739. //
  1740. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), IsDlgButtonChecked(hDlg, IDC_NOTIFYMAN));
  1741. }
  1742. #define CX_PREVIEW 336
  1743. #define CY_PREVIEW 35
  1744. // need to do this by hand because dialog units to pixels will change,
  1745. // but the bitmaps won't
  1746. void _TaskbarOptionsSizeControls(HWND hDlg)
  1747. {
  1748. static const int c_IDC[] =
  1749. {
  1750. IDC_TASKBARAPPEARANCE,
  1751. IDC_NOTIFYAPPEARANCE
  1752. };
  1753. for (int i = 0; i < ARRAYSIZE(c_IDC); i++)
  1754. {
  1755. SetWindowPos(GetDlgItem(hDlg, c_IDC[i]), NULL, 0, 0, CX_PREVIEW, CY_PREVIEW,
  1756. SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
  1757. }
  1758. }
  1759. typedef BOOL (* PFCFGSTART) (HWND, BOOL);
  1760. void CallAppWiz(HWND hDlg, BOOL bDelItems)
  1761. {
  1762. HINSTANCE hmodWiz = LoadLibrary(TEXT("AppWiz.Cpl"));
  1763. if (hmodWiz)
  1764. {
  1765. PFCFGSTART pfnCfgStart = (PFCFGSTART)GetProcAddress(hmodWiz, "ConfigStartMenu");
  1766. if (pfnCfgStart)
  1767. {
  1768. pfnCfgStart(hDlg, bDelItems);
  1769. }
  1770. FreeLibrary(hmodWiz);
  1771. }
  1772. }
  1773. BOOL ExecExplorerAtStartMenu(HWND hDlg)
  1774. {
  1775. BOOL fRet = FALSE;
  1776. TCHAR szFile[MAX_PATH];
  1777. if (GetSystemWindowsDirectory(szFile, ARRAYSIZE(szFile)))
  1778. {
  1779. SHELLEXECUTEINFO ei = { 0 };
  1780. StrCatBuff(szFile, TEXT("\\explorer.exe"), ARRAYSIZE(szFile));
  1781. ei.lpFile = szFile;
  1782. ei.cbSize = sizeof(ei);
  1783. ei.hwnd = hDlg;
  1784. TCHAR szParams[MAX_PATH + ARRAYSIZE(TEXT("/E,/Root,"))];
  1785. if (IsUserAnAdmin())
  1786. {
  1787. lstrcpyn(szParams, TEXT("/E,"), ARRAYSIZE(szParams));
  1788. SHGetSpecialFolderPath(hDlg, &(szParams[ARRAYSIZE(TEXT("/E,"))-1]),
  1789. CSIDL_STARTMENU, FALSE);
  1790. }
  1791. else
  1792. {
  1793. lstrcpyn(szParams, TEXT("/E,/Root,"), ARRAYSIZE(szParams));
  1794. SHGetSpecialFolderPath(hDlg, &(szParams[ARRAYSIZE(TEXT("/E,/Root,"))-1]),
  1795. CSIDL_STARTMENU, FALSE);
  1796. }
  1797. ei.lpParameters = szParams;
  1798. ei.nShow = SW_SHOWDEFAULT;
  1799. ei.hInstApp = hinstCabinet;
  1800. fRet = ShellExecuteEx(&ei);
  1801. }
  1802. return fRet;
  1803. }
  1804. const TCHAR *c_szRegMruKeysToDelete[] =
  1805. {
  1806. TEXT("Software\\Microsoft\\Internet Explorer\\TypedURLs"),
  1807. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU"),
  1808. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Doc Find Spec MRU"),
  1809. // New for Whistler (should've been in Windows 2000 and Millennium but we forgot)
  1810. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Comdlg32\\OpenSaveMRU"),
  1811. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Comdlg32\\LastVisitedMRU"),
  1812. };
  1813. void SetDocButton(HWND hDlg, int id)
  1814. {
  1815. LPITEMIDLIST pidl;
  1816. BOOL bAreDocs = FALSE;
  1817. HRESULT hr = SHGetSpecialFolderLocation(hDlg, CSIDL_RECENT, &pidl);
  1818. if (SUCCEEDED(hr))
  1819. {
  1820. IShellFolder *psf = BindToFolder(pidl);
  1821. if (psf)
  1822. {
  1823. IEnumIDList *penum;
  1824. if (S_OK == psf->EnumObjects(hDlg, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &penum))
  1825. {
  1826. unsigned long celt;
  1827. LPITEMIDLIST pidlenum;
  1828. if ((S_OK == penum->Next(1, &pidlenum, &celt)) && (celt == 1))
  1829. {
  1830. ILFree(pidlenum);
  1831. bAreDocs = TRUE;
  1832. }
  1833. penum->Release();
  1834. }
  1835. psf->Release();
  1836. }
  1837. ILFree(pidl);
  1838. }
  1839. // Check other MRU registry keys
  1840. if (!bAreDocs)
  1841. {
  1842. int i;
  1843. for (i = 0; i < ARRAYSIZE(c_szRegMruKeysToDelete); i++)
  1844. {
  1845. HKEY hkey;
  1846. // ALL_ACCESS to delete c_szRegMruKeysToDelete.
  1847. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegMruKeysToDelete[i], 0L, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS)
  1848. {
  1849. bAreDocs = TRUE;
  1850. RegCloseKey(hkey);
  1851. }
  1852. }
  1853. }
  1854. Button_Enable(GetDlgItem(hDlg, id), bAreDocs);
  1855. }
  1856. void ClearRecentDocumentsAndMRUStuff(BOOL fBroadcastChange)
  1857. {
  1858. int i;
  1859. SHAddToRecentDocs(0, NULL);
  1860. // Flush other MRUs in the registry for privacy
  1861. for (i = 0; i < ARRAYSIZE(c_szRegMruKeysToDelete); i++)
  1862. {
  1863. SHDeleteKey(HKEY_CURRENT_USER, c_szRegMruKeysToDelete[i]);
  1864. if (fBroadcastChange)
  1865. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0,
  1866. (LPARAM)c_szRegMruKeysToDelete[i]);
  1867. }
  1868. }
  1869. void HandleClearButtonClick(HWND hwndClear)
  1870. {
  1871. HCURSOR hc = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1872. ClearRecentDocumentsAndMRUStuff(TRUE);
  1873. SetCursor(hc);
  1874. //
  1875. // Before disabling the button, shove focus off it.
  1876. //
  1877. if (GetFocus() == hwndClear)
  1878. {
  1879. SendMessage(GetParent(hwndClear), WM_NEXTDLGCTL, 0, MAKELONG(FALSE, 0));
  1880. }
  1881. Button_Enable(hwndClear, FALSE);
  1882. }
  1883. void Reorder(HDPA hdpa)
  1884. {
  1885. for (int i = DPA_GetPtrCount(hdpa) - 1; i >= 0; i--)
  1886. {
  1887. PORDERITEM poi = (PORDERITEM)DPA_FastGetPtr(hdpa, i);
  1888. poi->nOrder = i;
  1889. }
  1890. }
  1891. void MenuOrderSort(HKEY hkeyRoot, IShellFolder* psf);
  1892. void MenuOrderSortKeyWithFolder(HKEY hkeyRoot, LPTSTR pszKey, IShellFolder* psf)
  1893. {
  1894. HKEY hkey;
  1895. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, pszKey, 0, KEY_READ | KEY_WRITE, &hkey))
  1896. {
  1897. MenuOrderSort(hkey, psf);
  1898. RegCloseKey(hkey);
  1899. }
  1900. }
  1901. // Binds to the Key pszKey, under hkey root, using psf, and sorts the resultant order.
  1902. void MenuOrderSortSubKey(HKEY hkeyRoot, LPTSTR pszFolder, LPTSTR pszKey, IShellFolder* psf)
  1903. {
  1904. LPITEMIDLIST pidl;
  1905. DWORD cbEaten;
  1906. DWORD dwAttrib;
  1907. if (SUCCEEDED(psf->ParseDisplayName(NULL, NULL, pszFolder, &cbEaten, &pidl, &dwAttrib)))
  1908. {
  1909. IShellFolder* psfSub;
  1910. if (SUCCEEDED(psf->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfSub))))
  1911. {
  1912. MenuOrderSortKeyWithFolder(hkeyRoot, pszKey, psfSub);
  1913. psfSub->Release();
  1914. }
  1915. ILFree(pidl);
  1916. }
  1917. }
  1918. void MenuOrderSort(HKEY hkeyRoot, IShellFolder* psf)
  1919. {
  1920. // Try to open Value Order
  1921. IStream* pstm = SHOpenRegStream(hkeyRoot, TEXT(""), TEXT("Order"), STGM_READWRITE);
  1922. if (pstm)
  1923. {
  1924. IOrderList2* pol2;
  1925. if (SUCCEEDED(CoCreateInstance(CLSID_OrderListExport, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IOrderList2, &pol2))))
  1926. {
  1927. HDPA hdpa;
  1928. if (SUCCEEDED(pol2->LoadFromStream(pstm, &hdpa, psf)))
  1929. {
  1930. // Since it's stored ordered by name, this should be no problem.
  1931. Reorder(hdpa);
  1932. // Set the seek pointer at the beginning.
  1933. LARGE_INTEGER liZero = {0};
  1934. pstm->Seek(liZero, STREAM_SEEK_SET, NULL);
  1935. pol2->SaveToStream(pstm, hdpa);
  1936. DPA_Destroy(hdpa);
  1937. }
  1938. pol2->Release();
  1939. }
  1940. pstm->Release();
  1941. }
  1942. // Now enumerate sub keys.
  1943. TCHAR szKey[MAX_PATH];
  1944. DWORD cbKey = ARRAYSIZE(szKey);
  1945. int iIndex = 0;
  1946. while (ERROR_SUCCESS == RegEnumKeyEx(hkeyRoot, iIndex, szKey, &cbKey, NULL, NULL, NULL, NULL))
  1947. {
  1948. MenuOrderSortSubKey(hkeyRoot, szKey, szKey, psf);
  1949. iIndex++;
  1950. cbKey = ARRAYSIZE(szKey);
  1951. }
  1952. }
  1953. // Defined in Tray.c
  1954. IShellFolder* BindToFolder(LPCITEMIDLIST pidl);
  1955. void StartMenuSort()
  1956. {
  1957. IShellFolder* psf = NULL;
  1958. LPITEMIDLIST pidl;
  1959. HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_STARTMENU, &pidl);
  1960. if (SUCCEEDED(hr))
  1961. {
  1962. LPITEMIDLIST pidl2;
  1963. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_STARTMENU, &pidl2)))
  1964. {
  1965. IAugmentedShellFolder2* pasf;
  1966. IShellFolder* psfCommon;
  1967. IShellFolder* psfUser;
  1968. HRESULT hres = CoCreateInstance(CLSID_MergedFolder, NULL, CLSCTX_INPROC_SERVER,
  1969. IID_PPV_ARG(IAugmentedShellFolder2, &pasf));
  1970. if (SUCCEEDED(hres))
  1971. {
  1972. psfUser = BindToFolder(pidl);
  1973. if (psfUser)
  1974. {
  1975. pasf->AddNameSpace(NULL, psfUser, pidl, ASFF_DEFAULT | ASFF_DEFNAMESPACE_ALL);
  1976. psfUser->Release();
  1977. }
  1978. psfCommon = BindToFolder(pidl2);
  1979. if (psfCommon)
  1980. {
  1981. pasf->AddNameSpace(NULL, psfCommon, pidl2, ASFF_DEFAULT);
  1982. psfCommon->Release();
  1983. }
  1984. hres = pasf->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
  1985. pasf->Release();
  1986. }
  1987. ILFree(pidl2);
  1988. }
  1989. else
  1990. {
  1991. psf = BindToFolder(pidl);
  1992. }
  1993. ILFree(pidl);
  1994. }
  1995. if (psf)
  1996. {
  1997. HKEY hkeyRoot;
  1998. // Recursivly sort the orders. Should this be on another thread?
  1999. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, STRREG_STARTMENU,
  2000. 0, KEY_READ | KEY_WRITE, &hkeyRoot))
  2001. {
  2002. MenuOrderSort(hkeyRoot, psf);
  2003. // Sort the My Documents menu item:
  2004. LPITEMIDLIST pidlMyDocs;
  2005. SHGetFolderLocation(NULL, CSIDL_PERSONAL, NULL, 0, &pidlMyDocs);
  2006. if (pidlMyDocs)
  2007. {
  2008. IShellFolder* psfMyDocs;
  2009. if (SUCCEEDED(SHBindToObjectEx(NULL, pidlMyDocs, NULL, IID_PPV_ARG(IShellFolder, &psfMyDocs))))
  2010. {
  2011. MenuOrderSortKeyWithFolder(hkeyRoot, TEXT("MyDocuments"), psfMyDocs);
  2012. psfMyDocs->Release();
  2013. }
  2014. ILFree(pidlMyDocs);
  2015. }
  2016. // What happens if the Filesystem programs is not equal to the hard coded string "Programs"? This
  2017. // happens on German: Programme != Programs and we fail to sort. So let's verify:
  2018. TCHAR szPath[MAX_PATH];
  2019. SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 0, szPath);
  2020. LPTSTR pszName = PathFindFileName(szPath);
  2021. if (StrCmpI(pszName, TEXT("Programs")) != 0)
  2022. {
  2023. // Ok, It's not the same, so go bind to that sub tree and sort it.
  2024. MenuOrderSortSubKey(hkeyRoot, pszName, TEXT("Programs"), psf);
  2025. }
  2026. RegCloseKey(hkeyRoot);
  2027. }
  2028. psf->Release();
  2029. }
  2030. }
  2031. BOOL Advanced_OnInitDialog(HWND hwndDlg, SMADVANCED* pAdv)
  2032. {
  2033. if (!pAdv || !pAdv->pTO)
  2034. {
  2035. EndDialog(hwndDlg, 0);
  2036. return FALSE; // no memory?
  2037. }
  2038. SetWindowPtr(hwndDlg, DWLP_USER, pAdv);
  2039. // since the large icon setting is stored in the tray state, not as a standalone reg key, we need to have a temp reg key for the regtreeop to use...
  2040. TRAYVIEWOPTS tvo;
  2041. c_tray.GetTrayViewOpts(&tvo);
  2042. BOOL fLargePrev = !tvo.fSMSmallIcons;
  2043. SHSetValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP, REG_DWORD, (void*) &fLargePrev, sizeof(fLargePrev));
  2044. pAdv->hwndTree = GetDlgItem( hwndDlg, IDC_STARTMENUSETTINGS );
  2045. // HACKHACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE
  2046. #undef TEXT
  2047. #define TEXT(s) s
  2048. HRESULT hr = pAdv->pTO->InitTree(pAdv->hwndTree, HKEY_LOCAL_MACHINE, REGSTR_PATH_SMADVANCED "\\StartMenu", NULL);
  2049. #undef TEXT
  2050. #define TEXT(s) __TEXT(s)
  2051. // find the first root and make sure that it is visible
  2052. TreeView_EnsureVisible(pAdv->hwndTree, TreeView_GetRoot( pAdv->hwndTree ));
  2053. SetDocButton(hwndDlg, IDC_KILLDOCUMENTS);
  2054. return SUCCEEDED(hr);
  2055. }
  2056. void InitStartMenu_DoTreeHelp(SMADVANCED* pAdv, WPARAM wParam)
  2057. {
  2058. TV_HITTESTINFO ht;
  2059. GetCursorPos( &ht.pt ); // get where we were hit
  2060. if (pAdv->hwndTree == WindowFromPoint(ht.pt))
  2061. {
  2062. ScreenToClient( pAdv->hwndTree, &ht.pt ); // translate it to our window
  2063. // retrieve the item hit
  2064. pAdv->pTO->ShowHelp(TreeView_HitTest( pAdv->hwndTree, &ht),HELP_CONTEXTMENU);
  2065. }
  2066. else
  2067. {
  2068. WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
  2069. (ULONG_PTR)(LPVOID)aInitStartMenuHelpIDs);
  2070. }
  2071. }
  2072. BOOL_PTR CALLBACK AdvancedOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  2073. {
  2074. SMADVANCED* pAdv = (SMADVANCED*)GetWindowPtr(hwndDlg, DWLP_USER);
  2075. INSTRUMENT_WNDPROC(SHCNFI_INITSTARTMENU_DLGPROC, hwndDlg, msg, wParam, lParam);
  2076. if (msg != WM_INITDIALOG && !pAdv)
  2077. {
  2078. // We've been re-entered after being destroyed. Bail.
  2079. return FALSE;
  2080. }
  2081. switch (msg)
  2082. {
  2083. case WM_COMMAND:
  2084. switch(GET_WM_COMMAND_ID(wParam, lParam))
  2085. {
  2086. case IDC_ADDSHORTCUT:
  2087. CallAppWiz(hwndDlg, FALSE);
  2088. break;
  2089. case IDC_DELSHORTCUT:
  2090. CallAppWiz(hwndDlg, TRUE);
  2091. break;
  2092. case IDC_RESORT:
  2093. {
  2094. SHChangeDWORDAsIDList dwidl;
  2095. StartMenuSort();
  2096. // Notify everyone that the order changed
  2097. dwidl.cb = sizeof(dwidl) - sizeof(dwidl.cbZero);
  2098. dwidl.dwItem1 = SHCNEE_ORDERCHANGED;
  2099. dwidl.dwItem2 = 0;
  2100. dwidl.cbZero = 0;
  2101. SHChangeNotify(SHCNE_EXTENDED_EVENT, SHCNF_FLUSH, (LPCITEMIDLIST)&dwidl, NULL);
  2102. break;
  2103. }
  2104. case IDC_EXPLOREMENUS:
  2105. ExecExplorerAtStartMenu(hwndDlg);
  2106. break;
  2107. case IDC_KILLDOCUMENTS:
  2108. {
  2109. HandleClearButtonClick(GET_WM_COMMAND_HWND(wParam, lParam));
  2110. }
  2111. break;
  2112. case IDOK:
  2113. {
  2114. pAdv->pTO->WalkTree(WALK_TREE_SAVE);
  2115. TRAYVIEWOPTS tvo;
  2116. c_tray.GetTrayViewOpts(&tvo);
  2117. BOOL fSmallPrev = tvo.fSMSmallIcons;
  2118. // note that we are loading the classic setting for large icons here....
  2119. BOOL fSmallNew = !SHRegGetBoolUSValue(REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP, FALSE, TRUE /* default to large*/);
  2120. if (fSmallPrev != fSmallNew)
  2121. {
  2122. tvo.fSMSmallIcons = fSmallNew;
  2123. c_tray.SetTrayViewOpts(&tvo);
  2124. IMenuPopup_SetIconSize(c_tray.GetStartMenu(), fSmallNew ? BMICON_SMALL : BMICON_LARGE);
  2125. }
  2126. ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)TEXT("TraySettings"), SMTO_NOTIMEOUTIFNOTHUNG, 1000, NULL);
  2127. }
  2128. // fall through
  2129. case IDCANCEL:
  2130. SHDeleteValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP);
  2131. EndDialog(hwndDlg, FALSE); // false to not enable parent's apply
  2132. break;
  2133. }
  2134. break;
  2135. case WM_INITDIALOG:
  2136. return Advanced_OnInitDialog(hwndDlg, (SMADVANCED *)lParam);
  2137. case WM_NOTIFY:
  2138. {
  2139. LPNMHDR pnm = (NMHDR *)lParam;
  2140. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, 0); // handled
  2141. switch (pnm->code)
  2142. {
  2143. case TVN_KEYDOWN:
  2144. {
  2145. TV_KEYDOWN *pnmKeyDown = (TV_KEYDOWN*)((NMHDR *)lParam);
  2146. if (pnmKeyDown->wVKey == VK_SPACE)
  2147. {
  2148. pAdv->pTO->ToggleItem((HTREEITEM)SendMessage(pAdv->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L));
  2149. SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0L);
  2150. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, TRUE); // eat the key
  2151. }
  2152. break;
  2153. }
  2154. case NM_CLICK:
  2155. case NM_DBLCLK:
  2156. // is this click in our tree?
  2157. if ( pnm->idFrom == IDC_STARTMENUSETTINGS )
  2158. {
  2159. TV_HITTESTINFO ht;
  2160. DWORD dwPos = GetMessagePos(); // get where we were hit
  2161. ht.pt.x = GET_X_LPARAM(dwPos);
  2162. ht.pt.y = GET_Y_LPARAM(dwPos);
  2163. ScreenToClient( pAdv->hwndTree, &ht.pt ); // translate it to our window
  2164. // retrieve the item hit
  2165. pAdv->pTO->ToggleItem(TreeView_HitTest( pAdv->hwndTree, &ht));
  2166. SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0L);
  2167. }
  2168. break;
  2169. case NM_RCLICK: // right mouse click
  2170. if (pnm->hwndFrom == pAdv->hwndTree)
  2171. {
  2172. InitStartMenu_DoTreeHelp(pAdv, (WPARAM)pnm->hwndFrom);
  2173. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, TRUE); // eat the click
  2174. return TRUE;
  2175. }
  2176. break;
  2177. }
  2178. break;
  2179. }
  2180. case WM_HELP: // F1
  2181. {
  2182. LPHELPINFO phi = (LPHELPINFO)lParam;
  2183. if (phi->iCtrlId != IDC_STARTMENUSETTINGS)
  2184. {
  2185. WinHelp( (HWND)(phi->hItemHandle), NULL,
  2186. HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aInitStartMenuHelpIDs);
  2187. }
  2188. else
  2189. {
  2190. HTREEITEM hItem;
  2191. //Is this help invoked throught F1 key
  2192. if (GetAsyncKeyState(VK_F1) < 0)
  2193. {
  2194. // Yes. WE need to give help for the currently selected item
  2195. hItem = TreeView_GetSelection(pAdv->hwndTree);
  2196. }
  2197. else
  2198. {
  2199. //No, We need to give help for the item at the cursor position
  2200. TV_HITTESTINFO ht;
  2201. ht.pt = phi->MousePos;
  2202. ScreenToClient(pAdv->hwndTree, &ht.pt); // Translate it to our window
  2203. hItem = TreeView_HitTest(pAdv->hwndTree, &ht);
  2204. }
  2205. pAdv->pTO->ShowHelp(hItem, HELP_WM_HELP);
  2206. }
  2207. break;
  2208. }
  2209. case WM_CONTEXTMENU: // right mouse click
  2210. {
  2211. InitStartMenu_DoTreeHelp(pAdv, wParam);
  2212. break;
  2213. }
  2214. case WM_DESTROY:
  2215. {
  2216. pAdv->pTO->WalkTree(WALK_TREE_DELETE);
  2217. ATOMICRELEASE(pAdv->pTO);
  2218. // make sure we don't re-enter
  2219. SetWindowPtr( hwndDlg, DWLP_USER, NULL );
  2220. }
  2221. break; // WM_DESTORY
  2222. default:
  2223. return FALSE;
  2224. }
  2225. return TRUE;
  2226. }
  2227. #define TPF_PAGEFLAGS (TPF_STARTMENUPAGE | TPF_TASKBARPAGE)
  2228. void DoTaskBarProperties(HWND hwnd, DWORD dwFlags)
  2229. {
  2230. ASSERT(((dwFlags & TPF_PAGEFLAGS) == TPF_STARTMENUPAGE) ||
  2231. ((dwFlags & TPF_PAGEFLAGS) == TPF_TASKBARPAGE));
  2232. UINT nStartPage = (dwFlags & TPF_TASKBARPAGE) ? 0 : 1;
  2233. CTaskBarPropertySheet sheet(nStartPage, hwnd, dwFlags);
  2234. sheet.DoModal(hwnd);
  2235. }
  2236. // Passing iResource=0 deletes the bitmap in the control
  2237. void SetDlgItemBitmap(HWND hDlg, int idStatic, int iResource)
  2238. {
  2239. HBITMAP hbm;
  2240. if (iResource)
  2241. {
  2242. hbm = (HBITMAP)LoadImage(hinstCabinet, MAKEINTRESOURCE(iResource), IMAGE_BITMAP, 0,0, LR_LOADMAP3DCOLORS);
  2243. }
  2244. else
  2245. {
  2246. hbm = NULL;
  2247. }
  2248. hbm = (HBITMAP)SendDlgItemMessage(hDlg, idStatic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
  2249. if (hbm)
  2250. DeleteObject(hbm);
  2251. }
  2252. void SetDlgItemIcon(HWND hDlg, int idStatic, HICON hIcon)
  2253. {
  2254. HICON hiOld = (HICON)SendDlgItemMessage(hDlg, idStatic, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  2255. if (hiOld)
  2256. DestroyIcon(hiOld);
  2257. }
  2258. // REVIEW - use SHGetFileInfo?
  2259. void SetProgramIcon(HWND hDlg, int idLarge, int idSmall)
  2260. {
  2261. HICON hIconLarge = NULL;
  2262. HICON hIconSmall = NULL;
  2263. LPITEMIDLIST pidlMyComp = ILCreateFromPath(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}")); // CLSID_MyComputer;
  2264. if (pidlMyComp)
  2265. {
  2266. IShellFolder *psfDesktop;
  2267. if (SUCCEEDED(SHGetDesktopFolder(&psfDesktop)))
  2268. {
  2269. IExtractIcon *pxi;
  2270. if (SUCCEEDED(psfDesktop->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidlMyComp, IID_PPV_ARG_NULL(IExtractIcon, &pxi))))
  2271. {
  2272. TCHAR szIconFile[MAX_PATH];
  2273. int iIndex;
  2274. UINT wFlags;
  2275. if (S_OK == pxi->GetIconLocation(GIL_FORSHELL, szIconFile, ARRAYSIZE(szIconFile), &iIndex, &wFlags))
  2276. {
  2277. pxi->Extract(szIconFile, iIndex, &hIconLarge, &hIconSmall, (GetSystemMetrics(SM_CXSMICON)<<16) | GetSystemMetrics(SM_CXICON));
  2278. }
  2279. pxi->Release();
  2280. }
  2281. psfDesktop->Release();
  2282. }
  2283. ILFree(pidlMyComp);
  2284. }
  2285. if (hIconLarge)
  2286. SetDlgItemIcon(hDlg, idLarge, hIconLarge);
  2287. if (hIconSmall)
  2288. SetDlgItemIcon(hDlg, idSmall, hIconSmall);
  2289. }