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