feat, topmost window, exclude from capture
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
98f56fd506
commit
c23f377039
6
build.py
6
build.py
@ -57,9 +57,9 @@ def parse_rc_features(feature):
|
|||||||
},
|
},
|
||||||
'PrivacyMode': {
|
'PrivacyMode': {
|
||||||
'platform': ['windows'],
|
'platform': ['windows'],
|
||||||
'zip_url': 'https://github.com/fufesou/RustDeskTempTopMostWindow/releases/download/v0.2'
|
'zip_url': 'https://github.com/fufesou/RustDeskTempTopMostWindow/releases/download/v0.3'
|
||||||
'/TempTopMostWindow_x64_pic_en.zip',
|
'/TempTopMostWindow_x64.zip',
|
||||||
'checksum_url': 'https://github.com/fufesou/RustDeskTempTopMostWindow/releases/download/v0.2/checksum_md5',
|
'checksum_url': 'https://github.com/fufesou/RustDeskTempTopMostWindow/releases/download/v0.3/checksum_md5',
|
||||||
'include': ['WindowInjection.dll'],
|
'include': ['WindowInjection.dll'],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,11 +94,11 @@ mod windows {
|
|||||||
|
|
||||||
// Used for privacy mode(magnifier impl).
|
// Used for privacy mode(magnifier impl).
|
||||||
pub const RUNTIME_BROKER_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
|
pub const RUNTIME_BROKER_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
|
||||||
pub const WIN_MAG_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
|
pub const WIN_TOPMOST_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
|
||||||
|
|
||||||
pub(super) fn copy_runtime_broker(dir: &PathBuf) {
|
pub(super) fn copy_runtime_broker(dir: &PathBuf) {
|
||||||
let src = RUNTIME_BROKER_EXE;
|
let src = RUNTIME_BROKER_EXE;
|
||||||
let tgt = WIN_MAG_INJECTED_PROCESS_EXE;
|
let tgt = WIN_TOPMOST_INJECTED_PROCESS_EXE;
|
||||||
let target_file = dir.join(tgt);
|
let target_file = dir.join(tgt);
|
||||||
if target_file.exists() {
|
if target_file.exists() {
|
||||||
if let (Ok(src_file), Ok(tgt_file)) = (fs::read(src), fs::read(&target_file)) {
|
if let (Ok(src_file), Ok(tgt_file)) = (fs::read(src), fs::read(&target_file)) {
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", "模式 1 (不推荐)"),
|
("privacy_mode_impl_mag_tip", "模式 1 (不推荐)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "模式 2 (推荐)"),
|
("privacy_mode_impl_virtual_display_tip", "模式 2 (推荐)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", "模式 3"),
|
||||||
("Enter privacy mode", "进入隐私模式"),
|
("Enter privacy mode", "进入隐私模式"),
|
||||||
("Exit privacy mode", "退出隐私模式"),
|
("Exit privacy mode", "退出隐私模式"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Můžete zadat ID, přímou IP adresu nebo doménu s portem (<doména>:<port>).\nPokud chcete přistupovat k zařízení na jiném serveru, připojte adresu serveru (<id>@<adresa_serveru>?key=<hodnota_klíče>), například,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nPokud chcete přistupovat k zařízení na veřejném serveru, zadejte \"<id>@public\", klíč není pro veřejný server potřeba."),
|
("id_input_tip", "Můžete zadat ID, přímou IP adresu nebo doménu s portem (<doména>:<port>).\nPokud chcete přistupovat k zařízení na jiném serveru, připojte adresu serveru (<id>@<adresa_serveru>?key=<hodnota_klíče>), například,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nPokud chcete přistupovat k zařízení na veřejném serveru, zadejte \"<id>@public\", klíč není pro veřejný server potřeba."),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Sie können eine ID, eine direkte IP oder eine Domäne mit einem Port (<domain>:<port>) eingeben.\nWenn Sie auf ein Gerät auf einem anderen Server zugreifen möchten, fügen Sie bitte die Serveradresse (<id>@<server_address>?key=<key_value>) hinzu, zum Beispiel\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nWenn Sie auf ein Gerät auf einem öffentlichen Server zugreifen wollen, geben Sie bitte \"<id>@public\" ein. Der Schlüssel wird für öffentliche Server nicht benötigt."),
|
("id_input_tip", "Sie können eine ID, eine direkte IP oder eine Domäne mit einem Port (<domain>:<port>) eingeben.\nWenn Sie auf ein Gerät auf einem anderen Server zugreifen möchten, fügen Sie bitte die Serveradresse (<id>@<server_address>?key=<key_value>) hinzu, zum Beispiel\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nWenn Sie auf ein Gerät auf einem öffentlichen Server zugreifen wollen, geben Sie bitte \"<id>@public\" ein. Der Schlüssel wird für öffentliche Server nicht benötigt."),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -205,5 +205,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "You can input an ID, a direct IP, or a domain with a port (<domain>:<port>).\nIf you want to access a device on another server, please append the server address (<id>@<server_address>?key=<key_value>), for example,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nIf you want to access a device on a public server, please input \"<id>@public\", the key is not needed for public server"),
|
("id_input_tip", "You can input an ID, a direct IP, or a domain with a port (<domain>:<port>).\nIf you want to access a device on another server, please append the server address (<id>@<server_address>?key=<key_value>), for example,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nIf you want to access a device on a public server, please input \"<id>@public\", the key is not needed for public server"),
|
||||||
("privacy_mode_impl_mag_tip", "Mode 1 (deprecated)"),
|
("privacy_mode_impl_mag_tip", "Mode 1 (deprecated)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Mode 2 (recommended)"),
|
("privacy_mode_impl_virtual_display_tip", "Mode 2 (recommended)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", "Mode 3"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Puedes introducir una ID, una IP directa o un dominio con un puerto (<dominio>:<puerto>).\nSi quieres acceder a un dispositivo en otro servidor, por favor añade la ip del servidor (<id>@<dirección_servidor>?key=<clave_valor>), por ejemplo,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nSi quieres acceder a un dispositivo en un servidor público, por favor, introduce \"<id>@public\", la clave no es necesaria para un servidor público."),
|
("id_input_tip", "Puedes introducir una ID, una IP directa o un dominio con un puerto (<dominio>:<puerto>).\nSi quieres acceder a un dispositivo en otro servidor, por favor añade la ip del servidor (<id>@<dirección_servidor>?key=<clave_valor>), por ejemplo,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nSi quieres acceder a un dispositivo en un servidor público, por favor, introduce \"<id>@public\", la clave no es necesaria para un servidor público."),
|
||||||
("privacy_mode_impl_mag_tip", "Modo 1 (obsoleto)"),
|
("privacy_mode_impl_mag_tip", "Modo 1 (obsoleto)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Modo 2 (recomendado)"),
|
("privacy_mode_impl_virtual_display_tip", "Modo 2 (recomendado)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Entrar al modo privado"),
|
("Enter privacy mode", "Entrar al modo privado"),
|
||||||
("Exit privacy mode", "Salir del modo privado"),
|
("Exit privacy mode", "Salir del modo privado"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Anda bisa memasukkan ID, IP langsung, atau domain dengan port kostum yang sudah ditentukan (<domain>:<port>).\nJika anda ingin mengakses perangkat lain yang berbeda server, tambahkan alamat server setelah penulisan ID(<id>@<server_address>?key=<key_value>), sebagai contoh,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJika anda ingin mengakses perangkat yang menggunakan server publik, masukkan \"<id>@public\", server public tidak memerlukan key khusus"),
|
("id_input_tip", "Anda bisa memasukkan ID, IP langsung, atau domain dengan port kostum yang sudah ditentukan (<domain>:<port>).\nJika anda ingin mengakses perangkat lain yang berbeda server, tambahkan alamat server setelah penulisan ID(<id>@<server_address>?key=<key_value>), sebagai contoh,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJika anda ingin mengakses perangkat yang menggunakan server publik, masukkan \"<id>@public\", server public tidak memerlukan key khusus"),
|
||||||
("privacy_mode_impl_mag_tip", "Mode 1 (deprecated)"),
|
("privacy_mode_impl_mag_tip", "Mode 1 (deprecated)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Mode 2 (direkomendasikan)"),
|
("privacy_mode_impl_virtual_display_tip", "Mode 2 (direkomendasikan)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Masuk mode privasi"),
|
("Enter privacy mode", "Masuk mode privasi"),
|
||||||
("Exit privacy mode", "Keluar mode privasi"),
|
("Exit privacy mode", "Keluar mode privasi"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Puoi inserire un ID, un IP diretto o un dominio con una porta (<dominio>:<porta>).\nSe vuoi accedere as un dispositivo in un altro server, aggiungi l'indirizzo del server (<id>@<indirizzo_server >?key=<valore_chiave>), ad esempio\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nSe vuoi accedere as un dispositivo in un server pubblico, inserisci \"<id>@public\", per il server pubblico la chiave non è necessaria"),
|
("id_input_tip", "Puoi inserire un ID, un IP diretto o un dominio con una porta (<dominio>:<porta>).\nSe vuoi accedere as un dispositivo in un altro server, aggiungi l'indirizzo del server (<id>@<indirizzo_server >?key=<valore_chiave>), ad esempio\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nSe vuoi accedere as un dispositivo in un server pubblico, inserisci \"<id>@public\", per il server pubblico la chiave non è necessaria"),
|
||||||
("privacy_mode_impl_mag_tip", "Modo 1 (deprecato)"),
|
("privacy_mode_impl_mag_tip", "Modo 1 (deprecato)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Modo 2 (consigliato)"),
|
("privacy_mode_impl_virtual_display_tip", "Modo 2 (consigliato)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Entra in modalità privacy"),
|
("Enter privacy mode", "Entra in modalità privacy"),
|
||||||
("Exit privacy mode", "Esci dalla modalità privacy"),
|
("Exit privacy mode", "Esci dalla modalità privacy"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "입력된 ID, IP, 도메인과 포트(<domain>:<port>)를 입력할 수 있습니다.\n다른 서버에 있는 장치에 접속하려면 서버 주소(<id>@<server_address>?key=<key_value>)를 추가하세요"),
|
("id_input_tip", "입력된 ID, IP, 도메인과 포트(<domain>:<port>)를 입력할 수 있습니다.\n다른 서버에 있는 장치에 접속하려면 서버 주소(<id>@<server_address>?key=<key_value>)를 추가하세요"),
|
||||||
("privacy_mode_impl_mag_tip", "모드 1(더 이상 사용되지 않음)"),
|
("privacy_mode_impl_mag_tip", "모드 1(더 이상 사용되지 않음)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "모드 2(권장)"),
|
("privacy_mode_impl_virtual_display_tip", "모드 2(권장)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "개인정보 보호 모드 사용"),
|
("Enter privacy mode", "개인정보 보호 모드 사용"),
|
||||||
("Exit privacy mode", "개인정보 보호 모드 종료"),
|
("Exit privacy mode", "개인정보 보호 모드 종료"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Varat ievadīt ID, tiešo IP vai domēnu ar portu (<domēns>:<ports>).\nJa vēlaties piekļūt ierīcei citā serverī, lūdzu, pievienojiet servera adresi (<id>@<servera_adrese>?key=<atslēgas_vērtība>), piemēram,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJa vēlaties piekļūt ierīcei publiskajā serverī, lūdzu, ievadiet \"<id>@public\", publiskajam serverim atslēga nav nepieciešama"),
|
("id_input_tip", "Varat ievadīt ID, tiešo IP vai domēnu ar portu (<domēns>:<ports>).\nJa vēlaties piekļūt ierīcei citā serverī, lūdzu, pievienojiet servera adresi (<id>@<servera_adrese>?key=<atslēgas_vērtība>), piemēram,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJa vēlaties piekļūt ierīcei publiskajā serverī, lūdzu, ievadiet \"<id>@public\", publiskajam serverim atslēga nav nepieciešama"),
|
||||||
("privacy_mode_impl_mag_tip", "1. režīms (novecojis)"),
|
("privacy_mode_impl_mag_tip", "1. režīms (novecojis)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "2. režīms (ieteicams)"),
|
("privacy_mode_impl_virtual_display_tip", "2. režīms (ieteicams)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Ieiet privātuma režīmā"),
|
("Enter privacy mode", "Ieiet privātuma režīmā"),
|
||||||
("Exit privacy mode", "Iziet no privātuma režīma"),
|
("Exit privacy mode", "Iziet no privātuma režīma"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Je kunt een ID, een direct IP of een domein met een poort (<domein>:<poort>) invoeren. Als je toegang wilt als apparaat op een andere server, voeg dan het serveradres toe (<id>@<server_adres>?key=<key_value>), bijvoorbeeld \n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.Als je toegang wilt als apparaat op een openbare server, voer dan \"<id>@public\" in, voor de openbare server is de sleutel niet nodig."),
|
("id_input_tip", "Je kunt een ID, een direct IP of een domein met een poort (<domein>:<poort>) invoeren. Als je toegang wilt als apparaat op een andere server, voeg dan het serveradres toe (<id>@<server_adres>?key=<key_value>), bijvoorbeeld \n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.Als je toegang wilt als apparaat op een openbare server, voer dan \"<id>@public\" in, voor de openbare server is de sleutel niet nodig."),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Możesz wprowadzić identyfikator, bezpośredni adres IP lub domenę z portem (<adres_domenowy>:<port>).\nJeżeli chcesz uzyskać dostęp do urządzenia na innym serwerze, dołącz adres serwera (<id>@<adres_serwera>?key=<wartość_klucza>, np. \n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJeżeli chcesz uzyskać dostęp do urządzenia na serwerze publicznym, wpisz \"<id>@public\", klucz nie jest potrzebny dla serwera publicznego."),
|
("id_input_tip", "Możesz wprowadzić identyfikator, bezpośredni adres IP lub domenę z portem (<adres_domenowy>:<port>).\nJeżeli chcesz uzyskać dostęp do urządzenia na innym serwerze, dołącz adres serwera (<id>@<adres_serwera>?key=<wartość_klucza>, np. \n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nJeżeli chcesz uzyskać dostęp do urządzenia na serwerze publicznym, wpisz \"<id>@public\", klucz nie jest potrzebny dla serwera publicznego."),
|
||||||
("privacy_mode_impl_mag_tip", "Tryb 1 (przestarzały)"),
|
("privacy_mode_impl_mag_tip", "Tryb 1 (przestarzały)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Tryb 2 (zalecany)"),
|
("privacy_mode_impl_virtual_display_tip", "Tryb 2 (zalecany)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Wejdź w tryb prywatności"),
|
("Enter privacy mode", "Wejdź w tryb prywatności"),
|
||||||
("Exit privacy mode", "Wyjdź z trybu prywatności"),
|
("Exit privacy mode", "Wyjdź z trybu prywatności"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Можно ввести идентификатор, прямой IP-адрес или домен с портом (<домен>:<порт>).\nЕсли необходимо получить доступ к устройству на другом сервере, добавьте адрес сервера (<id>@<адрес_сервера>?key=<ключ_значение>), например:\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nЕсли необходимо получить доступ к устройству на общедоступном сервере, введите \"<id>@public\", ключ для публичного сервера не требуется."),
|
("id_input_tip", "Можно ввести идентификатор, прямой IP-адрес или домен с портом (<домен>:<порт>).\nЕсли необходимо получить доступ к устройству на другом сервере, добавьте адрес сервера (<id>@<адрес_сервера>?key=<ключ_значение>), например:\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nЕсли необходимо получить доступ к устройству на общедоступном сервере, введите \"<id>@public\", ключ для публичного сервера не требуется."),
|
||||||
("privacy_mode_impl_mag_tip", "Режим 1 (устаревший)"),
|
("privacy_mode_impl_mag_tip", "Режим 1 (устаревший)"),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Режим 2 (рекомендуемый)"),
|
("privacy_mode_impl_virtual_display_tip", "Режим 2 (рекомендуемый)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", "Включить режим конфиденциальности"),
|
("Enter privacy mode", "Включить режим конфиденциальности"),
|
||||||
("Exit privacy mode", "Отключить режим конфиденциальности"),
|
("Exit privacy mode", "Отключить режим конфиденциальности"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", "Môžete zadať ID, priamu IP adresu alebo doménu s portom (<doména>:<port>).\nAk chcete získať prístup k zariadeniu na inom serveri, doplňte adresu servera (<id>@<adresa_servera>?key=<hodnota_kľúča>), napríklad,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nAk chcete získať prístup k zariadeniu na verejnom serveri, zadajte \"<id>@public\", kľúč nie je potrebný pre verejný server."),
|
("id_input_tip", "Môžete zadať ID, priamu IP adresu alebo doménu s portom (<doména>:<port>).\nAk chcete získať prístup k zariadeniu na inom serveri, doplňte adresu servera (<id>@<adresa_servera>?key=<hodnota_kľúča>), napríklad,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nAk chcete získať prístup k zariadeniu na verejnom serveri, zadajte \"<id>@public\", kľúč nie je potrebný pre verejný server."),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -569,6 +569,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Enable blocking user input", "Блокувати введення для користувача"),
|
("Enable blocking user input", "Блокувати введення для користувача"),
|
||||||
("id_input_tip", "Ви можете ввести ID, безпосередню IP, або ж домен з портом (<домен>:<порт>).\nЯкщо ви хочете отримати доступ до пристрою на іншому сервері, будь ласка, додайте адресу сервера (<id>@<адреса_сервера>?key=<значення_ключа>), наприклад,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nЯкщо ви хочете отримати доступ до пристрою на публічному сервері, будь ласка, введіть \"<id>@public\", ключ для публічного сервера не потрібен."),
|
("id_input_tip", "Ви можете ввести ID, безпосередню IP, або ж домен з портом (<домен>:<порт>).\nЯкщо ви хочете отримати доступ до пристрою на іншому сервері, будь ласка, додайте адресу сервера (<id>@<адреса_сервера>?key=<значення_ключа>), наприклад,\n9123456234@192.168.16.1:21117?key=5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=.\nЯкщо ви хочете отримати доступ до пристрою на публічному сервері, будь ласка, введіть \"<id>@public\", ключ для публічного сервера не потрібен."),
|
||||||
("privacy_mode_impl_mag_tip", "Режим 1 (застарілий)"),
|
("privacy_mode_impl_mag_tip", "Режим 1 (застарілий)"),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", "Режим 2 (рекомендований)"),
|
("privacy_mode_impl_virtual_display_tip", "Режим 2 (рекомендований)"),
|
||||||
("Enter privacy mode", "Увійти в режим конфіденційності"),
|
("Enter privacy mode", "Увійти в режим конфіденційності"),
|
||||||
("Exit privacy mode", "Вийти з режиму конфіденційності"),
|
("Exit privacy mode", "Вийти з режиму конфіденційності"),
|
||||||
|
@ -570,6 +570,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("id_input_tip", ""),
|
("id_input_tip", ""),
|
||||||
("privacy_mode_impl_mag_tip", ""),
|
("privacy_mode_impl_mag_tip", ""),
|
||||||
("privacy_mode_impl_virtual_display_tip", ""),
|
("privacy_mode_impl_virtual_display_tip", ""),
|
||||||
|
("privacy_mode_impl_exclude_from_capture_tip", ""),
|
||||||
("Enter privacy mode", ""),
|
("Enter privacy mode", ""),
|
||||||
("Exit privacy mode", ""),
|
("Exit privacy mode", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
|
@ -3,7 +3,7 @@ use crate::common::PORTABLE_APPNAME_RUNTIME_ENV_KEY;
|
|||||||
use crate::{
|
use crate::{
|
||||||
ipc,
|
ipc,
|
||||||
license::*,
|
license::*,
|
||||||
privacy_mode::win_mag::{self, WIN_MAG_INJECTED_PROCESS_EXE},
|
privacy_mode::win_topmost_window::{self, WIN_TOPMOST_INJECTED_PROCESS_EXE},
|
||||||
};
|
};
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
@ -848,8 +848,8 @@ fn get_default_install_path() -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_update_broker_process() -> ResultType<()> {
|
pub fn check_update_broker_process() -> ResultType<()> {
|
||||||
let process_exe = win_mag::INJECTED_PROCESS_EXE;
|
let process_exe = win_topmost_window::INJECTED_PROCESS_EXE;
|
||||||
let origin_process_exe = win_mag::ORIGIN_PROCESS_EXE;
|
let origin_process_exe = win_topmost_window::ORIGIN_PROCESS_EXE;
|
||||||
|
|
||||||
let exe_file = std::env::current_exe()?;
|
let exe_file = std::env::current_exe()?;
|
||||||
let Some(cur_dir) = exe_file.parent() else {
|
let Some(cur_dir) = exe_file.parent() else {
|
||||||
@ -926,8 +926,8 @@ pub fn copy_exe_cmd(src_exe: &str, exe: &str, path: &str) -> ResultType<String>
|
|||||||
{main_exe}
|
{main_exe}
|
||||||
copy /Y \"{ORIGIN_PROCESS_EXE}\" \"{path}\\{broker_exe}\"
|
copy /Y \"{ORIGIN_PROCESS_EXE}\" \"{path}\\{broker_exe}\"
|
||||||
",
|
",
|
||||||
ORIGIN_PROCESS_EXE = win_mag::ORIGIN_PROCESS_EXE,
|
ORIGIN_PROCESS_EXE = win_topmost_window::ORIGIN_PROCESS_EXE,
|
||||||
broker_exe = win_mag::INJECTED_PROCESS_EXE,
|
broker_exe = win_topmost_window::INJECTED_PROCESS_EXE,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1157,7 +1157,7 @@ fn get_before_uninstall(kill_self: bool) -> String {
|
|||||||
reg delete HKEY_CLASSES_ROOT\\{ext} /f
|
reg delete HKEY_CLASSES_ROOT\\{ext} /f
|
||||||
netsh advfirewall firewall delete rule name=\"{app_name} Service\"
|
netsh advfirewall firewall delete rule name=\"{app_name} Service\"
|
||||||
",
|
",
|
||||||
broker_exe = WIN_MAG_INJECTED_PROCESS_EXE,
|
broker_exe = WIN_TOPMOST_INJECTED_PROCESS_EXE,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2164,7 +2164,7 @@ pub fn uninstall_service(show_new_window: bool) -> bool {
|
|||||||
taskkill /F /IM {app_name}.exe{filter}
|
taskkill /F /IM {app_name}.exe{filter}
|
||||||
",
|
",
|
||||||
app_name = crate::get_app_name(),
|
app_name = crate::get_app_name(),
|
||||||
broker_exe = WIN_MAG_INJECTED_PROCESS_EXE,
|
broker_exe = WIN_TOPMOST_INJECTED_PROCESS_EXE,
|
||||||
);
|
);
|
||||||
if let Err(err) = run_cmds(cmds, false, "uninstall") {
|
if let Err(err) = run_cmds(cmds, false, "uninstall") {
|
||||||
Config::set_option("stop-service".into(), "".into());
|
Config::set_option("stop-service".into(), "".into());
|
||||||
@ -2279,7 +2279,10 @@ fn run_after_run_cmds(silent: bool) {
|
|||||||
pub fn try_kill_broker() {
|
pub fn try_kill_broker() {
|
||||||
allow_err!(std::process::Command::new("cmd")
|
allow_err!(std::process::Command::new("cmd")
|
||||||
.arg("/c")
|
.arg("/c")
|
||||||
.arg(&format!("taskkill /F /IM {}", WIN_MAG_INJECTED_PROCESS_EXE))
|
.arg(&format!(
|
||||||
|
"taskkill /F /IM {}",
|
||||||
|
WIN_TOPMOST_INJECTED_PROCESS_EXE
|
||||||
|
))
|
||||||
.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW)
|
.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW)
|
||||||
.spawn());
|
.spawn());
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,14 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub mod win_exclude_from_capture;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod win_input;
|
mod win_input;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub mod win_mag;
|
pub mod win_mag;
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub mod win_topmost_window;
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||||
mod win_virtual_display;
|
mod win_virtual_display;
|
||||||
@ -34,6 +37,9 @@ pub const NO_DISPLAYS: &'static str = "No displays";
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub const PRIVACY_MODE_IMPL_WIN_MAG: &str = win_mag::PRIVACY_MODE_IMPL;
|
pub const PRIVACY_MODE_IMPL_WIN_MAG: &str = win_mag::PRIVACY_MODE_IMPL;
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub const PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE: &str =
|
||||||
|
win_exclude_from_capture::PRIVACY_MODE_IMPL;
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||||
pub const PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY: &str = win_virtual_display::PRIVACY_MODE_IMPL;
|
pub const PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY: &str = win_virtual_display::PRIVACY_MODE_IMPL;
|
||||||
@ -84,22 +90,23 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref DEFAULT_PRIVACY_MODE_IMPL: String = {
|
pub static ref DEFAULT_PRIVACY_MODE_IMPL: String = {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
if display_service::is_privacy_mode_mag_supported() {
|
PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE.to_owned()
|
||||||
PRIVACY_MODE_IMPL_WIN_MAG
|
// if display_service::is_privacy_mode_mag_supported() {
|
||||||
} else {
|
// PRIVACY_MODE_IMPL_WIN_MAG
|
||||||
#[cfg(feature = "virtual_display_driver")]
|
// } else {
|
||||||
{
|
// #[cfg(feature = "virtual_display_driver")]
|
||||||
if is_installed() {
|
// {
|
||||||
PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY
|
// if is_installed() {
|
||||||
} else {
|
// PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY
|
||||||
""
|
// } else {
|
||||||
}
|
// ""
|
||||||
}
|
// }
|
||||||
#[cfg(not(feature = "virtual_display_driver"))]
|
// }
|
||||||
{
|
// #[cfg(not(feature = "virtual_display_driver"))]
|
||||||
""
|
// {
|
||||||
}
|
// ""
|
||||||
}.to_owned()
|
// }
|
||||||
|
// }.to_owned()
|
||||||
}
|
}
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
@ -137,6 +144,10 @@ lazy_static::lazy_static! {
|
|||||||
Box::new(win_mag::PrivacyModeImpl::default())
|
Box::new(win_mag::PrivacyModeImpl::default())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
map.insert(win_exclude_from_capture::PRIVACY_MODE_IMPL, || {
|
||||||
|
Box::new(win_exclude_from_capture::PrivacyModeImpl::default())
|
||||||
|
});
|
||||||
|
|
||||||
#[cfg(feature = "virtual_display_driver")]
|
#[cfg(feature = "virtual_display_driver")]
|
||||||
map.insert(win_virtual_display::PRIVACY_MODE_IMPL, || {
|
map.insert(win_virtual_display::PRIVACY_MODE_IMPL, || {
|
||||||
Box::new(win_virtual_display::PrivacyModeImpl::default())
|
Box::new(win_virtual_display::PrivacyModeImpl::default())
|
||||||
@ -272,6 +283,10 @@ pub fn get_supported_privacy_mode_impl() -> Vec<(&'static str, &'static str)> {
|
|||||||
if display_service::is_privacy_mode_mag_supported() {
|
if display_service::is_privacy_mode_mag_supported() {
|
||||||
vec_impls.push((PRIVACY_MODE_IMPL_WIN_MAG, "privacy_mode_impl_mag_tip"));
|
vec_impls.push((PRIVACY_MODE_IMPL_WIN_MAG, "privacy_mode_impl_mag_tip"));
|
||||||
}
|
}
|
||||||
|
vec_impls.push((
|
||||||
|
PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE,
|
||||||
|
"privacy_mode_impl_exclude_from_capture_tip",
|
||||||
|
));
|
||||||
#[cfg(feature = "virtual_display_driver")]
|
#[cfg(feature = "virtual_display_driver")]
|
||||||
if is_installed() {
|
if is_installed() {
|
||||||
vec_impls.push((
|
vec_impls.push((
|
||||||
|
3
src/privacy_mode/win_exclude_from_capture.rs
Normal file
3
src/privacy_mode/win_exclude_from_capture.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub use super::win_topmost_window::PrivacyModeImpl;
|
||||||
|
|
||||||
|
pub(super) const PRIVACY_MODE_IMPL: &str = "privacy_mode_impl_exclude_from_capture";
|
@ -1,370 +1,11 @@
|
|||||||
use super::{PrivacyMode, INVALID_PRIVACY_MODE_CONN_ID};
|
use super::win_topmost_window::PRIVACY_WINDOW_NAME;
|
||||||
use crate::{platform::windows::get_user_token, privacy_mode::PrivacyModeState};
|
use hbb_common::{bail, log, ResultType};
|
||||||
use hbb_common::{allow_err, bail, log, ResultType};
|
use std::time::Instant;
|
||||||
use std::{
|
|
||||||
ffi::CString,
|
pub use super::win_topmost_window::PrivacyModeImpl;
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
use winapi::{
|
|
||||||
shared::{
|
|
||||||
minwindef::FALSE,
|
|
||||||
ntdef::{HANDLE, NULL},
|
|
||||||
windef::HWND,
|
|
||||||
},
|
|
||||||
um::{
|
|
||||||
errhandlingapi::GetLastError,
|
|
||||||
handleapi::CloseHandle,
|
|
||||||
libloaderapi::{GetModuleHandleA, GetProcAddress},
|
|
||||||
memoryapi::{VirtualAllocEx, WriteProcessMemory},
|
|
||||||
processthreadsapi::{
|
|
||||||
CreateProcessAsUserW, QueueUserAPC, ResumeThread, TerminateProcess,
|
|
||||||
PROCESS_INFORMATION, STARTUPINFOW,
|
|
||||||
},
|
|
||||||
winbase::{WTSGetActiveConsoleSessionId, CREATE_SUSPENDED, DETACHED_PROCESS},
|
|
||||||
winnt::{MEM_COMMIT, PAGE_READWRITE},
|
|
||||||
winuser::*,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(super) const PRIVACY_MODE_IMPL: &str = "privacy_mode_impl_mag";
|
pub(super) const PRIVACY_MODE_IMPL: &str = "privacy_mode_impl_mag";
|
||||||
|
|
||||||
pub const ORIGIN_PROCESS_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
|
|
||||||
pub const WIN_MAG_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
|
|
||||||
pub const INJECTED_PROCESS_EXE: &'static str = WIN_MAG_INJECTED_PROCESS_EXE;
|
|
||||||
const PRIVACY_WINDOW_NAME: &'static str = "RustDeskPrivacyWindow";
|
|
||||||
|
|
||||||
struct WindowHandlers {
|
|
||||||
hthread: u64,
|
|
||||||
hprocess: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for WindowHandlers {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowHandlers {
|
|
||||||
fn reset(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
if self.hprocess != 0 {
|
|
||||||
let _res = TerminateProcess(self.hprocess as _, 0);
|
|
||||||
CloseHandle(self.hprocess as _);
|
|
||||||
}
|
|
||||||
self.hprocess = 0;
|
|
||||||
if self.hthread != 0 {
|
|
||||||
CloseHandle(self.hthread as _);
|
|
||||||
}
|
|
||||||
self.hthread = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_default(&self) -> bool {
|
|
||||||
self.hthread == 0 && self.hprocess == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PrivacyModeImpl {
|
|
||||||
conn_id: i32,
|
|
||||||
handlers: WindowHandlers,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PrivacyModeImpl {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
conn_id: INVALID_PRIVACY_MODE_CONN_ID,
|
|
||||||
handlers: WindowHandlers {
|
|
||||||
hthread: 0,
|
|
||||||
hprocess: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrivacyMode for PrivacyModeImpl {
|
|
||||||
fn init(&self) -> ResultType<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) {
|
|
||||||
allow_err!(self.turn_off_privacy(self.conn_id, None));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn turn_on_privacy(&mut self, conn_id: i32) -> ResultType<bool> {
|
|
||||||
if self.check_on_conn_id(conn_id)? {
|
|
||||||
log::debug!("Privacy mode of conn {} is already on", conn_id);
|
|
||||||
return Ok(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
let exe_file = std::env::current_exe()?;
|
|
||||||
if let Some(cur_dir) = exe_file.parent() {
|
|
||||||
if !cur_dir.join("WindowInjection.dll").exists() {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bail!(
|
|
||||||
"Invalid exe parent for {}",
|
|
||||||
exe_file.to_string_lossy().as_ref()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.handlers.is_default() {
|
|
||||||
log::info!("turn_on_privacy, dll not found when started, try start");
|
|
||||||
self.start()?;
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(1_000));
|
|
||||||
}
|
|
||||||
|
|
||||||
let hwnd = wait_find_privacy_hwnd(0)?;
|
|
||||||
if hwnd.is_null() {
|
|
||||||
bail!("No privacy window created");
|
|
||||||
}
|
|
||||||
super::win_input::hook()?;
|
|
||||||
unsafe {
|
|
||||||
ShowWindow(hwnd as _, SW_SHOW);
|
|
||||||
}
|
|
||||||
self.conn_id = conn_id;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn turn_off_privacy(
|
|
||||||
&mut self,
|
|
||||||
conn_id: i32,
|
|
||||||
state: Option<PrivacyModeState>,
|
|
||||||
) -> ResultType<()> {
|
|
||||||
self.check_off_conn_id(conn_id)?;
|
|
||||||
super::win_input::unhook()?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let hwnd = wait_find_privacy_hwnd(0)?;
|
|
||||||
if !hwnd.is_null() {
|
|
||||||
ShowWindow(hwnd, SW_HIDE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
|
|
||||||
if let Some(state) = state {
|
|
||||||
allow_err!(super::set_privacy_mode_state(
|
|
||||||
conn_id,
|
|
||||||
state,
|
|
||||||
PRIVACY_MODE_IMPL.to_string(),
|
|
||||||
1_000
|
|
||||||
));
|
|
||||||
}
|
|
||||||
self.conn_id = INVALID_PRIVACY_MODE_CONN_ID.to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn pre_conn_id(&self) -> i32 {
|
|
||||||
self.conn_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrivacyModeImpl {
|
|
||||||
pub fn start(&mut self) -> ResultType<()> {
|
|
||||||
if self.handlers.hprocess != 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("Start privacy mode window broker, check_update_broker_process");
|
|
||||||
if let Err(e) = crate::platform::windows::check_update_broker_process() {
|
|
||||||
log::warn!(
|
|
||||||
"Failed to check update broker process. Privacy mode may not work properly. {}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let exe_file = std::env::current_exe()?;
|
|
||||||
let Some(cur_dir) = exe_file.parent() else {
|
|
||||||
bail!("Cannot get parent of current exe file");
|
|
||||||
};
|
|
||||||
|
|
||||||
let dll_file = cur_dir.join("WindowInjection.dll");
|
|
||||||
if !dll_file.exists() {
|
|
||||||
bail!(
|
|
||||||
"Failed to find required file {}",
|
|
||||||
dll_file.to_string_lossy().as_ref()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let hwnd = wait_find_privacy_hwnd(1_000)?;
|
|
||||||
if !hwnd.is_null() {
|
|
||||||
log::info!("Privacy window is ready");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// let cmdline = cur_dir.join("MiniBroker.exe").to_string_lossy().to_string();
|
|
||||||
let cmdline = cur_dir
|
|
||||||
.join(INJECTED_PROCESS_EXE)
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let cmd_utf16: Vec<u16> = cmdline.encode_utf16().chain(Some(0).into_iter()).collect();
|
|
||||||
|
|
||||||
let mut start_info = STARTUPINFOW {
|
|
||||||
cb: 0,
|
|
||||||
lpReserved: NULL as _,
|
|
||||||
lpDesktop: NULL as _,
|
|
||||||
lpTitle: NULL as _,
|
|
||||||
dwX: 0,
|
|
||||||
dwY: 0,
|
|
||||||
dwXSize: 0,
|
|
||||||
dwYSize: 0,
|
|
||||||
dwXCountChars: 0,
|
|
||||||
dwYCountChars: 0,
|
|
||||||
dwFillAttribute: 0,
|
|
||||||
dwFlags: 0,
|
|
||||||
wShowWindow: 0,
|
|
||||||
cbReserved2: 0,
|
|
||||||
lpReserved2: NULL as _,
|
|
||||||
hStdInput: NULL as _,
|
|
||||||
hStdOutput: NULL as _,
|
|
||||||
hStdError: NULL as _,
|
|
||||||
};
|
|
||||||
let mut proc_info = PROCESS_INFORMATION {
|
|
||||||
hProcess: NULL as _,
|
|
||||||
hThread: NULL as _,
|
|
||||||
dwProcessId: 0,
|
|
||||||
dwThreadId: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let session_id = WTSGetActiveConsoleSessionId();
|
|
||||||
let token = get_user_token(session_id, true);
|
|
||||||
if token.is_null() {
|
|
||||||
bail!("Failed to get token of current user");
|
|
||||||
}
|
|
||||||
|
|
||||||
let create_res = CreateProcessAsUserW(
|
|
||||||
token,
|
|
||||||
NULL as _,
|
|
||||||
cmd_utf16.as_ptr() as _,
|
|
||||||
NULL as _,
|
|
||||||
NULL as _,
|
|
||||||
FALSE,
|
|
||||||
CREATE_SUSPENDED | DETACHED_PROCESS,
|
|
||||||
NULL,
|
|
||||||
NULL as _,
|
|
||||||
&mut start_info,
|
|
||||||
&mut proc_info,
|
|
||||||
);
|
|
||||||
CloseHandle(token);
|
|
||||||
if 0 == create_res {
|
|
||||||
bail!(
|
|
||||||
"Failed to create privacy window process {}, code {}",
|
|
||||||
cmdline,
|
|
||||||
GetLastError()
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
inject_dll(
|
|
||||||
proc_info.hProcess,
|
|
||||||
proc_info.hThread,
|
|
||||||
dll_file.to_string_lossy().as_ref(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if 0xffffffff == ResumeThread(proc_info.hThread) {
|
|
||||||
// CloseHandle
|
|
||||||
CloseHandle(proc_info.hThread);
|
|
||||||
CloseHandle(proc_info.hProcess);
|
|
||||||
|
|
||||||
bail!(
|
|
||||||
"Failed to create privacy window process, {}",
|
|
||||||
GetLastError()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.handlers.hthread = proc_info.hThread as _;
|
|
||||||
self.handlers.hprocess = proc_info.hProcess as _;
|
|
||||||
|
|
||||||
let hwnd = wait_find_privacy_hwnd(1_000)?;
|
|
||||||
if hwnd.is_null() {
|
|
||||||
bail!("Failed to get hwnd after started");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn stop(&mut self) {
|
|
||||||
self.handlers.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for PrivacyModeImpl {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
|
|
||||||
allow_err!(self.turn_off_privacy(self.conn_id, None));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn inject_dll<'a>(hproc: HANDLE, hthread: HANDLE, dll_file: &'a str) -> ResultType<()> {
|
|
||||||
let dll_file_utf16: Vec<u16> = dll_file.encode_utf16().chain(Some(0).into_iter()).collect();
|
|
||||||
|
|
||||||
let buf = VirtualAllocEx(
|
|
||||||
hproc,
|
|
||||||
NULL as _,
|
|
||||||
dll_file_utf16.len() * 2,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
);
|
|
||||||
if buf.is_null() {
|
|
||||||
bail!("Failed VirtualAllocEx");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut written: usize = 0;
|
|
||||||
if 0 == WriteProcessMemory(
|
|
||||||
hproc,
|
|
||||||
buf,
|
|
||||||
dll_file_utf16.as_ptr() as _,
|
|
||||||
dll_file_utf16.len() * 2,
|
|
||||||
&mut written,
|
|
||||||
) {
|
|
||||||
bail!("Failed WriteProcessMemory");
|
|
||||||
}
|
|
||||||
|
|
||||||
let kernel32_modulename = CString::new("kernel32")?;
|
|
||||||
let hmodule = GetModuleHandleA(kernel32_modulename.as_ptr() as _);
|
|
||||||
if hmodule.is_null() {
|
|
||||||
bail!("Failed GetModuleHandleA");
|
|
||||||
}
|
|
||||||
|
|
||||||
let load_librarya_name = CString::new("LoadLibraryW")?;
|
|
||||||
let load_librarya = GetProcAddress(hmodule, load_librarya_name.as_ptr() as _);
|
|
||||||
if load_librarya.is_null() {
|
|
||||||
bail!("Failed GetProcAddress of LoadLibraryW");
|
|
||||||
}
|
|
||||||
|
|
||||||
if 0 == QueueUserAPC(Some(std::mem::transmute(load_librarya)), hthread, buf as _) {
|
|
||||||
bail!("Failed QueueUserAPC");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wait_find_privacy_hwnd(msecs: u128) -> ResultType<HWND> {
|
|
||||||
let tm_begin = Instant::now();
|
|
||||||
let wndname = CString::new(PRIVACY_WINDOW_NAME)?;
|
|
||||||
loop {
|
|
||||||
unsafe {
|
|
||||||
let hwnd = FindWindowA(NULL as _, wndname.as_ptr() as _);
|
|
||||||
if !hwnd.is_null() {
|
|
||||||
return Ok(hwnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if msecs == 0 || tm_begin.elapsed().as_millis() > msecs {
|
|
||||||
return Ok(NULL as _);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_capturer(
|
pub fn create_capturer(
|
||||||
privacy_mode_id: i32,
|
privacy_mode_id: i32,
|
||||||
origin: (i32, i32),
|
origin: (i32, i32),
|
||||||
|
375
src/privacy_mode/win_topmost_window.rs
Normal file
375
src/privacy_mode/win_topmost_window.rs
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
use super::{PrivacyMode, INVALID_PRIVACY_MODE_CONN_ID};
|
||||||
|
use crate::{platform::windows::get_user_token, privacy_mode::PrivacyModeState};
|
||||||
|
use hbb_common::{allow_err, bail, log, ResultType};
|
||||||
|
use std::{
|
||||||
|
ffi::CString,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
use winapi::{
|
||||||
|
shared::{
|
||||||
|
minwindef::FALSE,
|
||||||
|
ntdef::{HANDLE, NULL},
|
||||||
|
windef::HWND,
|
||||||
|
},
|
||||||
|
um::{
|
||||||
|
errhandlingapi::GetLastError,
|
||||||
|
handleapi::CloseHandle,
|
||||||
|
libloaderapi::{GetModuleHandleA, GetProcAddress},
|
||||||
|
memoryapi::{VirtualAllocEx, WriteProcessMemory},
|
||||||
|
processthreadsapi::{
|
||||||
|
CreateProcessAsUserW, QueueUserAPC, ResumeThread, TerminateProcess,
|
||||||
|
PROCESS_INFORMATION, STARTUPINFOW,
|
||||||
|
},
|
||||||
|
winbase::{WTSGetActiveConsoleSessionId, CREATE_SUSPENDED, DETACHED_PROCESS},
|
||||||
|
winnt::{MEM_COMMIT, PAGE_READWRITE},
|
||||||
|
winuser::*,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(super) const PRIVACY_MODE_IMPL: &str = "privacy_mode_impl_mag";
|
||||||
|
|
||||||
|
pub const ORIGIN_PROCESS_EXE: &'static str = "C:\\Windows\\System32\\RuntimeBroker.exe";
|
||||||
|
pub const WIN_TOPMOST_INJECTED_PROCESS_EXE: &'static str = "RuntimeBroker_rustdesk.exe";
|
||||||
|
pub const INJECTED_PROCESS_EXE: &'static str = WIN_TOPMOST_INJECTED_PROCESS_EXE;
|
||||||
|
pub(super) const PRIVACY_WINDOW_NAME: &'static str = "RustDeskPrivacyWindow";
|
||||||
|
|
||||||
|
struct WindowHandlers {
|
||||||
|
hthread: u64,
|
||||||
|
hprocess: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for WindowHandlers {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowHandlers {
|
||||||
|
fn reset(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.hprocess != 0 {
|
||||||
|
let _res = TerminateProcess(self.hprocess as _, 0);
|
||||||
|
CloseHandle(self.hprocess as _);
|
||||||
|
}
|
||||||
|
self.hprocess = 0;
|
||||||
|
if self.hthread != 0 {
|
||||||
|
CloseHandle(self.hthread as _);
|
||||||
|
}
|
||||||
|
self.hthread = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_default(&self) -> bool {
|
||||||
|
self.hthread == 0 && self.hprocess == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrivacyModeImpl {
|
||||||
|
conn_id: i32,
|
||||||
|
handlers: WindowHandlers,
|
||||||
|
hwnd: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PrivacyModeImpl {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
conn_id: INVALID_PRIVACY_MODE_CONN_ID,
|
||||||
|
handlers: WindowHandlers {
|
||||||
|
hthread: 0,
|
||||||
|
hprocess: 0,
|
||||||
|
},
|
||||||
|
hwnd: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrivacyMode for PrivacyModeImpl {
|
||||||
|
fn init(&self) -> ResultType<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
allow_err!(self.turn_off_privacy(self.conn_id, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn turn_on_privacy(&mut self, conn_id: i32) -> ResultType<bool> {
|
||||||
|
if self.check_on_conn_id(conn_id)? {
|
||||||
|
log::debug!("Privacy mode of conn {} is already on", conn_id);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let exe_file = std::env::current_exe()?;
|
||||||
|
if let Some(cur_dir) = exe_file.parent() {
|
||||||
|
if !cur_dir.join("WindowInjection.dll").exists() {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bail!(
|
||||||
|
"Invalid exe parent for {}",
|
||||||
|
exe_file.to_string_lossy().as_ref()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.handlers.is_default() {
|
||||||
|
log::info!("turn_on_privacy, dll not found when started, try start");
|
||||||
|
self.start()?;
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(1_000));
|
||||||
|
}
|
||||||
|
|
||||||
|
let hwnd = wait_find_privacy_hwnd(0)?;
|
||||||
|
if hwnd.is_null() {
|
||||||
|
bail!("No privacy window created");
|
||||||
|
}
|
||||||
|
super::win_input::hook()?;
|
||||||
|
unsafe {
|
||||||
|
ShowWindow(hwnd as _, SW_SHOW);
|
||||||
|
}
|
||||||
|
self.conn_id = conn_id;
|
||||||
|
self.hwnd = hwnd as _;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn turn_off_privacy(
|
||||||
|
&mut self,
|
||||||
|
conn_id: i32,
|
||||||
|
state: Option<PrivacyModeState>,
|
||||||
|
) -> ResultType<()> {
|
||||||
|
self.check_off_conn_id(conn_id)?;
|
||||||
|
super::win_input::unhook()?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let hwnd = wait_find_privacy_hwnd(0)?;
|
||||||
|
if !hwnd.is_null() {
|
||||||
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
|
||||||
|
if let Some(state) = state {
|
||||||
|
allow_err!(super::set_privacy_mode_state(
|
||||||
|
conn_id,
|
||||||
|
state,
|
||||||
|
PRIVACY_MODE_IMPL.to_string(),
|
||||||
|
1_000
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.conn_id = INVALID_PRIVACY_MODE_CONN_ID.to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pre_conn_id(&self) -> i32 {
|
||||||
|
self.conn_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrivacyModeImpl {
|
||||||
|
#[inline]
|
||||||
|
pub fn get_hwnd(&self) -> u64 {
|
||||||
|
self.hwnd
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&mut self) -> ResultType<()> {
|
||||||
|
if self.handlers.hprocess != 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("Start privacy mode window broker, check_update_broker_process");
|
||||||
|
if let Err(e) = crate::platform::windows::check_update_broker_process() {
|
||||||
|
log::warn!(
|
||||||
|
"Failed to check update broker process. Privacy mode may not work properly. {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let exe_file = std::env::current_exe()?;
|
||||||
|
let Some(cur_dir) = exe_file.parent() else {
|
||||||
|
bail!("Cannot get parent of current exe file");
|
||||||
|
};
|
||||||
|
|
||||||
|
let dll_file = cur_dir.join("WindowInjection.dll");
|
||||||
|
if !dll_file.exists() {
|
||||||
|
bail!(
|
||||||
|
"Failed to find required file {}",
|
||||||
|
dll_file.to_string_lossy().as_ref()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let hwnd = wait_find_privacy_hwnd(1_000)?;
|
||||||
|
if !hwnd.is_null() {
|
||||||
|
log::info!("Privacy window is ready");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// let cmdline = cur_dir.join("MiniBroker.exe").to_string_lossy().to_string();
|
||||||
|
let cmdline = cur_dir
|
||||||
|
.join(INJECTED_PROCESS_EXE)
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let cmd_utf16: Vec<u16> = cmdline.encode_utf16().chain(Some(0).into_iter()).collect();
|
||||||
|
|
||||||
|
let mut start_info = STARTUPINFOW {
|
||||||
|
cb: 0,
|
||||||
|
lpReserved: NULL as _,
|
||||||
|
lpDesktop: NULL as _,
|
||||||
|
lpTitle: NULL as _,
|
||||||
|
dwX: 0,
|
||||||
|
dwY: 0,
|
||||||
|
dwXSize: 0,
|
||||||
|
dwYSize: 0,
|
||||||
|
dwXCountChars: 0,
|
||||||
|
dwYCountChars: 0,
|
||||||
|
dwFillAttribute: 0,
|
||||||
|
dwFlags: 0,
|
||||||
|
wShowWindow: 0,
|
||||||
|
cbReserved2: 0,
|
||||||
|
lpReserved2: NULL as _,
|
||||||
|
hStdInput: NULL as _,
|
||||||
|
hStdOutput: NULL as _,
|
||||||
|
hStdError: NULL as _,
|
||||||
|
};
|
||||||
|
let mut proc_info = PROCESS_INFORMATION {
|
||||||
|
hProcess: NULL as _,
|
||||||
|
hThread: NULL as _,
|
||||||
|
dwProcessId: 0,
|
||||||
|
dwThreadId: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let session_id = WTSGetActiveConsoleSessionId();
|
||||||
|
let token = get_user_token(session_id, true);
|
||||||
|
if token.is_null() {
|
||||||
|
bail!("Failed to get token of current user");
|
||||||
|
}
|
||||||
|
|
||||||
|
let create_res = CreateProcessAsUserW(
|
||||||
|
token,
|
||||||
|
NULL as _,
|
||||||
|
cmd_utf16.as_ptr() as _,
|
||||||
|
NULL as _,
|
||||||
|
NULL as _,
|
||||||
|
FALSE,
|
||||||
|
CREATE_SUSPENDED | DETACHED_PROCESS,
|
||||||
|
NULL,
|
||||||
|
NULL as _,
|
||||||
|
&mut start_info,
|
||||||
|
&mut proc_info,
|
||||||
|
);
|
||||||
|
CloseHandle(token);
|
||||||
|
if 0 == create_res {
|
||||||
|
bail!(
|
||||||
|
"Failed to create privacy window process {}, code {}",
|
||||||
|
cmdline,
|
||||||
|
GetLastError()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
inject_dll(
|
||||||
|
proc_info.hProcess,
|
||||||
|
proc_info.hThread,
|
||||||
|
dll_file.to_string_lossy().as_ref(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if 0xffffffff == ResumeThread(proc_info.hThread) {
|
||||||
|
// CloseHandle
|
||||||
|
CloseHandle(proc_info.hThread);
|
||||||
|
CloseHandle(proc_info.hProcess);
|
||||||
|
|
||||||
|
bail!(
|
||||||
|
"Failed to create privacy window process, {}",
|
||||||
|
GetLastError()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.handlers.hthread = proc_info.hThread as _;
|
||||||
|
self.handlers.hprocess = proc_info.hProcess as _;
|
||||||
|
|
||||||
|
let hwnd = wait_find_privacy_hwnd(1_000)?;
|
||||||
|
if hwnd.is_null() {
|
||||||
|
bail!("Failed to get hwnd after started");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
self.handlers.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PrivacyModeImpl {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.conn_id != INVALID_PRIVACY_MODE_CONN_ID {
|
||||||
|
allow_err!(self.turn_off_privacy(self.conn_id, None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn inject_dll<'a>(hproc: HANDLE, hthread: HANDLE, dll_file: &'a str) -> ResultType<()> {
|
||||||
|
let dll_file_utf16: Vec<u16> = dll_file.encode_utf16().chain(Some(0).into_iter()).collect();
|
||||||
|
|
||||||
|
let buf = VirtualAllocEx(
|
||||||
|
hproc,
|
||||||
|
NULL as _,
|
||||||
|
dll_file_utf16.len() * 2,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
);
|
||||||
|
if buf.is_null() {
|
||||||
|
bail!("Failed VirtualAllocEx");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut written: usize = 0;
|
||||||
|
if 0 == WriteProcessMemory(
|
||||||
|
hproc,
|
||||||
|
buf,
|
||||||
|
dll_file_utf16.as_ptr() as _,
|
||||||
|
dll_file_utf16.len() * 2,
|
||||||
|
&mut written,
|
||||||
|
) {
|
||||||
|
bail!("Failed WriteProcessMemory");
|
||||||
|
}
|
||||||
|
|
||||||
|
let kernel32_modulename = CString::new("kernel32")?;
|
||||||
|
let hmodule = GetModuleHandleA(kernel32_modulename.as_ptr() as _);
|
||||||
|
if hmodule.is_null() {
|
||||||
|
bail!("Failed GetModuleHandleA");
|
||||||
|
}
|
||||||
|
|
||||||
|
let load_librarya_name = CString::new("LoadLibraryW")?;
|
||||||
|
let load_librarya = GetProcAddress(hmodule, load_librarya_name.as_ptr() as _);
|
||||||
|
if load_librarya.is_null() {
|
||||||
|
bail!("Failed GetProcAddress of LoadLibraryW");
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 == QueueUserAPC(Some(std::mem::transmute(load_librarya)), hthread, buf as _) {
|
||||||
|
bail!("Failed QueueUserAPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn wait_find_privacy_hwnd(msecs: u128) -> ResultType<HWND> {
|
||||||
|
let tm_begin = Instant::now();
|
||||||
|
let wndname = CString::new(PRIVACY_WINDOW_NAME)?;
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
let hwnd = FindWindowA(NULL as _, wndname.as_ptr() as _);
|
||||||
|
if !hwnd.is_null() {
|
||||||
|
return Ok(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if msecs == 0 || tm_begin.elapsed().as_millis() > msecs {
|
||||||
|
return Ok(NULL as _);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user