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);