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>
13 char g_ventoy_dir
[MAX_PATH
];
15 static BOOL g_ChromeFirst
= TRUE
;
16 static BOOL g_running
= FALSE
;
17 static HWND g_refresh_button
;
18 static HWND g_start_button
;
19 static HWND g_openlink_button
;
20 static HWND g_exit_button
;
21 static HWND g_ComboxHwnd
;
46 const WCHAR
*g_msg_cn
[MSGID_BUTT
] =
50 L
"请在 Ventoy 盘根目录下运行本程序!(存放ISO文件的位置)",
51 L
"创建 ventoy 目录失败,无法继续!",
52 L
"ventoy 目录存在,但是大小写不匹配,请先将其重命名!",
60 L
"停止运行后浏览器页面将会关闭,是否继续?",
62 L
"请先关闭正在运行的 VentoyPlugson 程序!",
63 L
"ventoy\\plugson.tar.xz 文件不存在,请在正确的目录下运行!",
65 const WCHAR
*g_msg_en
[MSGID_BUTT
] =
69 L
"Please run me at the root of Ventoy partition.",
70 L
"Failed to create ventoy directory!",
71 L
"ventoy directory case mismatch, please rename it first!",
72 L
"Internal error, the program will exit!",
79 L
"The browser page will close after stop, continue?",
80 L
"Service is running, continue?",
81 L
"Please close another running VentoyPlugson instance!",
82 L
"ventoy\\plugson.tar.xz does not exist, please run under the correct directory!",
85 #define UTF8_Log(fmt, wstr) \
87 memset(TmpPathA, 0, sizeof(TmpPathA));\
88 WideCharToMultiByte(CP_UTF8, 0, wstr, -1, TmpPathA, sizeof(TmpPathA), NULL, NULL);\
93 const WCHAR
**g_msg_lang
= NULL
;
97 char g_log_file
[MAX_PATH
];
98 char g_cur_dir
[MAX_PATH
];
100 int ventoy_log_init(void);
101 void ventoy_log_exit(void);
103 static BOOL
OnDestroyDialog()
115 static void OpenURL(void)
119 const static char * Browsers
[] =
121 "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
122 "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
123 "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
124 "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
128 sprintf_s(url
, sizeof(url
), "http://%s:%s/index.html", g_sysinfo
.ip
, g_sysinfo
.port
);
132 for (i
= 0; Browsers
[i
] != NULL
; i
++)
134 if (ventoy_is_file_exist("%s", Browsers
[i
]))
136 ShellExecuteA(NULL
, "open", Browsers
[i
], url
, NULL
, SW_SHOW
);
142 ShellExecuteA(NULL
, "open", url
, NULL
, NULL
, SW_SHOW
);
146 static void FillCombox(HWND hWnd
)
150 const ventoy_disk
*list
= NULL
;
151 CHAR DeviceName
[256];
154 SendMessage(g_ComboxHwnd
, CB_RESETCONTENT
, 0, 0);
156 list
= ventoy_get_disk_list(&num
);
157 if (NULL
== list
|| num
<= 0)
162 for (i
= 0; i
< num
; i
++)
164 sprintf_s(DeviceName
, sizeof(DeviceName
),
167 list
[i
].cur_capacity
,
169 SendMessageA(g_ComboxHwnd
, CB_ADDSTRING
, 0, (LPARAM
)DeviceName
);
171 SendMessage(g_ComboxHwnd
, CB_SETCURSEL
, 0, 0);
175 static BOOL
InitDialog(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
179 g_ComboxHwnd
= GetDlgItem(hWnd
, IDC_COMBO1
);
180 g_refresh_button
= GetDlgItem(hWnd
, IDC_BUTTON1
);
181 g_start_button
= GetDlgItem(hWnd
, IDC_BUTTON2
);
182 g_openlink_button
= GetDlgItem(hWnd
, IDC_BUTTON3
);
183 g_exit_button
= GetDlgItem(hWnd
, IDC_BUTTON4
);
185 hIcon
= LoadIcon(g_hInst
, MAKEINTRESOURCE(IDI_ICON1
));
186 SendMessage(hWnd
, WM_SETICON
, ICON_BIG
, (LPARAM
)hIcon
);
187 SendMessage(hWnd
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hIcon
);
189 SetWindowTextW(g_refresh_button
, g_msg_lang
[MSGID_BTN_REFRESH
]);
190 SetWindowTextW(g_start_button
, g_msg_lang
[MSGID_BTN_START
]);
191 SetWindowTextW(g_openlink_button
, g_msg_lang
[MSGID_BTN_LINK
]);
192 SetWindowTextW(g_exit_button
, g_msg_lang
[MSGID_BTN_EXIT
]);
194 EnableWindow(g_openlink_button
, FALSE
);
201 static void VentoyStopService()
206 static int VentoyStartService(int sel
)
211 char CurDir
[MAX_PATH
];
212 const ventoy_disk
*disk
= NULL
;
214 vlog("VentoyStartService ...\n");
216 disk
= ventoy_get_disk_node(sel
);
222 vlog("Start service at %C: %s %s ...\n", disk
->devname
[0], disk
->cur_model
, disk
->cur_ventoy_ver
);
224 g_cur_dir
[0] = disk
->devname
[0];
229 g_sysinfo
.pathcase
= disk
->pathcase
;
230 g_sysinfo
.cur_secureboot
= disk
->cur_secureboot
;
231 g_sysinfo
.cur_part_style
= disk
->cur_part_style
;
232 strlcpy(g_sysinfo
.cur_fsname
, disk
->cur_fsname
);
233 strlcpy(g_sysinfo
.cur_capacity
, disk
->cur_capacity
);
234 strlcpy(g_sysinfo
.cur_model
, disk
->cur_model
);
235 strlcpy(g_sysinfo
.cur_ventoy_ver
, disk
->cur_ventoy_ver
);
237 bRet
= SetCurrentDirectoryA(g_cur_dir
);
238 vlog("SetCurrentDirectoryA %u <%s>\n", bRet
, g_cur_dir
);
241 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
242 vlog("CurDir=<%s>\n", CurDir
);
244 if (strcmp(g_cur_dir
, CurDir
))
246 vlog("Failed to change current directory.");
251 if (ventoy_is_directory_exist("ventoy"))
253 if (g_sysinfo
.pathcase
)
255 vlog("ventoy directory already exist, check case sensitive.\n");
256 strlcpy(Path
, "ventoy");
258 rc
= ventoy_path_case(Path
, 0);
259 vlog("ventoy_path_case actual path is <%s> <count:%d>\n", Path
, rc
);
263 vlog("ventoy directory case mismatch, rename<%s>--><%s>\n", Path
, "ventoy");
264 if (MoveFileA(Path
, "ventoy"))
266 vlog("Rename <%s>--><%s> success\n", Path
, "ventoy");
270 vlog("Rename <%s>--><%s> failed %u\n", Path
, "ventoy", LASTERR
);
271 MessageBoxW(NULL
, g_msg_lang
[MSGID_RENAME_VENTOY
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
278 vlog("ventoy directory already exist, no need to check case sensitive.\n");
283 if (CreateDirectoryA("ventoy", NULL
))
285 vlog("Create ventoy directory success.\n");
289 vlog("Create ventoy directory failed %u.\n", LASTERR
);
290 MessageBoxW(NULL
, g_msg_lang
[MSGID_NEW_DIR_FAIL
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
295 return ventoy_http_start(g_sysinfo
.ip
, g_sysinfo
.port
);
298 INT_PTR CALLBACK
DialogProc(HWND hWnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
314 code
= ((LPNMHDR
)lParam
)->code
;
315 idFrom
= ((LPNMHDR
)lParam
)->idFrom
;
318 if (idFrom
== IDC_SYSLINK1
&& (NM_CLICK
== code
|| NM_RETURN
== code
))
326 NotifyCode
= HIWORD(wParam
);
327 CtrlID
= LOWORD(wParam
);
329 if (NotifyCode
== BN_CLICKED
)
331 if (CtrlID
== IDC_BUTTON1
)
341 else if (CtrlID
== IDC_BUTTON2
)
345 if (IDYES
== MessageBoxW(NULL
, g_msg_lang
[MSGID_BTN_STOP_TIP
], g_msg_lang
[MSGID_INFO
], MB_YESNO
| MB_ICONINFORMATION
))
350 SetWindowTextW(g_start_button
, g_msg_lang
[MSGID_BTN_START
]);
351 EnableWindow(g_ComboxHwnd
, TRUE
);
352 EnableWindow(g_refresh_button
, TRUE
);
353 EnableWindow(g_openlink_button
, FALSE
);
358 nCurSel
= (int)SendMessage(g_ComboxHwnd
, CB_GETCURSEL
, 0, 0);
359 if (CB_ERR
!= nCurSel
)
361 rc
= VentoyStartService(nCurSel
);
364 vlog("Ventoy failed to start http server, check %s for detail\n", g_log_file
);
365 MessageBoxW(NULL
, g_msg_lang
[MSGID_INTERNAL_ERR
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
370 SetWindowTextW(g_start_button
, g_msg_lang
[MSGID_BTN_STOP
]);
372 EnableWindow(g_ComboxHwnd
, FALSE
);
373 EnableWindow(g_refresh_button
, FALSE
);
374 EnableWindow(g_openlink_button
, TRUE
);
381 else if (CtrlID
== IDC_BUTTON3
)
388 else if (CtrlID
== IDC_BUTTON4
)
392 if (IDYES
!= MessageBoxW(NULL
, g_msg_lang
[MSGID_BTN_EXIT_TIP
], g_msg_lang
[MSGID_INFO
], MB_YESNO
| MB_ICONINFORMATION
))
408 InitDialog(hWnd
, wParam
, lParam
);
415 if (IDYES
!= MessageBoxW(NULL
, g_msg_lang
[MSGID_BTN_EXIT_TIP
], g_msg_lang
[MSGID_INFO
], MB_YESNO
| MB_ICONINFORMATION
))
432 static int ParseCmdLine(LPSTR lpCmdLine
, char *ip
, char *port
)
444 pos
= strstr(lpCmdLine
, "-H");
447 pos
= strstr(lpCmdLine
, "-h");
453 while (*pos
== ' ' || *pos
== '\t')
458 while (isdigit(*pos
) || *pos
== '.')
465 pos
= strstr(lpCmdLine
, "-P");
468 pos
= strstr(lpCmdLine
, "-p");
473 portnum
= (int)strtol(pos
+ 3, NULL
, 10);
474 sprintf_s(port
, 16, "%d", portnum
);
484 //Copyright © 2011-2021 Pete Batard <pete@akeo.ie>
486 #include <delayimp.h>
487 // For delay-loaded DLLs, use LOAD_LIBRARY_SEARCH_SYSTEM32 to avoid DLL search order hijacking.
488 FARPROC WINAPI
dllDelayLoadHook(unsigned dliNotify
, PDelayLoadInfo pdli
)
490 if (dliNotify
== dliNotePreLoadLibrary
) {
491 // Windows 7 without KB2533623 does not support the LOAD_LIBRARY_SEARCH_SYSTEM32 flag.
492 // That is is OK, because the delay load handler will interrupt the NULL return value
493 // to mean that it should perform a normal LoadLibrary.
494 return (FARPROC
)LoadLibraryExA(pdli
->szDll
, NULL
, LOAD_LIBRARY_SEARCH_SYSTEM32
);
499 #if defined(_MSC_VER)
500 // By default the Windows SDK headers have a `const` while MinGW does not.
503 PfnDliHook __pfnDliNotifyHook2
= dllDelayLoadHook
;
505 typedef BOOL(WINAPI
* SetDefaultDllDirectories_t
)(DWORD
);
506 static void DllProtect(void)
508 SetDefaultDllDirectories_t pfSetDefaultDllDirectories
= NULL
;
510 // Disable loading system DLLs from the current directory (sideloading mitigation)
511 // PS: You know that official MSDN documentation for SetDllDirectory() that explicitly
512 // indicates that "If the parameter is an empty string (""), the call removes the current
513 // directory from the default DLL search order"? Yeah, that doesn't work. At all.
514 // Still, we invoke it, for platforms where the following call might actually work...
515 SetDllDirectoryA("");
517 // For libraries on the KnownDLLs list, the system will always load them from System32.
518 // For other DLLs we link directly to, we can delay load the DLL and use a delay load
519 // hook to load them from System32. Note that, for this to work, something like:
520 // 'somelib.dll;%(DelayLoadDLLs)' must be added to the 'Delay Loaded Dlls' option of
521 // the linker properties in Visual Studio (which means this won't work with MinGW).
522 // For all other DLLs, use SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32).
523 // Finally, we need to perform the whole gymkhana below, where we can't call on
524 // SetDefaultDllDirectories() directly, because Windows 7 doesn't have the API exposed.
525 // Also, no, Coverity, we never need to care about freeing kernel32 as a library.
526 // coverity[leaked_storage]
528 pfSetDefaultDllDirectories
= (SetDefaultDllDirectories_t
)
529 GetProcAddress(LoadLibraryW(L
"kernel32.dll"), "SetDefaultDllDirectories");
530 if (pfSetDefaultDllDirectories
!= NULL
)
531 pfSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32
);
535 int APIENTRY
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, INT nCmdShow
)
542 WCHAR CurDir
[MAX_PATH
];
543 WCHAR ExePath
[MAX_PATH
];
544 WCHAR CurDirBk
[MAX_PATH
];
545 WCHAR ExePathBk
[MAX_PATH
];
546 CHAR TmpPathA
[MAX_PATH
];
548 UNREFERENCED_PARAMETER(hPrevInstance
);
550 for (i
= 0; i
< __argc
; i
++)
552 if (__argv
[i
] && _stricmp(__argv
[i
], "/F") == 0)
554 g_ChromeFirst
= FALSE
;
561 if (GetUserDefaultUILanguage() == 0x0804)
563 g_sysinfo
.language
= LANGUAGE_CN
;
564 g_msg_lang
= g_msg_cn
;
568 g_sysinfo
.language
= LANGUAGE_EN
;
569 g_msg_lang
= g_msg_en
;
572 hMutex
= CreateMutexA(NULL
, TRUE
, "PlugsonMUTEX");
573 if ((hMutex
!= NULL
) && (GetLastError() == ERROR_ALREADY_EXISTS
))
575 MessageBoxW(NULL
, g_msg_lang
[MSGID_RUNNING_TIP
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
579 GetCurrentDirectoryW(MAX_PATH
, CurDir
);
580 GetCurrentDirectoryW(MAX_PATH
, CurDirBk
);
581 GetModuleFileNameW(NULL
, ExePath
, MAX_PATH
);
582 GetModuleFileNameW(NULL
, ExePathBk
, MAX_PATH
);
584 for (Pos
= NULL
, i
= 0; i
< MAX_PATH
&& ExePath
[i
]; i
++)
586 if (ExePath
[i
] == '\\' || ExePath
[i
] == '/')
595 if (wcscmp(CurDir
, ExePath
))
598 SetCurrentDirectoryW(ExePath
);
599 GetCurrentDirectoryW(MAX_PATH
, CurDir
);
607 Pos
= wcsstr(CurDir
, L
"\\altexe");
612 SetCurrentDirectoryW(CurDir
);
616 WideCharToMultiByte(CP_UTF8
, 0, CurDir
, -1, g_cur_dir
, MAX_PATH
, NULL
, 0);
618 sprintf_s(g_ventoy_dir
, sizeof(g_ventoy_dir
), "%s", g_cur_dir
);
619 sprintf_s(g_log_file
, sizeof(g_log_file
), "%s", LOG_FILE
);
622 vlog("====================== Ventoy Plugson =========================\n");
624 UTF8_Log("Current Directory <%s>\n", CurDirBk
);
625 UTF8_Log("Exe file path <%s>\n", ExePathBk
);
629 UTF8_Log("Change current dir to exe <%s>\n", ExePath
);
633 vlog("Current directory check OK.\n");
637 UTF8_Log("altexe detected, change current dir to <%s>\n", CurDir
);
641 if (!ventoy_is_file_exist("%s\\ventoy\\%s", g_ventoy_dir
, PLUGSON_TXZ
))
643 MessageBoxW(NULL
, g_msg_lang
[MSGID_NO_TARXZ_TIP
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
647 ParseCmdLine(lpCmdLine
, g_sysinfo
.ip
, g_sysinfo
.port
);
648 if (g_sysinfo
.ip
[0] == 0)
650 strlcpy(g_sysinfo
.ip
, "127.0.0.1");
652 if (g_sysinfo
.port
[0] == 0)
654 strlcpy(g_sysinfo
.port
, "24681");
657 vlog("===============================================\n");
658 vlog("========= Ventoy Plugson %s:%s =========\n", g_sysinfo
.ip
, g_sysinfo
.port
);
659 vlog("===============================================\n");
664 rc
= ventoy_www_init();
667 vlog("Failed to init www\n");
668 MessageBoxW(NULL
, g_msg_lang
[MSGID_INTERNAL_ERR
], g_msg_lang
[MSGID_ERROR
], MB_OK
| MB_ICONERROR
);
678 DialogBox(hInstance
, MAKEINTRESOURCE(IDD_DIALOG1
), NULL
, DialogProc
);