libraries.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /*
  2. * WineCfg libraries tabsheet
  3. *
  4. * Copyright 2004 Robert van Herk
  5. * Copyright 2004 Mike Hearn
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. *
  21. */
  22. #include "config.h"
  23. #include "wine/port.h"
  24. #define WIN32_LEAN_AND_MEAN
  25. #include <windows.h>
  26. #include <commdlg.h>
  27. #include <wine/debug.h>
  28. #include <stdio.h>
  29. #include <dirent.h>
  30. #include <assert.h>
  31. #include <stdlib.h>
  32. #ifdef HAVE_SYS_STAT_H
  33. #include <sys/stat.h>
  34. #endif
  35. #ifdef HAVE_UNISTD_H
  36. #include <unistd.h>
  37. #endif
  38. #include "winecfg.h"
  39. #include "resource.h"
  40. WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
  41. /* dlls that shouldn't be configured anything other than builtin; list must be sorted*/
  42. static const char * const builtin_only[] =
  43. {
  44. "advapi32",
  45. "capi2032",
  46. "dbghelp",
  47. "ddraw",
  48. "gdi32",
  49. "gphoto2.ds",
  50. "icmp",
  51. "iphlpapi",
  52. "kernel32",
  53. "l3codeca.acm",
  54. "mountmgr.sys",
  55. "mswsock",
  56. "ntdll",
  57. "ntoskrnl.exe",
  58. "opengl32",
  59. "sane.ds",
  60. "secur32",
  61. "twain_32",
  62. "unicows",
  63. "user32",
  64. "vdmdbg",
  65. "w32skrnl",
  66. "winmm",
  67. "wintab32",
  68. "wnaspi32",
  69. "wow32",
  70. "ws2_32",
  71. "wsock32",
  72. };
  73. enum dllmode
  74. {
  75. BUILTIN_NATIVE,
  76. NATIVE_BUILTIN,
  77. BUILTIN,
  78. NATIVE,
  79. DISABLE,
  80. UNKNOWN /* Special value indicating an erroneous DLL override mode */
  81. };
  82. struct dll
  83. {
  84. char *name;
  85. enum dllmode mode;
  86. };
  87. static const WCHAR emptyW[1];
  88. /* Convert a registry string to a dllmode */
  89. static enum dllmode string_to_mode(char *in)
  90. {
  91. int i, j, len;
  92. char *out;
  93. enum dllmode res;
  94. len = strlen(in);
  95. out = HeapAlloc(GetProcessHeap(), 0, len + 1);
  96. /* remove the spaces */
  97. for (i = j = 0; i <= len; ++i) {
  98. if (in[i] != ' ') {
  99. out[j++] = in[i];
  100. }
  101. }
  102. /* parse the string */
  103. res = UNKNOWN;
  104. if (strcmp(out, "builtin,native") == 0) res = BUILTIN_NATIVE;
  105. if (strcmp(out, "native,builtin") == 0) res = NATIVE_BUILTIN;
  106. if (strcmp(out, "builtin") == 0) res = BUILTIN;
  107. if (strcmp(out, "native") == 0) res = NATIVE;
  108. if (strcmp(out, "") == 0) res = DISABLE;
  109. HeapFree(GetProcessHeap(), 0, out);
  110. return res;
  111. }
  112. /* Convert a dllmode to a registry string. */
  113. static const char* mode_to_string(enum dllmode mode)
  114. {
  115. switch( mode )
  116. {
  117. case NATIVE: return "native";
  118. case BUILTIN: return "builtin";
  119. case NATIVE_BUILTIN: return "native,builtin";
  120. case BUILTIN_NATIVE: return "builtin,native";
  121. case DISABLE: return "";
  122. default: return "";
  123. }
  124. }
  125. /* Convert a dllmode to a pretty string for display. TODO: use translations. */
  126. static const char* mode_to_label(enum dllmode mode)
  127. {
  128. static char buffer[256];
  129. UINT id = 0;
  130. switch( mode )
  131. {
  132. case NATIVE: id = IDS_DLL_NATIVE; break;
  133. case BUILTIN: id = IDS_DLL_BUILTIN; break;
  134. case NATIVE_BUILTIN: id = IDS_DLL_NATIVE_BUILTIN; break;
  135. case BUILTIN_NATIVE: id = IDS_DLL_BUILTIN_NATIVE; break;
  136. case DISABLE: id = IDS_DLL_DISABLED; break;
  137. default: return "??";
  138. }
  139. if (!LoadStringA( GetModuleHandleA(NULL), id, buffer, sizeof(buffer) )) buffer[0] = 0;
  140. return buffer;
  141. }
  142. /* Convert a control id (IDC_ constant) to a dllmode */
  143. static enum dllmode id_to_mode(DWORD id)
  144. {
  145. switch( id )
  146. {
  147. case IDC_RAD_BUILTIN: return BUILTIN;
  148. case IDC_RAD_NATIVE: return NATIVE;
  149. case IDC_RAD_NATIVE_BUILTIN: return NATIVE_BUILTIN;
  150. case IDC_RAD_BUILTIN_NATIVE: return BUILTIN_NATIVE;
  151. case IDC_RAD_DISABLE: return DISABLE;
  152. default: assert( FALSE ); return 0; /* should not be reached */
  153. }
  154. }
  155. /* Convert a dllmode to a control id (IDC_ constant) */
  156. static DWORD mode_to_id(enum dllmode mode)
  157. {
  158. switch( mode )
  159. {
  160. case BUILTIN: return IDC_RAD_BUILTIN;
  161. case NATIVE: return IDC_RAD_NATIVE;
  162. case NATIVE_BUILTIN: return IDC_RAD_NATIVE_BUILTIN;
  163. case BUILTIN_NATIVE: return IDC_RAD_BUILTIN_NATIVE;
  164. case DISABLE: return IDC_RAD_DISABLE;
  165. default: return IDC_RAD_BUILTIN_NATIVE;
  166. }
  167. }
  168. /* helper for is_builtin_only */
  169. static int compare_dll( const void *ptr1, const void *ptr2 )
  170. {
  171. const char * const *name1 = ptr1;
  172. const char * const *name2 = ptr2;
  173. return strcmp( *name1, *name2 );
  174. }
  175. /* check if dll is recommended as builtin only */
  176. static inline BOOL is_builtin_only( const char *name )
  177. {
  178. const char *ext = strrchr( name, '.' );
  179. if (ext)
  180. {
  181. if (!strcmp( ext, ".vxd" ) ||
  182. !strcmp( ext, ".drv" ) ||
  183. !strcmp( ext, ".tlb" ))
  184. return TRUE;
  185. }
  186. if (!strncmp( name, "wine", 4 )) return TRUE;
  187. return bsearch( &name, builtin_only, ARRAY_SIZE(builtin_only),
  188. sizeof(builtin_only[0]), compare_dll ) != NULL;
  189. }
  190. /* check if dll should be offered in the drop-down list */
  191. static BOOL show_dll_in_list( const char *name )
  192. {
  193. const char *ext = strrchr( name, '.' );
  194. if (ext)
  195. {
  196. /* skip 16-bit dlls */
  197. if (strlen(ext) > 2 && !strcmp( ext + strlen(ext) - 2, "16" )) return FALSE;
  198. /* skip exes */
  199. if (!strcmp( ext, ".exe" )) return FALSE;
  200. }
  201. /* skip api set placeholders */
  202. if (!strncmp( name, "api-ms-", 7 ) || !strncmp( name, "ext-ms-", 7 )) return FALSE;
  203. /* skip dlls that should always be builtin */
  204. return !is_builtin_only( name );
  205. }
  206. static void set_controls_from_selection(HWND dialog)
  207. {
  208. /* FIXME: display/update some information about the selected dll (purpose, recommended load order) maybe? */
  209. }
  210. static void clear_settings(HWND dialog)
  211. {
  212. int count = SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0);
  213. int i;
  214. WINE_TRACE("count=%d\n", count);
  215. for (i = 0; i < count; i++)
  216. {
  217. struct dll *dll = (struct dll *) SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, 0, 0);
  218. SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_DELETESTRING, 0, 0);
  219. HeapFree(GetProcessHeap(), 0, dll->name);
  220. HeapFree(GetProcessHeap(), 0, dll);
  221. }
  222. }
  223. /* load the list of available libraries from a given dir */
  224. static void load_library_list_from_dir( HWND dialog, const char *dir_path, int check_subdirs )
  225. {
  226. static const char * const ext[] = { ".dll", ".dll.so", ".so", "" };
  227. char *buffer, *p, name[256];
  228. unsigned int i;
  229. HANDLE handle;
  230. WIN32_FIND_DATAA data;
  231. buffer = HeapAlloc( GetProcessHeap(), 0, strlen(dir_path) + 2 * sizeof(name) + 10 );
  232. strcpy( buffer, dir_path );
  233. strcat( buffer, "\\*" );
  234. buffer[1] = '\\'; /* change \??\ to \\?\ */
  235. p = buffer + strlen(buffer) - 1;
  236. if ((handle = FindFirstFileA( buffer, &data )) == INVALID_HANDLE_VALUE)
  237. {
  238. HeapFree( GetProcessHeap(), 0, buffer );
  239. return;
  240. }
  241. do
  242. {
  243. size_t len = strlen(data.cFileName);
  244. if (len > sizeof(name)) continue;
  245. if (check_subdirs)
  246. {
  247. if (!strcmp( data.cFileName, "." )) continue;
  248. if (!strcmp( data.cFileName, ".." )) continue;
  249. if (!show_dll_in_list( data.cFileName )) continue;
  250. for (i = 0; i < ARRAY_SIZE( ext ); i++)
  251. {
  252. sprintf( p, "%s\\%s%s", data.cFileName, data.cFileName, ext[i] );
  253. if (GetFileAttributesA( buffer ) != INVALID_FILE_ATTRIBUTES)
  254. {
  255. SendDlgItemMessageA( dialog, IDC_DLLCOMBO, CB_ADDSTRING, 0, (LPARAM)data.cFileName );
  256. break;
  257. }
  258. }
  259. }
  260. else
  261. {
  262. for (i = 0; i < ARRAY_SIZE( ext ); i++)
  263. {
  264. if (!ext[i][0]) continue;
  265. if (len > strlen(ext[i]) && !strcmp( data.cFileName + len - strlen(ext[i]), ext[i]))
  266. {
  267. len -= strlen( ext[i] );
  268. memcpy( name, data.cFileName, len );
  269. name[len] = 0;
  270. if (!show_dll_in_list( name )) continue;
  271. SendDlgItemMessageA( dialog, IDC_DLLCOMBO, CB_ADDSTRING, 0, (LPARAM)name );
  272. }
  273. }
  274. }
  275. } while (FindNextFileA( handle, &data ));
  276. FindClose( handle );
  277. HeapFree( GetProcessHeap(), 0, buffer );
  278. }
  279. /* load the list of available libraries */
  280. static void load_library_list( HWND dialog )
  281. {
  282. unsigned int i = 0;
  283. char item1[256], item2[256], var[32], path[MAX_PATH];
  284. HCURSOR old_cursor = SetCursor( LoadCursorW(0, (LPWSTR)IDC_WAIT) );
  285. if (GetEnvironmentVariableA( "WINEBUILDDIR", path, MAX_PATH ))
  286. {
  287. char *dir = HeapAlloc( GetProcessHeap(), 0, strlen(path) + sizeof("\\dlls") );
  288. strcpy( dir, path );
  289. strcat( dir, "\\dlls" );
  290. load_library_list_from_dir( dialog, dir, TRUE );
  291. HeapFree( GetProcessHeap(), 0, dir );
  292. }
  293. for (;;)
  294. {
  295. sprintf( var, "WINEDLLDIR%u", i++ );
  296. if (!GetEnvironmentVariableA( var, path, MAX_PATH )) break;
  297. load_library_list_from_dir( dialog, path, FALSE );
  298. }
  299. /* get rid of duplicate entries */
  300. SendDlgItemMessageA( dialog, IDC_DLLCOMBO, CB_GETLBTEXT, 0, (LPARAM)item1 );
  301. i = 1;
  302. while (SendDlgItemMessageA( dialog, IDC_DLLCOMBO, CB_GETLBTEXT, i, (LPARAM)item2 ) >= 0)
  303. {
  304. if (!strcmp( item1, item2 ))
  305. {
  306. SendDlgItemMessageA( dialog, IDC_DLLCOMBO, CB_DELETESTRING, i, 0 );
  307. }
  308. else
  309. {
  310. strcpy( item1, item2 );
  311. i++;
  312. }
  313. }
  314. SetCursor( old_cursor );
  315. }
  316. static void load_library_settings(HWND dialog)
  317. {
  318. char **overrides = enumerate_values(config_key, keypath("DllOverrides"));
  319. char **p;
  320. int sel, count = 0;
  321. sel = SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
  322. WINE_TRACE("sel=%d\n", sel);
  323. clear_settings(dialog);
  324. if (!overrides || *overrides == NULL)
  325. {
  326. set_controls_from_selection(dialog);
  327. disable(IDC_DLLS_EDITDLL);
  328. disable(IDC_DLLS_REMOVEDLL);
  329. HeapFree(GetProcessHeap(), 0, overrides);
  330. return;
  331. }
  332. enable(IDC_DLLS_EDITDLL);
  333. enable(IDC_DLLS_REMOVEDLL);
  334. for (p = overrides; *p != NULL; p++)
  335. {
  336. int index;
  337. char *str, *value;
  338. const char *label;
  339. struct dll *dll;
  340. value = get_reg_key(config_key, keypath("DllOverrides"), *p, NULL);
  341. label = mode_to_label(string_to_mode(value));
  342. str = HeapAlloc(GetProcessHeap(), 0, strlen(*p) + 2 + strlen(label) + 2);
  343. strcpy(str, *p);
  344. strcat(str, " (");
  345. strcat(str, label);
  346. strcat(str, ")");
  347. dll = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dll));
  348. dll->name = *p;
  349. dll->mode = string_to_mode(value);
  350. index = SendDlgItemMessageA(dialog, IDC_DLLS_LIST, LB_ADDSTRING, (WPARAM) -1, (LPARAM) str);
  351. SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_SETITEMDATA, index, (LPARAM) dll);
  352. HeapFree(GetProcessHeap(), 0, str);
  353. count++;
  354. }
  355. HeapFree(GetProcessHeap(), 0, overrides);
  356. /* restore the previous selection, if possible */
  357. if (sel >= count - 1) sel = count - 1;
  358. else if (sel == -1) sel = 0;
  359. SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_SETCURSEL, sel, 0);
  360. set_controls_from_selection(dialog);
  361. }
  362. /* Called when the application is initialized (cannot reinit!) */
  363. static void init_libsheet(HWND dialog)
  364. {
  365. /* clear the add dll controls */
  366. SendDlgItemMessageW(dialog, IDC_DLLCOMBO, WM_SETTEXT, 1, (LPARAM)emptyW);
  367. load_library_list( dialog );
  368. disable(IDC_DLLS_ADDDLL);
  369. }
  370. static void on_add_combo_change(HWND dialog)
  371. {
  372. WCHAR buffer[1024];
  373. int sel, len;
  374. SendDlgItemMessageW(dialog, IDC_DLLCOMBO, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
  375. /* if lib was chosen from combobox, we receive an empty buffer, check manually */
  376. sel=SendDlgItemMessageW(dialog, IDC_DLLCOMBO, CB_GETCURSEL, 0, 0);
  377. len=SendDlgItemMessageW(dialog, IDC_DLLCOMBO, CB_GETLBTEXTLEN, sel, 0);
  378. if (buffer[0] || len>0)
  379. {
  380. enable(IDC_DLLS_ADDDLL)
  381. SendMessageW(GetParent(dialog), DM_SETDEFID, IDC_DLLS_ADDDLL, 0);
  382. }
  383. else
  384. {
  385. disable(IDC_DLLS_ADDDLL);
  386. SendMessageW(GetParent(dialog), DM_SETDEFID, IDOK, 0);
  387. }
  388. }
  389. static void set_dllmode(HWND dialog, DWORD id)
  390. {
  391. enum dllmode mode;
  392. struct dll *dll;
  393. int sel;
  394. const char *str;
  395. mode = id_to_mode(id);
  396. sel = SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
  397. if (sel == -1) return;
  398. dll = (struct dll *) SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
  399. str = mode_to_string(mode);
  400. WINE_TRACE("Setting %s to %s\n", dll->name, str);
  401. SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
  402. set_reg_key(config_key, keypath("DllOverrides"), dll->name, str);
  403. load_library_settings(dialog); /* ... and refresh */
  404. }
  405. static void on_add_click(HWND dialog)
  406. {
  407. static const char dotDll[] = ".dll";
  408. char buffer[1024], *ptr;
  409. ZeroMemory(buffer, sizeof(buffer));
  410. SendDlgItemMessageA(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer);
  411. if (lstrlenA(buffer) >= sizeof(dotDll))
  412. {
  413. ptr = buffer + lstrlenA(buffer) - sizeof(dotDll) + 1;
  414. if (!lstrcmpiA(ptr, dotDll))
  415. {
  416. WINE_TRACE("Stripping dll extension\n");
  417. *ptr = '\0';
  418. }
  419. }
  420. /* check if dll is in the builtin-only list */
  421. if (!(ptr = strrchr( buffer, '\\' )))
  422. {
  423. ptr = buffer;
  424. if (*ptr == '*') ptr++;
  425. }
  426. else ptr++;
  427. if (is_builtin_only( ptr ))
  428. {
  429. MSGBOXPARAMSA params;
  430. params.cbSize = sizeof(params);
  431. params.hwndOwner = dialog;
  432. params.hInstance = GetModuleHandleA( NULL );
  433. params.lpszText = MAKEINTRESOURCEA( IDS_DLL_WARNING );
  434. params.lpszCaption = MAKEINTRESOURCEA( IDS_DLL_WARNING_CAPTION );
  435. params.dwStyle = MB_ICONWARNING | MB_YESNO;
  436. params.lpszIcon = NULL;
  437. params.dwContextHelpId = 0;
  438. params.lpfnMsgBoxCallback = NULL;
  439. params.dwLanguageId = 0;
  440. if (MessageBoxIndirectA( &params ) != IDYES) return;
  441. }
  442. SendDlgItemMessageW(dialog, IDC_DLLCOMBO, WM_SETTEXT, 0, (LPARAM)emptyW);
  443. disable(IDC_DLLS_ADDDLL);
  444. SendMessageW(GetParent(dialog), DM_SETDEFID, IDOK, 0);
  445. WINE_TRACE("Adding %s as native, builtin\n", buffer);
  446. SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
  447. set_reg_key(config_key, keypath("DllOverrides"), buffer, "native,builtin");
  448. load_library_settings(dialog);
  449. SendDlgItemMessageA(dialog, IDC_DLLS_LIST, LB_SELECTSTRING, 0, (LPARAM) buffer);
  450. set_controls_from_selection(dialog);
  451. }
  452. static INT_PTR CALLBACK loadorder_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  453. {
  454. static WORD sel;
  455. switch(uMsg)
  456. {
  457. case WM_INITDIALOG:
  458. CheckRadioButton(hwndDlg, IDC_RAD_BUILTIN, IDC_RAD_DISABLE, lParam);
  459. sel = lParam;
  460. return TRUE;
  461. case WM_COMMAND:
  462. if(HIWORD(wParam) != BN_CLICKED) break;
  463. switch (LOWORD(wParam))
  464. {
  465. case IDC_RAD_BUILTIN:
  466. case IDC_RAD_NATIVE:
  467. case IDC_RAD_BUILTIN_NATIVE:
  468. case IDC_RAD_NATIVE_BUILTIN:
  469. case IDC_RAD_DISABLE:
  470. sel = LOWORD(wParam);
  471. return TRUE;
  472. case IDOK:
  473. EndDialog(hwndDlg, sel);
  474. return TRUE;
  475. case IDCANCEL:
  476. EndDialog(hwndDlg, wParam);
  477. return TRUE;
  478. }
  479. }
  480. return FALSE;
  481. }
  482. static void on_edit_click(HWND hwnd)
  483. {
  484. INT_PTR ret;
  485. int index = SendDlgItemMessageW(hwnd, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
  486. struct dll *dll;
  487. DWORD id;
  488. /* if no override is selected the edit button should be disabled... */
  489. assert(index != -1);
  490. dll = (struct dll *) SendDlgItemMessageW(hwnd, IDC_DLLS_LIST, LB_GETITEMDATA, index, 0);
  491. id = mode_to_id(dll->mode);
  492. ret = DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_LOADORDER), hwnd, loadorder_dlgproc, id);
  493. if(ret != IDCANCEL)
  494. set_dllmode(hwnd, ret);
  495. }
  496. static void on_remove_click(HWND dialog)
  497. {
  498. int sel = SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETCURSEL, 0, 0);
  499. struct dll *dll;
  500. if (sel == LB_ERR) return;
  501. dll = (struct dll *) SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETITEMDATA, sel, 0);
  502. SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_DELETESTRING, sel, 0);
  503. SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
  504. set_reg_key(config_key, keypath("DllOverrides"), dll->name, NULL);
  505. HeapFree(GetProcessHeap(), 0, dll->name);
  506. HeapFree(GetProcessHeap(), 0, dll);
  507. if (SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_GETCOUNT, 0, 0) > 0)
  508. SendDlgItemMessageW(dialog, IDC_DLLS_LIST, LB_SETCURSEL, max(sel - 1, 0), 0);
  509. else
  510. {
  511. disable(IDC_DLLS_EDITDLL);
  512. disable(IDC_DLLS_REMOVEDLL);
  513. }
  514. set_controls_from_selection(dialog);
  515. }
  516. INT_PTR CALLBACK
  517. LibrariesDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  518. {
  519. switch (uMsg)
  520. {
  521. case WM_INITDIALOG:
  522. init_libsheet(hDlg);
  523. break;
  524. case WM_SHOWWINDOW:
  525. set_window_title(hDlg);
  526. break;
  527. case WM_NOTIFY:
  528. switch (((LPNMHDR)lParam)->code) {
  529. case PSN_SETACTIVE:
  530. load_library_settings(hDlg);
  531. break;
  532. }
  533. break;
  534. case WM_COMMAND:
  535. switch(HIWORD(wParam)) {
  536. case CBN_EDITCHANGE:
  537. if (LOWORD(wParam) == IDC_DLLCOMBO)
  538. on_add_combo_change(hDlg);
  539. break;
  540. case CBN_SETFOCUS:
  541. if (LOWORD(wParam) == IDC_DLLCOMBO)
  542. on_add_combo_change(hDlg);
  543. break;
  544. case CBN_KILLFOCUS:
  545. if (LOWORD(wParam) == IDC_DLLCOMBO)
  546. SendMessageW(GetParent(hDlg), DM_SETDEFID, IDOK, 0);
  547. break;
  548. case BN_CLICKED:
  549. switch(LOWORD(wParam)) {
  550. case IDC_DLLS_ADDDLL:
  551. on_add_click(hDlg);
  552. break;
  553. case IDC_DLLS_EDITDLL:
  554. on_edit_click(hDlg);
  555. break;
  556. case IDC_DLLS_REMOVEDLL:
  557. on_remove_click(hDlg);
  558. break;
  559. }
  560. break;
  561. case LBN_SELCHANGE:
  562. if(LOWORD(wParam) == IDC_DLLCOMBO)
  563. on_add_combo_change(hDlg);
  564. else
  565. set_controls_from_selection(hDlg);
  566. break;
  567. }
  568. break;
  569. }
  570. return 0;
  571. }