1 /////////////////////////////////////////////////////////////////////////
2 // $Id: win32config.cc 14204 2021-03-27 17:23:31Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2003-2021 The Bochs Project
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 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 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
22 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
23 // is used to know when we are exporting symbols and when we are importing.
24 #define BX_PLUGGABLE
25
26 #include "win32dialog.h"
27 #include "bochs.h"
28 #include "bx_debug/debug.h"
29 #include "param_names.h"
30 #include "gui.h"
31 #include "win32res.h"
32 #include "win32paramdlg.h"
33 #include "plugin.h"
34
35 #if BX_USE_WIN32CONFIG
36
37 static int win32_ci_callback(void *userdata, ci_command_t command);
38 static BxEvent* win32_notify_callback(void *unused, BxEvent *event);
39
PLUGIN_ENTRY_FOR_MODULE(win32config)40 PLUGIN_ENTRY_FOR_MODULE(win32config)
41 {
42 if (mode == PLUGIN_INIT) {
43 SIM->register_configuration_interface("win32config", win32_ci_callback, NULL);
44 SIM->set_notify_callback(win32_notify_callback, NULL);
45 } else if (mode == PLUGIN_PROBE) {
46 return (int)PLUGTYPE_CI;
47 }
48 return 0; // Success
49 }
50
51 const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"};
52
GetBochsWindow()53 HWND GetBochsWindow()
54 {
55 HWND hwnd;
56
57 hwnd = FindWindow("Bochs for Windows", NULL);
58 if (hwnd == NULL) {
59 hwnd = GetForegroundWindow();
60 }
61 return hwnd;
62 }
63
BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)64 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
65 {
66 char path[MAX_PATH];
67
68 if (uMsg == BFFM_INITIALIZED) {
69 GetCurrentDirectory(MAX_PATH, path);
70 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)path);
71 }
72 return 0;
73 }
74
75 #ifndef BIF_NEWDIALOGSTYLE
76 #define BIF_NEWDIALOGSTYLE 0
77 #endif
78
BrowseDir(const char * Title,char * result)79 int BrowseDir(const char *Title, char *result)
80 {
81 BROWSEINFO browseInfo;
82 LPITEMIDLIST ItemIDList;
83 int r = -1;
84
85 memset(&browseInfo,0,sizeof(BROWSEINFO));
86 browseInfo.hwndOwner = GetBochsWindow();
87 browseInfo.pszDisplayName = result;
88 browseInfo.lpszTitle = (LPCSTR)Title;
89 browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
90 browseInfo.lpfn = BrowseCallbackProc;
91 ItemIDList = SHBrowseForFolder(&browseInfo);
92 if (ItemIDList != NULL) {
93 *result = 0;
94 if (SHGetPathFromIDList(ItemIDList, result)) {
95 if (result[0]) r = 0;
96 }
97 // free memory used
98 IMalloc * imalloc = 0;
99 if (SUCCEEDED(SHGetMalloc(&imalloc))) {
100 imalloc->Free(ItemIDList);
101 imalloc->Release();
102 }
103 }
104 return r;
105 }
106
LogAskProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)107 static BOOL CALLBACK LogAskProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
108 {
109 BxEvent *event;
110 int level;
111
112 switch (msg) {
113 case WM_INITDIALOG:
114 event = (BxEvent*)lParam;
115 level = event->u.logmsg.level;
116 SetWindowText(hDlg, SIM->get_log_level_name(level));
117 SetWindowText(GetDlgItem(hDlg, IDASKDEV), event->u.logmsg.prefix);
118 SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg);
119 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue");
120 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again");
121 if (event->u.logmsg.mode == BX_LOG_DLG_ASK) {
122 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation");
123 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)");
124 #if BX_DEBUGGER
125 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger");
126 #endif
127 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0);
128 } else {
129 SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0);
130 }
131 SetFocus(GetDlgItem(hDlg, IDASKLIST));
132 return FALSE;
133 case WM_CLOSE:
134 EndDialog(hDlg, BX_LOG_ASK_CHOICE_DIE);
135 break;
136 case WM_COMMAND:
137 switch (LOWORD(wParam)) {
138 case IDOK:
139 EndDialog(hDlg, SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_GETCURSEL, 0, 0));
140 break;
141 case IDCANCEL:
142 EndDialog(hDlg, BX_LOG_ASK_CHOICE_DIE);
143 break;
144 }
145 }
146 return FALSE;
147 }
148
StringParamProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)149 static BOOL CALLBACK StringParamProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
150 {
151 static bx_param_string_c *param;
152 char buffer[512];
153 const char *title;
154
155 switch (msg) {
156 case WM_INITDIALOG:
157 param = (bx_param_string_c *)lParam;
158 title = param->get_label();
159 if ((title == NULL) || (strlen(title) == 0)) {
160 title = param->get_name();
161 }
162 SetWindowText(hDlg, title);
163 SetWindowText(GetDlgItem(hDlg, IDSTRING), param->getptr());
164 SendMessage(GetDlgItem(hDlg, IDSTRING), EM_SETLIMITTEXT, param->get_maxsize(), 0);
165 return TRUE;
166 case WM_CLOSE:
167 EndDialog(hDlg, -1);
168 break;
169 case WM_COMMAND:
170 switch (LOWORD(wParam)) {
171 case IDOK:
172 GetDlgItemText(hDlg, IDSTRING, buffer, param->get_maxsize() + 1);
173 param->set(buffer);
174 EndDialog(hDlg, 1);
175 break;
176 case IDCANCEL:
177 EndDialog(hDlg, -1);
178 break;
179 }
180 }
181 return FALSE;
182 }
183
SetStandardLogOptions(HWND hDlg)184 void SetStandardLogOptions(HWND hDlg)
185 {
186 int level, idx;
187 int defchoice[5];
188
189 for (level=0; level<N_LOGLEV; level++) {
190 int mod = 0;
191 int first = SIM->get_log_action (mod, level);
192 BOOL consensus = true;
193 // now compare all others to first. If all match, then use "first" as
194 // the initial value.
195 for (mod=1; mod<SIM->get_n_log_modules(); mod++) {
196 if (first != SIM->get_log_action (mod, level)) {
197 consensus = false;
198 break;
199 }
200 }
201 if (consensus)
202 defchoice[level] = first;
203 else
204 defchoice[level] = 4;
205 }
206 for (level=0; level<N_LOGLEV; level++) {
207 idx = 0;
208 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_RESETCONTENT, 0, 0);
209 for (int action=0; action<5; action++) {
210 // the exclude expression allows some choices not being available if they
211 // don't make any sense. For example, it would be stupid to ignore a panic.
212 if (!BX_LOG_OPTS_EXCLUDE(level, action)) {
213 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_ADDSTRING, 0, (LPARAM)log_choices[action]);
214 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETITEMDATA, idx, action);
215 if (action == defchoice[level]) {
216 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETCURSEL, idx, 0);
217 }
218 idx++;
219 }
220 }
221 }
222 EnableWindow(GetDlgItem(hDlg, IDDEVLIST), FALSE);
223 }
224
SetAdvancedLogOptions(HWND hDlg)225 void SetAdvancedLogOptions(HWND hDlg)
226 {
227 int idx, level, mod;
228
229 idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETCURSEL, 0, 0);
230 mod = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETITEMDATA, idx, 0);
231 for (level=0; level<N_LOGLEV; level++) {
232 idx = 0;
233 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_RESETCONTENT, 0, 0);
234 for (int action=0; action<4; action++) {
235 // exclude some action / level combinations (see above)
236 if (!BX_LOG_OPTS_EXCLUDE(level, action)) {
237 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_ADDSTRING, 0, (LPARAM)log_choices[action]);
238 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETITEMDATA, idx, action);
239 if (action == SIM->get_log_action (mod, level)) {
240 SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETCURSEL, idx, 0);
241 }
242 idx++;
243 }
244 }
245 }
246 }
247
InitLogOptionsDialog(HWND hDlg,BOOL advanced)248 void InitLogOptionsDialog(HWND hDlg, BOOL advanced)
249 {
250 int idx, mod;
251 char name[32];
252
253 for (mod=0; mod<SIM->get_n_log_modules(); mod++) {
254 if (lstrcmp(SIM->get_logfn_name(mod), "?")) {
255 lstrcpyn(name, SIM->get_logfn_name(mod), 32);
256 idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_ADDSTRING, 0, (LPARAM)name);
257 SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETITEMDATA, idx, mod);
258 }
259 }
260 if (advanced) {
261 SendMessage(GetDlgItem(hDlg, IDADVLOGOPT), BM_SETCHECK, BST_CHECKED, 0);
262 SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, 0, 0);
263 SetAdvancedLogOptions(hDlg);
264 } else {
265 SetStandardLogOptions(hDlg);
266 }
267 }
268
ApplyLogOptions(HWND hDlg,BOOL advanced)269 void ApplyLogOptions(HWND hDlg, BOOL advanced)
270 {
271 int idx, level, mod, value;
272
273 if (advanced) {
274 idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETCURSEL, 0, 0);
275 mod = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETITEMDATA, idx, 0);
276 for (level=0; level<N_LOGLEV; level++) {
277 idx = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETCURSEL, 0, 0);
278 value = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETITEMDATA, idx, 0);
279 SIM->set_log_action(mod, level, value);
280 }
281 EnableWindow(GetDlgItem(hDlg, IDDEVLIST), TRUE);
282 } else {
283 for (level=0; level<N_LOGLEV; level++) {
284 idx = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETCURSEL, 0, 0);
285 value = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETITEMDATA, idx, 0);
286 if (value < 4) {
287 // set new default
288 SIM->set_default_log_action(level, value);
289 // apply that action to all modules (devices)
290 SIM->set_log_action(-1, level, value);
291 }
292 }
293 }
294 EnableWindow(GetDlgItem(hDlg, IDADVLOGOPT), TRUE);
295 }
296
LogOptDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)297 static BOOL CALLBACK LogOptDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
298 {
299 static BOOL advanced;
300 static BOOL changed;
301 long noticode;
302
303 switch (msg) {
304 case WM_INITDIALOG:
305 advanced = (BOOL)lParam;
306 InitLogOptionsDialog(hDlg, advanced);
307 changed = FALSE;
308 EnableWindow(GetDlgItem(hDlg, IDAPPLY), FALSE);
309 return TRUE;
310 case WM_CLOSE:
311 EndDialog(hDlg, 0);
312 break;
313 case WM_COMMAND:
314 noticode = HIWORD(wParam);
315 switch(noticode) {
316 case CBN_SELCHANGE: /* LBN_SELCHANGE is the same value */
317 switch (LOWORD(wParam)) {
318 case IDDEVLIST:
319 SetAdvancedLogOptions(hDlg);
320 break;
321 case IDLOGEVT1:
322 case IDLOGEVT2:
323 case IDLOGEVT3:
324 case IDLOGEVT4:
325 case IDLOGEVT5:
326 if (!changed) {
327 EnableWindow(GetDlgItem(hDlg, IDADVLOGOPT), FALSE);
328 if (advanced) {
329 EnableWindow(GetDlgItem(hDlg, IDDEVLIST), FALSE);
330 }
331 changed = TRUE;
332 EnableWindow(GetDlgItem(hDlg, IDAPPLY), TRUE);
333 }
334 break;
335 }
336 break;
337 default:
338 switch (LOWORD(wParam)) {
339 case IDADVLOGOPT:
340 if (SendMessage(GetDlgItem(hDlg, IDADVLOGOPT), BM_GETCHECK, 0, 0) == BST_CHECKED) {
341 EnableWindow(GetDlgItem(hDlg, IDDEVLIST), TRUE);
342 SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, 0, 0);
343 SetAdvancedLogOptions(hDlg);
344 advanced = TRUE;
345 } else {
346 SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, (WPARAM)-1, 0);
347 SetStandardLogOptions(hDlg);
348 advanced = FALSE;
349 }
350 break;
351 case IDAPPLY:
352 ApplyLogOptions(hDlg, advanced);
353 EnableWindow(GetDlgItem(hDlg, IDAPPLY), FALSE);
354 changed = FALSE;
355 break;
356 case IDOK:
357 if (changed) {
358 ApplyLogOptions(hDlg, advanced);
359 }
360 EndDialog(hDlg, 1);
361 break;
362 case IDCANCEL:
363 EndDialog(hDlg, 0);
364 break;
365 }
366 }
367 break;
368 }
369 return FALSE;
370 }
371
LogOptionsDialog(HWND hwnd,bool runtime)372 void LogOptionsDialog(HWND hwnd, bool runtime)
373 {
374 DialogBoxParam(NULL, MAKEINTRESOURCE(LOGOPT_DLG), hwnd, (DLGPROC)LogOptDlgProc, (LPARAM)runtime);
375 }
376
PluginCtrlDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)377 static BOOL CALLBACK PluginCtrlDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
378 {
379 int count, i;
380 long code;
381 bx_list_c *plugin_ctrl;
382 bx_param_bool_c *plugin;
383 char plugname[20], message[80];
384
385 switch (msg) {
386 case WM_INITDIALOG:
387 plugin_ctrl = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
388 count = plugin_ctrl->get_size();
389 for (i = 0; i < count; i++) {
390 plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
391 if (plugin->get()) {
392 SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
393 } else {
394 SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
395 }
396 }
397 EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
398 EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
399 return TRUE;
400 case WM_CLOSE:
401 EndDialog(hDlg, 0);
402 break;
403 case WM_COMMAND:
404 code = HIWORD(wParam);
405 switch (LOWORD(wParam)) {
406 case IDPLUGLIST1:
407 if (code == LBN_SELCHANGE) {
408 SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_SETCURSEL, -1, 0);
409 EnableWindow(GetDlgItem(hDlg, IDLOAD), TRUE);
410 EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
411 }
412 break;
413 case IDPLUGLIST2:
414 if (code == LBN_SELCHANGE) {
415 SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_SETCURSEL, -1, 0);
416 EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
417 EnableWindow(GetDlgItem(hDlg, IDUNLOAD), TRUE);
418 }
419 break;
420 case IDLOAD:
421 i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETCURSEL, 0, 0);
422 SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETTEXT, i, (LPARAM)plugname);
423 if (SIM->opt_plugin_ctrl(plugname, 1)) {
424 wsprintf(message, "Plugin '%s' loaded", plugname);
425 MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
426 SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_DELETESTRING, i, 0);
427 SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugname);
428 EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
429 }
430 break;
431 case IDUNLOAD:
432 i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETCURSEL, 0, 0);
433 SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETTEXT, i, (LPARAM)plugname);
434 if (SIM->opt_plugin_ctrl(plugname, 0)) {
435 wsprintf(message, "Plugin '%s' unloaded", plugname);
436 MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
437 SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugname);
438 SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_DELETESTRING, i, 0);
439 EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
440 }
441 break;
442 case IDOK:
443 EndDialog(hDlg, 1);
444 break;
445 }
446 break;
447 }
448 return FALSE;
449 }
450
PluginCtrlDialog(HWND hwnd)451 void PluginCtrlDialog(HWND hwnd)
452 {
453 DialogBox(NULL, MAKEINTRESOURCE(PLUGIN_CTRL_DLG), hwnd, (DLGPROC)PluginCtrlDlgProc);
454 }
455
456 typedef struct {
457 const char *label;
458 const char *param;
459 } edit_opts_t;
460
461 edit_opts_t start_options[] = {
462 {"Plugin Control", "#plugins"},
463 {"Logfile", "log"},
464 {"Log Options", "#logopts"},
465 {"CPU", "cpu"},
466 #if BX_CPU_LEVEL >= 4
467 {"CPUID", "cpuid"},
468 #endif
469 {"Memory", "memory"},
470 {"Clock & CMOS", "clock_cmos"},
471 {"PCI", "pci"},
472 {"Display & Interface", "display"},
473 {"Keyboard & Mouse", "keyboard_mouse"},
474 {"Disk & Boot", BXPN_MENU_DISK_WIN32},
475 {"Serial / Parallel / USB", "ports"},
476 {"Network card", "network"},
477 {"Sound card", "sound"},
478 {"Other", "misc"},
479 #if BX_PLUGINS
480 {"User-defined Options", "user"},
481 #endif
482 {NULL, NULL}
483 };
484
485 edit_opts_t runtime_options[] = {
486 {"CD-ROM", BXPN_MENU_RUNTIME_CDROM},
487 {"USB", BXPN_MENU_RUNTIME_USB},
488 {"Misc", BXPN_MENU_RUNTIME_MISC},
489 {"Log Options", "#logopts"},
490 {NULL, NULL}
491 };
MainMenuDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)492 static BOOL CALLBACK MainMenuDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
493 {
494 static bool runtime;
495 int choice, code, i;
496 bx_param_filename_c *rcfile;
497 char path[BX_PATHNAME_LEN];
498 const char *pname;
499
500 switch (msg) {
501 case WM_INITDIALOG:
502 runtime = (bool)lParam;
503 EnableWindow(GetDlgItem(hDlg, IDEDITCFG), FALSE);
504 if (runtime) {
505 SetWindowText(hDlg, "Bochs Runtime Menu");
506 EnableWindow(GetDlgItem(hDlg, IDREADRC), FALSE);
507 EnableWindow(GetDlgItem(hDlg, IDRESETCFG), FALSE);
508 EnableWindow(GetDlgItem(hDlg, IDRESTORE), FALSE);
509 SetWindowText(GetDlgItem(hDlg, IDOK), "&Continue");
510 i = 0;
511 while (runtime_options[i].label != NULL) {
512 SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_ADDSTRING, 0, (LPARAM)runtime_options[i].label);
513 i++;
514 }
515 choice = IDOK;
516 } else {
517 i = 0;
518 while (start_options[i].label != NULL) {
519 SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_ADDSTRING, 0, (LPARAM)start_options[i].label);
520 i++;
521 }
522 if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_LOAD_START) {
523 choice = IDREADRC;
524 } else {
525 choice = IDOK;
526 }
527 }
528 SetFocus(GetDlgItem(hDlg, choice));
529 return FALSE;
530 case WM_CLOSE:
531 if (runtime) {
532 EndDialog(hDlg, 1);
533 } else {
534 bx_user_quit = 1;
535 EndDialog(hDlg, -1);
536 }
537 break;
538 case WM_COMMAND:
539 code = HIWORD(wParam);
540 switch (LOWORD(wParam)) {
541 case IDREADRC:
542 rcfile = new bx_param_filename_c(NULL, "rcfile", "Load Bochs Config File",
543 "", "bochsrc.bxrc", BX_PATHNAME_LEN);
544 rcfile->set_extension("bxrc");
545 if (AskFilename(hDlg, rcfile, NULL) > 0) {
546 SIM->reset_all_param();
547 SIM->read_rc(rcfile->getptr());
548 }
549 delete rcfile;
550 break;
551 case IDWRITERC:
552 rcfile = new bx_param_filename_c(NULL, "rcfile", "Save Bochs Config File",
553 "", "bochsrc.bxrc", BX_PATHNAME_LEN);
554 rcfile->set_extension("bxrc");
555 rcfile->set_options(rcfile->SAVE_FILE_DIALOG);
556 if (AskFilename(hDlg, rcfile, NULL) > 0) {
557 SIM->write_rc(rcfile->getptr(), 1);
558 }
559 delete rcfile;
560 break;
561 case IDEDITBOX:
562 if ((code == LBN_SELCHANGE) ||
563 (code == LBN_DBLCLK)) {
564 EnableWindow(GetDlgItem(hDlg, IDEDITCFG), TRUE);
565 }
566 if (code != LBN_DBLCLK) {
567 break;
568 }
569 case IDEDITCFG:
570 i = SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_GETCURSEL, 0, 0);
571 if (runtime) {
572 pname = runtime_options[i].param;
573 } else {
574 pname = start_options[i].param;
575 }
576 if (pname[0] != '#') {
577 bx_list_c *list = (bx_list_c*)SIM->get_param(pname);
578 if (list != NULL) {
579 if (list->get_size() > 0) {
580 win32ParamDialog(hDlg, pname);
581 } else {
582 MessageBox(hDlg, "Nothing to configure in this section", "Warning", MB_ICONEXCLAMATION);
583 }
584 } else {
585 MessageBox(hDlg, "Nothing to configure in this section", "Warning", MB_ICONEXCLAMATION);
586 }
587 } else {
588 if (!lstrcmp(pname, "#logopts")) {
589 LogOptionsDialog(hDlg, runtime);
590 } else if (!lstrcmp(pname, "#plugins")) {
591 PluginCtrlDialog(hDlg);
592 } else {
593 MessageBox(hDlg, "Unknown keyword", "Warning", MB_ICONEXCLAMATION);
594 }
595 }
596 break;
597 case IDRESETCFG:
598 if (MessageBox(hDlg, "Reset all options back to their factory defaults ?",
599 "Reset Configuration", MB_ICONEXCLAMATION | MB_YESNO) == IDYES) {
600 SIM->reset_all_param();
601 }
602 break;
603 case IDRESTORE:
604 path[0] = 0;
605 if (BrowseDir("Restore Bochs state from...", path) >= 0) {
606 SIM->get_param_bool(BXPN_RESTORE_FLAG)->set(1);
607 SIM->get_param_string(BXPN_RESTORE_PATH)->set(path);
608 EndDialog(hDlg, 1);
609 }
610 break;
611 case IDOK:
612 if (runtime) {
613 SIM->update_runtime_options();
614 }
615 EndDialog(hDlg, 1);
616 break;
617 case IDCANCEL:
618 if (runtime) {
619 EndDialog(hDlg, 1);
620 break;
621 }
622 case IDQUIT:
623 bx_user_quit = 1;
624 EndDialog(hDlg, -1);
625 break;
626 }
627 }
628 return FALSE;
629 }
630
LogAskDialog(BxEvent * event)631 void LogAskDialog(BxEvent *event)
632 {
633 event->retcode = (Bit32s) DialogBoxParam(NULL, MAKEINTRESOURCE(ASK_DLG), GetBochsWindow(),
634 (DLGPROC)LogAskProc, (LPARAM)event);
635 }
636
AskString(bx_param_string_c * param)637 int AskString(bx_param_string_c *param)
638 {
639 return (int) DialogBoxParam(NULL, MAKEINTRESOURCE(STRING_DLG), GetBochsWindow(),
640 (DLGPROC)StringParamProc, (LPARAM)param);
641 }
642
MainMenuDialog(HWND hwnd,bool runtime)643 int MainMenuDialog(HWND hwnd, bool runtime)
644 {
645 return (int) DialogBoxParam(NULL, MAKEINTRESOURCE(MAINMENU_DLG), hwnd,
646 (DLGPROC)MainMenuDlgProc, (LPARAM)runtime);
647 }
648
win32_notify_callback(void * unused,BxEvent * event)649 BxEvent* win32_notify_callback(void *unused, BxEvent *event)
650 {
651 int opts;
652 bx_param_c *param;
653 bx_param_string_c *sparam;
654 char pname[BX_PATHNAME_LEN];
655
656 event->retcode = -1;
657 switch (event->type)
658 {
659 case BX_SYNC_EVT_LOG_DLG:
660 LogAskDialog(event);
661 return event;
662 case BX_SYNC_EVT_MSG_BOX:
663 MessageBox(GetBochsWindow(), event->u.logmsg.msg, event->u.logmsg.prefix, MB_ICONERROR);
664 return event;
665 case BX_SYNC_EVT_ASK_PARAM:
666 param = event->u.param.param;
667 if (param->get_type() == BXT_PARAM_STRING || param->get_type() == BXT_PARAM_BYTESTRING) {
668 sparam = (bx_param_string_c *)param;
669 opts = sparam->get_options();
670 if (opts & sparam->IS_FILENAME) {
671 if (opts & sparam->SELECT_FOLDER_DLG) {
672 event->retcode = BrowseDir(sparam->get_label(), sparam->getptr());
673 } else {
674 event->retcode = AskFilename(GetBochsWindow(), (bx_param_filename_c *)sparam, NULL);
675 }
676 return event;
677 } else {
678 event->retcode = AskString(sparam);
679 return event;
680 }
681 } else if (param->get_type() == BXT_LIST) {
682 param->get_param_path(pname, BX_PATHNAME_LEN);
683 if (!strncmp(pname, "floppy", 6)) {
684 event->retcode = (Bit32s) win32FloppyParamDialog(GetBochsWindow(), pname);
685 } else {
686 event->retcode = (Bit32s) win32ParamDialog(GetBochsWindow(), pname);
687 }
688 return event;
689 } else if (param->get_type() == BXT_PARAM_BOOL) {
690 UINT flag = MB_YESNO | MB_SETFOREGROUND;
691 if (((bx_param_bool_c *)param)->get() == 0) {
692 flag |= MB_DEFBUTTON2;
693 }
694 ((bx_param_bool_c *)param)->set(MessageBox(GetActiveWindow(), param->get_description(), param->get_label(), flag) == IDYES);
695 event->retcode = 0;
696 return event;
697 }
698 case BX_SYNC_EVT_TICK: // called periodically by siminterface.
699 event->retcode = 0;
700 // fall into default case
701 default:
702 return event;
703 }
704 }
705
win32_ci_callback(void * userdata,ci_command_t command)706 static int win32_ci_callback(void *userdata, ci_command_t command)
707 {
708 switch (command)
709 {
710 case CI_START:
711 if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_QUICK_START) {
712 SIM->begin_simulation(bx_startup_flags.argc, bx_startup_flags.argv);
713 // we don't expect it to return, but if it does, quit
714 SIM->quit_sim(1);
715 } else {
716 if (MainMenuDialog(GetActiveWindow(), 0) == 1) {
717 SIM->begin_simulation(bx_startup_flags.argc, bx_startup_flags.argv);
718 }
719 SIM->quit_sim(1);
720 }
721 break;
722 case CI_RUNTIME_CONFIG:
723 if (!bx_gui->has_gui_console()) {
724 if (MainMenuDialog(GetBochsWindow(), 1) < 0) {
725 bx_user_quit = 1;
726 #if !BX_DEBUGGER
727 bx_atexit();
728 SIM->quit_sim(1);
729 #else
730 bx_dbg_exit(1);
731 #endif
732 return -1;
733 }
734 }
735 break;
736 case CI_SHUTDOWN:
737 break;
738 }
739 return 0;
740 }
741
742 #endif // BX_USE_WIN32CONFIG
743