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.

565 lines
14 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. twkeng.c
  5. Abstract:
  6. UI engine for the kerntwk utility. Provides common
  7. registry/UI handling code to make it simple to add
  8. new property pages and items.
  9. Author:
  10. John Vert (jvert) 10-Mar-1995
  11. Revision History:
  12. --*/
  13. #include "nt.h"
  14. #include "ntrtl.h"
  15. #include "nturtl.h"
  16. #include <windows.h>
  17. #include <commctrl.h>
  18. #include "dialogs.h"
  19. #include "twkeng.h"
  20. //
  21. // Local type definitions
  22. //
  23. typedef enum _CONTROL_TYPE {
  24. Edit,
  25. Button,
  26. Unknown
  27. } CONTROL_TYPE;
  28. //
  29. // Globals to this module
  30. //
  31. PTWEAK_PAGE CurrentPage=NULL;
  32. //
  33. // Prototypes for local functions
  34. //
  35. CONTROL_TYPE
  36. GetControlType(
  37. HWND hDlg,
  38. ULONG ControlId
  39. );
  40. VOID
  41. InitializeKnobs(
  42. HWND hDlg
  43. );
  44. PKNOB
  45. FindKnobById(
  46. HWND hPage,
  47. ULONG DialogId
  48. );
  49. BOOL
  50. ProcessCommand(
  51. HWND hDlg,
  52. WPARAM wParam,
  53. LPARAM lParam
  54. );
  55. BOOL
  56. ApplyChanges(
  57. HWND hDlg
  58. );
  59. INT_PTR
  60. APIENTRY
  61. RebootDlgProc(
  62. HWND hDlg,
  63. UINT message,
  64. WPARAM wParam,
  65. LPARAM lParam
  66. );
  67. BOOL
  68. ApplyChanges(
  69. HWND hDlg
  70. )
  71. {
  72. PTWEAK_PAGE Page;
  73. PKNOB Current;
  74. int i;
  75. Page = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
  76. //
  77. // Iterate through the knobs and set their values into the controls
  78. //
  79. i = 0;
  80. Current = Page->Knobs[0];
  81. while (Current != NULL) {
  82. HWND hControl;
  83. TCHAR ClassName[100];
  84. BOOL Translated;
  85. //
  86. // Determine whether the control is an edit
  87. // control or a check box
  88. //
  89. switch (GetControlType(hDlg, Current->DialogId)) {
  90. case Button:
  91. Current->NewValue = IsDlgButtonChecked(hDlg, Current->DialogId);
  92. Current->Flags &= ~KNOB_NO_NEW_VALUE;
  93. break;
  94. case Edit:
  95. Current->NewValue = GetDlgItemInt(hDlg,
  96. Current->DialogId,
  97. &Translated,
  98. FALSE);
  99. if (!Translated) {
  100. Current->Flags |= KNOB_NO_NEW_VALUE;
  101. } else {
  102. Current->Flags &= ~KNOB_NO_NEW_VALUE;
  103. }
  104. break;
  105. }
  106. Current = Page->Knobs[++i];
  107. }
  108. //
  109. // If this page has a dynamic callback, allow it to try and apply
  110. // its own knobs. If there is no dynamic callback, or the callback's
  111. // initialization fails, get the defaults from the registry. If the
  112. // appropriate value does not exist, set the knob to be empty.
  113. //
  114. if ((Page->DynamicChange == NULL) ||
  115. (Page->DynamicChange(FALSE,hDlg) == FALSE)) {
  116. //
  117. // Attempt to update registry from the knobs
  118. //
  119. i = 0;
  120. Current = Page->Knobs[i];
  121. while (Current != NULL) {
  122. LONG Result;
  123. HKEY Key;
  124. DWORD Size;
  125. DWORD Value;
  126. DWORD Disposition;
  127. if (Current->KeyPath != NULL) {
  128. Result = RegCreateKeyEx(Current->RegistryRoot,
  129. Current->KeyPath,
  130. 0,
  131. NULL,
  132. 0,
  133. MAXIMUM_ALLOWED,
  134. NULL,
  135. &Key,
  136. &Disposition);
  137. if (Result == ERROR_SUCCESS) {
  138. if (Current->Flags & KNOB_NO_NEW_VALUE) {
  139. //
  140. // Try and delete the value
  141. //
  142. Result = RegDeleteValue(Key, Current->ValueName);
  143. RegCloseKey(Key);
  144. if (Result == ERROR_SUCCESS) {
  145. Current->Flags |= KNOB_NO_CURRENT_VALUE;
  146. }
  147. } else {
  148. //
  149. // Set the current value
  150. //
  151. Result = RegSetValueEx(Key,
  152. Current->ValueName,
  153. 0,
  154. REG_DWORD,
  155. (LPBYTE)&Current->NewValue,
  156. sizeof(Current->NewValue));
  157. RegCloseKey(Key);
  158. if (Result == ERROR_SUCCESS) {
  159. Current->CurrentValue = Current->NewValue;
  160. Current->Flags &= ~KNOB_NO_CURRENT_VALUE;
  161. }
  162. }
  163. }
  164. } else {
  165. Current->CurrentValue = Current->NewValue;
  166. Current->Flags = 0;
  167. }
  168. Current = Page->Knobs[++i];
  169. }
  170. SendMessage(GetParent(hDlg),
  171. PSM_REBOOTSYSTEM,
  172. 0,
  173. 0);
  174. }
  175. return(TRUE);
  176. }
  177. BOOL
  178. ProcessCommand(
  179. HWND hDlg,
  180. WPARAM wParam,
  181. LPARAM lParam
  182. )
  183. {
  184. PKNOB Knob;
  185. ULONG DialogId;
  186. BOOL Translated;
  187. DialogId = LOWORD(wParam);
  188. Knob = FindKnobById(hDlg, DialogId);
  189. switch (GetControlType(hDlg, DialogId)) {
  190. case Edit:
  191. if (HIWORD(wParam) == EN_CHANGE) {
  192. if (Knob != NULL) {
  193. Knob->NewValue = GetDlgItemInt(hDlg, DialogId, &Translated, FALSE);
  194. if ((Knob->NewValue != Knob->CurrentValue) ||
  195. (Translated && (Knob->Flags & KNOB_NO_CURRENT_VALUE)) ||
  196. (!Translated && ((Knob->Flags & KNOB_NO_CURRENT_VALUE) == 0))) {
  197. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  198. }
  199. if (Translated) {
  200. Knob->Flags &= ~KNOB_NO_NEW_VALUE;
  201. }
  202. } else {
  203. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  204. }
  205. return(TRUE);
  206. }
  207. break;
  208. case Button:
  209. if (HIWORD(wParam) == BN_CLICKED) {
  210. if (Knob != NULL) {
  211. Knob->NewValue = IsDlgButtonChecked(hDlg, DialogId);
  212. if (Knob->NewValue != Knob->CurrentValue) {
  213. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  214. }
  215. } else {
  216. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  217. }
  218. return(TRUE);
  219. }
  220. break;
  221. }
  222. return(FALSE);
  223. }
  224. CONTROL_TYPE
  225. GetControlType(
  226. HWND hDlg,
  227. ULONG ControlId
  228. )
  229. {
  230. HWND hControl;
  231. TCHAR ClassName[100];
  232. hControl = GetDlgItem(hDlg, ControlId);
  233. if (hControl != NULL) {
  234. GetClassName(hControl, ClassName, 100);
  235. if (_stricmp(ClassName, "BUTTON")==0) {
  236. return(Button);
  237. } else if (_stricmp(ClassName, "EDIT") == 0) {
  238. return(Edit);
  239. }
  240. }
  241. return(Unknown);
  242. }
  243. VOID
  244. InitializeKnobs(
  245. HWND hDlg
  246. )
  247. {
  248. PTWEAK_PAGE Page;
  249. PKNOB Current;
  250. int i;
  251. Page = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
  252. //
  253. // If this page has a dynamic callback, allow it to try and initialize
  254. // its own knobs. If there is no dynamic callback, or the callback's
  255. // initialization fails, get the defaults from the registry. If the
  256. // appropriate value does not exist, set the knob to be empty.
  257. //
  258. if ((Page->DynamicChange == NULL) ||
  259. (Page->DynamicChange(TRUE,hDlg) == FALSE)) {
  260. //
  261. // Attempt to initialize knobs from the registry.
  262. //
  263. i = 0;
  264. Current = Page->Knobs[0];
  265. while (Current != NULL) {
  266. LONG Result;
  267. HKEY Key;
  268. DWORD Size;
  269. DWORD Value;
  270. Result = RegOpenKeyEx(Current->RegistryRoot,
  271. Current->KeyPath,
  272. 0,
  273. KEY_QUERY_VALUE,
  274. &Key);
  275. if (Result == ERROR_SUCCESS) {
  276. //
  277. // Query out the value we are interested in
  278. //
  279. Size = 4;
  280. Result = RegQueryValueEx(Key,
  281. Current->ValueName,
  282. 0,
  283. NULL,
  284. (LPBYTE)&Value,
  285. &Size);
  286. RegCloseKey(Key);
  287. if (Result == ERROR_SUCCESS) {
  288. Current->Flags = 0;
  289. Current->CurrentValue = Value;
  290. }
  291. }
  292. if (Result != ERROR_SUCCESS) {
  293. Current->Flags |= KNOB_NO_CURRENT_VALUE;
  294. Current->Flags |= KNOB_NO_NEW_VALUE;
  295. }
  296. Current = Page->Knobs[++i];
  297. }
  298. }
  299. //
  300. // Iterate through the knobs and set their values into the controls
  301. //
  302. i = 0;
  303. Current = Page->Knobs[0];
  304. while (Current != NULL) {
  305. HWND hControl;
  306. TCHAR ClassName[100];
  307. //
  308. // Determine whether the control is an edit
  309. // control or a check box
  310. //
  311. if ((Current->Flags & KNOB_NO_CURRENT_VALUE) == 0) {
  312. switch (GetControlType(hDlg, Current->DialogId)) {
  313. case Button:
  314. CheckDlgButton(hDlg,
  315. Current->DialogId,
  316. Current->CurrentValue);
  317. break;
  318. case Edit:
  319. SetDlgItemInt(hDlg,
  320. Current->DialogId,
  321. Current->CurrentValue,
  322. FALSE);
  323. break;
  324. }
  325. }
  326. Current = Page->Knobs[++i];
  327. }
  328. }
  329. PKNOB
  330. FindKnobById(
  331. HWND hPage,
  332. ULONG DialogId
  333. )
  334. {
  335. PTWEAK_PAGE Page;
  336. PKNOB Current;
  337. int i;
  338. Page = (PTWEAK_PAGE)GetWindowLongPtr(hPage, DWLP_USER);
  339. i=0;
  340. Current = Page->Knobs[0];
  341. while (Current != NULL) {
  342. if (Current->DialogId == DialogId) {
  343. break;
  344. }
  345. Current = Page->Knobs[++i];
  346. }
  347. return(Current);
  348. }
  349. INT_PTR
  350. APIENTRY
  351. PageDlgProc(
  352. HWND hDlg,
  353. UINT message,
  354. WPARAM wParam,
  355. LPARAM lParam)
  356. {
  357. LPNMHDR Notify;
  358. PTWEAK_PAGE TweakPage;
  359. TweakPage = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
  360. switch (message) {
  361. case WM_INITDIALOG:
  362. //
  363. // This page is being created.
  364. //
  365. TweakPage = (PTWEAK_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
  366. //
  367. // Stash a pointer to our page
  368. //
  369. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)TweakPage);
  370. //
  371. // Initialize controls.
  372. //
  373. InitializeKnobs(hDlg);
  374. return(TRUE);
  375. case WM_COMMAND:
  376. return(ProcessCommand(hDlg, wParam, lParam));
  377. case WM_NOTIFY:
  378. Notify = (LPNMHDR)lParam;
  379. switch (Notify->code) {
  380. case PSN_SETACTIVE:
  381. CurrentPage = TweakPage;
  382. break;
  383. case PSN_APPLY:
  384. //
  385. // User has chosen to apply the changes.
  386. //
  387. if (ApplyChanges(hDlg)) {
  388. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  389. return(TRUE);
  390. }
  391. }
  392. }
  393. return FALSE;
  394. }
  395. int
  396. TweakSheet(
  397. DWORD PageCount,
  398. PTWEAK_PAGE TweakPages[]
  399. )
  400. /*++
  401. Routine Description:
  402. Assembles the appropriate structures for a property sheet
  403. and creates the sheet.
  404. Arguments:
  405. PageCount - Supplies the number of pages.
  406. TweakPages - Supplies the pages.
  407. Return Value:
  408. Return value from PropertySheet()
  409. --*/
  410. {
  411. PROPSHEETHEADER psh;
  412. PROPSHEETPAGE *Page;
  413. DWORD i;
  414. INT_PTR Status;
  415. Page = LocalAlloc(LMEM_FIXED, PageCount * sizeof(PROPSHEETPAGE));
  416. if (Page==NULL) {
  417. return(ERROR_NOT_ENOUGH_MEMORY);
  418. }
  419. //
  420. // Initialize pages.
  421. //
  422. for (i=0; i<PageCount; i++) {
  423. Page[i].dwSize = sizeof(PROPSHEETPAGE);
  424. Page[i].dwFlags = PSP_USEICONID;
  425. Page[i].hInstance = GetModuleHandle(NULL);
  426. Page[i].pszIcon = MAKEINTRESOURCE(IDI_KERNTWEAK);
  427. Page[i].pszTemplate = TweakPages[i]->DlgTemplate;
  428. Page[i].pfnDlgProc = PageDlgProc;
  429. Page[i].pszTitle = NULL;
  430. Page[i].lParam = (LPARAM)TweakPages[i];
  431. }
  432. //
  433. // Initialize header.
  434. //
  435. psh.dwSize = sizeof(PROPSHEETHEADER);
  436. psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
  437. psh.hwndParent = NULL;
  438. psh.hInstance = GetModuleHandle(NULL);
  439. psh.pszIcon = MAKEINTRESOURCE(IDI_KERNTWEAK);
  440. psh.pszCaption = TEXT("Windows NT Kernel Tweaker");
  441. psh.nPages = PageCount;
  442. psh.ppsp = (LPCPROPSHEETPAGE)Page;
  443. CurrentPage = TweakPages[0];
  444. Status = PropertySheet(&psh);
  445. if ((Status == ID_PSREBOOTSYSTEM) ||
  446. (Status == ID_PSRESTARTWINDOWS)) {
  447. BOOLEAN Enabled;
  448. Status = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(DLG_REBOOT), NULL, RebootDlgProc);
  449. RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
  450. TRUE,
  451. FALSE,
  452. &Enabled);
  453. if (Status == ID_FAST_REBOOT) {
  454. ExitWindowsEx(EWX_FORCE | EWX_REBOOT, 0);
  455. } else if (Status == ID_SLOW_REBOOT) {
  456. ExitWindowsEx(EWX_REBOOT, 0);
  457. }
  458. }
  459. return((int)Status);
  460. }
  461. INT_PTR
  462. APIENTRY
  463. RebootDlgProc(
  464. HWND hDlg,
  465. UINT message,
  466. WPARAM wParam,
  467. LPARAM lParam
  468. )
  469. {
  470. switch (message) {
  471. case WM_COMMAND:
  472. if (HIWORD(wParam) == BN_CLICKED) {
  473. switch (LOWORD(wParam)) {
  474. case ID_FAST_REBOOT:
  475. EndDialog(hDlg, ID_FAST_REBOOT);
  476. return(1);
  477. case ID_SLOW_REBOOT:
  478. EndDialog(hDlg, ID_SLOW_REBOOT);
  479. return(1);
  480. case ID_NO_REBOOT:
  481. EndDialog(hDlg, ID_NO_REBOOT);
  482. return(1);
  483. }
  484. }
  485. }
  486. return(0);
  487. }