- rewrite the transaction system to be based on a settings overlay,
to have a nicer API, and to actually work (always a bonus) - change the libraries page to be based on a listbox rather than a treeview, clean up and shrink the code - add accelerator keys to the libraries page, focus management - make the window title reflect what the user is currently editing - remove bogus root warning - remove some unused control IDs in resource.h - start converting the x11drv dialog to kernel_style from javaStyle - bugfixing
This commit is contained in:
parent
a5ce4ee7aa
commit
0af614e77b
|
@ -84,20 +84,18 @@ STYLE WS_CHILD | WS_DISABLED
|
|||
FONT 8, "MS Shell Dlg"
|
||||
BEGIN
|
||||
GROUPBOX "DLL Overrides",IDC_STATIC,8,4,244,240
|
||||
LTEXT "Libraries can be specified individually to be either builtin or native. A DLL entry specified as ""*"" pertains to all DLLs not specified explicitly."
|
||||
LTEXT "Dynamic Link Libraries can be specified individually to be either builtin (provided by Wine) or native (taken from Windows or provided by the application)."
|
||||
, IDC_STATIC,15,17,228,32
|
||||
CONTROL "DLL Overrides", IDC_TREE_DLLS, "SysTreeView32", WS_BORDER | WS_TABSTOP | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_HASBUTTONS, 15,50,142,187
|
||||
LISTBOX IDC_DLLS_LIST,15,50,142,187,WS_BORDER | WS_TABSTOP | WS_VSCROLL
|
||||
LTEXT "Load order:",IDC_STATIC,163,50,37,8
|
||||
CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,163,65,75,10
|
||||
CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,163,80,75,10
|
||||
CONTROL "Builtin, Native",IDC_RAD_BUILTIN_NATIVE,"Button", BS_AUTORADIOBUTTON,163,95,75,10
|
||||
CONTROL "Native, Builtin",IDC_RAD_NATIVE_BUILTIN,"Button", BS_AUTORADIOBUTTON,163,110,75,10
|
||||
CONTROL "Disable",IDC_RAD_DISABLE,"Button", BS_AUTORADIOBUTTON,163,125,75,10
|
||||
PUSHBUTTON "Add application...",IDC_DLLS_ADDAPP,163,144,82,14
|
||||
PUSHBUTTON "Remove application",IDC_DLLS_REMOVEAPP, 163,164,82,14
|
||||
PUSHBUTTON "Add DLL override for:",IDC_DLLS_ADDDLL, 163,184,82,14
|
||||
COMBOBOX IDC_DLLLIST,163,204,82,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | CBS_SORT | CBS_LOWERCASE
|
||||
PUSHBUTTON "Remove DLL override",IDC_DLLS_REMOVEDLL,163,224,82,14
|
||||
CONTROL "&Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,163,65,75,10
|
||||
CONTROL "&Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,163,80,75,10
|
||||
CONTROL "Bui<in then Native",IDC_RAD_BUILTIN_NATIVE,"Button", BS_AUTORADIOBUTTON,163,95,75,10
|
||||
CONTROL "Nati&ve then Builtin",IDC_RAD_NATIVE_BUILTIN,"Button", BS_AUTORADIOBUTTON,163,110,75,10
|
||||
CONTROL "&Disable",IDC_RAD_DISABLE,"Button", BS_AUTORADIOBUTTON,163,125,75,10
|
||||
PUSHBUTTON "&Add DLL override for:",IDC_DLLS_ADDDLL, 163,184,82,14
|
||||
COMBOBOX IDC_DLLCOMBO,163,204,82,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | CBS_SORT | CBS_LOWERCASE
|
||||
PUSHBUTTON "&Remove DLL override",IDC_DLLS_REMOVEDLL,163,224,82,14
|
||||
END
|
||||
|
||||
IDD_SYSTEMCFG DIALOG DISCARDABLE 0, 0, 260, 250
|
||||
|
|
|
@ -40,23 +40,21 @@ static void update_comboboxes(HWND dialog)
|
|||
char *winver, *dosver;
|
||||
|
||||
/* retrieve the registry values */
|
||||
winver = getConfigValue(keypath("Version"), "Windows", NULL);
|
||||
dosver = getConfigValue(keypath("Version"), "DOS", NULL);
|
||||
winver = get(keypath("Version"), "Windows", "");
|
||||
dosver = get(keypath("Version"), "DOS", "");
|
||||
|
||||
/* NULL winver/dosver means use automatic mode (ie the builtin dll linkage heuristics) */
|
||||
/* empty winver/dosver means use automatic mode (ie the builtin dll linkage heuristics) */
|
||||
|
||||
WINE_TRACE("winver is %s\n", winver ? winver : "null (automatic mode)");
|
||||
WINE_TRACE("dosver is %s\n", dosver ? dosver : "null (automatic mode)");
|
||||
WINE_TRACE("winver is %s\n", *winver != '\0' ? winver : "null (automatic mode)");
|
||||
WINE_TRACE("dosver is %s\n", *dosver != '\0' ? dosver : "null (automatic mode)");
|
||||
|
||||
/* normalize the version strings */
|
||||
if (winver && strlen(winver))
|
||||
if (*winver != '\0')
|
||||
{
|
||||
if ((pVer = getWinVersions ()))
|
||||
{
|
||||
WINE_TRACE("Windows version\n");
|
||||
for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
|
||||
{
|
||||
WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
|
||||
if (!strcasecmp (pVer->szVersion, winver))
|
||||
{
|
||||
SendDlgItemMessage (dialog, IDC_WINVER, CB_SETCURSEL, (WPARAM) (i + 1), 0);
|
||||
|
@ -71,14 +69,12 @@ static void update_comboboxes(HWND dialog)
|
|||
SendDlgItemMessage (dialog, IDC_WINVER, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
if (dosver && strlen(dosver))
|
||||
if (*dosver != '\0')
|
||||
{
|
||||
if ((pVer = getDOSVersions ()))
|
||||
{
|
||||
WINE_TRACE("DOS version\n");
|
||||
for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
|
||||
{
|
||||
WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
|
||||
if (!strcasecmp (pVer->szVersion, dosver))
|
||||
{
|
||||
SendDlgItemMessage (dialog, IDC_DOSVER, CB_SETCURSEL,
|
||||
|
@ -94,8 +90,8 @@ static void update_comboboxes(HWND dialog)
|
|||
SendDlgItemMessage (dialog, IDC_DOSVER, CB_SETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
if (winver) free(winver);
|
||||
if (dosver) free(dosver);
|
||||
HeapFree(GetProcessHeap(), 0, winver);
|
||||
HeapFree(GetProcessHeap(), 0, dosver);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -153,6 +149,7 @@ static void add_listview_item(HWND listview, char *text, void *association)
|
|||
ListView_InsertItem(listview, &item);
|
||||
}
|
||||
|
||||
/* Called when the application is initialized (cannot reinit!) */
|
||||
static void init_appsheet(HWND dialog)
|
||||
{
|
||||
HWND listview;
|
||||
|
@ -160,7 +157,6 @@ static void init_appsheet(HWND dialog)
|
|||
int i;
|
||||
DWORD size;
|
||||
char appname[1024];
|
||||
FILETIME ft;
|
||||
|
||||
WINE_TRACE("()\n");
|
||||
|
||||
|
@ -170,12 +166,12 @@ static void init_appsheet(HWND dialog)
|
|||
* for instance, to use the tile view or to display the EXEs embedded 'display name' */
|
||||
add_listview_item(listview, "Default Settings", NULL);
|
||||
|
||||
/* do the application specific stuff, then add the default item last */
|
||||
if (RegOpenKey(configKey, "AppDefaults", &key) == ERROR_SUCCESS)
|
||||
/* because this list is only populated once, it's safe to bypass the settings list here */
|
||||
if (RegOpenKey(config_key, "AppDefaults", &key) == ERROR_SUCCESS)
|
||||
{
|
||||
i = 0;
|
||||
size = sizeof(appname);
|
||||
while (RegEnumKeyEx(key, i, appname, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
|
||||
while (RegEnumKeyEx(key, i, appname, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
add_listview_item(listview, appname, strdup(appname));
|
||||
|
||||
|
@ -218,6 +214,7 @@ static int get_listview_selection(HWND listview)
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* called when the user selects a different application */
|
||||
static void on_selection_change(HWND dialog, HWND listview)
|
||||
{
|
||||
|
@ -253,6 +250,8 @@ static void on_selection_change(HWND dialog, HWND listview)
|
|||
init_comboboxes(dialog);
|
||||
|
||||
update_comboboxes(dialog);
|
||||
|
||||
set_window_title(dialog);
|
||||
}
|
||||
|
||||
static void on_add_app_click(HWND dialog)
|
||||
|
@ -295,14 +294,14 @@ static void on_remove_app_click(HWND dialog)
|
|||
{
|
||||
HWND listview = GetDlgItem(dialog, IDC_APP_LISTVIEW);
|
||||
int selection = get_listview_selection(listview);
|
||||
char *section = keypath("");
|
||||
char *section = keypath(""); /* AppDefaults\\whatever.exe\\ */
|
||||
|
||||
WINE_TRACE("selection=%d, section=%s\n", selection, section);
|
||||
|
||||
assert( selection != 0 ); /* user cannot click this button when "default settings" is selected */
|
||||
|
||||
section[strlen(section)] = '\0'; /* remove last backslash */
|
||||
addTransaction(section, NULL, ACTION_REMOVE, NULL);
|
||||
set(section, NULL, NULL); /* delete the section */
|
||||
ListView_DeleteItem(listview, selection);
|
||||
|
||||
SetFocus(listview);
|
||||
|
@ -316,13 +315,16 @@ static void on_winver_change(HWND dialog)
|
|||
if (selection == 0)
|
||||
{
|
||||
WINE_TRACE("automatic/default selected so removing current setting\n");
|
||||
addTransaction(keypath("Version"), "Windows", ACTION_REMOVE, NULL);
|
||||
set(keypath("Version"), "Windows", NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
WINE_TRACE("setting Version\\Windows key to value '%s'\n", ver[selection - 1].szVersion);
|
||||
addTransaction(keypath("Version"), "Windows", ACTION_SET, ver[selection - 1].szVersion);
|
||||
set(keypath("Version"), "Windows", ver[selection - 1].szVersion);
|
||||
}
|
||||
|
||||
/* enable the apply button */
|
||||
SendMessage(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
|
||||
}
|
||||
|
||||
static void on_dosver_change(HWND dialog)
|
||||
|
@ -333,13 +335,16 @@ static void on_dosver_change(HWND dialog)
|
|||
if (selection == 0)
|
||||
{
|
||||
WINE_TRACE("automatic/default selected so removing current setting\n");
|
||||
addTransaction(keypath("Version"), "DOS", ACTION_REMOVE, NULL);
|
||||
set(keypath("Version"), "DOS", NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
WINE_TRACE("setting Version\\DOS key to value '%s'\n", ver[selection - 1].szVersion);
|
||||
addTransaction(keypath("Version"), "DOS", ACTION_SET, ver[selection - 1].szVersion);
|
||||
set(keypath("Version"), "DOS", ver[selection - 1].szVersion);
|
||||
}
|
||||
|
||||
/* enable the apply button */
|
||||
SendMessage(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK
|
||||
|
@ -348,17 +353,25 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
init_appsheet(hDlg);
|
||||
break;
|
||||
init_appsheet(hDlg);
|
||||
break;
|
||||
|
||||
case WM_SHOWWINDOW:
|
||||
set_window_title(hDlg);
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
|
||||
switch (((LPNMHDR)lParam)->code)
|
||||
{
|
||||
case LVN_ITEMCHANGED:
|
||||
on_selection_change(hDlg, GetDlgItem(hDlg, IDC_APP_LISTVIEW));
|
||||
break;
|
||||
on_selection_change(hDlg, GetDlgItem(hDlg, IDC_APP_LISTVIEW));
|
||||
break;
|
||||
case PSN_APPLY:
|
||||
apply();
|
||||
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
@ -383,6 +396,7 @@ AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ void selectAudioDriver(HWND hDlg, char *drivername)
|
|||
{
|
||||
if (!strcmp (pAudioDrv->szDriver, drivername))
|
||||
{
|
||||
addTransaction("Winmm", "Drivers", ACTION_SET, pAudioDrv->szDriver);
|
||||
set("Winmm", "Drivers", (char *) pAudioDrv->szDriver);
|
||||
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM) hDlg, 0); /* enable apply button */
|
||||
SendDlgItemMessage(hDlg, IDC_AUDIO_DRIVER, CB_SETCURSEL,
|
||||
(WPARAM) i, 0);
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ void selectAudioDriver(HWND hDlg, char *drivername)
|
|||
void
|
||||
initAudioDlg (HWND hDlg)
|
||||
{
|
||||
char *curAudioDriver = getConfigValue("Winmm", "Drivers", "winealsa.drv");
|
||||
char *curAudioDriver = get("Winmm", "Drivers", "winealsa.drv");
|
||||
const AUDIO_DRIVER *pAudioDrv = NULL;
|
||||
int i;
|
||||
|
||||
|
@ -176,12 +177,17 @@ AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_SHOWWINDOW:
|
||||
set_window_title(hDlg);
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
switch(((LPNMHDR)lParam)->code) {
|
||||
case PSN_KILLACTIVE:
|
||||
SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
|
||||
break;
|
||||
case PSN_APPLY:
|
||||
apply();
|
||||
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||
break;
|
||||
case PSN_SETACTIVE:
|
||||
|
|
|
@ -212,14 +212,13 @@ int refreshDriveDlg (HWND dialog)
|
|||
ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_HIDE);
|
||||
|
||||
/* disable or enable controls depending on whether we are editing global vs app specific config */
|
||||
if (appSettings == EDITING_GLOBAL) {
|
||||
if (currentApp) {
|
||||
WINE_TRACE("enabling controls\n");
|
||||
enable(IDC_LIST_DRIVES);
|
||||
enable(IDC_BUTTON_ADD);
|
||||
enable(IDC_BUTTON_REMOVE);
|
||||
enable(IDC_BUTTON_EDIT);
|
||||
enable(IDC_BUTTON_AUTODETECT);
|
||||
|
||||
} else {
|
||||
WINE_TRACE("disabling controls\n");
|
||||
disable(IDC_LIST_DRIVES);
|
||||
|
@ -1016,6 +1015,11 @@ DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_INITDIALOG:
|
||||
onDriveInitDialog();
|
||||
break;
|
||||
|
||||
case WM_SHOWWINDOW:
|
||||
set_window_title(hDlg);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDC_LIST_DRIVES:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* WineCfg libraries tabsheet
|
||||
*
|
||||
* Copyright 2004 Robert van Herk
|
||||
* Copyright 2004 Mike Hearn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -24,535 +25,324 @@
|
|||
#include <commdlg.h>
|
||||
#include <wine/debug.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "winecfg.h"
|
||||
#include "resource.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
|
||||
|
||||
typedef enum _DLGMODE
|
||||
enum dllmode
|
||||
{
|
||||
DLL,
|
||||
APP,
|
||||
GLOBAL,
|
||||
} DLGMODE;
|
||||
|
||||
typedef enum _DLLMODE {
|
||||
BUILTIN_NATIVE,
|
||||
NATIVE_BUILTIN,
|
||||
BUILTIN,
|
||||
NATIVE,
|
||||
DISABLE,
|
||||
UNKNOWN /*Special value indicating an erronous DLL override mode*/
|
||||
} DLLMODE;
|
||||
UNKNOWN /* Special value indicating an erronous DLL override mode */
|
||||
};
|
||||
|
||||
static void removeSpaces(char* in, char* out)
|
||||
struct dll
|
||||
{
|
||||
int i,j;
|
||||
j = 0;
|
||||
for (i = 0; i < strlen(in); i++)
|
||||
{
|
||||
if (in[i] != ' ')
|
||||
char *name;
|
||||
enum dllmode mode;
|
||||
};
|
||||
|
||||
static enum dllmode parse_override(char *in)
|
||||
{
|
||||
int i, j;
|
||||
char *out;
|
||||
|
||||
out = HeapAlloc(GetProcessHeap(), 0, strlen(in));
|
||||
|
||||
/* remove the spaces */
|
||||
j = 0;
|
||||
for (i = 0; i < strlen(in); i++)
|
||||
{
|
||||
out[j] = in[i];
|
||||
j++;
|
||||
if (in[i] != ' ')
|
||||
{
|
||||
out[j] = in[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
out[j] = 0;
|
||||
}
|
||||
out[j] = 0;
|
||||
|
||||
/* parse the string */
|
||||
if (strcmp(out, "builtin,native") == 0) return BUILTIN_NATIVE;
|
||||
else if (strcmp(out, "native,builtin") == 0) return NATIVE_BUILTIN;
|
||||
else if (strcmp(out, "native") == 0) return NATIVE;
|
||||
else if (strcmp(out, "builtin") == 0) return BUILTIN;
|
||||
else if (strcmp(out, "") == 0) return DISABLE;
|
||||
|
||||
static DLLMODE Str2DLLMode(char* c)
|
||||
{
|
||||
/*Parse a string into a DLLMode*/
|
||||
char* d = HeapAlloc(GetProcessHeap(), 0, sizeof(c));
|
||||
removeSpaces(c,d);
|
||||
if (strcmp (d, "builtin,native") == 0) {
|
||||
return BUILTIN_NATIVE;
|
||||
} else
|
||||
if (strcmp (d, "native,builtin") == 0) {
|
||||
return NATIVE_BUILTIN;
|
||||
} else
|
||||
if (strcmp (d, "native") == 0){
|
||||
return NATIVE;
|
||||
} else
|
||||
if (strcmp (d, "builtin") == 0) {
|
||||
return BUILTIN;
|
||||
} else
|
||||
if (strcmp (d, "") == 0) {
|
||||
return DISABLE;
|
||||
} else
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
static char* DLLMode2Str(DLLMODE mode)
|
||||
/* this is used to convert a dllmode to a human readable string. we should read from the translations here */
|
||||
static char* mode_to_label(enum dllmode mode)
|
||||
{
|
||||
char* res;
|
||||
switch (mode) {
|
||||
case NATIVE:
|
||||
res = "native";
|
||||
break;
|
||||
case BUILTIN:
|
||||
res = "builtin";
|
||||
break;
|
||||
case NATIVE_BUILTIN:
|
||||
res = "native, builtin";
|
||||
break;
|
||||
case BUILTIN_NATIVE:
|
||||
res = "builtin, native";
|
||||
break;
|
||||
case DISABLE:
|
||||
res = "";
|
||||
break;
|
||||
default:
|
||||
res = "unknown";
|
||||
}
|
||||
return strdup(res);
|
||||
char* res;
|
||||
|
||||
switch (mode) {
|
||||
case NATIVE:
|
||||
res = "native";
|
||||
break;
|
||||
case BUILTIN:
|
||||
res = "builtin";
|
||||
break;
|
||||
case NATIVE_BUILTIN:
|
||||
res = "native, builtin";
|
||||
break;
|
||||
case BUILTIN_NATIVE:
|
||||
res = "builtin, native";
|
||||
break;
|
||||
case DISABLE:
|
||||
res = "disabled";
|
||||
break;
|
||||
default:
|
||||
res = "unknown/invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef struct _DLLOVERRIDE
|
||||
static void set_controls_from_selection(HWND dialog)
|
||||
{
|
||||
char* lpcKey; /*The actual dll name*/
|
||||
DLLMODE mode;
|
||||
} DLLOVERRIDE, *LPDLLOVERRIDE;
|
||||
int index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
|
||||
struct dll *dll;
|
||||
DWORD id;
|
||||
int i;
|
||||
|
||||
static LPDLLOVERRIDE CreateDLLOverride(char* lpcKey)
|
||||
{
|
||||
LPDLLOVERRIDE out = HeapAlloc(GetProcessHeap(),0,sizeof(DLLOVERRIDE));
|
||||
out->lpcKey = strdup (lpcKey);
|
||||
return out;
|
||||
if (index == -1) /* no selection */
|
||||
{
|
||||
for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++)
|
||||
disable(i);
|
||||
|
||||
CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, -1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable the controls */
|
||||
for (i = IDC_RAD_BUILTIN; i <= IDC_RAD_DISABLE; i++)
|
||||
enable(i);
|
||||
|
||||
dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0);
|
||||
|
||||
switch (dll->mode)
|
||||
{
|
||||
case NATIVE:
|
||||
id = IDC_RAD_NATIVE;
|
||||
break;
|
||||
case BUILTIN:
|
||||
id = IDC_RAD_BUILTIN;
|
||||
break;
|
||||
case NATIVE_BUILTIN:
|
||||
id = IDC_RAD_NATIVE_BUILTIN;
|
||||
break;
|
||||
case BUILTIN_NATIVE:
|
||||
id = IDC_RAD_BUILTIN_NATIVE;
|
||||
break;
|
||||
case DISABLE:
|
||||
id = IDC_RAD_DISABLE;
|
||||
break;
|
||||
|
||||
case UNKNOWN:
|
||||
default:
|
||||
id = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
CheckRadioButton(dialog, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, id);
|
||||
}
|
||||
|
||||
static VOID FreeDLLOverride(LPDLLOVERRIDE ldo)
|
||||
|
||||
static void clear_settings(HWND dialog)
|
||||
{
|
||||
if (ldo->lpcKey)
|
||||
free(ldo->lpcKey);
|
||||
HeapFree(GetProcessHeap(),0,ldo);
|
||||
int count = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0);
|
||||
int i;
|
||||
|
||||
WINE_TRACE("count=%d\n", count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
struct dll *dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, 0, 0);
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, 0, 0);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, dll->name);
|
||||
HeapFree(GetProcessHeap(), 0, dll);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _APPL
|
||||
static void load_library_settings(HWND dialog)
|
||||
{
|
||||
BOOL isGlobal;
|
||||
char* lpcApplication;
|
||||
char* lpcSection; /*Registry section*/
|
||||
} APPL, *LPAPPL;
|
||||
char **overrides = enumerate_values(keypath("DllOverrides"));
|
||||
char **p;
|
||||
int sel, count = 0;
|
||||
|
||||
static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* section)
|
||||
{
|
||||
LPAPPL out;
|
||||
out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
|
||||
out->lpcApplication = strdup(application);
|
||||
out->lpcSection = strdup(section);
|
||||
out->isGlobal = isGlobal;
|
||||
return out;
|
||||
sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
|
||||
|
||||
WINE_TRACE("sel=%d\n", sel);
|
||||
|
||||
clear_settings(dialog);
|
||||
|
||||
if (!overrides || *overrides == NULL)
|
||||
{
|
||||
set_controls_from_selection(dialog);
|
||||
disable(IDC_DLLS_REMOVEDLL);
|
||||
HeapFree(GetProcessHeap(), 0, overrides);
|
||||
return;
|
||||
}
|
||||
|
||||
enable(IDC_DLLS_REMOVEDLL);
|
||||
|
||||
for (p = overrides; *p != NULL; p++)
|
||||
{
|
||||
int index;
|
||||
char *str, *value, *label;
|
||||
struct dll *dll;
|
||||
|
||||
value = get(keypath("DllOverrides"), *p, NULL);
|
||||
|
||||
label = mode_to_label(parse_override(value));
|
||||
|
||||
str = HeapAlloc(GetProcessHeap(), 0, strlen(*p) + 2 + strlen(label) + 2);
|
||||
strcpy(str, *p);
|
||||
strcat(str, " (");
|
||||
strcat(str, label);
|
||||
strcat(str, ")");
|
||||
|
||||
dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll));
|
||||
dll->name = *p;
|
||||
dll->mode = parse_override(value);
|
||||
|
||||
index = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_ADDSTRING, (WPARAM) -1, (LPARAM) str);
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETITEMDATA, index, (LPARAM) dll);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, overrides);
|
||||
|
||||
/* restore the previous selection, if possible */
|
||||
if (sel >= count - 1) sel = count - 1;
|
||||
else if (sel == -1) sel = 0;
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, sel, 0);
|
||||
|
||||
set_controls_from_selection(dialog);
|
||||
}
|
||||
|
||||
static VOID FreeAppl(LPAPPL lpAppl)
|
||||
/* Called when the application is initialized (cannot reinit!) */
|
||||
static void init_libsheet(HWND dialog)
|
||||
{
|
||||
if (lpAppl->lpcApplication)
|
||||
free(lpAppl->lpcApplication); /* The strings were strdup-ped, so we use "free" */
|
||||
if (lpAppl->lpcSection)
|
||||
free(lpAppl->lpcSection);
|
||||
HeapFree(GetProcessHeap(),0,lpAppl);
|
||||
/* clear the add dll controls */
|
||||
SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM) "");
|
||||
disable(IDC_DLLS_ADDDLL);
|
||||
}
|
||||
|
||||
typedef struct _ITEMTAG
|
||||
{
|
||||
LPAPPL lpAppl;
|
||||
LPDLLOVERRIDE lpDo;
|
||||
} ITEMTAG, *LPITEMTAG;
|
||||
|
||||
static LPITEMTAG CreateItemTag()
|
||||
static void on_add_combo_change(HWND dialog)
|
||||
{
|
||||
LPITEMTAG out;
|
||||
out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
|
||||
out->lpAppl = 0;
|
||||
out->lpDo = 0;
|
||||
return out;
|
||||
char buffer[1024];
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
|
||||
|
||||
if (strlen(buffer))
|
||||
enable(IDC_DLLS_ADDDLL)
|
||||
else
|
||||
disable(IDC_DLLS_ADDDLL);
|
||||
}
|
||||
|
||||
static VOID FreeItemTag(LPITEMTAG lpit)
|
||||
static void set_dllmode(HWND dialog, DWORD id)
|
||||
{
|
||||
if (lpit->lpAppl)
|
||||
FreeAppl(lpit->lpAppl);
|
||||
if (lpit->lpDo)
|
||||
FreeDLLOverride(lpit->lpDo);
|
||||
HeapFree(GetProcessHeap(),0,lpit);
|
||||
enum dllmode mode;
|
||||
struct dll *dll;
|
||||
int sel;
|
||||
char *str;
|
||||
|
||||
#define CONVERT(s) case IDC_RAD_##s: mode = s; break;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
CONVERT( BUILTIN );
|
||||
CONVERT( NATIVE );
|
||||
CONVERT( BUILTIN_NATIVE );
|
||||
CONVERT( NATIVE_BUILTIN );
|
||||
CONVERT( DISABLE );
|
||||
|
||||
default: assert( FALSE ); /* should not be reached */
|
||||
}
|
||||
|
||||
#undef CONVERT
|
||||
|
||||
sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
|
||||
if (sel == -1) return;
|
||||
|
||||
dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case BUILTIN: str = "builtin"; break;
|
||||
case NATIVE: str = "native"; break;
|
||||
case BUILTIN_NATIVE: str = "builtin, native"; break;
|
||||
case NATIVE_BUILTIN: str = "native, builtin"; break;
|
||||
case DISABLE: str = ""; break;
|
||||
default: assert( FALSE ); /* unreachable */
|
||||
}
|
||||
WINE_TRACE("Setting %s to %s\n", dll->name, str);
|
||||
|
||||
set(keypath("DllOverrides"), dll->name, str);
|
||||
|
||||
load_library_settings(dialog); /* ... and refresh */
|
||||
}
|
||||
|
||||
static VOID UpdateDLLList(HWND hDlg, char* dll)
|
||||
static void on_add_click(HWND dialog)
|
||||
{
|
||||
/*Add if it isn't already in*/
|
||||
if (SendDlgItemMessage(hDlg, IDC_DLLLIST, CB_FINDSTRING, 1, (LPARAM) dll) == CB_ERR)
|
||||
SendDlgItemMessage(hDlg,IDC_DLLLIST,CB_ADDSTRING,0,(LPARAM) dll);
|
||||
char buffer[1024];
|
||||
|
||||
ZeroMemory(buffer, sizeof(buffer));
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM) "");
|
||||
disable(IDC_DLLS_ADDDLL);
|
||||
|
||||
WINE_TRACE("Adding %s as native, builtin", buffer);
|
||||
|
||||
set(keypath("DllOverrides"), buffer, "native,builtin");
|
||||
|
||||
load_library_settings(dialog);
|
||||
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, (WPARAM) 0, (LPARAM) buffer);
|
||||
|
||||
set_controls_from_selection(dialog);
|
||||
}
|
||||
|
||||
static VOID LoadLibrarySettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
|
||||
static void on_remove_click(HWND dialog)
|
||||
{
|
||||
HKEY key;
|
||||
int i;
|
||||
DWORD size;
|
||||
DWORD readSize;
|
||||
char name [255];
|
||||
char read [255];
|
||||
LPITEMTAG lpIt;
|
||||
TVINSERTSTRUCT tis;
|
||||
HTREEITEM hParent;
|
||||
LPDLLOVERRIDE lpdo;
|
||||
int sel = SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
|
||||
struct dll *dll;
|
||||
|
||||
WINE_TRACE("opening %s\n", appl->lpcSection);
|
||||
if (RegOpenKey (configKey, appl->lpcSection, &key) == ERROR_SUCCESS)
|
||||
{
|
||||
i = 0;
|
||||
size = 255;
|
||||
readSize = 255;
|
||||
if (sel == LB_ERR) return;
|
||||
|
||||
lpIt = CreateItemTag();
|
||||
lpIt->lpAppl = appl;
|
||||
dll = (struct dll *) SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
|
||||
|
||||
tis.hParent = NULL;
|
||||
tis.hInsertAfter = TVI_LAST;
|
||||
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tis.u.item.pszText = appl->lpcApplication;
|
||||
tis.u.item.lParam = (LPARAM)lpIt;
|
||||
hParent = TreeView_InsertItem(hwndTV,&tis);
|
||||
tis.hParent = hParent;
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0);
|
||||
|
||||
while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
|
||||
{
|
||||
WINE_TRACE("Reading value %s, namely %s\n", name, read);
|
||||
set(keypath("DllOverrides"), dll->name, NULL);
|
||||
|
||||
lpIt = CreateItemTag();
|
||||
lpdo = CreateDLLOverride(name);
|
||||
lpIt->lpDo = lpdo;
|
||||
tis.u.item.lParam = (LPARAM)lpIt;
|
||||
tis.u.item.pszText = name;
|
||||
HeapFree(GetProcessHeap(), 0, dll->name);
|
||||
HeapFree(GetProcessHeap(), 0, dll);
|
||||
|
||||
lpdo->mode = Str2DLLMode(read);
|
||||
if (SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0)
|
||||
SendDlgItemMessage(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0);
|
||||
else
|
||||
disable(IDC_DLLS_REMOVEDLL);
|
||||
|
||||
TreeView_InsertItem(hwndTV,&tis);
|
||||
UpdateDLLList(hDlg, name);
|
||||
i ++; size = 255; readSize = 255;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID SetEnabledDLLControls(HWND dialog, DLGMODE dlgmode)
|
||||
{
|
||||
if (dlgmode == DLL) {
|
||||
enable(IDC_RAD_BUILTIN);
|
||||
enable(IDC_RAD_NATIVE);
|
||||
enable(IDC_RAD_BUILTIN_NATIVE);
|
||||
enable(IDC_RAD_NATIVE_BUILTIN);
|
||||
enable(IDC_RAD_DISABLE);
|
||||
enable(IDC_DLLS_REMOVEDLL);
|
||||
} else {
|
||||
disable(IDC_RAD_BUILTIN);
|
||||
disable(IDC_RAD_NATIVE);
|
||||
disable(IDC_RAD_BUILTIN_NATIVE);
|
||||
disable(IDC_RAD_NATIVE_BUILTIN);
|
||||
disable(IDC_RAD_DISABLE);
|
||||
disable(IDC_DLLS_REMOVEDLL);
|
||||
}
|
||||
|
||||
if (dlgmode == APP) {
|
||||
enable(IDC_DLLS_REMOVEAPP);
|
||||
}
|
||||
else {
|
||||
disable(IDC_DLLS_REMOVEAPP);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID OnInitLibrariesDlg(HWND hDlg)
|
||||
{
|
||||
HWND hwndTV;
|
||||
LPAPPL lpAppl;
|
||||
HKEY applKey;
|
||||
int i;
|
||||
DWORD size;
|
||||
char appl [255];
|
||||
char lpcKey [255];
|
||||
FILETIME ft;
|
||||
|
||||
hwndTV = GetDlgItem(hDlg,IDC_TREE_DLLS);
|
||||
lpAppl = CreateAppl(TRUE,"Global DLL Overrides", "DllOverrides");
|
||||
LoadLibrarySettings(lpAppl, hDlg, hwndTV);
|
||||
|
||||
/*And now the application specific stuff:*/
|
||||
if (RegOpenKey(configKey, "AppDefaults", &applKey) == ERROR_SUCCESS) {
|
||||
i = 0;
|
||||
size = 255;
|
||||
while (RegEnumKeyEx(applKey, i, appl, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
|
||||
{
|
||||
sprintf(lpcKey, "AppDefaults\\%s\\DllOverrides", appl);
|
||||
lpAppl = CreateAppl(FALSE,appl, lpcKey);
|
||||
LoadLibrarySettings(lpAppl, hDlg, hwndTV);
|
||||
i++; size = 255;
|
||||
}
|
||||
RegCloseKey(applKey);
|
||||
}
|
||||
|
||||
SetEnabledDLLControls(hDlg, GLOBAL);
|
||||
}
|
||||
|
||||
static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
|
||||
{
|
||||
TVITEM ti;
|
||||
LPITEMTAG lpit;
|
||||
int buttonId;
|
||||
|
||||
ti.mask = TVIF_PARAM;
|
||||
ti.hItem = TreeView_GetSelection(hTV);
|
||||
if (TreeView_GetItem (hTV, &ti))
|
||||
{
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
if (lpit->lpDo)
|
||||
{
|
||||
WINE_TRACE("%s\n", lpit->lpDo->lpcKey);
|
||||
buttonId = IDC_RAD_BUILTIN;
|
||||
switch (lpit->lpDo->mode)
|
||||
{
|
||||
case NATIVE:
|
||||
buttonId = IDC_RAD_NATIVE;
|
||||
break;
|
||||
case BUILTIN:
|
||||
buttonId = IDC_RAD_BUILTIN;
|
||||
break;
|
||||
case NATIVE_BUILTIN:
|
||||
buttonId = IDC_RAD_NATIVE_BUILTIN;
|
||||
break;
|
||||
case BUILTIN_NATIVE:
|
||||
buttonId = IDC_RAD_BUILTIN_NATIVE;
|
||||
break;
|
||||
case DISABLE:
|
||||
buttonId = IDC_RAD_DISABLE;
|
||||
break;
|
||||
case UNKNOWN:
|
||||
buttonId = -1;
|
||||
break;
|
||||
}
|
||||
CheckRadioButton(hDlg, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, buttonId);
|
||||
SetEnabledDLLControls(hDlg, DLL);
|
||||
} else {
|
||||
if (lpit->lpAppl)
|
||||
{
|
||||
if (lpit->lpAppl->isGlobal == TRUE)
|
||||
SetEnabledDLLControls(hDlg, GLOBAL);
|
||||
else
|
||||
SetEnabledDLLControls(hDlg, APP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID SetDLLMode(HWND hDlg, DLLMODE mode)
|
||||
{
|
||||
HWND hTV;
|
||||
TVITEM ti;
|
||||
LPITEMTAG lpit;
|
||||
char* cMode;
|
||||
TVITEM tiPar;
|
||||
LPITEMTAG lpitPar;
|
||||
|
||||
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
|
||||
ti.mask = TVIF_PARAM;
|
||||
ti.hItem = TreeView_GetSelection(hTV);
|
||||
if (TreeView_GetItem (hTV, &ti))
|
||||
{
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
if (lpit->lpDo)
|
||||
{
|
||||
lpit->lpDo->mode = mode;
|
||||
cMode = DLLMode2Str (mode);
|
||||
/*Find parent, so we can read registry section*/
|
||||
tiPar.mask = TVIF_PARAM;
|
||||
tiPar.hItem = TreeView_GetParent(hTV, ti.hItem);
|
||||
if (TreeView_GetItem(hTV,&tiPar))
|
||||
{
|
||||
lpitPar = (LPITEMTAG) tiPar.lParam;
|
||||
if (lpitPar->lpAppl)
|
||||
{
|
||||
addTransaction(lpitPar->lpAppl->lpcSection, lpit->lpDo->lpcKey, ACTION_SET, cMode);
|
||||
}
|
||||
}
|
||||
free(cMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID OnBuiltinClick(HWND hDlg)
|
||||
{
|
||||
SetDLLMode(hDlg, BUILTIN);
|
||||
}
|
||||
|
||||
static VOID OnNativeClick(HWND hDlg)
|
||||
{
|
||||
SetDLLMode(hDlg, NATIVE);
|
||||
}
|
||||
|
||||
static VOID OnBuiltinNativeClick(HWND hDlg)
|
||||
{
|
||||
SetDLLMode(hDlg, BUILTIN_NATIVE);
|
||||
}
|
||||
|
||||
static VOID OnNativeBuiltinClick(HWND hDlg)
|
||||
{
|
||||
SetDLLMode(hDlg, NATIVE_BUILTIN);
|
||||
}
|
||||
|
||||
static VOID OnDisableClick(HWND hDlg)
|
||||
{
|
||||
SetDLLMode(hDlg, DISABLE);
|
||||
}
|
||||
|
||||
static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
|
||||
{
|
||||
FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
|
||||
}
|
||||
|
||||
static VOID OnAddDLLClick(HWND hDlg)
|
||||
{
|
||||
HWND hTV;
|
||||
TVITEM ti;
|
||||
LPITEMTAG lpit;
|
||||
LPITEMTAG lpitNew;
|
||||
TVITEM childti;
|
||||
char dll [255];
|
||||
BOOL doAdd;
|
||||
TVINSERTSTRUCT tis;
|
||||
|
||||
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
|
||||
ti.mask = TVIF_PARAM;
|
||||
ti.hItem = TreeView_GetSelection(hTV);
|
||||
if (TreeView_GetItem (hTV, &ti))
|
||||
{
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
if (lpit->lpDo) { /*Is this a DLL override (that is: a subitem), then find the parent*/
|
||||
ti.hItem = TreeView_GetParent(hTV, ti.hItem);
|
||||
if (TreeView_GetItem(hTV,&ti)) {
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
} else return;
|
||||
}
|
||||
} else return;
|
||||
/*Now we should have an parent item*/
|
||||
if (lpit->lpAppl)
|
||||
{
|
||||
lpitNew = CreateItemTag();
|
||||
SendDlgItemMessage(hDlg,IDC_DLLLIST,WM_GETTEXT,(WPARAM)255, (LPARAM) dll);
|
||||
if (strlen(dll) > 0) {
|
||||
/*Is the dll already in the list? If so, don't do it*/
|
||||
doAdd = TRUE;
|
||||
childti.mask = TVIF_PARAM;
|
||||
if ((childti.hItem = TreeView_GetNextItem(hTV, ti.hItem, TVGN_CHILD))) {
|
||||
/*Retrieved first child*/
|
||||
while (TreeView_GetItem (hTV, &childti))
|
||||
{
|
||||
if (strcmp(((LPITEMTAG)childti.lParam)->lpDo->lpcKey,dll) == 0) {
|
||||
doAdd = FALSE;
|
||||
break;
|
||||
}
|
||||
childti.hItem = TreeView_GetNextItem(hTV, childti.hItem, TVGN_NEXT);
|
||||
}
|
||||
}
|
||||
if (doAdd)
|
||||
{
|
||||
lpitNew->lpDo = CreateDLLOverride(dll);
|
||||
lpitNew->lpDo->mode = NATIVE;
|
||||
tis.hInsertAfter = TVI_LAST;
|
||||
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tis.u.item.pszText = dll;
|
||||
tis.u.item.lParam = (LPARAM)lpitNew;
|
||||
tis.hParent = ti.hItem;
|
||||
TreeView_InsertItem(hTV,&tis);
|
||||
UpdateDLLList(hDlg, dll);
|
||||
addTransaction(lpit->lpAppl->lpcSection, dll, ACTION_SET, "native");
|
||||
} else MessageBox(hDlg, "A DLL with that name is already in this list...", "", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
} else return;
|
||||
}
|
||||
|
||||
static VOID OnRemoveDLLClick(HWND hDlg)
|
||||
{
|
||||
HWND hTV;
|
||||
TVITEM ti;
|
||||
LPITEMTAG lpit;
|
||||
TVITEM tiPar;
|
||||
LPITEMTAG lpitPar;
|
||||
|
||||
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
|
||||
ti.mask = TVIF_PARAM;
|
||||
ti.hItem = TreeView_GetSelection(hTV);
|
||||
if (TreeView_GetItem (hTV, &ti)) {
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
if (lpit->lpDo)
|
||||
{
|
||||
/*Find parent for section*/
|
||||
tiPar.mask = TVIF_PARAM;
|
||||
tiPar.hItem = TreeView_GetParent(hTV, ti.hItem);
|
||||
if (TreeView_GetItem(hTV,&tiPar))
|
||||
{
|
||||
lpitPar = (LPITEMTAG) tiPar.lParam;
|
||||
if (lpitPar->lpAppl)
|
||||
{
|
||||
addTransaction(lpitPar->lpAppl->lpcSection, lpit->lpDo->lpcKey, ACTION_REMOVE, NULL);
|
||||
TreeView_DeleteItem(hTV,ti.hItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID OnAddApplicationClick(HWND hDlg)
|
||||
{
|
||||
char szFileTitle [255];
|
||||
char szFile [255];
|
||||
char lpcKey [255];
|
||||
|
||||
TVINSERTSTRUCT tis;
|
||||
LPITEMTAG lpit;
|
||||
OPENFILENAME ofn = { sizeof(OPENFILENAME),
|
||||
0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL, 0, 0, NULL,
|
||||
0, NULL, 0, NULL, NULL,
|
||||
OFN_SHOWHELP, 0, 0, NULL, 0, NULL };
|
||||
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.lpstrFileTitle[0] = '\0';
|
||||
ofn.nMaxFileTitle = sizeof(szFileTitle);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
|
||||
if (GetOpenFileName(&ofn))
|
||||
{
|
||||
tis.hParent = NULL;
|
||||
tis.hInsertAfter = TVI_LAST;
|
||||
tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tis.u.item.pszText = szFileTitle;
|
||||
lpit = CreateItemTag();
|
||||
sprintf(lpcKey, "AppDefaults\\%s\\DllOverrides", szFileTitle);
|
||||
lpit->lpAppl = CreateAppl(FALSE,szFileTitle,lpcKey);
|
||||
tis.u.item.lParam = (LPARAM)lpit;
|
||||
TreeView_InsertItem(GetDlgItem(hDlg,IDC_TREE_DLLS), &tis);
|
||||
setConfigValue(lpcKey,NULL,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID OnRemoveApplicationClick(HWND hDlg)
|
||||
{
|
||||
HWND hTV;
|
||||
TVITEM ti;
|
||||
LPITEMTAG lpit;
|
||||
|
||||
hTV = GetDlgItem(hDlg, IDC_TREE_DLLS);
|
||||
ti.mask = TVIF_PARAM;
|
||||
ti.hItem = TreeView_GetSelection(hTV);
|
||||
if (TreeView_GetItem (hTV, &ti)) {
|
||||
lpit = (LPITEMTAG) ti.lParam;
|
||||
if (lpit->lpAppl)
|
||||
{
|
||||
addTransaction(lpit->lpAppl->lpcSection, NULL, ACTION_REMOVE, NULL);
|
||||
TreeView_DeleteItem(hTV,ti.hItem);
|
||||
}
|
||||
}
|
||||
set_controls_from_selection(dialog);
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK
|
||||
|
@ -561,56 +351,53 @@ LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
OnInitLibrariesDlg(hDlg);
|
||||
init_libsheet(hDlg);
|
||||
break;
|
||||
case WM_SHOWWINDOW:
|
||||
set_window_title(hDlg);
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
switch (((LPNMHDR)lParam)->code) {
|
||||
case TVN_SELCHANGED: {
|
||||
switch(LOWORD(wParam)) {
|
||||
case IDC_TREE_DLLS:
|
||||
OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_TREE_DLLS));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TVN_DELETEITEM:
|
||||
OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
|
||||
break;
|
||||
case PSN_SETACTIVE:
|
||||
load_library_settings(hDlg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch(HIWORD(wParam)) {
|
||||
|
||||
/* FIXME: when the user hits enter in the DLL combo box we should invoke the add
|
||||
* add button, rather than the propsheet OK button. But I don't know how to do that!
|
||||
*/
|
||||
|
||||
case CBN_EDITCHANGE:
|
||||
if(LOWORD(wParam) == IDC_DLLCOMBO)
|
||||
{
|
||||
on_add_combo_change(hDlg);
|
||||
break;
|
||||
}
|
||||
|
||||
case BN_CLICKED:
|
||||
switch(LOWORD(wParam)) {
|
||||
case IDC_RAD_BUILTIN:
|
||||
OnBuiltinClick(hDlg);
|
||||
break;
|
||||
case IDC_RAD_NATIVE:
|
||||
OnNativeClick(hDlg);
|
||||
break;
|
||||
case IDC_RAD_BUILTIN_NATIVE:
|
||||
OnBuiltinNativeClick(hDlg);
|
||||
break;
|
||||
case IDC_RAD_NATIVE_BUILTIN:
|
||||
OnNativeBuiltinClick(hDlg);
|
||||
break;
|
||||
case IDC_RAD_DISABLE:
|
||||
OnDisableClick(hDlg);
|
||||
break;
|
||||
case IDC_DLLS_ADDAPP:
|
||||
OnAddApplicationClick(hDlg);
|
||||
break;
|
||||
case IDC_DLLS_REMOVEAPP:
|
||||
OnRemoveApplicationClick(hDlg);
|
||||
break;
|
||||
set_dllmode(hDlg, LOWORD(wParam));
|
||||
break;
|
||||
|
||||
case IDC_DLLS_ADDDLL:
|
||||
OnAddDLLClick(hDlg);
|
||||
break;
|
||||
on_add_click(hDlg);
|
||||
break;
|
||||
case IDC_DLLS_REMOVEDLL:
|
||||
OnRemoveDLLClick(hDlg);
|
||||
break;
|
||||
on_remove_click(hDlg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LBN_SELCHANGE:
|
||||
set_controls_from_selection(hDlg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -218,10 +218,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nShow)
|
|||
ExitProcess(1);
|
||||
}
|
||||
|
||||
/* is the user running as root? */
|
||||
if(getuid() == 0)
|
||||
MessageBox(NULL, "It is not advisable to run wine as root. Doing so may compromise the security of your computer. Please run wine as a normal user.", "", MB_OK);
|
||||
|
||||
/*
|
||||
* The next 3 lines should be all that is needed
|
||||
* for the Wine Configuration property sheet
|
||||
|
|
|
@ -53,26 +53,17 @@
|
|||
#define IDC_DESKTOP_BY 1026
|
||||
#define IDC_XDGA 1027
|
||||
#define IDC_XSHM 1028
|
||||
|
||||
/* dll editing */
|
||||
#define IDC_RAD_BUILTIN 1029
|
||||
#define IDC_RAD_NATIVE 1030
|
||||
#define IDC_RAD_BUILTIN_NATIVE 1031
|
||||
#define IDC_RAD_NATIVE_BUILTIN 1032
|
||||
#define IDC_RAD_DISABLE 1033
|
||||
#define IDC_TREE_DLLS 1034
|
||||
#define IDC_DLLS_ADDAPP 8000
|
||||
#define IDC_DLLS_LIST 1034
|
||||
#define IDC_DLLS_ADDDLL 8001
|
||||
#define IDC_DLLS_REMOVEAPP 8002
|
||||
#define IDC_DLLS_REMOVEDLL 8003
|
||||
#define IDC_DLLLIST 8004
|
||||
#define IDC_RADIO_DEFAULT_BUILTIN 1033
|
||||
#define IDC_RADIO_DEFAULT_NATIVE 1034
|
||||
#define IDC_RADIO_VIRTUAL 1035
|
||||
#define IDC_EDIT_VIRTUAL 1036
|
||||
#define IDC_BUTTON_VIRTUAL 1037
|
||||
#define IDC_RADIO_REAL 1038
|
||||
#define IDC_EDIT_REAL 1039
|
||||
#define IDC_BUTTON_REAL 1040
|
||||
#define IDC_BUTTON_FOLDERS 1041
|
||||
#define IDC_DLLCOMBO 8004
|
||||
|
||||
/* drive editing */
|
||||
#define IDC_LIST_DRIVES 1042
|
||||
|
|
|
@ -19,23 +19,6 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* TODO: (in rough order of priority)
|
||||
* - A mind bogglingly vast amount of stuff
|
||||
*
|
||||
* - Implement autodetect for drive configuration
|
||||
* - Figure out whether we need the virtual vs real drive selection stuff at the top of the property page
|
||||
* - Implement explicit mode vs instant-apply mode
|
||||
* - DLL editing
|
||||
* - Multimedia page
|
||||
* - Settings migration code (from old configs)
|
||||
* - Clean up resource.h, it's a bog
|
||||
*
|
||||
* Minor things that should be done someday:
|
||||
* - Make the desktop size UI a combo box, with a Custom option, so it's more obvious what you might want to choose here
|
||||
*
|
||||
* BUGS:
|
||||
* - x11drv page triggers key writes on entry
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -44,49 +27,70 @@
|
|||
#include <windows.h>
|
||||
#include <winreg.h>
|
||||
#include <wine/debug.h>
|
||||
#include <wine/list.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
|
||||
|
||||
#include "winecfg.h"
|
||||
|
||||
HKEY configKey = NULL;
|
||||
HKEY config_key = NULL;
|
||||
|
||||
|
||||
int initialize(void) {
|
||||
DWORD res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &configKey);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
|
||||
return 1;
|
||||
|
||||
/* this is called from the WM_SHOWWINDOW handlers of each tab page.
|
||||
*
|
||||
* it's a nasty hack, necessary because the property sheet insists on resetting the window title
|
||||
* to the title of the tab, which is utterly useless. dropping the property sheet is on the todo list.
|
||||
*/
|
||||
void set_window_title(HWND dialog)
|
||||
{
|
||||
char *newtitle;
|
||||
|
||||
/* update the window title */
|
||||
if (currentApp)
|
||||
{
|
||||
char *template = "Wine Configuration for %s";
|
||||
newtitle = HeapAlloc(GetProcessHeap(), 0, strlen(template) + strlen(currentApp) + 1);
|
||||
sprintf(newtitle, template, currentApp);
|
||||
}
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
newtitle = strdupA("Wine Configuration");
|
||||
}
|
||||
|
||||
WINE_TRACE("setting title to %s\n", newtitle);
|
||||
SendMessage(GetParent(dialog), PSM_SETTITLE, 0, (LPARAM) newtitle);
|
||||
HeapFree(GetProcessHeap(), 0, newtitle);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* getConfigValue: Retrieves a configuration value from the registry
|
||||
/**
|
||||
* getkey: Retrieves a configuration value from the registry
|
||||
*
|
||||
* const char *subKey : the name of the config section
|
||||
* const char *valueName : the name of the config value
|
||||
* const char *defaultResult : if the key isn't found, return this value instead
|
||||
* char *subkey : the name of the config section
|
||||
* char *name : the name of the config value
|
||||
* char *default : if the key isn't found, return this value instead
|
||||
*
|
||||
* Returns a buffer holding the value if successful, NULL if not. Caller is responsible for freeing the result.
|
||||
* Returns a buffer holding the value if successful, NULL if
|
||||
* not. Caller is responsible for releasing the result.
|
||||
*
|
||||
*/
|
||||
char *getConfigValue (const char *subkey, const char *valueName, const char *defaultResult)
|
||||
static char *getkey (char *subkey, char *name, char *def)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
DWORD dataLength;
|
||||
LPBYTE buffer = NULL;
|
||||
DWORD len;
|
||||
HKEY hSubKey = NULL;
|
||||
DWORD res;
|
||||
|
||||
WINE_TRACE("subkey=%s, valueName=%s, defaultResult=%s\n", subkey, valueName, defaultResult);
|
||||
WINE_TRACE("subkey=%s, name=%s, def=%s\n", subkey, name, def);
|
||||
|
||||
res = RegOpenKeyEx( configKey, subkey, 0, KEY_ALL_ACCESS, &hSubKey );
|
||||
if(res != ERROR_SUCCESS) {
|
||||
if( res==ERROR_FILE_NOT_FOUND )
|
||||
res = RegOpenKeyEx(config_key, subkey, 0, KEY_READ, &hSubKey);
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
if (res == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
WINE_TRACE("Section key not present - using default\n");
|
||||
return defaultResult ? strdup(defaultResult) : NULL;
|
||||
return def ? strdupA(def) : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -95,192 +99,367 @@ char *getConfigValue (const char *subkey, const char *valueName, const char *def
|
|||
goto end;
|
||||
}
|
||||
|
||||
res = RegQueryValueExA( hSubKey, valueName, NULL, NULL, NULL, &dataLength);
|
||||
if( res == ERROR_FILE_NOT_FOUND ) {
|
||||
WINE_TRACE("Value not present - using default\n");
|
||||
buffer = defaultResult ? strdup(defaultResult) : NULL;
|
||||
goto end;
|
||||
} else if( res!=ERROR_SUCCESS ) {
|
||||
WINE_ERR("Couldn't query value's length (res=%ld)\n", res );
|
||||
goto end;
|
||||
}
|
||||
|
||||
buffer = malloc(dataLength);
|
||||
if( buffer==NULL )
|
||||
res = RegQueryValueExA(hSubKey, name, NULL, NULL, NULL, &len);
|
||||
if (res == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
WINE_ERR("Couldn't allocate %lu bytes for the value\n", dataLength );
|
||||
WINE_TRACE("Value not present - using default\n");
|
||||
buffer = def ? strdupA(def) : NULL;
|
||||
goto end;
|
||||
} else if (res != ERROR_SUCCESS)
|
||||
{
|
||||
WINE_ERR("Couldn't query value's length (res=%ld)\n", res);
|
||||
goto end;
|
||||
}
|
||||
|
||||
RegQueryValueEx(hSubKey, valueName, NULL, NULL, (LPBYTE)buffer, &dataLength);
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, len + 1);
|
||||
|
||||
RegQueryValueEx(hSubKey, name, NULL, NULL, buffer, &len);
|
||||
|
||||
WINE_TRACE("buffer=%s\n", buffer);
|
||||
end:
|
||||
if( hSubKey!=NULL )
|
||||
RegCloseKey( hSubKey );
|
||||
if (hSubKey) RegCloseKey(hSubKey);
|
||||
|
||||
return buffer;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* setConfigValue : Sets a configuration key in the registry. Section
|
||||
* will be created if it doesn't already exist
|
||||
/**
|
||||
* setkey: convenience wrapper to set a key/value pair
|
||||
*
|
||||
* HKEY hCurrent : the registry key that the configuration is rooted at
|
||||
* const char *subKey : the name of the config section
|
||||
* const char *valueName : the name of the config value
|
||||
* const char *value : the value to set the configuration key to
|
||||
*
|
||||
* Returns 0 on success, non-zero otherwise
|
||||
*
|
||||
* If *valueName or *value is NULL, an empty section will be created
|
||||
* If valueName or value is NULL, an empty section will be created
|
||||
*/
|
||||
int setConfigValue (const char *subkey, const char *valueName, const char *value) {
|
||||
int setkey(const char *subkey, const char *name, const char *value) {
|
||||
DWORD res = 1;
|
||||
HKEY key = NULL;
|
||||
|
||||
WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey, valueName, value);
|
||||
WINE_TRACE("subkey=%s: name=%s, value=%s\n", subkey, name, value);
|
||||
|
||||
assert( subkey != NULL );
|
||||
|
||||
res = RegCreateKey(configKey, subkey, &key);
|
||||
res = RegCreateKey(config_key, subkey, &key);
|
||||
if (res != ERROR_SUCCESS) goto end;
|
||||
if (value == NULL || valueName == NULL) goto end;
|
||||
if (name == NULL || value == NULL) goto end;
|
||||
|
||||
res = RegSetValueEx(key, valueName, 0, REG_SZ, value, strlen(value) + 1);
|
||||
res = RegSetValueEx(key, name, 0, REG_SZ, value, strlen(value) + 1);
|
||||
if (res != ERROR_SUCCESS) goto end;
|
||||
|
||||
res = 0;
|
||||
end:
|
||||
if (key) RegCloseKey(key);
|
||||
if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", valueName, subkey, value, res);
|
||||
if (res != 0) WINE_ERR("Unable to set configuration key %s in section %s to %s, res=%ld\n", name, subkey, value, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* returns 0 on success, an HRESULT from the registry funtions otherwise */
|
||||
HRESULT doesConfigValueExist(const char *subkey, const char *valueName) {
|
||||
/* removes the requested value from the registry, however, does not
|
||||
* remove the section if empty. Returns S_OK (0) on success.
|
||||
*/
|
||||
static HRESULT remove_value(const char *subkey, const char *name)
|
||||
{
|
||||
HRESULT hr;
|
||||
HKEY key;
|
||||
|
||||
WINE_TRACE("subkey=%s, valueName=%s - ", subkey, valueName);
|
||||
WINE_TRACE("subkey=%s, name=%s\n", subkey, name);
|
||||
|
||||
hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
|
||||
if (hr != S_OK) {
|
||||
WINE_TRACE("no: subkey does not exist\n");
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = RegQueryValueEx(key, valueName, NULL, NULL, NULL, NULL);
|
||||
if (hr != S_OK) {
|
||||
WINE_TRACE("no: key does not exist\n");
|
||||
return hr;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
WINE_TRACE("yes\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* removes the requested value from the registry, however, does not remove the section if empty. Returns S_OK (0) on success. */
|
||||
HRESULT removeConfigValue(const char *subkey, const char *valueName) {
|
||||
HRESULT hr;
|
||||
HKEY key;
|
||||
WINE_TRACE("subkey=%s, valueName=%s\n", subkey, valueName);
|
||||
|
||||
hr = RegOpenKeyEx(configKey, subkey, 0, KEY_READ, &key);
|
||||
hr = RegOpenKeyEx(config_key, subkey, 0, KEY_READ, &key);
|
||||
if (hr != S_OK) return hr;
|
||||
|
||||
hr = RegDeleteValue(key, valueName);
|
||||
hr = RegDeleteValue(key, name);
|
||||
if (hr != ERROR_SUCCESS) return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* removes the requested configuration section (subkey) from the registry, assuming it exists */
|
||||
/* this function might be slightly pointless, but in future we may wish to treat recursion specially etc, so we'll keep it for now */
|
||||
HRESULT removeConfigSection(char *section) {
|
||||
HRESULT hr;
|
||||
/* removes the requested subkey from the registry, assuming it exists */
|
||||
static HRESULT remove_path(char *section) {
|
||||
WINE_TRACE("section=%s\n", section);
|
||||
|
||||
return hr = RegDeleteKey(configKey, section);
|
||||
return RegDeleteKey(config_key, section);
|
||||
}
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* Transaction management code */
|
||||
|
||||
struct transaction *tqhead, *tqtail;
|
||||
int instantApply = 1;
|
||||
/* This code exists for the following reasons:
|
||||
*
|
||||
* - It makes working with the registry easier
|
||||
* - By storing a mini cache of the registry, we can more easily implement
|
||||
* cancel/revert and apply. The 'settings list' is an overlay on top of
|
||||
* the actual registry data that we can write out at will.
|
||||
*
|
||||
* Rather than model a tree in memory, we simply store each absolute (rooted
|
||||
* at the config key) path.
|
||||
*
|
||||
*/
|
||||
|
||||
void destroyTransaction(struct transaction *trans) {
|
||||
assert( trans != NULL );
|
||||
|
||||
WINE_TRACE("destroying %p\n", trans);
|
||||
|
||||
free(trans->section);
|
||||
if (trans->key) free(trans->key);
|
||||
if (trans->newValue) free(trans->newValue);
|
||||
|
||||
if (trans->next) trans->next->prev = trans->prev;
|
||||
if (trans->prev) trans->prev->next = trans->next;
|
||||
if (trans == tqhead) tqhead = NULL;
|
||||
if (trans == tqtail) tqtail = NULL;
|
||||
|
||||
free(trans);
|
||||
}
|
||||
|
||||
void addTransaction(const char *section, const char *key, enum transaction_action action, const char *newValue) {
|
||||
struct transaction *trans = calloc(sizeof(struct transaction),1);
|
||||
|
||||
assert( section != NULL );
|
||||
if (action == ACTION_SET) assert( newValue != NULL );
|
||||
if (action == ACTION_SET) assert( key != NULL );
|
||||
|
||||
trans->section = strdup(section);
|
||||
if (key) trans->key = strdup(key);
|
||||
if (newValue) trans->newValue = strdup(newValue);
|
||||
trans->action = action;
|
||||
|
||||
if (tqtail == NULL) {
|
||||
tqtail = trans;
|
||||
tqhead = tqtail;
|
||||
} else {
|
||||
tqhead->next = trans;
|
||||
trans->prev = tqhead;
|
||||
tqhead = trans;
|
||||
}
|
||||
|
||||
if (instantApply) {
|
||||
processTransaction(trans);
|
||||
destroyTransaction(trans);
|
||||
}
|
||||
}
|
||||
|
||||
void processTransaction(struct transaction *trans) {
|
||||
if (trans->action == ACTION_SET) {
|
||||
WINE_TRACE("Setting %s\\%s to '%s'\n", trans->section, trans->key, trans->newValue);
|
||||
setConfigValue(trans->section, trans->key, trans->newValue);
|
||||
} else if (trans->action == ACTION_REMOVE) {
|
||||
if (trans->key) {
|
||||
WINE_TRACE("Removing %s\\%s\n", trans->section, trans->key);
|
||||
removeConfigValue(trans->section, trans->key);
|
||||
} else {
|
||||
/* NULL key means remove that section entirely */
|
||||
WINE_TRACE("Removing section %s\n", trans->section);
|
||||
removeConfigSection(trans->section);
|
||||
}
|
||||
}
|
||||
/* TODO: implement notifications here */
|
||||
}
|
||||
|
||||
void processTransQueue(void)
|
||||
struct setting
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
while (tqtail != NULL) {
|
||||
struct transaction *next = tqtail->next;
|
||||
processTransaction(tqtail);
|
||||
destroyTransaction(tqtail);
|
||||
tqtail = next;
|
||||
struct list entry;
|
||||
char *path; /* path in the registry rooted at the config key */
|
||||
char *name; /* name of the registry value */
|
||||
char *value; /* contents of the registry value. if null, this means a deletion */
|
||||
};
|
||||
|
||||
struct list *settings;
|
||||
|
||||
static void free_setting(struct setting *setting)
|
||||
{
|
||||
assert( setting != NULL );
|
||||
|
||||
WINE_TRACE("destroying %p\n", setting);
|
||||
|
||||
assert( setting->path && setting->name );
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, setting->path);
|
||||
HeapFree(GetProcessHeap(), 0, setting->name);
|
||||
if (setting->value) HeapFree(GetProcessHeap(), 0, setting->value);
|
||||
|
||||
list_remove(&setting->entry);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the value at path. If not in the settings
|
||||
* list, it will be fetched from the registry - failing that, the
|
||||
* default will be used.
|
||||
*
|
||||
* If already in the list, the contents as given there will be
|
||||
* returned. You are expected to HeapFree the result.
|
||||
*/
|
||||
char *get(char *path, char *name, char *def)
|
||||
{
|
||||
struct list *cursor;
|
||||
struct setting *s;
|
||||
char *val;
|
||||
|
||||
WINE_TRACE("path=%s, name=%s, def=%s\n", path, name, def);
|
||||
|
||||
/* check if it's in the list */
|
||||
LIST_FOR_EACH( cursor, settings )
|
||||
{
|
||||
s = LIST_ENTRY(cursor, struct setting, entry);
|
||||
|
||||
if (strcasecmp(path, s->path) != 0) continue;
|
||||
if (strcasecmp(name, s->name) != 0) continue;
|
||||
|
||||
WINE_TRACE("found %s:%s in settings list, returning %s\n", path, name, s->value);
|
||||
return strdupA(s->value);
|
||||
}
|
||||
|
||||
/* no, so get from the registry */
|
||||
val = getkey(path, name, def);
|
||||
|
||||
WINE_TRACE("returning %s\n", val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set a registry key.
|
||||
*
|
||||
* path is rooted at the config key, ie use "Version" or
|
||||
* "AppDefaults\\fooapp.exe\\Version". You can use keypath()
|
||||
* to get such a string.
|
||||
*
|
||||
* name is the value name, it must not be null (you cannot create
|
||||
* empty groups, sorry ...)
|
||||
*
|
||||
* value is what to set the value to, or NULL to delete it.
|
||||
*
|
||||
* These values will be copied when necessary.
|
||||
*/
|
||||
void set(char *path, char *name, char *value)
|
||||
{
|
||||
struct list *cursor;
|
||||
struct setting *s;
|
||||
|
||||
assert( path != NULL );
|
||||
assert( name != NULL );
|
||||
|
||||
WINE_TRACE("path=%s, name=%s, value=%s\n", path, name, value);
|
||||
|
||||
/* firstly, see if we already set this setting */
|
||||
LIST_FOR_EACH( cursor, settings )
|
||||
{
|
||||
struct setting *s = LIST_ENTRY(cursor, struct setting, entry);
|
||||
|
||||
if (strcasecmp(s->path, path) != 0) continue;
|
||||
if (strcasecmp(s->name, name) != 0) continue;
|
||||
|
||||
/* yes, we have already set it, so just replace the content and return */
|
||||
if (s->value) HeapFree(GetProcessHeap(), 0, s->value);
|
||||
s->value = value ? strdupA(value) : NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* otherwise add a new setting for it */
|
||||
s = HeapAlloc(GetProcessHeap(), 0, sizeof(struct setting));
|
||||
s->path = strdupA(path);
|
||||
s->name = strdupA(name);
|
||||
s->value = value ? strdupA(value) : NULL;
|
||||
|
||||
list_add_tail(settings, &s->entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* enumerates the value names at the given path, taking into account
|
||||
* the changes in the settings list.
|
||||
*
|
||||
* you are expected to HeapFree each element of the array, which is null
|
||||
* terminated, as well as the array itself.
|
||||
*/
|
||||
char **enumerate_values(char *path)
|
||||
{
|
||||
HKEY key;
|
||||
DWORD res, i = 0;
|
||||
char **values = NULL;
|
||||
int valueslen = 0;
|
||||
struct list *cursor;
|
||||
|
||||
res = RegOpenKeyEx(config_key, path, 0, KEY_READ, &key);
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
char name[1024];
|
||||
DWORD namesize = sizeof(name);
|
||||
BOOL removed = FALSE;
|
||||
|
||||
/* find out the needed size, allocate a buffer, read the value */
|
||||
if ((res = RegEnumValue(key, i, name, &namesize, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
WINE_TRACE("name=%s\n", name);
|
||||
|
||||
/* check if this value name has been removed in the settings list */
|
||||
LIST_FOR_EACH( cursor, settings )
|
||||
{
|
||||
struct setting *s = LIST_ENTRY(cursor, struct setting, entry);
|
||||
if (strcasecmp(s->path, path) != 0) continue;
|
||||
if (strcasecmp(s->name, name) != 0) continue;
|
||||
|
||||
if (!s->value)
|
||||
{
|
||||
WINE_TRACE("this key has been removed, so skipping\n");
|
||||
removed = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) /* this value was deleted by the user, so don't include it */
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, name);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* grow the array if necessary, add buffer to it, iterate */
|
||||
if (values) values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
|
||||
else values = HeapAlloc(GetProcessHeap(), 0, sizeof(char*));
|
||||
|
||||
values[valueslen++] = strdupA(name);
|
||||
WINE_TRACE("valueslen is now %d\n", valueslen);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WINE_WARN("failed opening registry key %s, res=0x%lx\n", path, res);
|
||||
}
|
||||
|
||||
WINE_TRACE("adding settings in list but not registry\n");
|
||||
|
||||
/* now we have to add the values that aren't in the registry but are in the settings list */
|
||||
LIST_FOR_EACH( cursor, settings )
|
||||
{
|
||||
struct setting *setting = LIST_ENTRY(cursor, struct setting, entry);
|
||||
BOOL found = FALSE;
|
||||
|
||||
if (strcasecmp(setting->path, path) != 0) continue;
|
||||
|
||||
if (!setting->value) continue;
|
||||
|
||||
for (i = 0; i < valueslen; i++)
|
||||
{
|
||||
if (strcasecmp(setting->name, values[i]) == 0)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) continue;
|
||||
|
||||
WINE_TRACE("%s in list but not registry\n", setting->name);
|
||||
|
||||
/* otherwise it's been set by the user but isn't in the registry */
|
||||
if (values) values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
|
||||
else values = HeapAlloc(GetProcessHeap(), 0, sizeof(char*));
|
||||
|
||||
values[valueslen++] = strdupA(setting->name);
|
||||
}
|
||||
|
||||
WINE_TRACE("adding null terminator\n");
|
||||
if (values)
|
||||
{
|
||||
values = HeapReAlloc(GetProcessHeap(), 0, values, sizeof(char*) * (valueslen + 1));
|
||||
values[valueslen] = NULL;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the given key/value pair exists in the registry or
|
||||
* has been written to.
|
||||
*/
|
||||
BOOL exists(char *path, char *name)
|
||||
{
|
||||
char *val = get(path, name, NULL);
|
||||
|
||||
if (val)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, val);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void process_setting(struct setting *s)
|
||||
{
|
||||
if (s->value)
|
||||
{
|
||||
WINE_TRACE("Setting %s:%s to '%s'\n", s->path, s->name, s->value);
|
||||
setkey(s->path, s->name, s->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NULL name means remove that path/section entirely */
|
||||
if (s->path && s->name) remove_value(s->path, s->name);
|
||||
else if (s->path && !s->name) remove_path(s->path);
|
||||
}
|
||||
}
|
||||
|
||||
void apply(void)
|
||||
{
|
||||
if (list_empty(settings)) return; /* we will be called for each page when the user clicks OK */
|
||||
|
||||
WINE_TRACE("()\n");
|
||||
|
||||
while (!list_empty(settings))
|
||||
{
|
||||
struct setting *s = (struct setting *) list_head(settings);
|
||||
process_setting(s);
|
||||
free_setting(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,11 +472,11 @@ char *keypath(char *section)
|
|||
{
|
||||
static char *result = NULL;
|
||||
|
||||
if (result) release(result);
|
||||
if (result) HeapFree(GetProcessHeap(), 0, result);
|
||||
|
||||
if (currentApp)
|
||||
{
|
||||
result = alloc(strlen("AppDefaults\\") + strlen(currentApp) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
|
||||
result = HeapAlloc(GetProcessHeap(), 0, strlen("AppDefaults\\") + strlen(currentApp) + 2 /* \\ */ + strlen(section) + 1 /* terminator */);
|
||||
sprintf(result, "AppDefaults\\%s\\%s", currentApp, section);
|
||||
}
|
||||
else
|
||||
|
@ -326,3 +505,18 @@ void PRINTERROR(void)
|
|||
(LPSTR)&msg, 0, NULL);
|
||||
WINE_TRACE("error: '%s'\n", msg);
|
||||
}
|
||||
|
||||
int initialize(void) {
|
||||
DWORD res = RegCreateKey(HKEY_LOCAL_MACHINE, WINE_KEY_ROOT, &config_key);
|
||||
|
||||
if (res != ERROR_SUCCESS) {
|
||||
WINE_ERR("RegOpenKey failed on wine config key (%ld)\n", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we could probably just have the list as static data */
|
||||
settings = HeapAlloc(GetProcessHeap(), 0, sizeof(struct list));
|
||||
list_init(settings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -46,30 +46,21 @@
|
|||
|
||||
#define WRITEME(owner) MessageBox(owner, "Write me!", "", MB_OK | MB_ICONEXCLAMATION);
|
||||
|
||||
|
||||
/* Transaction management */
|
||||
enum transaction_action {
|
||||
ACTION_SET,
|
||||
ACTION_REMOVE
|
||||
};
|
||||
|
||||
struct transaction {
|
||||
char *section;
|
||||
char *key;
|
||||
char *newValue;
|
||||
enum transaction_action action;
|
||||
struct transaction *next, *prev;
|
||||
};
|
||||
extern struct transaction *tqhead, *tqtail;
|
||||
|
||||
extern int instantApply; /* non-zero means apply all changes instantly */
|
||||
|
||||
#define EDITING_GLOBAL 0
|
||||
#define EDITING_APP 1
|
||||
extern int appSettings; /* non-zero means we are editing appdefault settings */
|
||||
|
||||
extern char *currentApp; /* NULL means editing global settings */
|
||||
|
||||
/* Use get and set to alter registry settings. The changes made through set
|
||||
won't be committed to the registry until process_all_settings is called,
|
||||
however get will still return accurate information.
|
||||
|
||||
You are expected to release the result of get. The parameters to set will
|
||||
be copied, so release them too when necessary.
|
||||
*/
|
||||
void set(char *path, char *name, char *value);
|
||||
char *get(char *path, char *name, char *def);
|
||||
BOOL exists(char *path, char *name);
|
||||
void apply(void);
|
||||
char **enumerate_values(char *path);
|
||||
|
||||
/* returns a string of the form "AppDefaults\\appname.exe\\section", or just "section" if
|
||||
* the user is editing the global settings.
|
||||
*
|
||||
|
@ -77,31 +68,11 @@ extern char *currentApp; /* NULL means editing global settings */
|
|||
*/
|
||||
char *keypath(char *section);
|
||||
|
||||
/* Commits a transaction to the registry */
|
||||
void processTransaction(struct transaction *trans);
|
||||
|
||||
/* Processes every pending transaction in the queue, removing them as it works from head to tail */
|
||||
void processTransQueue();
|
||||
|
||||
/* Adds a transaction to the head of the queue. If we're using instant apply, this calls processTransaction
|
||||
* action can be either:
|
||||
* ACTION_SET -> this transaction will change a registry key, newValue is the replacement value
|
||||
* ACTION_REMOVE -> this transaction will remove a registry key. In this case, newValue is ignored.
|
||||
*/
|
||||
void addTransaction(const char *section, const char *key, enum transaction_action action, const char *newValue);
|
||||
|
||||
/* frees the transaction structure, all fields, and removes it from the queue if in it */
|
||||
void destroyTransaction(struct transaction *trans);
|
||||
|
||||
/* Initializes the transaction system */
|
||||
int initialize(void);
|
||||
extern HKEY configKey;
|
||||
extern HKEY config_key;
|
||||
|
||||
/* don't use these directly! */
|
||||
int setConfigValue (const char *subkey, const char *valueName, const char *value);
|
||||
char *getConfigValue (const char *subkey, const char *valueName, const char *defaultResult);
|
||||
HRESULT doesConfigValueExist (const char *subkey, const char *valueName);
|
||||
HRESULT removeConfigValue (const char *subkey, const char *valueName);
|
||||
void set_window_title(HWND dialog);
|
||||
|
||||
/* Graphics */
|
||||
|
||||
|
@ -125,14 +96,12 @@ INT_PTR CALLBACK AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
|||
char *getDialogItemText(HWND hDlg, WORD controlID);
|
||||
#define disable(id) EnableWindow(GetDlgItem(dialog, id), 0);
|
||||
#define enable(id) EnableWindow(GetDlgItem(dialog, id), 1);
|
||||
#define alloc(size) HeapAlloc(GetProcessHeap(), 0, size);
|
||||
#define release(ptr) HeapFree(GetProcessHeap(), 0, ptr);
|
||||
void PRINTERROR(void); /* WINE_TRACE() the plaintext error message from GetLastError() */
|
||||
|
||||
/* returns a string in the win32 heap */
|
||||
static inline char *strdupA(char *s)
|
||||
{
|
||||
char *r = alloc(strlen(s));
|
||||
char *r = HeapAlloc(GetProcessHeap(), 0, strlen(s));
|
||||
return strcpy(r, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,19 +36,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
|
|||
|
||||
#define RES_MAXLEN 5 /* the maximum number of characters in a screen dimension. 5 digits should be plenty, what kind of crazy person runs their screen >10,000 pixels across? */
|
||||
|
||||
int updatingUI;
|
||||
int updating_ui;
|
||||
|
||||
int appSettings = EDITING_GLOBAL; /* start by editing global */
|
||||
|
||||
void updateGUIForDesktopMode(HWND dialog) {
|
||||
void update_gui_for_desktop_mode(HWND dialog) {
|
||||
WINE_TRACE("\n");
|
||||
|
||||
updatingUI = TRUE;
|
||||
updating_ui = TRUE;
|
||||
|
||||
/* do we have desktop mode enabled? */
|
||||
if (doesConfigValueExist(keypath("x11drv"), "Desktop") == S_OK) {
|
||||
if (exists(keypath("x11drv"), "Desktop"))
|
||||
{
|
||||
CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_CHECKED);
|
||||
/* enable the controls */
|
||||
|
||||
enable(IDC_DESKTOP_WIDTH);
|
||||
enable(IDC_DESKTOP_HEIGHT);
|
||||
enable(IDC_DESKTOP_SIZE);
|
||||
|
@ -57,9 +56,10 @@ void updateGUIForDesktopMode(HWND dialog) {
|
|||
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "640");
|
||||
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "480");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_UNCHECKED);
|
||||
/* disable the controls */
|
||||
|
||||
disable(IDC_DESKTOP_WIDTH);
|
||||
disable(IDC_DESKTOP_HEIGHT);
|
||||
disable(IDC_DESKTOP_SIZE);
|
||||
|
@ -69,22 +69,22 @@ void updateGUIForDesktopMode(HWND dialog) {
|
|||
SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "");
|
||||
}
|
||||
|
||||
updatingUI = FALSE;
|
||||
updating_ui = FALSE;
|
||||
}
|
||||
|
||||
/* pokes the win32 api to setup the dialog from the config struct */
|
||||
void initGraphDlg (HWND hDlg)
|
||||
{
|
||||
static const char default_desktop[] = "640x480";
|
||||
static char *default_desktop = "640x480";
|
||||
char *buf;
|
||||
char *bufindex;
|
||||
|
||||
updateGUIForDesktopMode(hDlg);
|
||||
update_gui_for_desktop_mode(hDlg);
|
||||
|
||||
updatingUI = TRUE;
|
||||
updating_ui = TRUE;
|
||||
|
||||
/* desktop size */
|
||||
buf = getConfigValue(keypath("x11drv"), "Desktop", default_desktop);
|
||||
buf = get(keypath("x11drv"), "Desktop", default_desktop);
|
||||
bufindex = strchr(buf, 'x');
|
||||
if(!bufindex) /* handle invalid "Desktop" values */
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ void initGraphDlg (HWND hDlg)
|
|||
bufindex++;
|
||||
SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_WIDTH), buf);
|
||||
SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_HEIGHT), bufindex);
|
||||
free(buf);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_RESETCONTENT, 0, 0);
|
||||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "8 bit");
|
||||
|
@ -104,7 +104,7 @@ void initGraphDlg (HWND hDlg)
|
|||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "24 bit");
|
||||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "32 bit"); /* is this valid? */
|
||||
|
||||
buf = getConfigValue(keypath("x11drv"), "ScreenDepth", "24");
|
||||
buf = get(keypath("x11drv"), "ScreenDepth", "24");
|
||||
if (strcmp(buf, "8") == 0)
|
||||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 0, 0);
|
||||
else if (strcmp(buf, "16") == 0)
|
||||
|
@ -115,36 +115,34 @@ void initGraphDlg (HWND hDlg)
|
|||
SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 3, 0);
|
||||
else
|
||||
WINE_ERR("Invalid screen depth read from registry (%s)\n", buf);
|
||||
free(buf);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
SendDlgItemMessage(hDlg, IDC_DESKTOP_WIDTH, EM_LIMITTEXT, RES_MAXLEN, 0);
|
||||
SendDlgItemMessage(hDlg, IDC_DESKTOP_HEIGHT, EM_LIMITTEXT, RES_MAXLEN, 0);
|
||||
|
||||
buf = getConfigValue(keypath("x11drv"), "DXGrab", "Y");
|
||||
buf = get(keypath("x11drv"), "DXGrab", "Y");
|
||||
if (IS_OPTION_TRUE(*buf))
|
||||
CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_CHECKED);
|
||||
else
|
||||
CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_UNCHECKED);
|
||||
free(buf);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
buf = getConfigValue(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
|
||||
buf = get(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
|
||||
if (IS_OPTION_TRUE(*buf))
|
||||
CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_CHECKED);
|
||||
else
|
||||
CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_UNCHECKED);
|
||||
free(buf);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
updatingUI = FALSE;
|
||||
updating_ui = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setFromDesktopSizeEdits(HWND hDlg) {
|
||||
char *width = malloc(RES_MAXLEN+1);
|
||||
char *height = malloc(RES_MAXLEN+1);
|
||||
char *newStr = malloc((RES_MAXLEN*2) + 2);
|
||||
char *width = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
|
||||
char *height = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
|
||||
char *new = HeapAlloc(GetProcessHeap(), 0, (RES_MAXLEN*2) + 2);
|
||||
|
||||
if (updatingUI) return;
|
||||
if (updating_ui) goto end;
|
||||
|
||||
WINE_TRACE("\n");
|
||||
|
||||
|
@ -154,12 +152,13 @@ void setFromDesktopSizeEdits(HWND hDlg) {
|
|||
if (strcmp(width, "") == 0) strcpy(width, "640");
|
||||
if (strcmp(height, "") == 0) strcpy(height, "480");
|
||||
|
||||
sprintf(newStr, "%sx%s", width, height);
|
||||
addTransaction(keypath("x11drv"), "Desktop", ACTION_SET, newStr);
|
||||
sprintf(new, "%sx%s", width, height);
|
||||
set(keypath("x11drv"), "Desktop", new);
|
||||
|
||||
free(width);
|
||||
free(height);
|
||||
free(newStr);
|
||||
end:
|
||||
HeapFree(GetProcessHeap(), 0, width);
|
||||
HeapFree(GetProcessHeap(), 0, height);
|
||||
HeapFree(GetProcessHeap(), 0, new);
|
||||
}
|
||||
|
||||
void onEnableDesktopClicked(HWND hDlg) {
|
||||
|
@ -169,9 +168,9 @@ void onEnableDesktopClicked(HWND hDlg) {
|
|||
setFromDesktopSizeEdits(hDlg);
|
||||
} else {
|
||||
/* it was just checked, so remove the config values */
|
||||
addTransaction(keypath("x11drv"), "Desktop", ACTION_REMOVE, NULL);
|
||||
set(keypath("x11drv"), "Desktop", NULL);
|
||||
}
|
||||
updateGUIForDesktopMode(hDlg);
|
||||
update_gui_for_desktop_mode(hDlg);
|
||||
}
|
||||
|
||||
void onScreenDepthChanged(HWND hDlg) {
|
||||
|
@ -179,26 +178,26 @@ void onScreenDepthChanged(HWND hDlg) {
|
|||
char *spaceIndex = strchr(newvalue, ' ');
|
||||
|
||||
WINE_TRACE("newvalue=%s\n", newvalue);
|
||||
if (updatingUI) return;
|
||||
if (updating_ui) return;
|
||||
|
||||
*spaceIndex = '\0';
|
||||
addTransaction(keypath("x11drv"), "ScreenDepth", ACTION_SET, newvalue);
|
||||
set(keypath("x11drv"), "ScreenDepth", newvalue);
|
||||
free(newvalue);
|
||||
}
|
||||
|
||||
void onDXMouseGrabClicked(HWND hDlg) {
|
||||
if (IsDlgButtonChecked(hDlg, IDC_DX_MOUSE_GRAB) == BST_CHECKED)
|
||||
addTransaction(keypath("x11drv"), "DXGrab", ACTION_SET, "Y");
|
||||
set(keypath("x11drv"), "DXGrab", "Y");
|
||||
else
|
||||
addTransaction(keypath("x11drv"), "DXGrab", ACTION_SET, "N");
|
||||
set(keypath("x11drv"), "DXGrab", "N");
|
||||
}
|
||||
|
||||
|
||||
void onDoubleBufferClicked(HWND hDlg) {
|
||||
if (IsDlgButtonChecked(hDlg, IDC_DOUBLE_BUFFER) == BST_CHECKED)
|
||||
addTransaction(keypath("x11drv"), "DesktopDoubleBuffered", ACTION_SET, "Y");
|
||||
set(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
|
||||
else
|
||||
addTransaction(keypath("x11drv"), "DesktopDoubleBuffered", ACTION_SET, "N");
|
||||
set(keypath("x11drv"), "DesktopDoubleBuffered", "N");
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK
|
||||
|
@ -208,16 +207,20 @@ GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_INITDIALOG:
|
||||
break;
|
||||
|
||||
case WM_SHOWWINDOW:
|
||||
set_window_title(hDlg);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(HIWORD(wParam)) {
|
||||
case EN_CHANGE: {
|
||||
SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
|
||||
if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updatingUI )
|
||||
if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updating_ui )
|
||||
setFromDesktopSizeEdits(hDlg);
|
||||
break;
|
||||
}
|
||||
case BN_CLICKED: {
|
||||
if (updatingUI) break;
|
||||
if (updating_ui) break;
|
||||
switch(LOWORD(wParam)) {
|
||||
case IDC_ENABLE_DESKTOP: onEnableDesktopClicked(hDlg); break;
|
||||
case IDC_DX_MOUSE_GRAB: onDXMouseGrabClicked(hDlg); break;
|
||||
|
@ -243,6 +246,7 @@ GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
}
|
||||
case PSN_APPLY: {
|
||||
apply();
|
||||
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue