2 * WineCfg libraries tabsheet
4 * Copyright 2004 Robert van Herk
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define NONAMELESSUNION
25 #include <wine/debug.h>
30 WINE_DEFAULT_DEBUG_CHANNEL(winecfg
);
39 typedef enum _DLLMODE
{
44 typedef struct _DLLOVERRIDE
46 char* lpcKey
; /*The actual dll name*/
48 } DLLOVERRIDE
, *LPDLLOVERRIDE
;
50 static LPDLLOVERRIDE
CreateDLLOverride(char* lpcKey
)
52 LPDLLOVERRIDE out
= HeapAlloc(GetProcessHeap(),0,sizeof(DLLOVERRIDE
));
53 out
->lpcKey
= strdup (lpcKey
);
57 static VOID
FreeDLLOverride(LPDLLOVERRIDE ldo
)
61 HeapFree(GetProcessHeap(),0,ldo
);
68 char* lpcSection
; /*Registry section*/
71 static LPAPPL
CreateAppl(BOOL isGlobal
, char* application
, char* section
)
74 out
= HeapAlloc(GetProcessHeap(),0,sizeof(APPL
));
75 out
->lpcApplication
= strdup(application
);
76 out
->lpcSection
= strdup(section
);
77 out
->isGlobal
= isGlobal
;
81 static VOID
FreeAppl(LPAPPL lpAppl
)
83 if (lpAppl
->lpcApplication
)
84 free(lpAppl
->lpcApplication
); /* The strings were strdup-ped, so we use "free" */
85 if (lpAppl
->lpcSection
)
86 free(lpAppl
->lpcSection
);
87 HeapFree(GetProcessHeap(),0,lpAppl
);
90 typedef struct _ITEMTAG
94 } ITEMTAG
, *LPITEMTAG
;
96 static LPITEMTAG
CreateItemTag()
99 out
= HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG
));
105 static VOID
FreeItemTag(LPITEMTAG lpit
)
108 FreeAppl(lpit
->lpAppl
);
110 FreeDLLOverride(lpit
->lpDo
);
111 HeapFree(GetProcessHeap(),0,lpit
);
114 static VOID
UpdateDLLList(HWND hDlg
, char* dll
)
116 /*Add if it isn't already in*/
117 if (SendDlgItemMessage(hDlg
, IDC_DLLLIST
, CB_FINDSTRING
, 1, (LPARAM
) dll
) == CB_ERR
)
118 SendDlgItemMessage(hDlg
,IDC_DLLLIST
,CB_ADDSTRING
,0,(LPARAM
) dll
);
121 static VOID
LoadLibrarySettings(LPAPPL appl
/*DON'T FREE, treeview will own this*/, HWND hDlg
, HWND hwndTV
)
134 WINE_TRACE("opening %s\n", appl
->lpcSection
);
135 if (RegOpenKey (configKey
, appl
->lpcSection
, &key
) == ERROR_SUCCESS
)
141 lpIt
= CreateItemTag();
145 tis
.hInsertAfter
= TVI_LAST
;
146 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
147 tis
.u
.item
.pszText
= appl
->lpcApplication
;
148 tis
.u
.item
.lParam
= (LPARAM
)lpIt
;
149 hParent
= TreeView_InsertItem(hwndTV
,&tis
);
150 tis
.hParent
= hParent
;
152 while (RegEnumValue(key
, i
, name
, &size
, NULL
, NULL
, read
, &readSize
) == ERROR_SUCCESS
)
154 WINE_TRACE("Reading value %s, namely %s\n", name
, read
);
156 lpIt
= CreateItemTag();
157 lpdo
= CreateDLLOverride(name
);
159 tis
.u
.item
.lParam
= (LPARAM
)lpIt
;
160 tis
.u
.item
.pszText
= name
;
161 if (strncmp (read
, "built", 5) == 0)
162 lpdo
->mode
= BUILTIN
;
166 TreeView_InsertItem(hwndTV
,&tis
);
167 UpdateDLLList(hDlg
, name
);
168 i
++; size
= 255; readSize
= 255;
174 static VOID
SetEnabledDLLControls(HWND dialog
, DLGMODE dlgmode
)
176 if (dlgmode
== DLL
) {
177 enable(IDC_RAD_BUILTIN
);
178 enable(IDC_RAD_NATIVE
);
179 enable(IDC_DLLS_REMOVEDLL
);
181 disable(IDC_RAD_BUILTIN
);
182 disable(IDC_RAD_NATIVE
);
183 disable(IDC_DLLS_REMOVEDLL
);
186 if (dlgmode
== APP
) {
187 enable(IDC_DLLS_REMOVEAPP
);
190 disable(IDC_DLLS_REMOVEAPP
);
194 static VOID
OnInitLibrariesDlg(HWND hDlg
)
205 hwndTV
= GetDlgItem(hDlg
,IDC_TREE_DLLS
);
206 lpAppl
= CreateAppl(TRUE
,"Global DLL Overrides", "DllOverrides");
207 LoadLibrarySettings(lpAppl
, hDlg
, hwndTV
);
209 /*And now the application specific stuff:*/
210 if (RegOpenKey(configKey
, "AppDefaults", &applKey
) == ERROR_SUCCESS
) {
213 while (RegEnumKeyEx(applKey
, i
, appl
, &size
, NULL
, NULL
, NULL
, &ft
) == ERROR_SUCCESS
)
215 sprintf(lpcKey
, "AppDefaults\\%s\\DllOverrides", appl
);
216 lpAppl
= CreateAppl(FALSE
,appl
, lpcKey
);
217 LoadLibrarySettings(lpAppl
, hDlg
, hwndTV
);
220 RegCloseKey(applKey
);
223 SetEnabledDLLControls(hDlg
, GLOBAL
);
226 static VOID
OnTreeViewChangeItem(HWND hDlg
, HWND hTV
)
231 ti
.mask
= TVIF_PARAM
;
232 ti
.hItem
= TreeView_GetSelection(hTV
);
233 if (TreeView_GetItem (hTV
, &ti
))
235 lpit
= (LPITEMTAG
) ti
.lParam
;
238 WINE_TRACE("%s\n", lpit
->lpDo
->lpcKey
);
239 if (lpit
->lpDo
->mode
== BUILTIN
) {
240 CheckRadioButton(hDlg
, IDC_RAD_BUILTIN
, IDC_RAD_NATIVE
, IDC_RAD_BUILTIN
);
242 CheckRadioButton(hDlg
, IDC_RAD_BUILTIN
, IDC_RAD_NATIVE
, IDC_RAD_NATIVE
);
244 SetEnabledDLLControls(hDlg
, DLL
);
248 if (lpit
->lpAppl
->isGlobal
== TRUE
)
249 SetEnabledDLLControls(hDlg
, GLOBAL
);
251 SetEnabledDLLControls(hDlg
, APP
);
257 static VOID
SetDLLMode(HWND hDlg
, DLLMODE mode
)
266 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
267 ti
.mask
= TVIF_PARAM
;
268 ti
.hItem
= TreeView_GetSelection(hTV
);
269 if (TreeView_GetItem (hTV
, &ti
))
271 lpit
= (LPITEMTAG
) ti
.lParam
;
274 lpit
->lpDo
->mode
= mode
;
276 cMode
= "native, builtin";
278 cMode
= "builtin, native";
280 /*Find parent, so we can read registry section*/
281 tiPar
.mask
= TVIF_PARAM
;
282 tiPar
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
283 if (TreeView_GetItem(hTV
,&tiPar
))
285 lpitPar
= (LPITEMTAG
) tiPar
.lParam
;
288 addTransaction(lpitPar
->lpAppl
->lpcSection
, lpit
->lpDo
->lpcKey
, ACTION_SET
, cMode
);
295 static VOID
OnBuiltinClick(HWND hDlg
)
297 SetDLLMode(hDlg
, BUILTIN
);
300 static VOID
OnNativeClick(HWND hDlg
)
302 SetDLLMode(hDlg
, NATIVE
);
305 static VOID
OnTreeViewDeleteItem(NMTREEVIEW
* nmt
)
307 FreeItemTag((LPITEMTAG
)(nmt
->itemOld
.lParam
));
310 static VOID
OnAddDLLClick(HWND hDlg
)
321 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
322 ti
.mask
= TVIF_PARAM
;
323 ti
.hItem
= TreeView_GetSelection(hTV
);
324 if (TreeView_GetItem (hTV
, &ti
))
326 lpit
= (LPITEMTAG
) ti
.lParam
;
327 if (lpit
->lpDo
) { /*Is this a DLL override (that is: a subitem), then find the parent*/
328 ti
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
329 if (TreeView_GetItem(hTV
,&ti
)) {
330 lpit
= (LPITEMTAG
) ti
.lParam
;
334 /*Now we should have an parent item*/
337 lpitNew
= CreateItemTag();
338 SendDlgItemMessage(hDlg
,IDC_DLLLIST
,WM_GETTEXT
,(WPARAM
)255, (LPARAM
) dll
);
339 if (strlen(dll
) > 0) {
340 /*Is the dll already in the list? If so, don't do it*/
342 childti
.mask
= TVIF_PARAM
;
343 if ((childti
.hItem
= TreeView_GetNextItem(hTV
, ti
.hItem
, TVGN_CHILD
))) {
344 /*Retrieved first child*/
345 while (TreeView_GetItem (hTV
, &childti
))
347 if (strcmp(((LPITEMTAG
)childti
.lParam
)->lpDo
->lpcKey
,dll
) == 0) {
351 childti
.hItem
= TreeView_GetNextItem(hTV
, childti
.hItem
, TVGN_NEXT
);
356 lpitNew
->lpDo
= CreateDLLOverride(dll
);
357 lpitNew
->lpDo
->mode
= NATIVE
;
358 tis
.hInsertAfter
= TVI_LAST
;
359 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
360 tis
.u
.item
.pszText
= dll
;
361 tis
.u
.item
.lParam
= (LPARAM
)lpitNew
;
362 tis
.hParent
= ti
.hItem
;
363 TreeView_InsertItem(hTV
,&tis
);
364 UpdateDLLList(hDlg
, dll
);
365 addTransaction(lpit
->lpAppl
->lpcSection
, dll
, ACTION_SET
, "native, builtin");
366 } else MessageBox(hDlg
, "A DLL with that name is already in this list...", "", MB_OK
| MB_ICONINFORMATION
);
371 static VOID
OnRemoveDLLClick(HWND hDlg
)
379 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
380 ti
.mask
= TVIF_PARAM
;
381 ti
.hItem
= TreeView_GetSelection(hTV
);
382 if (TreeView_GetItem (hTV
, &ti
)) {
383 lpit
= (LPITEMTAG
) ti
.lParam
;
386 /*Find parent for section*/
387 tiPar
.mask
= TVIF_PARAM
;
388 tiPar
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
389 if (TreeView_GetItem(hTV
,&tiPar
))
391 lpitPar
= (LPITEMTAG
) tiPar
.lParam
;
394 addTransaction(lpitPar
->lpAppl
->lpcSection
, lpit
->lpDo
->lpcKey
, ACTION_REMOVE
, NULL
);
395 TreeView_DeleteItem(hTV
,ti
.hItem
);
402 static VOID
OnAddApplicationClick(HWND hDlg
)
404 char szFileTitle
[255];
410 OPENFILENAME ofn
= { sizeof(OPENFILENAME
),
411 0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL
, 0, 0, NULL
,
412 0, NULL
, 0, NULL
, NULL
,
413 OFN_SHOWHELP
, 0, 0, NULL
, 0, NULL
};
415 ofn
.lpstrFileTitle
= szFileTitle
;
416 ofn
.lpstrFileTitle
[0] = '\0';
417 ofn
.nMaxFileTitle
= sizeof(szFileTitle
);
418 ofn
.lpstrFile
= szFile
;
419 ofn
.lpstrFile
[0] = '\0';
420 ofn
.nMaxFile
= sizeof(szFile
);
422 if (GetOpenFileName(&ofn
))
425 tis
.hInsertAfter
= TVI_LAST
;
426 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
427 tis
.u
.item
.pszText
= szFileTitle
;
428 lpit
= CreateItemTag();
429 sprintf(lpcKey
, "AppDefaults\\%s\\DllOverrides", szFileTitle
);
430 lpit
->lpAppl
= CreateAppl(FALSE
,szFileTitle
,lpcKey
);
431 tis
.u
.item
.lParam
= (LPARAM
)lpit
;
432 TreeView_InsertItem(GetDlgItem(hDlg
,IDC_TREE_DLLS
), &tis
);
433 setConfigValue(lpcKey
,NULL
,NULL
);
437 static VOID
OnRemoveApplicationClick(HWND hDlg
)
443 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
444 ti
.mask
= TVIF_PARAM
;
445 ti
.hItem
= TreeView_GetSelection(hTV
);
446 if (TreeView_GetItem (hTV
, &ti
)) {
447 lpit
= (LPITEMTAG
) ti
.lParam
;
450 addTransaction(lpit
->lpAppl
->lpcSection
, NULL
, ACTION_REMOVE
, NULL
);
451 TreeView_DeleteItem(hTV
,ti
.hItem
);
457 LibrariesDlgProc (HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
462 OnInitLibrariesDlg(hDlg
);
465 switch (((LPNMHDR
)lParam
)->code
) {
466 case TVN_SELCHANGED
: {
467 switch(LOWORD(wParam
)) {
469 OnTreeViewChangeItem(hDlg
, GetDlgItem(hDlg
,IDC_TREE_DLLS
));
475 OnTreeViewDeleteItem ((LPNMTREEVIEW
)lParam
);
480 switch(HIWORD(wParam
)) {
482 switch(LOWORD(wParam
)) {
483 case IDC_RAD_BUILTIN
:
484 OnBuiltinClick(hDlg
);
489 case IDC_DLLS_ADDAPP
:
490 OnAddApplicationClick(hDlg
);
492 case IDC_DLLS_REMOVEAPP
:
493 OnRemoveApplicationClick(hDlg
);
495 case IDC_DLLS_ADDDLL
:
498 case IDC_DLLS_REMOVEDLL
:
499 OnRemoveDLLClick(hDlg
);