This is a patch that adds a tabsheet to winecfg, that allows the user to change the dll overrides; both globally and per app.
With special thanx to Mike Hearn ;-).
Grtz, Robert
? programs/winecfg/tbsLibraries.c Index: programs/winecfg/En.rc =================================================================== RCS file: /home/wine/wine/programs/winecfg/En.rc,v retrieving revision 1.14 diff -u -r1.14 En.rc --- programs/winecfg/En.rc 26 Nov 2003 03:55:01 -0000 1.14 +++ programs/winecfg/En.rc 4 Jan 2004 18:20:36 -0000 @@ -96,15 +96,18 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Sans Serif" BEGIN - GROUPBOX "Static",IDC_STATIC,8,4,244,157 - CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,59,144,57,10 - CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,121,144,72,10 - LTEXT "Libraries can be specified individually to be either builtin or native. A DLL entry specified as ""*"" pertains to all DLLs not specified explicitly.", - IDC_STATIC,15,17,228,27 - CONTROL "List3",IDC_LIST_DLLS,"SysListView32",LVS_LIST | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | - WS_TABSTOP,15,47,227,90 - LTEXT "Load order:",IDC_STATIC,16,144,37,8 + 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.\n\nBe careful, wrong settings here have the potential to pretty much kill your setup." + , IDC_STATIC,15,17,228,47 + CONTROL "DLL Overrides", IDC_TREE_DLLS, "SysTreeView32", WS_TABSTOP | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_HASBUTTONS, 15,65,142,172 + LTEXT "Load order:",IDC_STATIC,163,65,37,8 + CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,163,80,57,10 + CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,163,95,72,10 + PUSHBUTTON "Add application...",IDC_DLLS_ADDAPP,163,114,82,14 + PUSHBUTTON "Remove application",IDC_DLLS_REMOVEAPP, 163,134,82,14 + PUSHBUTTON "Add DLL override for:",IDC_DLLS_ADDDLL, 163,154,82,14 + COMBOBOX IDC_DLLLIST,163,174,82,14,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | CBS_SORT | CBS_LOWERCASE + PUSHBUTTON "Remove DLL override",IDC_DLLS_REMOVEDLL,163,194,82,14 END IDD_SYSTEMCFG DIALOG DISCARDABLE 0, 0, 260, 250 Index: programs/winecfg/Es.rc =================================================================== RCS file: /home/wine/wine/programs/winecfg/Es.rc,v retrieving revision 1.4 diff -u -r1.4 Es.rc --- programs/winecfg/Es.rc 26 Nov 2003 03:55:01 -0000 1.4 +++ programs/winecfg/Es.rc 4 Jan 2004 18:20:37 -0000 @@ -84,15 +84,6 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Sans Serif" BEGIN - GROUPBOX "Estático",IDC_STATIC,8,4,244,157 - CONTROL "Integrado (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,59,144,57,10 - CONTROL "Nativo (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,121,144,72,10 - LTEXT "Las librerías pueden especificarse individualmente para ser integradas o nativas. Una entrada de DLL especificada como ""*"" se refiere a todas las DLL no especificadas explícitamente.", - IDC_STATIC,15,17,228,27 - CONTROL "List3",IDC_LIST_DLLS,"SysListView32",LVS_LIST | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | - WS_TABSTOP,15,47,227,90 - LTEXT "Orden de carga:",IDC_STATIC,16,144,37,8 END IDD_SYSTEMCFG DIALOG DISCARDABLE 0, 0, 260, 250 Index: programs/winecfg/Makefile.in =================================================================== RCS file: /home/wine/wine/programs/winecfg/Makefile.in,v retrieving revision 1.6 diff -u -r1.6 Makefile.in --- programs/winecfg/Makefile.in 3 Oct 2003 05:01:33 -0000 1.6 +++ programs/winecfg/Makefile.in 4 Jan 2004 18:20:37 -0000 @@ -4,7 +4,7 @@ VPATH = @srcdir@ MODULE = winecfg.exe APPMODE = gui -IMPORTS = comctl32 user32 advapi32 +IMPORTS = comctl32 user32 advapi32 comdlg32 C_SRCS = \ appdefaults.c \ @@ -12,7 +12,8 @@ main.c \ properties.c \ winecfg.c \ - x11drvdlg.c + x11drvdlg.c \ + tbsLibraries.c RC_SRCS = winecfg.rc RC_BINSRC = winecfg.rc Index: programs/winecfg/Pt.rc =================================================================== RCS file: /home/wine/wine/programs/winecfg/Pt.rc,v retrieving revision 1.4 diff -u -r1.4 Pt.rc --- programs/winecfg/Pt.rc 26 Nov 2003 03:55:01 -0000 1.4 +++ programs/winecfg/Pt.rc 4 Jan 2004 18:20:37 -0000 @@ -40,7 +40,6 @@ GROUPBOX "Comportamento padrão",IDC_STATIC,8,115,244,97 LTEXT "Wine providencia a aplicações Windows, a habilidade de se parecer a várias versões e estilos de Windows", IDC_STATIC,15,128,227,20 - GROUPBOX "Informação",IDC_STATIC,8,4,244,106 CTEXT "This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,59 END @@ -93,15 +92,6 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Sans Serif" BEGIN - GROUPBOX "Estático",IDC_STATIC,8,4,244,157 - CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,59,144,57,10 - CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,121,144,72,10 - LTEXT "Bibliotecas podem ser especificadas individualmente a ser builtin ou native. Uma entrada de DLL especificada como ""*"" define todas as DLLs não especificadas explicitamente.", - IDC_STATIC,15,17,228,27 - CONTROL "List3",IDC_LIST_DLLS,"SysListView32",LVS_LIST | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | - WS_TABSTOP,15,47,227,90 - LTEXT "Ordem de carga:",IDC_STATIC,16,144,37,8 END Index: programs/winecfg/Ru.rc =================================================================== RCS file: /home/wine/wine/programs/winecfg/Ru.rc,v retrieving revision 1.2 diff -u -r1.2 Ru.rc --- programs/winecfg/Ru.rc 26 Nov 2003 03:55:01 -0000 1.2 +++ programs/winecfg/Ru.rc 4 Jan 2004 18:20:39 -0000 @@ -97,15 +97,6 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Sans Serif" BEGIN - GROUPBOX "Ñòàòè÷íûå",IDC_STATIC,8,4,244,157 - CONTROL "Âñòðîåííàÿ (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,59,144,57,10 - CONTROL "Âíåøíÿÿ (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,121,144,72,10 - LTEXT "Ìîæíî èíäèâèäóëüíî âûáðàòü èñïîëüçîâàòü âíóòðåííèå èëè âíåøíèå áèáëèîòåêè. Çàïèñü ""*"" äåéñòâóåò íà âñå áèáëèîòåêè íå ïåðå÷èñëåííûå íàïðÿìóþ.", - IDC_STATIC,15,17,228,27 - CONTROL "List3",IDC_LIST_DLLS,"SysListView32",LVS_LIST | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | - WS_TABSTOP,15,47,227,90 - LTEXT "Ïîðÿäîê çàãðóçêè:",IDC_STATIC,16,144,37,8 END IDD_SYSTEMCFG DIALOG DISCARDABLE 0, 0, 260, 250 Index: programs/winecfg/Si.rc =================================================================== RCS file: /home/wine/wine/programs/winecfg/Si.rc,v retrieving revision 1.3 diff -u -r1.3 Si.rc --- programs/winecfg/Si.rc 26 Nov 2003 03:55:01 -0000 1.3 +++ programs/winecfg/Si.rc 4 Jan 2004 18:20:39 -0000 @@ -88,15 +88,6 @@ STYLE WS_CHILD | WS_DISABLED FONT 8, "MS Sans Serif" BEGIN - GROUPBOX "Static",IDC_STATIC,8,4,244,157 - CONTROL "Builtin (Wine)",IDC_RAD_BUILTIN,"Button", BS_AUTORADIOBUTTON | WS_GROUP,59,144,57,10 - CONTROL "Native (Windows)",IDC_RAD_NATIVE,"Button", BS_AUTORADIOBUTTON,121,144,72,10 - LTEXT "Libraries can be specified individually to be either builtin or native. A DLL entry specified as ""*"" pertains to all DLLs not specified explicitly.", - IDC_STATIC,15,17,228,27 - CONTROL "List3",IDC_LIST_DLLS,"SysListView32",LVS_LIST | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | - WS_TABSTOP,15,47,227,90 - LTEXT "Load order:",IDC_STATIC,16,144,37,8 END STRINGTABLE DISCARDABLE Index: programs/winecfg/main.c =================================================================== RCS file: /home/wine/wine/programs/winecfg/main.c,v retrieving revision 1.11 diff -u -r1.11 main.c --- programs/winecfg/main.c 22 Oct 2003 03:02:26 -0000 1.11 +++ programs/winecfg/main.c 4 Jan 2004 18:20:39 -0000 @@ -177,22 +177,6 @@ return FALSE; } - -INT_PTR CALLBACK -DllDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case WM_COMMAND: - break; - - default: - break; - } - return FALSE; -} - - #define NUM_PROPERTY_PAGES 5 INT_PTR doPropertySheet (HINSTANCE hInstance, HWND hOwner) @@ -235,7 +219,7 @@ psp[2].hInstance = hInstance; psp[2].u.pszTemplate = MAKEINTRESOURCE (IDD_DLLCFG); psp[2].u2.pszIcon = NULL; - psp[2].pfnDlgProc = DllDlgProc; + psp[2].pfnDlgProc = LibrariesDlgProc; psp[2].pszTitle = "Libraries"; psp[2].lParam = 0; Index: programs/winecfg/resource.h =================================================================== RCS file: /home/wine/wine/programs/winecfg/resource.h,v retrieving revision 1.9 diff -u -r1.9 resource.h --- programs/winecfg/resource.h 30 Sep 2003 00:27:55 -0000 1.9 +++ programs/winecfg/resource.h 4 Jan 2004 18:20:39 -0000 @@ -54,9 +54,12 @@ #define IDC_XSHM 1028 #define IDC_RAD_BUILTIN 1029 #define IDC_RAD_NATIVE 1030 -#define IDC_LIST_DLLS 1031 -#define IDC_LIST_BUILTIN_DLLS 1031 -#define IDC_LIST_NATIVE_DLLS 1032 +#define IDC_TREE_DLLS 1031 +#define IDC_DLLS_ADDAPP 8000 +#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 Index: programs/winecfg/winecfg.c =================================================================== RCS file: /home/wine/wine/programs/winecfg/winecfg.c,v retrieving revision 1.17 diff -u -r1.17 winecfg.c --- programs/winecfg/winecfg.c 24 Oct 2003 04:18:17 -0000 1.17 +++ programs/winecfg/winecfg.c 4 Jan 2004 18:20:39 -0000 @@ -132,7 +132,8 @@ * 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 */ int setConfigValue (const char *subkey, const char *valueName, const char *value) { DWORD res = 1; @@ -141,11 +142,10 @@ WINE_TRACE("subkey=%s, valueName=%s, value=%s\n", subkey, valueName, value); assert( subkey != NULL ); - assert( valueName != NULL ); - assert( value != NULL ); res = RegCreateKey(configKey, subkey, &key); if (res != ERROR_SUCCESS) goto end; + if (value == NULL || valueName == NULL) goto end; res = RegSetValueEx(key, valueName, 0, REG_SZ, value, strlen(value) + 1); if (res != ERROR_SUCCESS) goto end; Index: programs/winecfg/winecfg.h =================================================================== RCS file: /home/wine/wine/programs/winecfg/winecfg.h,v retrieving revision 1.11 diff -u -r1.11 winecfg.h --- programs/winecfg/winecfg.h 9 Oct 2003 04:39:01 -0000 1.11 +++ programs/winecfg/winecfg.h 4 Jan 2004 18:20:39 -0000 @@ -109,6 +109,7 @@ INT_PTR CALLBACK DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); /* some basic utilities to make win32 suck less */ char *getDialogItemText(HWND hDlg, WORD controlID); @@ -117,5 +118,4 @@ #define WINE_KEY_ROOT "Software\\Wine\\Wine\\Config" - #endif --- /dev/null 2003-12-26 12:00:33.000000000 +0100 +++ programs/winecfg/tbsLibraries.c 2004-01-04 18:00:39.000000000 +0100 @@ -0,0 +1,505 @@ +/* + * WineCfg libraries tabsheet + * + * Copyright 2004 Robert van Herk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <windows.h> +#include <commdlg.h> +#include <wine/debug.h> +#include <stdio.h> +#include "winecfg.h" +#include "resource.h" +WINE_DEFAULT_DEBUG_CHANNEL(winecfg); + +typedef enum _DLGMODE +{ + DLL, + APP, + GLOBAL, +} DLGMODE; + +typedef enum _DLLMODE { + BUILTIN, + NATIVE +} DLLMODE; + +typedef struct _DLLOVERRIDE +{ + char* lpcKey; /*The actual dll name*/ + DLLMODE mode; +} DLLOVERRIDE, *LPDLLOVERRIDE; + +LPDLLOVERRIDE CreateDLLOverride(char* lpcKey) +{ + LPDLLOVERRIDE out = HeapAlloc(GetProcessHeap(),0,sizeof(DLLOVERRIDE)); + out->lpcKey = strdup (lpcKey); + return out; +} + +VOID FreeDLLOverride(LPDLLOVERRIDE ldo) +{ + if (ldo->lpcKey) + free(ldo->lpcKey); + HeapFree(GetProcessHeap(),0,ldo); +} + +typedef struct _APPL +{ + BOOL isGlobal; + char* lpcApplication; + char* lpcSection; /*Registry section*/ +} APPL, *LPAPPL; + +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; +} + +VOID FreeAppl(LPAPPL lpAppl) +{ + 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); +} + +typedef struct _ITEMTAG +{ + LPAPPL lpAppl; + LPDLLOVERRIDE lpDo; +} ITEMTAG, *LPITEMTAG; + +LPITEMTAG CreateItemTag() +{ + LPITEMTAG out; + out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG)); + out->lpAppl = 0; + out->lpDo = 0; + return out; +} + +VOID FreeItemTag(LPITEMTAG lpit) +{ + if (lpit->lpAppl) + FreeAppl(lpit->lpAppl); + if (lpit->lpDo) + FreeDLLOverride(lpit->lpDo); + HeapFree(GetProcessHeap(),0,lpit); +} + +VOID UpdateDLLList(HWND hDlg, char* dll) +{ + /*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); +} + +VOID LoadLibrarySettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV) +{ + HKEY key; + int i; + DWORD size; + DWORD readSize; + char name [255]; + char read [255]; + LPITEMTAG lpIt; + TVINSERTSTRUCT tis; + HTREEITEM hParent; + LPDLLOVERRIDE lpdo; + + WINE_TRACE("opening %s\n", appl->lpcSection); + if (RegOpenKey (configKey, appl->lpcSection, &key) == ERROR_SUCCESS) + { + i = 0; + size = 255; + readSize = 255; + + lpIt = CreateItemTag(); + lpIt->lpAppl = appl; + + tis.hParent = NULL; + tis.hInsertAfter = TVI_LAST; + tis.item.mask = TVIF_TEXT | TVIF_PARAM; + tis.item.pszText = appl->lpcApplication; + tis.item.lParam = (LPARAM)lpIt; + hParent = TreeView_InsertItem(hwndTV,&tis); + tis.hParent = hParent; + + while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS) + { + WINE_TRACE("Reading value %s, namely %s\n", name, read); + + lpIt = CreateItemTag(); + lpdo = CreateDLLOverride(name); + lpIt->lpDo = lpdo; + tis.item.lParam = (LPARAM)lpIt; + tis.item.pszText = name; + if (strncmp (read, "built", 5) == 0) + lpdo->mode = BUILTIN; + else + lpdo->mode = NATIVE; + + TreeView_InsertItem(hwndTV,&tis); + UpdateDLLList(hDlg, name); + i ++; size = 255; readSize = 255; + } + RegCloseKey(key); + } +} + +VOID SetEnabledDLLControls(HWND dialog, DLGMODE dlgmode) +{ + if (dlgmode == DLL) { + enable(IDC_RAD_BUILTIN); + enable(IDC_RAD_NATIVE); + enable(IDC_DLLS_REMOVEDLL); + } else { + disable(IDC_RAD_BUILTIN); + disable(IDC_RAD_NATIVE); + disable(IDC_DLLS_REMOVEDLL); + } + + if (dlgmode == APP) { + enable(IDC_DLLS_REMOVEAPP); + } + else { + disable(IDC_DLLS_REMOVEAPP); + } +} + +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); +} + +VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV) +{ + TVITEM ti; + LPITEMTAG lpit; + + 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); + if (lpit->lpDo->mode == BUILTIN) { + CheckRadioButton(hDlg, IDC_RAD_BUILTIN, IDC_RAD_NATIVE, IDC_RAD_BUILTIN); + } else { + CheckRadioButton(hDlg, IDC_RAD_BUILTIN, IDC_RAD_NATIVE, IDC_RAD_NATIVE); + } + SetEnabledDLLControls(hDlg, DLL); + } else { + if (lpit->lpAppl) + { + if (lpit->lpAppl->isGlobal == TRUE) + SetEnabledDLLControls(hDlg, GLOBAL); + else + SetEnabledDLLControls(hDlg, APP); + } + } + } +} + +VOID SetDLLMode(HWND hDlg, DLLMODE mode); +VOID OnBuiltinClick(HWND hDlg) +{ + SetDLLMode(hDlg, BUILTIN); +} +VOID OnNativeClick(HWND hDlg) +{ + SetDLLMode(hDlg, NATIVE); +} +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; + if (mode == NATIVE) + cMode = "native, builtin"; + else + cMode = "builtin, native"; + + /*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); + } + } + } + } +} + +VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt) +{ + FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam)); +} + +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.item.mask = TVIF_TEXT | TVIF_PARAM; + tis.item.pszText = dll; + tis.item.lParam = (LPARAM)lpitNew; + tis.hParent = ti.hItem; + TreeView_InsertItem(hTV,&tis); + UpdateDLLList(hDlg, dll); + addTransaction(lpit->lpAppl->lpcSection, dll, ACTION_SET, "native, builtin"); + } else MessageBox(hDlg, "A DLL with that name is already in this list...", "", MB_OK | MB_ICONINFORMATION); + } + } else return; +} + +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); + } + } + } + } +} + +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.item.mask = TVIF_TEXT | TVIF_PARAM; + tis.item.pszText = szFileTitle; + lpit = CreateItemTag(); + sprintf(lpcKey, "AppDefaults\\%s\\DllOverrides", szFileTitle); + lpit->lpAppl = CreateAppl(FALSE,szFileTitle,lpcKey); + tis.item.lParam = (LPARAM)lpit; + TreeView_InsertItem(GetDlgItem(hDlg,IDC_TREE_DLLS), &tis); + setConfigValue(lpcKey,NULL,NULL); + } +} + +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); + } + } +} + +INT_PTR CALLBACK +LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + OnInitLibrariesDlg(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; + } + break; + case WM_COMMAND: + switch(HIWORD(wParam)) { + case BN_CLICKED: + switch(LOWORD(wParam)) { + case IDC_RAD_BUILTIN: + OnBuiltinClick(hDlg); + break; + case IDC_RAD_NATIVE: + OnNativeClick(hDlg); + break; + case IDC_DLLS_ADDAPP: + OnAddApplicationClick(hDlg); + break; + case IDC_DLLS_REMOVEAPP: + OnRemoveApplicationClick(hDlg); + break; + case IDC_DLLS_ADDDLL: + OnAddDLLClick(hDlg); + break; + case IDC_DLLS_REMOVEDLL: + OnRemoveDLLClick(hDlg); + break; + } + break; + } + break; + } + + return 0; +}