]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/main_windows.c
VentoyPlugson ---- A GUI ventoy.json configurator
[Ventoy.git] / Plugson / src / main_windows.c
1 #include <Windows.h>
2 #include <Shlobj.h>
3 #include <tlhelp32.h>
4 #include <Psapi.h>
5 #include <commctrl.h>
6 #include <resource.h>
7 #include <ventoy_define.h>
8 #include <ventoy_util.h>
9 #include <ventoy_json.h>
10 #include <ventoy_disk.h>
11 #include <ventoy_http.h>
12
13 static BOOL g_running = FALSE;
14 static HWND g_refresh_button;
15 static HWND g_start_button;
16 static HWND g_openlink_button;
17 static HWND g_exit_button;
18 static HWND g_ComboxHwnd;
19
20 typedef enum MSGID
21 {
22 MSGID_ERROR = 0,
23 MSGID_INFO,
24 MSGID_INVALID_DIR,
25 MSGID_NEW_DIR_FAIL,
26 MSGID_RENAME_VENTOY,
27 MSGID_INTERNAL_ERR,
28 MSGID_BTN_REFRESH,
29 MSGID_BTN_START,
30 MSGID_BTN_STOP,
31 MSGID_BTN_LINK,
32 MSGID_BTN_EXIT,
33
34 MSGID_BTN_STOP_TIP,
35 MSGID_BTN_EXIT_TIP,
36 MSGID_RUNNING_TIP,
37
38 MSGID_BUTT
39 }MSGID;
40
41
42 const WCHAR *g_msg_cn[MSGID_BUTT] =
43 {
44 L"´íÎó",
45 L"ÌáÐÑ",
46 L"ÇëÔÚ Ventoy Å̸ùĿ¼ÏÂÔËÐб¾³ÌÐò£¡£¨´æ·ÅISOÎļþµÄλÖã©",
47 L"´´½¨ ventoy Ŀ¼ʧ°Ü£¬ÎÞ·¨¼ÌÐø£¡",
48 L"ventoy Ŀ¼´æÔÚ£¬µ«ÊÇ´óСд²»Æ¥Å䣬ÇëÏȽ«ÆäÖØÃüÃû£¡",
49 L"ÄÚ²¿´íÎ󣬳ÌÐò¼´½«Í˳ö£¡",
50 L"Ë¢ÐÂ",
51 L"Æô¶¯",
52 L"ֹͣ",
53 L"Á´½Ó",
54 L"Í˳ö",
55
56 L"Í£Ö¹ÔËÐкóä¯ÀÀÆ÷Ò³Ãæ½«»á¹Ø±Õ£¬ÊÇ·ñ¼ÌÐø£¿",
57 L"µ±Ç°·þÎñÕýÔÚÔËÐУ¬ÊÇ·ñÍ˳ö£¿",
58 L"ÇëÏȹرÕÕýÔÚÔËÐÐµÄ VentoyPlugson ³ÌÐò£¡",
59 };
60 const WCHAR *g_msg_en[MSGID_BUTT] =
61 {
62 L"Error",
63 L"Info",
64 L"Please run me at the root of Ventoy partition.",
65 L"Failed to create ventoy directory!",
66 L"ventoy directory case mismatch, please rename it first!",
67 L"Internal error, the program will exit!",
68 L"Refresh",
69 L"Start",
70 L"Stop",
71 L"Link",
72 L"Exit",
73
74 L"The browser page will close after stop, continue?",
75 L"Service is running, continue?",
76 L"Please close another running VentoyPlugson instance!",
77 };
78
79 const WCHAR **g_msg_lang = NULL;
80
81 HINSTANCE g_hInst;
82
83 char g_log_file[MAX_PATH];
84 char g_cur_dir[MAX_PATH];
85
86 int ventoy_log_init(void);
87 void ventoy_log_exit(void);
88
89 static BOOL OnDestroyDialog()
90 {
91 ventoy_http_exit();
92 ventoy_disk_exit();
93 #ifndef VENTOY_SIM
94 ventoy_www_exit();
95 #endif
96 ventoy_log_exit();
97 return TRUE;
98 }
99
100
101 static void OpenURL(void)
102 {
103 int i;
104 char url[128];
105 const static char * Browsers[] =
106 {
107 "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
108 "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
109 "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
110 "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
111 NULL
112 };
113
114 sprintf_s(url, sizeof(url), "http://%s:%s/index.html", g_sysinfo.ip, g_sysinfo.port);
115
116 for (i = 0; Browsers[i] != NULL; i++)
117 {
118 if (ventoy_is_file_exist("%s", Browsers[i]))
119 {
120 ShellExecuteA(NULL, "open", Browsers[i], url, NULL, SW_SHOW);
121 return;
122 }
123 }
124
125 ShellExecuteA(NULL, "open", url, NULL, NULL, SW_SHOW);
126 }
127
128
129 static void FillCombox(HWND hWnd)
130 {
131 int i = 0;
132 int num = 0;
133 const ventoy_disk *list = NULL;
134 CHAR DeviceName[256];
135
136 // delete all items
137 SendMessage(g_ComboxHwnd, CB_RESETCONTENT, 0, 0);
138
139 list = ventoy_get_disk_list(&num);
140 if (NULL == list || num <= 0)
141 {
142 return;
143 }
144
145 for (i = 0; i < num; i++)
146 {
147 sprintf_s(DeviceName, sizeof(DeviceName),
148 "%C: [%s] %s",
149 list[i].devname[0],
150 list[i].cur_capacity,
151 list[i].cur_model);
152 SendMessageA(g_ComboxHwnd, CB_ADDSTRING, 0, (LPARAM)DeviceName);
153 }
154 SendMessage(g_ComboxHwnd, CB_SETCURSEL, 0, 0);
155 }
156
157
158 static BOOL InitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
159 {
160 HICON hIcon;
161
162 g_ComboxHwnd = GetDlgItem(hWnd, IDC_COMBO1);
163 g_refresh_button = GetDlgItem(hWnd, IDC_BUTTON1);
164 g_start_button = GetDlgItem(hWnd, IDC_BUTTON2);
165 g_openlink_button = GetDlgItem(hWnd, IDC_BUTTON3);
166 g_exit_button = GetDlgItem(hWnd, IDC_BUTTON4);
167
168 hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
169 SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
170 SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
171
172 SetWindowTextW(g_refresh_button, g_msg_lang[MSGID_BTN_REFRESH]);
173 SetWindowTextW(g_start_button, g_msg_lang[MSGID_BTN_START]);
174 SetWindowTextW(g_openlink_button, g_msg_lang[MSGID_BTN_LINK]);
175 SetWindowTextW(g_exit_button, g_msg_lang[MSGID_BTN_EXIT]);
176
177 EnableWindow(g_openlink_button, FALSE);
178
179 FillCombox(hWnd);
180
181 return TRUE;
182 }
183
184 static void VentoyStopService()
185 {
186 ventoy_http_stop();
187 }
188
189 static int VentoyStartService(int sel)
190 {
191 int rc;
192 BOOL bRet;
193 char Path[128];
194 char CurDir[MAX_PATH];
195 const ventoy_disk *disk = NULL;
196
197 vlog("VentoyStartService ...\n");
198
199 disk = ventoy_get_disk_node(sel);
200 if (disk == NULL)
201 {
202 return 1;
203 }
204
205 vlog("Start service at %C: %s %s ...\n", disk->devname[0], disk->cur_model, disk->cur_ventoy_ver);
206
207 g_cur_dir[0] = disk->devname[0];
208 g_cur_dir[1] = ':';
209 g_cur_dir[2] = '\\';
210 g_cur_dir[3] = 0;
211
212 g_sysinfo.pathcase = disk->pathcase;
213 g_sysinfo.cur_secureboot = disk->cur_secureboot;
214 g_sysinfo.cur_part_style = disk->cur_part_style;
215 strlcpy(g_sysinfo.cur_fsname, disk->cur_fsname);
216 strlcpy(g_sysinfo.cur_capacity, disk->cur_capacity);
217 strlcpy(g_sysinfo.cur_model, disk->cur_model);
218 strlcpy(g_sysinfo.cur_ventoy_ver, disk->cur_ventoy_ver);
219
220 bRet = SetCurrentDirectoryA(g_cur_dir);
221 vlog("SetCurrentDirectoryA %u <%s>\n", bRet, g_cur_dir);
222
223 CurDir[0] = 0;
224 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
225 vlog("CurDir=<%s>\n", CurDir);
226
227 if (strcmp(g_cur_dir, CurDir))
228 {
229 vlog("Failed to change current directory.");
230 }
231
232 g_cur_dir[2] = 0;
233
234 if (ventoy_is_directory_exist("ventoy"))
235 {
236 if (g_sysinfo.pathcase)
237 {
238 vlog("ventoy directory already exist, check case sensitive.\n");
239 strlcpy(Path, "ventoy");
240
241 rc = ventoy_path_case(Path, 0);
242 vlog("ventoy_path_case actual path is <%s> <count:%d>\n", Path, rc);
243
244 if (rc)
245 {
246 vlog("ventoy directory case mismatch, rename<%s>--><%s>\n", Path, "ventoy");
247 if (MoveFileA(Path, "ventoy"))
248 {
249 vlog("Rename <%s>--><%s> success\n", Path, "ventoy");
250 }
251 else
252 {
253 vlog("Rename <%s>--><%s> failed %u\n", Path, "ventoy", LASTERR);
254 MessageBoxW(NULL, g_msg_lang[MSGID_RENAME_VENTOY], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
255 return 1;
256 }
257 }
258 }
259 else
260 {
261 vlog("ventoy directory already exist, no need to check case sensitive.\n");
262 }
263 }
264 else
265 {
266 if (CreateDirectoryA("ventoy", NULL))
267 {
268 vlog("Create ventoy directory success.\n");
269 }
270 else
271 {
272 vlog("Create ventoy directory failed %u.\n", LASTERR);
273 MessageBoxW(NULL, g_msg_lang[MSGID_NEW_DIR_FAIL], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
274 return 1;
275 }
276 }
277
278 return ventoy_http_start(g_sysinfo.ip, g_sysinfo.port);
279 }
280
281 INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
282 {
283 int rc;
284 int nCurSel;
285 WORD NotifyCode;
286 WORD CtrlID;
287
288 switch (Message)
289 {
290 case WM_NOTIFY:
291 {
292 UINT code = 0;
293 UINT_PTR idFrom = 0;
294
295 if (lParam)
296 {
297 code = ((LPNMHDR)lParam)->code;
298 idFrom = ((LPNMHDR)lParam)->idFrom;
299 }
300
301 if (idFrom == IDC_SYSLINK1 && (NM_CLICK == code || NM_RETURN == code))
302 {
303 OpenURL();
304 }
305 break;
306 }
307 case WM_COMMAND:
308 {
309 NotifyCode = HIWORD(wParam);
310 CtrlID = LOWORD(wParam);
311
312 if (NotifyCode == BN_CLICKED)
313 {
314 if (CtrlID == IDC_BUTTON1)
315 {
316 if (!g_running)
317 {
318 //refresh
319 ventoy_disk_exit();
320 ventoy_disk_init();
321 FillCombox(hWnd);
322 }
323 }
324 else if (CtrlID == IDC_BUTTON2)
325 {
326 if (g_running)
327 {
328 if (IDYES == MessageBoxW(NULL, g_msg_lang[MSGID_BTN_STOP_TIP], g_msg_lang[MSGID_INFO], MB_YESNO | MB_ICONINFORMATION))
329 {
330 VentoyStopService();
331
332 g_running = FALSE;
333 SetWindowTextW(g_start_button, g_msg_lang[MSGID_BTN_START]);
334 EnableWindow(g_ComboxHwnd, TRUE);
335 EnableWindow(g_refresh_button, TRUE);
336 EnableWindow(g_openlink_button, FALSE);
337 }
338 }
339 else
340 {
341 nCurSel = (int)SendMessage(g_ComboxHwnd, CB_GETCURSEL, 0, 0);
342 if (CB_ERR != nCurSel)
343 {
344 rc = VentoyStartService(nCurSel);
345 if (rc)
346 {
347 vlog("Ventoy failed to start http server, check %s for detail\n", g_log_file);
348 MessageBoxW(NULL, g_msg_lang[MSGID_INTERNAL_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
349 }
350 else
351 {
352 g_running = TRUE;
353 SetWindowTextW(g_start_button, g_msg_lang[MSGID_BTN_STOP]);
354
355 EnableWindow(g_ComboxHwnd, FALSE);
356 EnableWindow(g_refresh_button, FALSE);
357 EnableWindow(g_openlink_button, TRUE);
358
359 OpenURL();
360 }
361 }
362 }
363 }
364 else if (CtrlID == IDC_BUTTON3)
365 {
366 if (g_running)
367 {
368 OpenURL();
369 }
370 }
371 else if (CtrlID == IDC_BUTTON4)
372 {
373 if (g_running)
374 {
375 if (IDYES != MessageBoxW(NULL, g_msg_lang[MSGID_BTN_EXIT_TIP], g_msg_lang[MSGID_INFO], MB_YESNO | MB_ICONINFORMATION))
376 {
377 return 0;
378 }
379
380 ventoy_http_stop();
381 }
382
383 OnDestroyDialog();
384 EndDialog(hWnd, 0);
385 }
386 }
387 break;
388 }
389 case WM_INITDIALOG:
390 {
391 InitDialog(hWnd, wParam, lParam);
392 break;
393 }
394 case WM_CLOSE:
395 {
396 if (g_running)
397 {
398 if (IDYES != MessageBoxW(NULL, g_msg_lang[MSGID_BTN_EXIT_TIP], g_msg_lang[MSGID_INFO], MB_YESNO | MB_ICONINFORMATION))
399 {
400 return 0;
401 }
402
403 VentoyStopService();
404 }
405
406 OnDestroyDialog();
407 EndDialog(hWnd, 0);
408 }
409 }
410
411 return 0;
412 }
413
414 static int ParseCmdLine(LPSTR lpCmdLine, char *ip, char *port)
415 {
416 int portnum;
417 char *ipstart = ip;
418 char *pos;
419
420
421 if (!lpCmdLine)
422 {
423 return 0;
424 }
425
426 pos = strstr(lpCmdLine, "-H");
427 if (!pos)
428 {
429 pos = strstr(lpCmdLine, "-h");
430 }
431
432 if (pos)
433 {
434 pos += 2;
435 while (*pos == ' ' || *pos == '\t')
436 {
437 pos++;
438 }
439
440 while (isdigit(*pos) || *pos == '.')
441 {
442 *ipstart++ = *pos++;
443 }
444 }
445
446
447 pos = strstr(lpCmdLine, "-P");
448 if (!pos)
449 {
450 pos = strstr(lpCmdLine, "-p");
451 }
452
453 if (pos)
454 {
455 portnum = (int)strtol(pos + 3, NULL, 10);
456 sprintf_s(port, 16, "%d", portnum);
457 }
458
459 return 0;
460 }
461
462 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
463 {
464 int rc;
465 HANDLE hMutex;
466
467 UNREFERENCED_PARAMETER(hPrevInstance);
468
469 if (GetUserDefaultUILanguage() == 0x0804)
470 {
471 g_sysinfo.language = LANGUAGE_CN;
472 g_msg_lang = g_msg_cn;
473 }
474 else
475 {
476 g_sysinfo.language = LANGUAGE_EN;
477 g_msg_lang = g_msg_en;
478 }
479
480 hMutex = CreateMutexA(NULL, TRUE, "PlugsonMUTEX");
481 if ((hMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
482 {
483 MessageBoxW(NULL, g_msg_lang[MSGID_RUNNING_TIP], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
484 return 1;
485 }
486
487 GetCurrentDirectoryA(MAX_PATH, g_cur_dir);
488 sprintf_s(g_log_file, sizeof(g_log_file), "%s\\%s", g_cur_dir, LOG_FILE);
489 ventoy_log_init();
490
491
492 ParseCmdLine(lpCmdLine, g_sysinfo.ip, g_sysinfo.port);
493 if (g_sysinfo.ip[0] == 0)
494 {
495 strlcpy(g_sysinfo.ip, "127.0.0.1");
496 }
497 if (g_sysinfo.port[0] == 0)
498 {
499 strlcpy(g_sysinfo.port, "24681");
500 }
501
502 vlog("===============================================\n");
503 vlog("===== Ventoy Plugson %s:%s =====\n", g_sysinfo.ip, g_sysinfo.port);
504 vlog("===============================================\n");
505
506
507 ventoy_disk_init();
508 #ifndef VENTOY_SIM
509 rc = ventoy_www_init();
510 if (rc)
511 {
512 vlog("Failed to init www\n");
513 MessageBoxW(NULL, g_msg_lang[MSGID_INTERNAL_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
514
515 ventoy_disk_exit();
516 ventoy_log_exit();
517 return 1;
518 }
519 #endif
520 ventoy_http_init();
521
522 g_hInst = hInstance;
523 DialogBoxA(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
524
525 return 0;
526 }
527