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
{
45 UNKNOWN
/*Special value indicating an erronous DLL override mode*/
48 static void removeSpaces(char* in
, char* out
)
52 for (i
= 0; i
< strlen(in
); i
++)
63 static DLLMODE
Str2DLLMode(char* c
)
65 /*Parse a string into a DLLMode*/
66 char* d
= HeapAlloc(GetProcessHeap(), 0, sizeof(c
));
68 if (strcmp (d
, "builtin,native") == 0) {
69 return BUILTIN_NATIVE
;
71 if (strcmp (d
, "native,builtin") == 0) {
72 return NATIVE_BUILTIN
;
74 if (strcmp (d
, "native") == 0){
77 if (strcmp (d
, "builtin") == 0) {
80 if (strcmp (d
, "") == 0) {
86 static char* DLLMode2Str(DLLMODE mode
)
97 res
= "native, builtin";
100 res
= "builtin, native";
111 typedef struct _DLLOVERRIDE
113 char* lpcKey
; /*The actual dll name*/
115 } DLLOVERRIDE
, *LPDLLOVERRIDE
;
117 static LPDLLOVERRIDE
CreateDLLOverride(char* lpcKey
)
119 LPDLLOVERRIDE out
= HeapAlloc(GetProcessHeap(),0,sizeof(DLLOVERRIDE
));
120 out
->lpcKey
= strdup (lpcKey
);
124 static VOID
FreeDLLOverride(LPDLLOVERRIDE ldo
)
128 HeapFree(GetProcessHeap(),0,ldo
);
134 char* lpcApplication
;
135 char* lpcSection
; /*Registry section*/
138 static LPAPPL
CreateAppl(BOOL isGlobal
, char* application
, char* section
)
141 out
= HeapAlloc(GetProcessHeap(),0,sizeof(APPL
));
142 out
->lpcApplication
= strdup(application
);
143 out
->lpcSection
= strdup(section
);
144 out
->isGlobal
= isGlobal
;
148 static VOID
FreeAppl(LPAPPL lpAppl
)
150 if (lpAppl
->lpcApplication
)
151 free(lpAppl
->lpcApplication
); /* The strings were strdup-ped, so we use "free" */
152 if (lpAppl
->lpcSection
)
153 free(lpAppl
->lpcSection
);
154 HeapFree(GetProcessHeap(),0,lpAppl
);
157 typedef struct _ITEMTAG
161 } ITEMTAG
, *LPITEMTAG
;
163 static LPITEMTAG
CreateItemTag()
166 out
= HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG
));
172 static VOID
FreeItemTag(LPITEMTAG lpit
)
175 FreeAppl(lpit
->lpAppl
);
177 FreeDLLOverride(lpit
->lpDo
);
178 HeapFree(GetProcessHeap(),0,lpit
);
181 static VOID
UpdateDLLList(HWND hDlg
, char* dll
)
183 /*Add if it isn't already in*/
184 if (SendDlgItemMessage(hDlg
, IDC_DLLLIST
, CB_FINDSTRING
, 1, (LPARAM
) dll
) == CB_ERR
)
185 SendDlgItemMessage(hDlg
,IDC_DLLLIST
,CB_ADDSTRING
,0,(LPARAM
) dll
);
188 static VOID
LoadLibrarySettings(LPAPPL appl
/*DON'T FREE, treeview will own this*/, HWND hDlg
, HWND hwndTV
)
201 WINE_TRACE("opening %s\n", appl
->lpcSection
);
202 if (RegOpenKey (configKey
, appl
->lpcSection
, &key
) == ERROR_SUCCESS
)
208 lpIt
= CreateItemTag();
212 tis
.hInsertAfter
= TVI_LAST
;
213 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
214 tis
.u
.item
.pszText
= appl
->lpcApplication
;
215 tis
.u
.item
.lParam
= (LPARAM
)lpIt
;
216 hParent
= TreeView_InsertItem(hwndTV
,&tis
);
217 tis
.hParent
= hParent
;
219 while (RegEnumValue(key
, i
, name
, &size
, NULL
, NULL
, read
, &readSize
) == ERROR_SUCCESS
)
221 WINE_TRACE("Reading value %s, namely %s\n", name
, read
);
223 lpIt
= CreateItemTag();
224 lpdo
= CreateDLLOverride(name
);
226 tis
.u
.item
.lParam
= (LPARAM
)lpIt
;
227 tis
.u
.item
.pszText
= name
;
229 lpdo
->mode
= Str2DLLMode(read
);
231 TreeView_InsertItem(hwndTV
,&tis
);
232 UpdateDLLList(hDlg
, name
);
233 i
++; size
= 255; readSize
= 255;
239 static VOID
SetEnabledDLLControls(HWND dialog
, DLGMODE dlgmode
)
241 if (dlgmode
== DLL
) {
242 enable(IDC_RAD_BUILTIN
);
243 enable(IDC_RAD_NATIVE
);
244 enable(IDC_RAD_BUILTIN_NATIVE
);
245 enable(IDC_RAD_NATIVE_BUILTIN
);
246 enable(IDC_RAD_DISABLE
);
247 enable(IDC_DLLS_REMOVEDLL
);
249 disable(IDC_RAD_BUILTIN
);
250 disable(IDC_RAD_NATIVE
);
251 disable(IDC_RAD_BUILTIN_NATIVE
);
252 disable(IDC_RAD_NATIVE_BUILTIN
);
253 disable(IDC_RAD_DISABLE
);
254 disable(IDC_DLLS_REMOVEDLL
);
257 if (dlgmode
== APP
) {
258 enable(IDC_DLLS_REMOVEAPP
);
261 disable(IDC_DLLS_REMOVEAPP
);
265 static VOID
OnInitLibrariesDlg(HWND hDlg
)
276 hwndTV
= GetDlgItem(hDlg
,IDC_TREE_DLLS
);
277 lpAppl
= CreateAppl(TRUE
,"Global DLL Overrides", "DllOverrides");
278 LoadLibrarySettings(lpAppl
, hDlg
, hwndTV
);
280 /*And now the application specific stuff:*/
281 if (RegOpenKey(configKey
, "AppDefaults", &applKey
) == ERROR_SUCCESS
) {
284 while (RegEnumKeyEx(applKey
, i
, appl
, &size
, NULL
, NULL
, NULL
, &ft
) == ERROR_SUCCESS
)
286 sprintf(lpcKey
, "AppDefaults\\%s\\DllOverrides", appl
);
287 lpAppl
= CreateAppl(FALSE
,appl
, lpcKey
);
288 LoadLibrarySettings(lpAppl
, hDlg
, hwndTV
);
291 RegCloseKey(applKey
);
294 SetEnabledDLLControls(hDlg
, GLOBAL
);
297 static VOID
OnTreeViewChangeItem(HWND hDlg
, HWND hTV
)
303 ti
.mask
= TVIF_PARAM
;
304 ti
.hItem
= TreeView_GetSelection(hTV
);
305 if (TreeView_GetItem (hTV
, &ti
))
307 lpit
= (LPITEMTAG
) ti
.lParam
;
310 WINE_TRACE("%s\n", lpit
->lpDo
->lpcKey
);
311 buttonId
= IDC_RAD_BUILTIN
;
312 switch (lpit
->lpDo
->mode
)
315 buttonId
= IDC_RAD_NATIVE
;
318 buttonId
= IDC_RAD_BUILTIN
;
321 buttonId
= IDC_RAD_NATIVE_BUILTIN
;
324 buttonId
= IDC_RAD_BUILTIN_NATIVE
;
327 buttonId
= IDC_RAD_DISABLE
;
333 CheckRadioButton(hDlg
, IDC_RAD_BUILTIN
, IDC_RAD_DISABLE
, buttonId
);
334 SetEnabledDLLControls(hDlg
, DLL
);
338 if (lpit
->lpAppl
->isGlobal
== TRUE
)
339 SetEnabledDLLControls(hDlg
, GLOBAL
);
341 SetEnabledDLLControls(hDlg
, APP
);
347 static VOID
SetDLLMode(HWND hDlg
, DLLMODE mode
)
356 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
357 ti
.mask
= TVIF_PARAM
;
358 ti
.hItem
= TreeView_GetSelection(hTV
);
359 if (TreeView_GetItem (hTV
, &ti
))
361 lpit
= (LPITEMTAG
) ti
.lParam
;
364 lpit
->lpDo
->mode
= mode
;
365 cMode
= DLLMode2Str (mode
);
366 /*Find parent, so we can read registry section*/
367 tiPar
.mask
= TVIF_PARAM
;
368 tiPar
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
369 if (TreeView_GetItem(hTV
,&tiPar
))
371 lpitPar
= (LPITEMTAG
) tiPar
.lParam
;
374 addTransaction(lpitPar
->lpAppl
->lpcSection
, lpit
->lpDo
->lpcKey
, ACTION_SET
, cMode
);
382 static VOID
OnBuiltinClick(HWND hDlg
)
384 SetDLLMode(hDlg
, BUILTIN
);
387 static VOID
OnNativeClick(HWND hDlg
)
389 SetDLLMode(hDlg
, NATIVE
);
392 static VOID
OnBuiltinNativeClick(HWND hDlg
)
394 SetDLLMode(hDlg
, BUILTIN_NATIVE
);
397 static VOID
OnNativeBuiltinClick(HWND hDlg
)
399 SetDLLMode(hDlg
, NATIVE_BUILTIN
);
402 static VOID
OnDisableClick(HWND hDlg
)
404 SetDLLMode(hDlg
, DISABLE
);
407 static VOID
OnTreeViewDeleteItem(NMTREEVIEW
* nmt
)
409 FreeItemTag((LPITEMTAG
)(nmt
->itemOld
.lParam
));
412 static VOID
OnAddDLLClick(HWND hDlg
)
423 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
424 ti
.mask
= TVIF_PARAM
;
425 ti
.hItem
= TreeView_GetSelection(hTV
);
426 if (TreeView_GetItem (hTV
, &ti
))
428 lpit
= (LPITEMTAG
) ti
.lParam
;
429 if (lpit
->lpDo
) { /*Is this a DLL override (that is: a subitem), then find the parent*/
430 ti
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
431 if (TreeView_GetItem(hTV
,&ti
)) {
432 lpit
= (LPITEMTAG
) ti
.lParam
;
436 /*Now we should have an parent item*/
439 lpitNew
= CreateItemTag();
440 SendDlgItemMessage(hDlg
,IDC_DLLLIST
,WM_GETTEXT
,(WPARAM
)255, (LPARAM
) dll
);
441 if (strlen(dll
) > 0) {
442 /*Is the dll already in the list? If so, don't do it*/
444 childti
.mask
= TVIF_PARAM
;
445 if ((childti
.hItem
= TreeView_GetNextItem(hTV
, ti
.hItem
, TVGN_CHILD
))) {
446 /*Retrieved first child*/
447 while (TreeView_GetItem (hTV
, &childti
))
449 if (strcmp(((LPITEMTAG
)childti
.lParam
)->lpDo
->lpcKey
,dll
) == 0) {
453 childti
.hItem
= TreeView_GetNextItem(hTV
, childti
.hItem
, TVGN_NEXT
);
458 lpitNew
->lpDo
= CreateDLLOverride(dll
);
459 lpitNew
->lpDo
->mode
= NATIVE
;
460 tis
.hInsertAfter
= TVI_LAST
;
461 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
462 tis
.u
.item
.pszText
= dll
;
463 tis
.u
.item
.lParam
= (LPARAM
)lpitNew
;
464 tis
.hParent
= ti
.hItem
;
465 TreeView_InsertItem(hTV
,&tis
);
466 UpdateDLLList(hDlg
, dll
);
467 addTransaction(lpit
->lpAppl
->lpcSection
, dll
, ACTION_SET
, "native");
468 } else MessageBox(hDlg
, "A DLL with that name is already in this list...", "", MB_OK
| MB_ICONINFORMATION
);
473 static VOID
OnRemoveDLLClick(HWND hDlg
)
481 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
482 ti
.mask
= TVIF_PARAM
;
483 ti
.hItem
= TreeView_GetSelection(hTV
);
484 if (TreeView_GetItem (hTV
, &ti
)) {
485 lpit
= (LPITEMTAG
) ti
.lParam
;
488 /*Find parent for section*/
489 tiPar
.mask
= TVIF_PARAM
;
490 tiPar
.hItem
= TreeView_GetParent(hTV
, ti
.hItem
);
491 if (TreeView_GetItem(hTV
,&tiPar
))
493 lpitPar
= (LPITEMTAG
) tiPar
.lParam
;
496 addTransaction(lpitPar
->lpAppl
->lpcSection
, lpit
->lpDo
->lpcKey
, ACTION_REMOVE
, NULL
);
497 TreeView_DeleteItem(hTV
,ti
.hItem
);
504 static VOID
OnAddApplicationClick(HWND hDlg
)
506 char szFileTitle
[255];
512 OPENFILENAME ofn
= { sizeof(OPENFILENAME
),
513 0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL
, 0, 0, NULL
,
514 0, NULL
, 0, NULL
, NULL
,
515 OFN_SHOWHELP
, 0, 0, NULL
, 0, NULL
};
517 ofn
.lpstrFileTitle
= szFileTitle
;
518 ofn
.lpstrFileTitle
[0] = '\0';
519 ofn
.nMaxFileTitle
= sizeof(szFileTitle
);
520 ofn
.lpstrFile
= szFile
;
521 ofn
.lpstrFile
[0] = '\0';
522 ofn
.nMaxFile
= sizeof(szFile
);
524 if (GetOpenFileName(&ofn
))
527 tis
.hInsertAfter
= TVI_LAST
;
528 tis
.u
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
529 tis
.u
.item
.pszText
= szFileTitle
;
530 lpit
= CreateItemTag();
531 sprintf(lpcKey
, "AppDefaults\\%s\\DllOverrides", szFileTitle
);
532 lpit
->lpAppl
= CreateAppl(FALSE
,szFileTitle
,lpcKey
);
533 tis
.u
.item
.lParam
= (LPARAM
)lpit
;
534 TreeView_InsertItem(GetDlgItem(hDlg
,IDC_TREE_DLLS
), &tis
);
535 setConfigValue(lpcKey
,NULL
,NULL
);
539 static VOID
OnRemoveApplicationClick(HWND hDlg
)
545 hTV
= GetDlgItem(hDlg
, IDC_TREE_DLLS
);
546 ti
.mask
= TVIF_PARAM
;
547 ti
.hItem
= TreeView_GetSelection(hTV
);
548 if (TreeView_GetItem (hTV
, &ti
)) {
549 lpit
= (LPITEMTAG
) ti
.lParam
;
552 addTransaction(lpit
->lpAppl
->lpcSection
, NULL
, ACTION_REMOVE
, NULL
);
553 TreeView_DeleteItem(hTV
,ti
.hItem
);
559 LibrariesDlgProc (HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
564 OnInitLibrariesDlg(hDlg
);
567 switch (((LPNMHDR
)lParam
)->code
) {
568 case TVN_SELCHANGED
: {
569 switch(LOWORD(wParam
)) {
571 OnTreeViewChangeItem(hDlg
, GetDlgItem(hDlg
,IDC_TREE_DLLS
));
577 OnTreeViewDeleteItem ((LPNMTREEVIEW
)lParam
);
582 switch(HIWORD(wParam
)) {
584 switch(LOWORD(wParam
)) {
585 case IDC_RAD_BUILTIN
:
586 OnBuiltinClick(hDlg
);
591 case IDC_RAD_BUILTIN_NATIVE
:
592 OnBuiltinNativeClick(hDlg
);
594 case IDC_RAD_NATIVE_BUILTIN
:
595 OnNativeBuiltinClick(hDlg
);
597 case IDC_RAD_DISABLE
:
598 OnDisableClick(hDlg
);
600 case IDC_DLLS_ADDAPP
:
601 OnAddApplicationClick(hDlg
);
603 case IDC_DLLS_REMOVEAPP
:
604 OnRemoveApplicationClick(hDlg
);
606 case IDC_DLLS_ADDDLL
:
609 case IDC_DLLS_REMOVEDLL
:
610 OnRemoveDLLClick(hDlg
);