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.

421 lines
14 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1996 **
  4. //*********************************************************************
  5. //
  6. // ADVANCED.C - "Advanced" Property Sheet
  7. //
  8. //
  9. // This is a registry driven UI that walk through the part of the
  10. // registry tree and convert it into a tree view list.
  11. // Note that registry values can be localized, so internation versions
  12. // have to localize the INF file so that setup will set the registry
  13. // with the right text.
  14. //
  15. // Here is how the registry key looks like,
  16. //
  17. // HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions\
  18. // GroupKey1\
  19. // Type="group"
  20. // Text="text to display"
  21. // DefaultImage="somedll.dll,icon_index", (optional).
  22. //
  23. // RadioKey1.1\
  24. // Type="radio"
  25. // Text="text to display"
  26. // (optional) HKeyRoot=any one of the pre-defined root HKEY in DWORD,
  27. // ; default to HKEY_CURRENT_USER.
  28. // (optional) RegPath="path to the key where the setting value is stored."
  29. // ; default to Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions
  30. // ValueName="reg value name."
  31. // CheckedValue=... ; value for this radio button,
  32. // ; if the value is platform dependent, use one of the following two instead
  33. // CheckedValueNT=... ; if the value is platform dependent
  34. // CheckedValueW95=... ; if the value is platform dependent
  35. // DefaultValue=...
  36. // (optional) SPIAction=uiAction param to SystemParametersInfo in DWORD
  37. // (optional) SPIParamON=uiParam param to SystemParametersInfo for this radio button in DWORD
  38. // (optional) Mask=... ; mask for the bitfield 1's for the bits we want to be able to set/clear
  39. //
  40. // RadioKey1.2\
  41. // Type="radio"
  42. // Text="text to display"
  43. // (optional) HKeyRoot=any one of the pre-defined root HKEY in DWORD,
  44. // ; default to HKEY_CURRENT_USER.
  45. // (optional) RegPath="path to the key where the setting value is stored."
  46. // ; default to Software\Microsoft\Windows\CurrentVersion\Explorer\AdvancedOptions
  47. // ValueName="reg value name."
  48. // CheckedValue=... ; value for this checkbox if it's checked
  49. // ; if the value is platform dependent, use one of the following two instead
  50. // CheckedValueNT=... ; if the value is platform dependent
  51. // CheckedValueW95=... ; if the value is platform dependent
  52. // UncheckedValue=... ; value for this checkbox if it's unchecked
  53. // DefaultValue=...
  54. // (optional) SPIAction=uiAction param to SystemParametersInfo in DWORD
  55. // (optional) SPIParamON=uiParam param to SystemParametersInfo if checked in DWORD
  56. // (optional) SPIParamOFF=uiParam param to SystemParametersInfo if checked in DWORD
  57. // (optional) Mask=... ; mask for the bitfield 1's for the bits we want to be able to set/clear
  58. //
  59. // CheckBoxKey1.1\
  60. // ...
  61. // GroupKey1.1\
  62. // ...
  63. // GroupKey2\
  64. // ...
  65. // CheckBoxKey2.1\
  66. // ...
  67. // CheckBoxKey2.2\
  68. // ...
  69. //
  70. //
  71. // Notes:
  72. // 1. All the settings are store in HKCU\...\Explorer\Settings key,
  73. // code can be added to support any random absolute reg path for
  74. // the settings.
  75. //
  76. #include "stdafx.h"
  77. #include "utils.h"
  78. #pragma hdrstop
  79. void Cabinet_StateChanged(void);
  80. //
  81. // Private Calls and structures
  82. //
  83. //
  84. typedef struct {
  85. HWND hDlg; // handle of our dialog
  86. HWND hwndTree; // handle to the treeview
  87. IRegTreeOptions *pTO; // pointer to RegTreeOptions interface
  88. CFolderOptionsPsx *ppsx; // to talk to our propsheet sibling
  89. BOOL fDirty; // Dirty bit to detect if anything changed.
  90. } ADVANCEDPAGE, *LPADVANCEDPAGE;
  91. #define ENABLEAPPLY(hDlg) SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L)
  92. //
  93. // Initializes Advanced property sheet
  94. //
  95. // History:
  96. void Install_AdvancedShellSettings(SHELLSTATE * pss);
  97. BOOL AdvancedDlgInit(HWND hDlg, LPARAM lParam)
  98. {
  99. HRESULT hr;
  100. LPADVANCEDPAGE pAdv = (LPADVANCEDPAGE)LocalAlloc(LPTR, sizeof(*pAdv));
  101. if (!pAdv)
  102. {
  103. EndDialog(hDlg, 0);
  104. return FALSE; // no memory?
  105. }
  106. // We expose some of SHGetSetSettings in the advanced settings section,
  107. // so we need to migrate these PER-USER settings from the SHELLSTATE
  108. // structure into the registry tree structure once per user. Since we
  109. // don't have a per-user install section, do it here on demand.
  110. // We don't have to do it every time, but that's easier...
  111. Install_AdvancedShellSettings(NULL);
  112. // tell dialog where to get info
  113. SetWindowPtr(hDlg, DWLP_USER, pAdv);
  114. PROPSHEETPAGE *pps = (PROPSHEETPAGE *)lParam;
  115. pAdv->ppsx = (CFolderOptionsPsx *)pps->lParam;
  116. //Check if we have pointer to Shell Browser
  117. if (!pAdv->ppsx->HasBrowserService())
  118. {
  119. //Hey ! we dont have pointer to Shell Browser so we must have been
  120. //invoked through a global Folder Options . In this case it doesn't
  121. //make sense to say "You can make all your folders look the same Like Current Folder"
  122. //because we dont have a current folder so let just disable the button "Like Current Folder"
  123. EnableWindow(GetDlgItem(hDlg, IDC_ADVO_USECURRENTFOLDER), FALSE);
  124. }
  125. // save dialog handle
  126. pAdv->hDlg = hDlg;
  127. pAdv->hwndTree = GetDlgItem(pAdv->hDlg, IDC_ADVO_ADVANCEDTREE);
  128. DWORD dwServerType = CLSCTX_INPROC_SERVER;
  129. hr = CoCreateInstance(CLSID_CRegTreeOptions, NULL, dwServerType,
  130. IID_IRegTreeOptions, (LPVOID *)&(pAdv->pTO));
  131. if (SUCCEEDED(hr))
  132. {
  133. // HACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE
  134. #undef TEXT
  135. #define TEXT(s) s
  136. hr = pAdv->pTO->InitTree(pAdv->hwndTree, HKEY_LOCAL_MACHINE, REGSTR_EXPLORER_ADVANCED, NULL);
  137. #undef TEXT
  138. #define TEXT(s) __TEXT(s)
  139. }
  140. // find the first root and make sure that it is visible
  141. TreeView_EnsureVisible(pAdv->hwndTree, TreeView_GetRoot(pAdv->hwndTree));
  142. return SUCCEEDED(hr) ? TRUE : FALSE;
  143. }
  144. void Tree_OnNotify(LPADVANCEDPAGE pAdv)
  145. {
  146. TV_HITTESTINFO ht;
  147. GetCursorPos(&ht.pt); // get where we were hit
  148. ScreenToClient(pAdv->hwndTree, &ht.pt); // translate it to our window
  149. // retrieve the item hit
  150. // IRegTreeOptions might fail to cocreate under stress conditions and
  151. // low memory, in which case we would fault here if we dont check for
  152. // pTO. Bug # 211108 - ramkumar
  153. if (pAdv->pTO)
  154. {
  155. pAdv->pTO->ToggleItem(TreeView_HitTest(pAdv->hwndTree, &ht));
  156. ENABLEAPPLY(pAdv->hDlg);
  157. pAdv->fDirty = TRUE;
  158. }
  159. } // Tree_OnNotify
  160. #if 0
  161. void AnimateToTray(HWND hwnd)
  162. {
  163. HWND hwndTray = FindWindow(TEXT("Shell_TrayWnd"), NULL);
  164. if (hwndTray)
  165. {
  166. HWND hwndIcons = FindWindowEx(hwndTray, NULL, TEXT("TrayNotifyWnd"), NULL);
  167. if (hwndIcons)
  168. {
  169. RECT rcSource, rcDest;
  170. GetWindowRect(hwnd, &rcSource);
  171. GetWindowRect(hwndIcons, &rcDest);
  172. DrawAnimatedRects(hwnd, IDANI_CAPTION, &rcSource, &rcDest);
  173. }
  174. }
  175. }
  176. #endif
  177. //
  178. // AdvancedDlgOnNotify()
  179. //
  180. // Handles Advanced property sheets WM_NOTIFY messages
  181. //
  182. //
  183. void AdvancedDlgOnNotify(LPADVANCEDPAGE pAdv, LPNMHDR psn)
  184. {
  185. SetWindowLongPtr(pAdv->hDlg, DWLP_MSGRESULT, 0); // handled
  186. switch (psn->code)
  187. {
  188. case TVN_KEYDOWN:
  189. {
  190. TV_KEYDOWN *pnm = (TV_KEYDOWN*)psn;
  191. if (pnm->wVKey == VK_SPACE)
  192. {
  193. pAdv->pTO->ToggleItem((HTREEITEM)SendMessage(pAdv->hwndTree, TVM_GETNEXTITEM, TVGN_CARET, NULL));
  194. ENABLEAPPLY(pAdv->hDlg);
  195. pAdv->fDirty = TRUE;
  196. // Specify that we handled the key, so we don't beep
  197. SetWindowLongPtr(pAdv->hDlg, DWLP_MSGRESULT, TRUE);
  198. }
  199. break;
  200. }
  201. case NM_CLICK:
  202. case NM_DBLCLK:
  203. // is this click in our tree?
  204. if (psn->idFrom == IDC_ADVO_ADVANCEDTREE)
  205. {
  206. // yes...
  207. Tree_OnNotify(pAdv);
  208. }
  209. break;
  210. case PSN_APPLY:
  211. if (pAdv->fDirty) //We will save these only if something changed.
  212. {
  213. pAdv->pTO->WalkTree(WALK_TREE_SAVE);
  214. CABINETSTATE cs;
  215. ReadCabinetState(&cs, sizeof(cs)); // refresh the global CABINETSTATE
  216. WriteCabinetState(&cs); // and make sure we commit to the bitfield.
  217. // We should only notify if needed.
  218. SHRefreshSettings(); // refresh the SHELLSTATE structure
  219. SHSettingsChanged(0, 0); // invalidate the restrictions
  220. // Let everybody know about the new settings
  221. SendNotifyMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
  222. // Okay now tell all Cabinets to refresh
  223. Cabinet_RefreshAll(Cabinet_RefreshEnum, (LPARAM)0L);
  224. }
  225. break;
  226. }
  227. }
  228. const static DWORD aAdvOptsHelpIDs[] = { // Context Help IDs
  229. IDC_ADVO_GROUPBOX, IDH_COMM_GROUPBOX,
  230. IDC_ADVO_ADVANCEDTEXT, IDH_GROUPBOX,
  231. IDC_ADVO_ADV_RESTORE_DEF, IDH_RESTORE_DEFAULT,
  232. IDC_ADVO_RESETTOORIGINAL, IDH_RESET_TO_ORIGINAL,
  233. IDC_ADVO_USECURRENTFOLDER, IDH_USE_CURRENT_FOLDER,
  234. IDC_ADVO_IMAGEFOLDER, -1, //Suppress help for this item.
  235. IDC_ADVO_STATICTEXT, -1, //Suppress help for this item.
  236. 0, 0
  237. };
  238. //
  239. // AdvancedDlgProc
  240. //
  241. // History:
  242. //
  243. //
  244. BOOL_PTR CALLBACK AdvancedOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  245. {
  246. LPADVANCEDPAGE pAdv = (LPADVANCEDPAGE)GetWindowPtr(hDlg, DWLP_USER);
  247. if (uMsg == WM_INITDIALOG)
  248. {
  249. // Initialize Dialog controls
  250. return AdvancedDlgInit(hDlg, lParam);
  251. }
  252. if (pAdv)
  253. {
  254. switch (uMsg)
  255. {
  256. case WM_NOTIFY:
  257. AdvancedDlgOnNotify(pAdv, (LPNMHDR)lParam);
  258. return TRUE;
  259. break;
  260. case WM_COMMAND:
  261. switch (GET_WM_COMMAND_ID(wParam, lParam))
  262. {
  263. case IDC_ADVO_ADV_RESTORE_DEF:
  264. pAdv->pTO->WalkTree(WALK_TREE_RESTORE);
  265. ENABLEAPPLY(hDlg);
  266. pAdv->fDirty = TRUE;
  267. break;
  268. case IDC_ADVO_USECURRENTFOLDER:
  269. if (ShellMessageBox(HINST_THISDLL, hDlg,
  270. MAKEINTRESOURCE(IDS_LIKECURRENT_TEXT),
  271. MAKEINTRESOURCE(IDS_FOLDERVIEWS),
  272. MB_YESNO | MB_ICONINFORMATION) == IDYES)
  273. {
  274. pAdv->ppsx->SetAsDefFolderSettings();
  275. pAdv->ppsx->SetNeedRefresh(TRUE);
  276. pAdv->fDirty = TRUE;
  277. }
  278. break;
  279. case IDC_ADVO_RESETTOORIGINAL:
  280. if (ShellMessageBox(HINST_THISDLL, hDlg,
  281. MAKEINTRESOURCE(IDS_RESETALL_TEXT),
  282. MAKEINTRESOURCE(IDS_FOLDERVIEWS),
  283. MB_YESNO | MB_ICONINFORMATION) == IDYES)
  284. {
  285. pAdv->ppsx->ResetDefFolderSettings();
  286. pAdv->ppsx->SetNeedRefresh(TRUE);
  287. pAdv->fDirty = TRUE;
  288. }
  289. break;
  290. }
  291. break;
  292. case WM_HELP: // F1
  293. {
  294. HELPINFO *phi = (HELPINFO *)lParam;
  295. //if the help is for one of the command buttons then call winhelp
  296. if (phi->iCtrlId != IDC_ADVO_ADVANCEDTREE)
  297. {
  298. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT(SHELL_HLP),
  299. HELP_WM_HELP, (DWORD_PTR)(LPSTR)aAdvOptsHelpIDs);
  300. }
  301. else
  302. {
  303. //Help is for the tree item so we need to do some special processing
  304. HTREEITEM hItem;
  305. // Is this help invoked throught F1 key
  306. if (GetAsyncKeyState(VK_F1) < 0)
  307. {
  308. // Yes. WE need to give help for the currently selected item
  309. hItem = TreeView_GetSelection(pAdv->hwndTree);
  310. }
  311. else
  312. {
  313. //No, We need to give help for the item at the cursor position
  314. TV_HITTESTINFO ht;
  315. ht.pt = phi->MousePos;
  316. ScreenToClient(pAdv->hwndTree, &ht.pt); // Translate it to our window
  317. hItem = TreeView_HitTest(pAdv->hwndTree, &ht);
  318. }
  319. if (FAILED(pAdv->pTO->ShowHelp(hItem, HELP_WM_HELP)))
  320. {
  321. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, NULL,
  322. HELP_WM_HELP, (DWORD_PTR)(LPSTR)aAdvOptsHelpIDs);
  323. }
  324. }
  325. break;
  326. }
  327. case WM_CONTEXTMENU: // right mouse click
  328. {
  329. HTREEITEM hti;
  330. if ((LPARAM)-1 == lParam)
  331. {
  332. hti = TreeView_GetSelection(pAdv->hwndTree);
  333. }
  334. else
  335. {
  336. TV_HITTESTINFO ht;
  337. ht.pt.x = GET_X_LPARAM(lParam);
  338. ht.pt.y = GET_Y_LPARAM(lParam);
  339. ScreenToClient(pAdv->hwndTree, &ht.pt);
  340. hti = TreeView_HitTest(pAdv->hwndTree, &ht);
  341. }
  342. // retrieve the item hit
  343. if (FAILED(pAdv->pTO->ShowHelp(hti, HELP_CONTEXTMENU)))
  344. {
  345. WinHelp((HWND) wParam, TEXT(SHELL_HLP),
  346. HELP_CONTEXTMENU, (ULONG_PTR)(LPSTR)aAdvOptsHelpIDs);
  347. }
  348. break;
  349. }
  350. case WM_DESTROY:
  351. // free the tree
  352. if (pAdv->pTO)
  353. {
  354. pAdv->pTO->WalkTree(WALK_TREE_DELETE);
  355. ATOMICRELEASE(pAdv->pTO);
  356. }
  357. LocalFree(pAdv);
  358. // make sure we don't re-enter
  359. SetWindowPtr(hDlg, DWLP_USER, NULL);
  360. break; // WM_DESTORY
  361. }
  362. }
  363. return FALSE; // not handled
  364. }