feat: add boot on start
This commit is contained in:
parent
b006570ab7
commit
ac07317119
79
main.jai
79
main.jai
@ -229,6 +229,43 @@ file_exists :: (path: string) -> bool {
|
|||||||
return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY);
|
return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_autostart_enabled :: () -> bool {
|
||||||
|
hKey: HKEY;
|
||||||
|
subkey := utf8_to_wide("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
|
||||||
|
status := RegOpenKeyExW(HKEY_CURRENT_USER, subkey, 0, KEY_READ, *hKey);
|
||||||
|
if status != 0 return false;
|
||||||
|
defer RegCloseKey(hKey);
|
||||||
|
|
||||||
|
value_name := utf8_to_wide("SingboxTray");
|
||||||
|
|
||||||
|
type: DWORD;
|
||||||
|
status = RegQueryValueExW(hKey, value_name, null, *type, null, null);
|
||||||
|
return status == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_autostart :: (enable: bool) -> bool {
|
||||||
|
hKey: HKEY;
|
||||||
|
subkey := utf8_to_wide("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
|
||||||
|
status := RegOpenKeyExW(HKEY_CURRENT_USER, subkey, 0, KEY_WRITE, *hKey);
|
||||||
|
if status != 0 return false;
|
||||||
|
defer RegCloseKey(hKey);
|
||||||
|
|
||||||
|
value_name := utf8_to_wide("SingboxTray");
|
||||||
|
|
||||||
|
if enable {
|
||||||
|
path_buffer: [MAX_PATH] u16;
|
||||||
|
len := GetModuleFileNameW(null, path_buffer.data, MAX_PATH);
|
||||||
|
if len == 0 return false;
|
||||||
|
|
||||||
|
path_len_bytes := cast(DWORD) ((len + 1) * 2);
|
||||||
|
status = RegSetValueExW(hKey, value_name, 0, REG_SZ, cast(*u8) path_buffer.data, path_len_bytes);
|
||||||
|
return status == 0;
|
||||||
|
} else {
|
||||||
|
status = RegDeleteValueW(hKey, value_name);
|
||||||
|
return status == 0 || status == 2; // ERROR_FILE_NOT_FOUND is 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hidden Process Spawning with Job Object configuration and stdout/stderr redirection
|
// Hidden Process Spawning with Job Object configuration and stdout/stderr redirection
|
||||||
create_process_hidden :: (cmd: string, stdout_handle: HANDLE = INVALID_HANDLE_VALUE) -> HANDLE, PROCESS_INFORMATION, bool {
|
create_process_hidden :: (cmd: string, stdout_handle: HANDLE = INVALID_HANDLE_VALUE) -> HANDLE, PROCESS_INFORMATION, bool {
|
||||||
startup_info: STARTUPINFOW;
|
startup_info: STARTUPINFOW;
|
||||||
@ -579,6 +616,14 @@ show_context_menu :: (app: *App_State) {
|
|||||||
|
|
||||||
AppendMenuW(hMenu, MF_SEPARATOR, 0, null);
|
AppendMenuW(hMenu, MF_SEPARATOR, 0, null);
|
||||||
|
|
||||||
|
autostart_flags := MF_STRING;
|
||||||
|
if is_autostart_enabled() {
|
||||||
|
autostart_flags |= MF_CHECKED;
|
||||||
|
}
|
||||||
|
AppendMenuW(hMenu, autostart_flags, CMD_TOGGLE_AUTOSTART, utf8_to_wide("Start on Windows boot"));
|
||||||
|
|
||||||
|
AppendMenuW(hMenu, MF_SEPARATOR, 0, null);
|
||||||
|
|
||||||
AppendMenuW(hMenu, MF_STRING, CMD_EXIT, utf8_to_wide("Exit"));
|
AppendMenuW(hMenu, MF_STRING, CMD_EXIT, utf8_to_wide("Exit"));
|
||||||
|
|
||||||
cursor_pos: POINT;
|
cursor_pos: POINT;
|
||||||
@ -678,6 +723,21 @@ show_context_menu :: (app: *App_State) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case CMD_TOGGLE_AUTOSTART; {
|
||||||
|
currently_enabled := is_autostart_enabled();
|
||||||
|
success := set_autostart(!currently_enabled);
|
||||||
|
if success {
|
||||||
|
new_state := !currently_enabled;
|
||||||
|
if new_state {
|
||||||
|
log_info("Autostart on boot enabled.\n");
|
||||||
|
} else {
|
||||||
|
log_info("Autostart on boot disabled.\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log_error("Failed to toggle autostart registry configuration.\n");
|
||||||
|
MessageBoxW(app.hwnd, utf8_to_wide("Failed to update Windows registry autostart configuration."), utf8_to_wide("Sing-box Tray"), MB_ICONERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
case CMD_EXIT; {
|
case CMD_EXIT; {
|
||||||
DestroyWindow(app.hwnd);
|
DestroyWindow(app.hwnd);
|
||||||
}
|
}
|
||||||
@ -767,6 +827,25 @@ main :: () {
|
|||||||
}
|
}
|
||||||
global_is_test_mode = is_test;
|
global_is_test_mode = is_test;
|
||||||
|
|
||||||
|
// Change working directory to the executable's directory to resolve relative paths
|
||||||
|
// correctly when started via Windows autostart/registry.
|
||||||
|
{
|
||||||
|
buffer: [2048] u16;
|
||||||
|
len := GetModuleFileNameW(null, buffer.data, 2048);
|
||||||
|
if len > 0 {
|
||||||
|
last_backslash_idx := -1;
|
||||||
|
for i: 0..len-1 {
|
||||||
|
if buffer[i] == #char "\\" || buffer[i] == #char "/" {
|
||||||
|
last_backslash_idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if last_backslash_idx != -1 {
|
||||||
|
buffer[last_backslash_idx] = 0;
|
||||||
|
SetCurrentDirectoryW(buffer.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hInstance := GetModuleHandleW(null);
|
hInstance := GetModuleHandleW(null);
|
||||||
class_name_str := ifx is_test then "SingboxTrayControllerClassTest" else "SingboxTrayControllerClass";
|
class_name_str := ifx is_test then "SingboxTrayControllerClassTest" else "SingboxTrayControllerClass";
|
||||||
class_name := utf8_to_wide(class_name_str);
|
class_name := utf8_to_wide(class_name_str);
|
||||||
|
|||||||
12
win32.jai
12
win32.jai
@ -82,6 +82,7 @@ CMD_EXIT :: 1005;
|
|||||||
CMD_MODE_PROXY :: 1006;
|
CMD_MODE_PROXY :: 1006;
|
||||||
CMD_MODE_SYS_PROXY :: 1007;
|
CMD_MODE_SYS_PROXY :: 1007;
|
||||||
CMD_SET_PORT :: 1008;
|
CMD_SET_PORT :: 1008;
|
||||||
|
CMD_TOGGLE_AUTOSTART:: 1009;
|
||||||
|
|
||||||
// Boolean constants
|
// Boolean constants
|
||||||
FALSE :: 0;
|
FALSE :: 0;
|
||||||
@ -143,6 +144,7 @@ REGSAM :: u32;
|
|||||||
HKEY_CURRENT_USER :: cast(HKEY) 0x80000001;
|
HKEY_CURRENT_USER :: cast(HKEY) 0x80000001;
|
||||||
|
|
||||||
KEY_WRITE :: 0x20006;
|
KEY_WRITE :: 0x20006;
|
||||||
|
KEY_READ :: 0x20019;
|
||||||
|
|
||||||
INTERNET_OPTION_SETTINGS_CHANGED :: 39;
|
INTERNET_OPTION_SETTINGS_CHANGED :: 39;
|
||||||
INTERNET_OPTION_REFRESH :: 37;
|
INTERNET_OPTION_REFRESH :: 37;
|
||||||
@ -150,6 +152,15 @@ INTERNET_OPTION_REFRESH :: 37;
|
|||||||
RegOpenKeyExW :: (hKey: HKEY, lpSubKey: LPCWSTR, ulOptions: DWORD, samDesired: REGSAM, phkResult: *HKEY) -> LSTATUS #foreign advapi32;
|
RegOpenKeyExW :: (hKey: HKEY, lpSubKey: LPCWSTR, ulOptions: DWORD, samDesired: REGSAM, phkResult: *HKEY) -> LSTATUS #foreign advapi32;
|
||||||
RegSetValueExW :: (hKey: HKEY, lpValueName: LPCWSTR, Reserved: DWORD, dwType: DWORD, lpData: *u8, cbData: DWORD) -> LSTATUS #foreign advapi32;
|
RegSetValueExW :: (hKey: HKEY, lpValueName: LPCWSTR, Reserved: DWORD, dwType: DWORD, lpData: *u8, cbData: DWORD) -> LSTATUS #foreign advapi32;
|
||||||
RegCloseKey :: (hKey: HKEY) -> LSTATUS #foreign advapi32;
|
RegCloseKey :: (hKey: HKEY) -> LSTATUS #foreign advapi32;
|
||||||
|
RegDeleteValueW :: (hKey: HKEY, lpValueName: LPCWSTR) -> LSTATUS #foreign advapi32;
|
||||||
|
RegQueryValueExW :: (
|
||||||
|
hKey: HKEY,
|
||||||
|
lpValueName: LPCWSTR,
|
||||||
|
lpReserved: *DWORD,
|
||||||
|
lpType: *DWORD,
|
||||||
|
lpData: *u8,
|
||||||
|
lpcbData: *DWORD
|
||||||
|
) -> LSTATUS #foreign advapi32;
|
||||||
|
|
||||||
InternetSetOptionW :: (hInternet: HANDLE, dwOption: DWORD, lpBuffer: *void, dwBufferLength: DWORD) -> BOOL #foreign wininet;
|
InternetSetOptionW :: (hInternet: HANDLE, dwOption: DWORD, lpBuffer: *void, dwBufferLength: DWORD) -> BOOL #foreign wininet;
|
||||||
|
|
||||||
@ -265,3 +276,4 @@ set_windows_system_proxy :: (enable: bool, server: string) -> bool {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user