Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

626 lines
22 KiB

  1. #include "stdafx.h"
  2. #include <trayp.h>
  3. #include "utils.h"
  4. #include "..\deskfldr.h"
  5. #pragma hdrstop
  6. #define SZ_FOLDEROPTSTUBCLASS TEXT("MSGlobalFolderOptionsStub")
  7. void Cabinet_StateChanged(CABINETSTATE *pcs);
  8. const static DWORD aFolderOptsHelpIDs[] = { // Context Help IDs
  9. IDC_FCUS_SAME_WINDOW, IDH_BROWSE_SAME_WINDOW,
  10. IDC_FCUS_SEPARATE_WINDOWS, IDH_BROWSE_SEPARATE_WINDOWS,
  11. IDC_FCUS_WHENEVER_POSSIBLE, IDH_SHOW_WEB_WHEN_POSSIBLE,
  12. IDC_FCUS_WHEN_CHOOSE, IDH_SHOW_WEB_WHEN_CHOOSE,
  13. IDC_FCUS_SINGLECLICK, IDH_SINGLE_CLICK_MODE,
  14. IDC_FCUS_DOUBLECLICK, IDH_DOUBLE_CLICK_MODE,
  15. IDC_FCUS_ICON_IE, IDH_TITLES_LIKE_LINKS,
  16. IDC_FCUS_ICON_HOVER, IDH_TITLES_WHEN_POINT,
  17. IDC_FCUS_ICON_WEBVIEW, IDH_WEB_VIEW_GEN,
  18. IDC_FCUS_ICON_WINDOW, IDH_BROWSE_FOLDERS_GEN,
  19. IDC_FCUS_ICON_CLICKS, IDH_ICON_OPEN_GEN,
  20. IDC_FCUS_RESTORE_DEFAULTS, IDH_RESTORE_DEFAULTS_GEN,
  21. IDC_FCUS_WEBVIEW_GROUP_STATIC, -1, // Suppress help for this item.
  22. 0, 0
  23. };
  24. typedef struct
  25. {
  26. CABINETSTATE cs; // Cached "current" CabState.
  27. CFolderOptionsPsx *ppsx; // to talk to our propsheet sibling
  28. // The icons corresponding to the radio button selected are stored here.
  29. HICON ahIcon[IDC_FCUS_ICON_MAX - IDC_FCUS_WHENEVER_POSSIBLE + 1];
  30. } FOLDEROPTDATA;
  31. //This functions gets/sets the current Active Desktop value
  32. // if 'set' is true then it takes the value in *pActDesk and sets the ActiveDesktop
  33. // accordingly (TRUE-Active Desktop is On, FALSE-Active Desktop is off)
  34. // if 'set' is false then it gets the ActiveDesktop state and assigns that value to the
  35. // *pActDesk
  36. void GetSetActiveDesktop(BOOL *pActDesk, BOOL fset)
  37. {
  38. //This restriction takes precedence over NOACTIVEDESKTOP.
  39. if (SHRestricted(REST_FORCEACTIVEDESKTOPON))
  40. {
  41. *pActDesk = TRUE;
  42. return;
  43. }
  44. else
  45. {
  46. if (PolicyNoActiveDesktop())
  47. {
  48. *pActDesk = FALSE;
  49. return;
  50. }
  51. }
  52. IActiveDesktop* pad;
  53. if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktop, &pad))))
  54. {
  55. COMPONENTSOPT co;
  56. co.dwSize = sizeof(COMPONENTSOPT);
  57. //Get the Current Options
  58. pad->GetDesktopItemOptions(&co, NULL);
  59. //Do we have to set new value ?
  60. if (fset)
  61. {
  62. if (co.fActiveDesktop != *pActDesk)
  63. {
  64. //Yes? Set the new value
  65. co.fActiveDesktop = *pActDesk;
  66. pad->SetDesktopItemOptions(&co, NULL);
  67. //Apply the change
  68. pad->ApplyChanges(AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH);
  69. }
  70. }
  71. else
  72. {
  73. //No, Get the current state and return
  74. *pActDesk = co.fActiveDesktop;
  75. }
  76. pad->Release();
  77. }
  78. }
  79. // Reads CabinetState and Default Folder Settings
  80. void ReadStateAndSettings(HWND hDlg)
  81. {
  82. FOLDEROPTDATA *pfod = (FOLDEROPTDATA *)GetWindowLongPtr(hDlg, DWLP_USER);
  83. pfod->ppsx->SetNeedRefresh(FALSE);
  84. //Get the current Cabinet State
  85. ReadCabinetState(&pfod->cs, sizeof(pfod->cs));
  86. }
  87. //
  88. // This function selects a given radio button among a set of radio buttons AND it sets the Icon
  89. // image corresponding to the radio button selected.
  90. void CheckRBtnAndSetIcon(HWND hDlg, int idStartBtn, int idEndBtn, int idSelectedBtn, FOLDEROPTDATA *pfod, BOOL fCheckBtn)
  91. {
  92. //
  93. // Check the radio button if required
  94. //
  95. if (fCheckBtn)
  96. CheckRadioButton(hDlg, idStartBtn, idEndBtn, idSelectedBtn);
  97. // Now, select the Icon corresponding to this selection
  98. // The following code assumes the order and sequence of the following IDs.
  99. // So, we verify that no one has broken them inadvertently by doing the following
  100. // compile time checks.
  101. COMPILETIME_ASSERT((IDC_FCUS_WHENEVER_POSSIBLE + 1) == IDC_FCUS_WHEN_CHOOSE);
  102. COMPILETIME_ASSERT((IDC_FCUS_WHEN_CHOOSE + 1) == IDC_FCUS_SAME_WINDOW);
  103. COMPILETIME_ASSERT((IDC_FCUS_SAME_WINDOW + 1) == IDC_FCUS_SEPARATE_WINDOWS);
  104. COMPILETIME_ASSERT((IDC_FCUS_SEPARATE_WINDOWS + 1) == IDC_FCUS_SINGLECLICK);
  105. COMPILETIME_ASSERT((IDC_FCUS_SINGLECLICK + 1) == IDC_FCUS_DOUBLECLICK);
  106. COMPILETIME_ASSERT((IDC_FCUS_DOUBLECLICK + 1) == IDC_FCUS_ICON_IE);
  107. COMPILETIME_ASSERT((IDC_FCUS_ICON_IE + 1) == IDC_FCUS_ICON_HOVER);
  108. COMPILETIME_ASSERT((IDC_FCUS_ICON_HOVER + 1) == IDC_FCUS_ICON_MAX);
  109. COMPILETIME_ASSERT((IDI_WEBVIEW_ON + 1) == IDI_WEBVIEW_OFF);
  110. COMPILETIME_ASSERT((IDI_WEBVIEW_OFF + 1) == IDI_SAME_WINDOW);
  111. COMPILETIME_ASSERT((IDI_SAME_WINDOW + 1) == IDI_SEPARATE_WINDOW);
  112. COMPILETIME_ASSERT((IDI_SEPARATE_WINDOW + 1)== IDI_SINGLE_CLICK);
  113. COMPILETIME_ASSERT((IDI_SINGLE_CLICK + 1) == IDI_DOUBLE_CLICK);
  114. COMPILETIME_ASSERT((IDC_FCUS_ICON_WEBVIEW + 1) == IDC_FCUS_ICON_WINDOW);
  115. COMPILETIME_ASSERT((IDC_FCUS_ICON_WINDOW + 1) == IDC_FCUS_ICON_CLICKS);
  116. ASSERT((IDC_FCUS_ICON_MAX - IDC_FCUS_WHENEVER_POSSIBLE + 1) == ARRAYSIZE(pfod->ahIcon));
  117. int iIndex = idSelectedBtn - IDC_FCUS_WHENEVER_POSSIBLE; //Calculate the index into the Icon Table
  118. ASSERT(iIndex < ARRAYSIZE(pfod->ahIcon));
  119. if (pfod->ahIcon[iIndex] == NULL)
  120. pfod->ahIcon[iIndex] = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDI_WEBVIEW_ON + iIndex), IMAGE_ICON, 0,0, LR_DEFAULTSIZE);
  121. // Set the Icon image corresponding to the Radio button selected.
  122. // This dialog is broken into sections of radio buttons. Each section has two and only two main
  123. // radio buttons and a corresponding icon. In order to associate the radio buttons with their
  124. // corresponding icon, all button ids and all icon ids are kept in order (hence the above COMPILETIME_ASSERTs),
  125. // such that the first and second radio buttons belong with the first icon, second and third radio buttons
  126. // belong with the second icon, and so on. Now, given a radio button id, get its position in the list of
  127. // all the radio buttons (that is the index assigment just above) and shift it right by one bit to get the index
  128. // of the corresponding icon. The shift is neccesary because there is only one icon every two radio buttons.
  129. SendDlgItemMessage(hDlg, IDC_FCUS_ICON_WEBVIEW + (iIndex >> 1), STM_SETICON, (WPARAM)(pfod->ahIcon[iIndex]), 0);
  130. }
  131. BOOL_PTR CALLBACK FolderOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  132. {
  133. static BOOL fCheckedSingleClickDialog = FALSE;
  134. static BOOL fCheckedWebStyle = FALSE;
  135. int idSelectedBtn, i;
  136. FOLDEROPTDATA *pfod = (FOLDEROPTDATA *)GetWindowLongPtr(hDlg, DWLP_USER);
  137. switch (uMsg)
  138. {
  139. case WM_INITDIALOG:
  140. {
  141. pfod = (FOLDEROPTDATA *)LocalAlloc(LPTR, sizeof(*pfod));
  142. if (pfod)
  143. {
  144. BOOL fClassicShell, fForceActiveDesktopOn;
  145. SHELLSTATE ss = { 0 };
  146. //Set the Folder Options data
  147. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pfod);
  148. PROPSHEETPAGE *pps = (PROPSHEETPAGE *)lParam;
  149. pfod->ppsx = (CFolderOptionsPsx *)pps->lParam;
  150. ReadStateAndSettings(hDlg);
  151. // No need to initialize the array of icons with zeros
  152. // for(i = 0; i < ARRAYSIZE(pfod->ahIcon); i++)
  153. // pfod->ahIcon[i] = NULL;
  154. fClassicShell = SHRestricted(REST_CLASSICSHELL);
  155. fForceActiveDesktopOn = SHRestricted(REST_FORCEACTIVEDESKTOPON);
  156. SHGetSetSettings(&ss, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC | SSF_WEBVIEW, FALSE);
  157. // browse folder options
  158. CheckRBtnAndSetIcon(hDlg,
  159. IDC_FCUS_SAME_WINDOW,
  160. IDC_FCUS_SEPARATE_WINDOWS,
  161. pfod->cs.fNewWindowMode ? IDC_FCUS_SEPARATE_WINDOWS:IDC_FCUS_SAME_WINDOW, pfod, TRUE);
  162. // show folders as web pages
  163. CheckRBtnAndSetIcon(hDlg,
  164. IDC_FCUS_WHENEVER_POSSIBLE,
  165. IDC_FCUS_WHEN_CHOOSE,
  166. ss.fWebView && !fClassicShell? IDC_FCUS_WHENEVER_POSSIBLE : IDC_FCUS_WHEN_CHOOSE, pfod, TRUE);
  167. if (SHRestricted(REST_NOWEBVIEW) || fClassicShell)
  168. {
  169. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_WHENEVER_POSSIBLE), FALSE);
  170. //EnableWindow(GetDlgItem(hDlg, IDC_FCUS_WHEN_CHOOSE), FALSE);
  171. //EnableWindow(GetDlgItem(hDlg, IDC_FCUS_WEBVIEW_GROUP_STATIC), FALSE);
  172. }
  173. // single/double click
  174. CheckRBtnAndSetIcon(hDlg,
  175. IDC_FCUS_SINGLECLICK,IDC_FCUS_DOUBLECLICK,
  176. !ss.fWin95Classic
  177. ? (ss.fDoubleClickInWebView ? IDC_FCUS_DOUBLECLICK:IDC_FCUS_SINGLECLICK)
  178. : IDC_FCUS_DOUBLECLICK, pfod, TRUE);
  179. if (fClassicShell)
  180. {
  181. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_SINGLECLICK), FALSE);
  182. }
  183. // gray out icon underline behvaior when not in single click mode
  184. BOOL fChecked = IsDlgButtonChecked(hDlg, IDC_FCUS_SINGLECLICK);
  185. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_IE), fChecked);
  186. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_HOVER), fChecked);
  187. DWORD dwIconUnderline = ICON_IE;
  188. if (!fClassicShell)
  189. {
  190. DWORD cb = sizeof(dwIconUnderline);
  191. SHRegGetUSValue(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  192. TEXT("IconUnderline"),
  193. NULL,
  194. &dwIconUnderline,
  195. &cb,
  196. FALSE,
  197. &dwIconUnderline,
  198. cb);
  199. }
  200. // JANK : Fix for MIL bug #105236
  201. // Since these are sub radio buttons, they do not have an icon and therefore do not need
  202. // the CheckRBtnAndSetIcon call
  203. CheckRadioButton(hDlg, IDC_FCUS_ICON_IE, IDC_FCUS_ICON_HOVER,
  204. dwIconUnderline == ICON_IE ? IDC_FCUS_ICON_IE : IDC_FCUS_ICON_HOVER);
  205. /*
  206. CheckRBtnAndSetIcon(hDlg,
  207. IDC_FCUS_ICON_IE, IDC_FCUS_ICON_HOVER,
  208. dwIconUnderline == ICON_IE ? IDC_FCUS_ICON_IE : IDC_FCUS_ICON_HOVER, pfod, TRUE);
  209. */
  210. if (fClassicShell)
  211. {
  212. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_HOVER), FALSE);
  213. }
  214. }
  215. else
  216. {
  217. // Can't use EndDialog because we weren't created by DialogBox()
  218. DestroyWindow(hDlg);
  219. }
  220. return TRUE;
  221. }
  222. case WM_NOTIFY:
  223. switch (((NMHDR *)lParam)->code)
  224. {
  225. case PSN_APPLY:
  226. {
  227. SHELLSTATE oldss = {0}, ss = { 0 };
  228. SHGetSetSettings(&oldss, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC | SSF_WEBVIEW, FALSE);
  229. BOOL fOldValue = BOOLIFY(pfod->cs.fNewWindowMode);
  230. if (IsDlgButtonChecked(hDlg, IDC_FCUS_SAME_WINDOW))
  231. pfod->cs.fNewWindowMode = FALSE;
  232. else
  233. pfod->cs.fNewWindowMode = TRUE;
  234. if (fOldValue != (pfod->cs.fNewWindowMode ? 1 : 0))
  235. Cabinet_StateChanged(&pfod->cs);
  236. if (IsDlgButtonChecked(hDlg, IDC_FCUS_WHENEVER_POSSIBLE))
  237. {
  238. ss.fWin95Classic = FALSE;
  239. ss.fWebView = TRUE;
  240. }
  241. else
  242. {
  243. ss.fWin95Classic = TRUE;
  244. ss.fWebView = FALSE;
  245. }
  246. if (IsDlgButtonChecked(hDlg, IDC_FCUS_SINGLECLICK))
  247. {
  248. ss.fDoubleClickInWebView = FALSE;
  249. ss.fWin95Classic = FALSE;
  250. }
  251. else
  252. {
  253. ss.fDoubleClickInWebView = TRUE;
  254. ss.fWin95Classic = FALSE;
  255. }
  256. DWORD dwIconUnderline, dwOldIconUnderline, dwDefaultIconUnderline;
  257. DWORD cb = sizeof(dwIconUnderline);
  258. //Get the current settings for "IconUnderline"
  259. dwDefaultIconUnderline = -1; // not ICON_IE or will not WM_WININICHANGE
  260. SHRegGetUSValue(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  261. TEXT("IconUnderline"), NULL, &dwOldIconUnderline, &cb,
  262. FALSE, &dwDefaultIconUnderline, sizeof(dwDefaultIconUnderline));
  263. if (IsDlgButtonChecked(hDlg, IDC_FCUS_ICON_IE))
  264. dwIconUnderline = ICON_IE;
  265. else
  266. dwIconUnderline = ICON_HOVER;
  267. if (dwOldIconUnderline != dwIconUnderline) //See if this setting has changed
  268. {
  269. cb = sizeof(dwIconUnderline);
  270. SHRegSetUSValue(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  271. TEXT("IconUnderline"), NULL, &dwIconUnderline, cb,
  272. SHREGSET_DEFAULT);
  273. SHSendMessageBroadcast(WM_WININICHANGE, 0, (LPARAM)TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\IconUnderline"));
  274. }
  275. DWORD dwMask = 0;
  276. if (ss.fWebView != oldss.fWebView)
  277. {
  278. dwMask |= SSF_WEBVIEW;
  279. }
  280. if (ss.fWin95Classic != oldss.fWin95Classic)
  281. {
  282. dwMask |= SSF_WIN95CLASSIC;
  283. }
  284. if (ss.fDoubleClickInWebView != oldss.fDoubleClickInWebView)
  285. {
  286. dwMask |= SSF_DOUBLECLICKINWEBVIEW;
  287. }
  288. if (dwMask)
  289. {
  290. SHGetSetSettings(&ss, dwMask, TRUE);
  291. }
  292. if (ss.fWebView != oldss.fWebView)
  293. {
  294. Cabinet_RefreshAll(Cabinet_UpdateWebViewEnum, (LPARAM)ss.fWebView);
  295. // Note: This refreshes as well.
  296. }
  297. if ((ss.fWin95Classic != oldss.fWin95Classic)
  298. || (ss.fDoubleClickInWebView != oldss.fDoubleClickInWebView))
  299. {
  300. Cabinet_RefreshAll(Cabinet_RefreshEnum, (LPARAM)0);
  301. }
  302. return TRUE;
  303. }
  304. case PSN_KILLACTIVE:
  305. // validate here
  306. // SetWindowLongPtr(hDlg, DWLP_MSGRESULT, !ValidateLink()); // don't allow close
  307. return TRUE;
  308. case PSN_SETACTIVE:
  309. if (pfod->ppsx->NeedRefresh())
  310. {
  311. ReadStateAndSettings(hDlg);
  312. }
  313. return TRUE;
  314. }
  315. break;
  316. case WM_HELP:
  317. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, TEXT(SHELL_HLP),
  318. HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aFolderOptsHelpIDs);
  319. break;
  320. case WM_CONTEXTMENU:
  321. WinHelp((HWND) wParam, TEXT(SHELL_HLP), HELP_CONTEXTMENU,
  322. (ULONG_PTR)(void *)aFolderOptsHelpIDs);
  323. break;
  324. case WM_COMMAND:
  325. idSelectedBtn = GET_WM_COMMAND_ID(wParam, lParam);
  326. switch (idSelectedBtn)
  327. {
  328. case IDC_FCUS_SINGLECLICK:
  329. case IDC_FCUS_DOUBLECLICK:
  330. if (GET_WM_COMMAND_CMD(wParam,lParam) == BN_CLICKED)
  331. {
  332. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_IE), GET_WM_COMMAND_ID(wParam,lParam) == IDC_FCUS_SINGLECLICK);
  333. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_HOVER), GET_WM_COMMAND_ID(wParam,lParam) == IDC_FCUS_SINGLECLICK);
  334. }
  335. //Fall through ...
  336. case IDC_FCUS_WHENEVER_POSSIBLE:
  337. case IDC_FCUS_WHEN_CHOOSE:
  338. case IDC_FCUS_SAME_WINDOW:
  339. case IDC_FCUS_SEPARATE_WINDOWS:
  340. // We do not need to Check the radio button; It is alreay checked. We just need to
  341. // set the corresponding Icon. Hence we pass FALSE.
  342. CheckRBtnAndSetIcon(hDlg, 0, 0, idSelectedBtn, pfod, FALSE);
  343. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  344. break;
  345. case IDC_FCUS_ICON_IE:
  346. case IDC_FCUS_ICON_HOVER:
  347. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  348. break;
  349. case IDC_FCUS_RESTORE_DEFAULTS:
  350. //Set the "factory settings" as the default.
  351. // Don't set the default web view option if web view is disabled via system policy.
  352. if (0 == SHRestricted(REST_NOWEBVIEW))
  353. {
  354. CheckRBtnAndSetIcon(hDlg, IDC_FCUS_WHENEVER_POSSIBLE, IDC_FCUS_WHEN_CHOOSE, IDC_FCUS_WHENEVER_POSSIBLE, pfod, TRUE);
  355. }
  356. CheckRBtnAndSetIcon(hDlg, IDC_FCUS_SAME_WINDOW, IDC_FCUS_SEPARATE_WINDOWS, IDC_FCUS_SAME_WINDOW, pfod, TRUE);
  357. CheckRBtnAndSetIcon(hDlg, IDC_FCUS_SINGLECLICK, IDC_FCUS_DOUBLECLICK, IDC_FCUS_DOUBLECLICK, pfod, TRUE);
  358. CheckRadioButton(hDlg, IDC_FCUS_ICON_IE, IDC_FCUS_ICON_HOVER, IDC_FCUS_ICON_IE);
  359. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_IE), FALSE); //Disable
  360. EnableWindow(GetDlgItem(hDlg, IDC_FCUS_ICON_HOVER), FALSE); //Disable
  361. //Enable the "Apply" button because changes have happened.
  362. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  363. break;
  364. }
  365. break;
  366. case WM_DESTROY:
  367. if (pfod)
  368. {
  369. //Cleanup the Icons array!
  370. for (i = 0; i < ARRAYSIZE(pfod->ahIcon); i++)
  371. {
  372. if (pfod->ahIcon[i])
  373. DestroyIcon(pfod->ahIcon[i]);
  374. }
  375. SetWindowLongPtr(hDlg, DWLP_USER, 0);
  376. LocalFree((HANDLE)pfod);
  377. }
  378. break;
  379. }
  380. return FALSE;
  381. }
  382. // Moved from defview.cpp, which never used these functions
  383. const TCHAR c_szExploreClass[] = TEXT("ExploreWClass");
  384. const TCHAR c_szIExploreClass[] = TEXT("IEFrame");
  385. const TCHAR c_szCabinetClass[] = TEXT("CabinetWClass");
  386. BOOL IsNamedWindow(HWND hwnd, LPCTSTR pszClass)
  387. {
  388. TCHAR szClass[32];
  389. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  390. return lstrcmp(szClass, pszClass) == 0;
  391. }
  392. BOOL IsExplorerWindow(HWND hwnd)
  393. {
  394. return IsNamedWindow(hwnd, c_szExploreClass);
  395. }
  396. BOOL IsTrayWindow(HWND hwnd)
  397. {
  398. return IsNamedWindow(hwnd, TEXT(WNDCLASS_TRAYNOTIFY));
  399. }
  400. BOOL IsFolderWindow(HWND hwnd)
  401. {
  402. TCHAR szClass[32];
  403. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  404. return (lstrcmp(szClass, c_szCabinetClass) == 0) || (lstrcmp(szClass, c_szIExploreClass) == 0);
  405. }
  406. BOOL CALLBACK Cabinet_GlobalStateEnum(HWND hwnd, LPARAM lParam)
  407. {
  408. if (IsFolderWindow(hwnd) || IsExplorerWindow(hwnd))
  409. {
  410. PostMessage(hwnd, CWM_GLOBALSTATECHANGE, 0, 0);
  411. }
  412. return TRUE;
  413. }
  414. void Cabinet_StateChanged(CABINETSTATE *pcs)
  415. {
  416. // Save the new settings away...
  417. WriteCabinetState(pcs);
  418. EnumWindows(Cabinet_GlobalStateEnum, 0);
  419. }
  420. HWND CreateGlobalFolderOptionsStubWindow(void)
  421. {
  422. WNDCLASS wc = {0};
  423. wc.lpfnWndProc = DefWindowProc;
  424. wc.hInstance = HINST_THISDLL;
  425. wc.hIcon = LoadIcon(HINST_THISDLL, MAKEINTRESOURCE(IDI_FOLDEROPTIONS));
  426. wc.lpszClassName = SZ_FOLDEROPTSTUBCLASS;
  427. RegisterClass(&wc);
  428. DWORD dwExStyle = WS_EX_TOOLWINDOW;
  429. if (IS_BIDI_LOCALIZED_SYSTEM())
  430. {
  431. dwExStyle |= dwExStyleRTLMirrorWnd;
  432. }
  433. return CreateWindowEx(dwExStyle, SZ_FOLDEROPTSTUBCLASS, c_szNULL, WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, HINST_THISDLL, NULL);
  434. }
  435. BOOL CALLBACK AddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  436. {
  437. PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *)lParam;
  438. if (ppsh->nPages < MAXPROPPAGES)
  439. {
  440. ppsh->phpage[ppsh->nPages++] = hpage;
  441. return TRUE;
  442. }
  443. return FALSE;
  444. }
  445. void AddPropSheetCLSID(REFCLSID clsid, PROPSHEETHEADER *ppsh)
  446. {
  447. IShellPropSheetExt *psx;
  448. HRESULT hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellPropSheetExt, &psx));
  449. if (SUCCEEDED(hres))
  450. {
  451. psx->AddPages(AddPropSheetPage, (LPARAM)ppsh);
  452. psx->Release();
  453. }
  454. }
  455. DWORD CALLBACK GlobalFolderOptPropSheetThreadProc(void *)
  456. {
  457. HWND hwndStub = CreateGlobalFolderOptionsStubWindow();
  458. if (!SHRestricted(REST_NOFOLDEROPTIONS))
  459. {
  460. PROPSHEETHEADER psh = {0};
  461. HPROPSHEETPAGE rPages[MAXPROPPAGES];
  462. psh.dwSize = sizeof(psh);
  463. psh.dwFlags = PSH_DEFAULT;
  464. psh.hInstance = HINST_THISDLL;
  465. psh.hwndParent = hwndStub;
  466. psh.pszCaption = MAKEINTRESOURCE(IDS_FOLDEROPT_TITLE);
  467. psh.phpage = rPages;
  468. AddPropSheetCLSID(CLSID_ShellFldSetExt, &psh);
  469. AddPropSheetCLSID(CLSID_FileTypes, &psh);
  470. AddPropSheetCLSID(CLSID_OfflineFilesOptions, &psh);
  471. // Display the property sheet.
  472. PropertySheet(&psh);
  473. }
  474. else
  475. {
  476. SHRestrictedMessageBox(hwndStub);
  477. }
  478. // Clean up stub window.
  479. DestroyWindow(hwndStub);
  480. return 0;
  481. }
  482. BOOL CALLBACK FindFolderOptionsEnumProc(HWND hwnd, LPARAM lParam)
  483. {
  484. BOOL fRet = TRUE;
  485. HWND *phwnd = (HWND *)lParam;
  486. TCHAR szClass[MAX_PATH];
  487. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  488. if (lstrcmp(szClass, SZ_FOLDEROPTSTUBCLASS) == 0)
  489. {
  490. *phwnd = hwnd;
  491. fRet = FALSE;
  492. }
  493. return fRet;
  494. }
  495. void DoGlobalFolderOptions(void)
  496. {
  497. HWND hwnd = NULL;
  498. EnumWindows(FindFolderOptionsEnumProc, (LPARAM)&hwnd);
  499. if (hwnd)
  500. {
  501. hwnd = GetLastActivePopup(hwnd);
  502. if (hwnd && IsWindow(hwnd))
  503. {
  504. SetForegroundWindow(hwnd);
  505. }
  506. }
  507. else
  508. {
  509. SHCreateThread(GlobalFolderOptPropSheetThreadProc, NULL, CTF_COINIT, NULL);
  510. }
  511. }
  512. // Public entry point for asking Explorer to launch Options stuff
  513. STDAPI_(void) Options_RunDLLA(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  514. {
  515. PostMessage(GetShellWindow(), CWM_SHOWFOLDEROPT, StrToIntA(pszCmdLine), (LPARAM)0);
  516. }
  517. STDAPI_(void) Options_RunDLLW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR pszCmdLine, int nCmdShow)
  518. {
  519. PostMessage(GetShellWindow(), CWM_SHOWFOLDEROPT, StrToIntW(pszCmdLine), (LPARAM)0);
  520. }