566 lines
14 KiB
C
566 lines
14 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
twkeng.c
|
|
|
|
Abstract:
|
|
|
|
UI engine for the kerntwk utility. Provides common
|
|
registry/UI handling code to make it simple to add
|
|
new property pages and items.
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 10-Mar-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
#include "nturtl.h"
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include "dialogs.h"
|
|
#include "twkeng.h"
|
|
|
|
//
|
|
// Local type definitions
|
|
//
|
|
|
|
typedef enum _CONTROL_TYPE {
|
|
Edit,
|
|
Button,
|
|
Unknown
|
|
} CONTROL_TYPE;
|
|
|
|
|
|
|
|
//
|
|
// Globals to this module
|
|
//
|
|
|
|
PTWEAK_PAGE CurrentPage=NULL;
|
|
|
|
//
|
|
// Prototypes for local functions
|
|
//
|
|
CONTROL_TYPE
|
|
GetControlType(
|
|
HWND hDlg,
|
|
ULONG ControlId
|
|
);
|
|
|
|
VOID
|
|
InitializeKnobs(
|
|
HWND hDlg
|
|
);
|
|
|
|
PKNOB
|
|
FindKnobById(
|
|
HWND hPage,
|
|
ULONG DialogId
|
|
);
|
|
|
|
BOOL
|
|
ProcessCommand(
|
|
HWND hDlg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
BOOL
|
|
ApplyChanges(
|
|
HWND hDlg
|
|
);
|
|
|
|
INT_PTR
|
|
APIENTRY
|
|
RebootDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
BOOL
|
|
ApplyChanges(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
PTWEAK_PAGE Page;
|
|
PKNOB Current;
|
|
int i;
|
|
|
|
Page = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
//
|
|
// Iterate through the knobs and set their values into the controls
|
|
//
|
|
i = 0;
|
|
Current = Page->Knobs[0];
|
|
while (Current != NULL) {
|
|
HWND hControl;
|
|
TCHAR ClassName[100];
|
|
BOOL Translated;
|
|
|
|
//
|
|
// Determine whether the control is an edit
|
|
// control or a check box
|
|
//
|
|
switch (GetControlType(hDlg, Current->DialogId)) {
|
|
case Button:
|
|
|
|
Current->NewValue = IsDlgButtonChecked(hDlg, Current->DialogId);
|
|
Current->Flags &= ~KNOB_NO_NEW_VALUE;
|
|
break;
|
|
|
|
case Edit:
|
|
Current->NewValue = GetDlgItemInt(hDlg,
|
|
Current->DialogId,
|
|
&Translated,
|
|
FALSE);
|
|
if (!Translated) {
|
|
Current->Flags |= KNOB_NO_NEW_VALUE;
|
|
} else {
|
|
Current->Flags &= ~KNOB_NO_NEW_VALUE;
|
|
}
|
|
break;
|
|
}
|
|
Current = Page->Knobs[++i];
|
|
}
|
|
|
|
//
|
|
// If this page has a dynamic callback, allow it to try and apply
|
|
// its own knobs. If there is no dynamic callback, or the callback's
|
|
// initialization fails, get the defaults from the registry. If the
|
|
// appropriate value does not exist, set the knob to be empty.
|
|
//
|
|
if ((Page->DynamicChange == NULL) ||
|
|
(Page->DynamicChange(FALSE,hDlg) == FALSE)) {
|
|
//
|
|
// Attempt to update registry from the knobs
|
|
//
|
|
i = 0;
|
|
Current = Page->Knobs[i];
|
|
while (Current != NULL) {
|
|
LONG Result;
|
|
HKEY Key;
|
|
DWORD Size;
|
|
DWORD Value;
|
|
DWORD Disposition;
|
|
|
|
if (Current->KeyPath != NULL) {
|
|
Result = RegCreateKeyEx(Current->RegistryRoot,
|
|
Current->KeyPath,
|
|
0,
|
|
NULL,
|
|
0,
|
|
MAXIMUM_ALLOWED,
|
|
NULL,
|
|
&Key,
|
|
&Disposition);
|
|
if (Result == ERROR_SUCCESS) {
|
|
if (Current->Flags & KNOB_NO_NEW_VALUE) {
|
|
//
|
|
// Try and delete the value
|
|
//
|
|
Result = RegDeleteValue(Key, Current->ValueName);
|
|
RegCloseKey(Key);
|
|
if (Result == ERROR_SUCCESS) {
|
|
Current->Flags |= KNOB_NO_CURRENT_VALUE;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Set the current value
|
|
//
|
|
Result = RegSetValueEx(Key,
|
|
Current->ValueName,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&Current->NewValue,
|
|
sizeof(Current->NewValue));
|
|
RegCloseKey(Key);
|
|
if (Result == ERROR_SUCCESS) {
|
|
Current->CurrentValue = Current->NewValue;
|
|
Current->Flags &= ~KNOB_NO_CURRENT_VALUE;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
Current->CurrentValue = Current->NewValue;
|
|
Current->Flags = 0;
|
|
}
|
|
|
|
Current = Page->Knobs[++i];
|
|
}
|
|
SendMessage(GetParent(hDlg),
|
|
PSM_REBOOTSYSTEM,
|
|
0,
|
|
0);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL
|
|
ProcessCommand(
|
|
HWND hDlg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PKNOB Knob;
|
|
ULONG DialogId;
|
|
BOOL Translated;
|
|
|
|
DialogId = LOWORD(wParam);
|
|
Knob = FindKnobById(hDlg, DialogId);
|
|
switch (GetControlType(hDlg, DialogId)) {
|
|
case Edit:
|
|
if (HIWORD(wParam) == EN_CHANGE) {
|
|
if (Knob != NULL) {
|
|
Knob->NewValue = GetDlgItemInt(hDlg, DialogId, &Translated, FALSE);
|
|
if ((Knob->NewValue != Knob->CurrentValue) ||
|
|
(Translated && (Knob->Flags & KNOB_NO_CURRENT_VALUE)) ||
|
|
(!Translated && ((Knob->Flags & KNOB_NO_CURRENT_VALUE) == 0))) {
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
|
|
}
|
|
if (Translated) {
|
|
Knob->Flags &= ~KNOB_NO_NEW_VALUE;
|
|
}
|
|
} else {
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
|
|
|
|
}
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case Button:
|
|
if (HIWORD(wParam) == BN_CLICKED) {
|
|
if (Knob != NULL) {
|
|
Knob->NewValue = IsDlgButtonChecked(hDlg, DialogId);
|
|
if (Knob->NewValue != Knob->CurrentValue) {
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
|
|
}
|
|
} else {
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
CONTROL_TYPE
|
|
GetControlType(
|
|
HWND hDlg,
|
|
ULONG ControlId
|
|
)
|
|
{
|
|
HWND hControl;
|
|
TCHAR ClassName[100];
|
|
|
|
hControl = GetDlgItem(hDlg, ControlId);
|
|
if (hControl != NULL) {
|
|
GetClassName(hControl, ClassName, 100);
|
|
if (_stricmp(ClassName, "BUTTON")==0) {
|
|
return(Button);
|
|
} else if (_stricmp(ClassName, "EDIT") == 0) {
|
|
return(Edit);
|
|
}
|
|
}
|
|
|
|
return(Unknown);
|
|
|
|
}
|
|
|
|
VOID
|
|
InitializeKnobs(
|
|
HWND hDlg
|
|
)
|
|
|
|
{
|
|
PTWEAK_PAGE Page;
|
|
PKNOB Current;
|
|
int i;
|
|
|
|
Page = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
//
|
|
// If this page has a dynamic callback, allow it to try and initialize
|
|
// its own knobs. If there is no dynamic callback, or the callback's
|
|
// initialization fails, get the defaults from the registry. If the
|
|
// appropriate value does not exist, set the knob to be empty.
|
|
//
|
|
if ((Page->DynamicChange == NULL) ||
|
|
(Page->DynamicChange(TRUE,hDlg) == FALSE)) {
|
|
//
|
|
// Attempt to initialize knobs from the registry.
|
|
//
|
|
i = 0;
|
|
Current = Page->Knobs[0];
|
|
while (Current != NULL) {
|
|
LONG Result;
|
|
HKEY Key;
|
|
DWORD Size;
|
|
DWORD Value;
|
|
|
|
Result = RegOpenKeyEx(Current->RegistryRoot,
|
|
Current->KeyPath,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&Key);
|
|
if (Result == ERROR_SUCCESS) {
|
|
//
|
|
// Query out the value we are interested in
|
|
//
|
|
Size = 4;
|
|
Result = RegQueryValueEx(Key,
|
|
Current->ValueName,
|
|
0,
|
|
NULL,
|
|
(LPBYTE)&Value,
|
|
&Size);
|
|
RegCloseKey(Key);
|
|
if (Result == ERROR_SUCCESS) {
|
|
Current->Flags = 0;
|
|
Current->CurrentValue = Value;
|
|
}
|
|
}
|
|
|
|
if (Result != ERROR_SUCCESS) {
|
|
Current->Flags |= KNOB_NO_CURRENT_VALUE;
|
|
Current->Flags |= KNOB_NO_NEW_VALUE;
|
|
}
|
|
Current = Page->Knobs[++i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Iterate through the knobs and set their values into the controls
|
|
//
|
|
i = 0;
|
|
Current = Page->Knobs[0];
|
|
while (Current != NULL) {
|
|
HWND hControl;
|
|
TCHAR ClassName[100];
|
|
|
|
//
|
|
// Determine whether the control is an edit
|
|
// control or a check box
|
|
//
|
|
if ((Current->Flags & KNOB_NO_CURRENT_VALUE) == 0) {
|
|
switch (GetControlType(hDlg, Current->DialogId)) {
|
|
case Button:
|
|
CheckDlgButton(hDlg,
|
|
Current->DialogId,
|
|
Current->CurrentValue);
|
|
break;
|
|
|
|
case Edit:
|
|
SetDlgItemInt(hDlg,
|
|
Current->DialogId,
|
|
Current->CurrentValue,
|
|
FALSE);
|
|
break;
|
|
}
|
|
}
|
|
Current = Page->Knobs[++i];
|
|
}
|
|
}
|
|
|
|
PKNOB
|
|
FindKnobById(
|
|
HWND hPage,
|
|
ULONG DialogId
|
|
)
|
|
{
|
|
PTWEAK_PAGE Page;
|
|
PKNOB Current;
|
|
int i;
|
|
|
|
Page = (PTWEAK_PAGE)GetWindowLongPtr(hPage, DWLP_USER);
|
|
i=0;
|
|
Current = Page->Knobs[0];
|
|
while (Current != NULL) {
|
|
if (Current->DialogId == DialogId) {
|
|
break;
|
|
}
|
|
Current = Page->Knobs[++i];
|
|
}
|
|
return(Current);
|
|
}
|
|
|
|
INT_PTR
|
|
APIENTRY
|
|
PageDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LPNMHDR Notify;
|
|
PTWEAK_PAGE TweakPage;
|
|
|
|
TweakPage = (PTWEAK_PAGE)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
|
|
//
|
|
// This page is being created.
|
|
//
|
|
TweakPage = (PTWEAK_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
|
|
|
|
//
|
|
// Stash a pointer to our page
|
|
//
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)TweakPage);
|
|
|
|
//
|
|
// Initialize controls.
|
|
//
|
|
|
|
InitializeKnobs(hDlg);
|
|
return(TRUE);
|
|
|
|
case WM_COMMAND:
|
|
|
|
return(ProcessCommand(hDlg, wParam, lParam));
|
|
|
|
case WM_NOTIFY:
|
|
Notify = (LPNMHDR)lParam;
|
|
switch (Notify->code) {
|
|
case PSN_SETACTIVE:
|
|
CurrentPage = TweakPage;
|
|
break;
|
|
case PSN_APPLY:
|
|
//
|
|
// User has chosen to apply the changes.
|
|
//
|
|
if (ApplyChanges(hDlg)) {
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int
|
|
TweakSheet(
|
|
DWORD PageCount,
|
|
PTWEAK_PAGE TweakPages[]
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assembles the appropriate structures for a property sheet
|
|
and creates the sheet.
|
|
|
|
Arguments:
|
|
|
|
PageCount - Supplies the number of pages.
|
|
|
|
TweakPages - Supplies the pages.
|
|
|
|
Return Value:
|
|
|
|
Return value from PropertySheet()
|
|
|
|
--*/
|
|
|
|
{
|
|
PROPSHEETHEADER psh;
|
|
PROPSHEETPAGE *Page;
|
|
DWORD i;
|
|
INT_PTR Status;
|
|
|
|
Page = LocalAlloc(LMEM_FIXED, PageCount * sizeof(PROPSHEETPAGE));
|
|
if (Page==NULL) {
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Initialize pages.
|
|
//
|
|
for (i=0; i<PageCount; i++) {
|
|
Page[i].dwSize = sizeof(PROPSHEETPAGE);
|
|
Page[i].dwFlags = PSP_USEICONID;
|
|
Page[i].hInstance = GetModuleHandle(NULL);
|
|
Page[i].pszIcon = MAKEINTRESOURCE(IDI_KERNTWEAK);
|
|
Page[i].pszTemplate = TweakPages[i]->DlgTemplate;
|
|
Page[i].pfnDlgProc = PageDlgProc;
|
|
Page[i].pszTitle = NULL;
|
|
Page[i].lParam = (LPARAM)TweakPages[i];
|
|
}
|
|
|
|
//
|
|
// Initialize header.
|
|
//
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
|
|
psh.hwndParent = NULL;
|
|
psh.hInstance = GetModuleHandle(NULL);
|
|
psh.pszIcon = MAKEINTRESOURCE(IDI_KERNTWEAK);
|
|
psh.pszCaption = TEXT("Windows NT Kernel Tweaker");
|
|
psh.nPages = PageCount;
|
|
psh.ppsp = (LPCPROPSHEETPAGE)Page;
|
|
|
|
CurrentPage = TweakPages[0];
|
|
|
|
Status = PropertySheet(&psh);
|
|
if ((Status == ID_PSREBOOTSYSTEM) ||
|
|
(Status == ID_PSRESTARTWINDOWS)) {
|
|
BOOLEAN Enabled;
|
|
|
|
Status = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(DLG_REBOOT), NULL, RebootDlgProc);
|
|
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&Enabled);
|
|
if (Status == ID_FAST_REBOOT) {
|
|
ExitWindowsEx(EWX_FORCE | EWX_REBOOT, 0);
|
|
} else if (Status == ID_SLOW_REBOOT) {
|
|
ExitWindowsEx(EWX_REBOOT, 0);
|
|
}
|
|
}
|
|
|
|
return((int)Status);
|
|
}
|
|
|
|
INT_PTR
|
|
APIENTRY
|
|
RebootDlgProc(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch (message) {
|
|
case WM_COMMAND:
|
|
if (HIWORD(wParam) == BN_CLICKED) {
|
|
switch (LOWORD(wParam)) {
|
|
case ID_FAST_REBOOT:
|
|
EndDialog(hDlg, ID_FAST_REBOOT);
|
|
return(1);
|
|
case ID_SLOW_REBOOT:
|
|
EndDialog(hDlg, ID_SLOW_REBOOT);
|
|
return(1);
|
|
case ID_NO_REBOOT:
|
|
EndDialog(hDlg, ID_NO_REBOOT);
|
|
return(1);
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
}
|