diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 9faa06d3..c3a8baba 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -549,6 +549,10 @@ class OverlayDialogManager { hideMobileActionsOverlay(); } } + + bool existing(String tag) { + return _dialogs.keys.contains(tag); + } } void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) { @@ -983,7 +987,7 @@ Widget getPlatformImage(String platform, {double size = 50}) { platform != kPeerPlatformAndroid) { platform = 'win'; } else { - platform = platform.toLowerCase(); + platform = platform.toLowerCase(); } return SvgPicture.asset('assets/$platform.svg', height: size, width: size); } diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index 2df80d9f..3b5af1d8 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../../common.dart'; import '../../models/model.dart'; @@ -367,6 +368,247 @@ void showServerSettingsWithValue( }); } +void showWaitUacDialog(String id, OverlayDialogManager dialogManager) { + dialogManager.dismissAll(); + dialogManager.show( + tag: '$id-wait-uac', + (setState, close) => CustomAlertDialog( + title: Text(translate('Wait')), + content: Text(translate('wait_accept_uac_tip')).marginAll(10), + )); +} + +void _showRequestElevationDialog( + String id, OverlayDialogManager dialogManager) { + RxString groupValue = ''.obs; + RxString errUser = ''.obs; + RxString errPwd = ''.obs; + TextEditingController userController = TextEditingController(); + TextEditingController pwdController = TextEditingController(); + + void onRadioChanged(String? value) { + if (value != null) { + groupValue.value = value; + } + } + + const minTextStyle = TextStyle(fontSize: 14); + + var content = Obx(() => Column(children: [ + Row( + children: [ + Radio( + value: '', + groupValue: groupValue.value, + onChanged: onRadioChanged), + Expanded( + child: + Text(translate('Ask the remote user for authentication'))), + ], + ), + Align( + alignment: Alignment.centerLeft, + child: Text( + translate( + 'Choose this if the remote account is administrator'), + style: TextStyle(fontSize: 13)) + .marginOnly(left: 40), + ).marginOnly(bottom: 15), + Row( + children: [ + Radio( + value: 'logon', + groupValue: groupValue.value, + onChanged: onRadioChanged), + Expanded( + child: Text(translate( + 'Transmit the username and password of administrator')), + ) + ], + ), + Row( + children: [ + Expanded( + flex: 1, + child: Text( + '${translate('Username')}:', + style: minTextStyle, + ).marginOnly(right: 10)), + Expanded( + flex: 3, + child: TextField( + controller: userController, + style: minTextStyle, + decoration: InputDecoration( + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 15), + hintText: 'eg: admin', + errorText: errUser.isEmpty ? null : errUser.value), + onChanged: (s) { + if (s.isNotEmpty) { + errUser.value = ''; + } + }, + ), + ) + ], + ).marginOnly(left: 40), + Row( + children: [ + Expanded( + flex: 1, + child: Text( + '${translate('Password')}:', + style: minTextStyle, + ).marginOnly(right: 10)), + Expanded( + flex: 3, + child: TextField( + controller: pwdController, + obscureText: true, + style: minTextStyle, + decoration: InputDecoration( + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 15), + errorText: errPwd.isEmpty ? null : errPwd.value), + onChanged: (s) { + if (s.isNotEmpty) { + errPwd.value = ''; + } + }, + ), + ), + ], + ).marginOnly(left: 40), + Align( + alignment: Alignment.centerLeft, + child: Text(translate('still_click_uac_tip'), + style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold)) + .marginOnly(top: 20)), + ])); + + dialogManager.dismissAll(); + dialogManager.show(tag: '$id-request-elevation', (setState, close) { + void submit() { + if (groupValue.value == 'logon') { + if (userController.text.isEmpty) { + errUser.value = translate('Empty Username'); + return; + } + if (pwdController.text.isEmpty) { + errPwd.value = translate('Empty Password'); + return; + } + bind.sessionElevateWithLogon( + id: id, + username: userController.text, + password: pwdController.text); + } else { + bind.sessionElevateDirect(id: id); + } + } + + return CustomAlertDialog( + title: Text(translate('Request Elevation')), + content: content, + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom(elevation: 0), + onPressed: submit, + child: Text(translate('OK')), + ), + OutlinedButton( + onPressed: () { + close(); + }, + child: Text(translate('Cancel')), + ), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} + +void showOnBlockDialog( + String id, + String type, + String title, + String text, + OverlayDialogManager dialogManager, +) { + if (dialogManager.existing('$id-wait-uac') || + dialogManager.existing('$id-request-elevation')) { + return; + } + var content = Column(children: [ + Align( + alignment: Alignment.centerLeft, + child: Text( + "${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}", + textAlign: TextAlign.left, + style: TextStyle(fontWeight: FontWeight.w400), + ).marginSymmetric(vertical: 15), + ), + ]); + dialogManager.show(tag: '$id-$type', (setState, close) { + void submit() { + close(); + _showRequestElevationDialog(id, dialogManager); + } + + return CustomAlertDialog( + title: Text(translate(title)), + content: content, + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom(elevation: 0), + onPressed: submit, + child: Text(translate('Request Elevation')), + ), + OutlinedButton( + onPressed: () { + close(); + }, + child: Text(translate('Wait')), + ), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} + +void showElevationError(String id, String type, String title, String text, + OverlayDialogManager dialogManager) { + dialogManager.show(tag: '$id-$type', (setState, close) { + void submit() { + close(); + _showRequestElevationDialog(id, dialogManager); + } + + return CustomAlertDialog( + title: Text(translate(title)), + content: Text(translate(text)), + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom(elevation: 0), + onPressed: submit, + child: Text(translate('Retry')), + ), + OutlinedButton( + onPressed: () { + close(); + }, + child: Text(translate('Cancel')), + ), + ], + onSubmit: submit, + onCancel: close, + ); + }); +} + Future validateAsync(String value) async { value = value.trim(); if (value.isEmpty) { diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 3a383d9a..83678ccb 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -272,6 +272,12 @@ class FfiModel with ChangeNotifier { } else if (type == 'wait-remote-accept-nook') { msgBoxCommon(dialogManager, title, Text(translate(text)), [msgBoxButton("Cancel", closeConnection)]); + } else if (type == 'on-uac' || type == 'on-foreground-elevated') { + showOnBlockDialog(id, type, title, text, dialogManager); + } else if (type == 'wait-uac') { + showWaitUacDialog(id, dialogManager); + } else if (type == 'elevation-error') { + showElevationError(id, type, title, text, dialogManager); } else { var hasRetry = evt['hasRetry'] == 'true'; showMsgBox(id, type, title, text, link, hasRetry, dialogManager); diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto index e39bc7c6..f5910d96 100644 --- a/libs/hbb_common/protos/message.proto +++ b/libs/hbb_common/protos/message.proto @@ -552,6 +552,18 @@ message BackNotification { } } +message ElevationRequestWithLogon { + string username = 1; + string password = 2; +} + +message ElevationRequest { + oneof union { + bool direct = 1; + ElevationRequestWithLogon logon = 2; + } +} + message Misc { oneof union { ChatMessage chat_message = 4; @@ -567,6 +579,9 @@ message Misc { bool uac = 15; bool foreground_window_elevated = 16; bool stop_service = 17; + ElevationRequest elevation_request = 18; + string elevation_response = 19; + bool portable_service_running = 20; } } diff --git a/src/client.rs b/src/client.rs index 43ee5bf0..8b2edbcd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1890,6 +1890,8 @@ pub enum Data { AddJob((i32, String, String, i32, bool, bool)), ResumeJob((i32, bool)), RecordScreen(bool, i32, i32, String), + ElevateDirect, + ElevateWithLogon(String, String), } /// Keycode for key events. diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index 71d353c8..b1594904 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -632,6 +632,28 @@ impl Remote { .video_sender .send(MediaData::RecordScreen(start, w, h, id)); } + Data::ElevateDirect => { + let mut request = ElevationRequest::new(); + request.set_direct(true); + let mut misc = Misc::new(); + misc.set_elevation_request(request); + let mut msg = Message::new(); + msg.set_misc(misc); + allow_err!(peer.send(&msg).await); + } + Data::ElevateWithLogon(username, password) => { + let mut request = ElevationRequest::new(); + request.set_logon(ElevationRequestWithLogon { + username, + password, + ..Default::default() + }); + let mut misc = Misc::new(); + misc.set_elevation_request(request); + let mut msg = Message::new(); + msg.set_misc(misc); + allow_err!(peer.send(&msg).await); + } _ => {} } true @@ -989,8 +1011,13 @@ impl Remote { self.handler.ui_handler.switch_display(&s); self.video_sender.send(MediaData::Reset).ok(); if s.width > 0 && s.height > 0 { - self.handler - .set_display(s.x, s.y, s.width, s.height, s.cursor_embedded); + self.handler.set_display( + s.x, + s.y, + s.width, + s.height, + s.cursor_embedded, + ); } } Some(misc::Union::CloseReason(c)) => { @@ -1003,31 +1030,85 @@ impl Remote { } } Some(misc::Union::Uac(uac)) => { - let msgtype = "custom-uac-nocancel"; - let title = "Prompt"; - let text = "Please wait for confirmation of UAC..."; - let link = ""; - if uac { - self.handler.msgbox(msgtype, title, text, link); - } else { - self.handler - .cancel_msgbox( - &format!("{}-{}-{}-{}", msgtype, title, text, link,), + #[cfg(feature = "flutter")] + { + if uac { + self.handler.msgbox( + "on-uac", + "Prompt", + "Please wait for confirmation of UAC...", + "", ); + } else { + self.handler.cancel_msgbox("on-uac"); + self.handler.cancel_msgbox("wait-uac"); + self.handler.cancel_msgbox("elevation-error"); + } + } + #[cfg(not(feature = "flutter"))] + { + let msgtype = "custom-uac-nocancel"; + let title = "Prompt"; + let text = "Please wait for confirmation of UAC..."; + let link = ""; + if uac { + self.handler.msgbox(msgtype, title, text, link); + } else { + self.handler.cancel_msgbox(&format!( + "{}-{}-{}-{}", + msgtype, title, text, link, + )); + } } } Some(misc::Union::ForegroundWindowElevated(elevated)) => { - let msgtype = "custom-elevated-foreground-nocancel"; - let title = "Prompt"; - let text = "elevated_foreground_window_tip"; - let link = ""; - if elevated { - self.handler.msgbox(msgtype, title, text, link); + #[cfg(feature = "flutter")] + { + if elevated { + self.handler.msgbox( + "on-foreground-elevated", + "Prompt", + "elevated_foreground_window_tip", + "", + ); + } else { + self.handler.cancel_msgbox("on-foreground-elevated"); + self.handler.cancel_msgbox("wait-uac"); + self.handler.cancel_msgbox("elevation-error"); + } + } + #[cfg(not(feature = "flutter"))] + { + let msgtype = "custom-elevated-foreground-nocancel"; + let title = "Prompt"; + let text = "elevated_foreground_window_tip"; + let link = ""; + if elevated { + self.handler.msgbox(msgtype, title, text, link); + } else { + self.handler.cancel_msgbox(&format!( + "{}-{}-{}-{}", + msgtype, title, text, link, + )); + } + } + } + Some(misc::Union::ElevationResponse(err)) => { + if err.is_empty() { + self.handler.msgbox("wait-uac", "", "", ""); } else { self.handler - .cancel_msgbox( - &format!("{}-{}-{}-{}", msgtype, title, text, link,), - ); + .msgbox("elevation-error", "Elevation Error", &err, ""); + } + } + Some(misc::Union::PortableServiceRunning(b)) => { + if b { + self.handler.msgbox( + "custom-nocancel", + "Successful", + "Elevate successfully", + "", + ); } } _ => {} diff --git a/src/core_main.rs b/src/core_main.rs index 720c01da..9083efe0 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -106,7 +106,8 @@ pub fn core_main() -> Option> { && !_is_elevate && !_is_run_as_system { - if let Err(e) = crate::portable_service::client::start_portable_service() { + use crate::portable_service::client; + if let Err(e) = client::start_portable_service(client::StartPara::Direct) { log::error!("Failed to start portable service:{:?}", e); } } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 594fe776..a4b6d139 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -492,6 +492,18 @@ pub fn session_resume_job(id: String, act_id: i32, is_remote: bool) { } } +pub fn session_elevate_direct(id: String) { + if let Some(session) = SESSIONS.read().unwrap().get(&id) { + session.elevate_direct(); + } +} + +pub fn session_elevate_with_logon(id: String, username: String, password: String) { + if let Some(session) = SESSIONS.read().unwrap().get(&id) { + session.elevate_with_logon(username, password); + } +} + pub fn main_get_sound_inputs() -> Vec { #[cfg(not(any(target_os = "android", target_os = "ios")))] return get_sound_inputs(); diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 9224d231..d54b588c 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 4c460a3b..61da5d33 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装nouveau驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"), ("Always use software rendering", "使用软件渲染"), ("config_input", "为了能够通过键盘控制远程桌面, 请给予 RustDesk \"输入监控\" 权限。"), + ("request_elevation_tip", "如果对面有人, 也可以请求提升权限。"), + ("Wait","等待"), + ("Elevation Error", "提权失败"), + ("Ask the remote user for authentication", "请求远端用户授权"), + ("Choose this if the remote account is administrator", "当对面电脑是管理员账号时选择该选项"), + ("Transmit the username and password of administrator", "发送管理员账号的用户名密码"), + ("still_click_uac_tip", "依然需要被控端用戶在運行RustDesk的UAC窗口點擊確認。"), + ("Request Elevation", "请求提权"), + ("wait_accept_uac_tip", "请等待远端用户确认UAC对话框。"), + ("Elevate successfully", "提权成功"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 3622aef8..d43a534e 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index f07d9914..0f7823b7 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index a195fcdb..8060deb4 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "Wenn Sie eine Nvidia-Grafikkarte haben und sich das entfernte Fenster sofort nach dem Herstellen der Verbindung schließt, kann es helfen, den Nouveau-Treiber zu installieren und Software-Rendering zu verwenden. Ein Neustart der Software ist erforderlich."), ("Always use software rendering", "Software-Rendering immer verwenden"), ("config_input", "Um den entfernten Desktop mit der Tastatur steuern zu können, müssen Sie RustDesk \"Input Monitoring\"-Rechte erteilen."), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 14d221ef..6eed43a7 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -39,5 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."), ("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."), ("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."), + ("request_elevation_tip","You can also request elevation if there is someone on the remote side."), + ("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."), + ("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk.") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 2a41fdcf..8503d153 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index e0e41071..b695a680 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "Si tienes una gráfica Nvidia y la ventana remota se cierra inmediatamente, instalar el driver nouveau y elegir renderizado por software podría ayudar. Se requiere reiniciar la aplicación."), ("Always use software rendering", "Usar siempre renderizado por software"), ("config_input", "Para controlar el escritorio remoto con el teclado necesitas dar a RustDesk permisos de \"Monitorización de entrada\"."), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 790d0168..6bdd0506 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 7c4d55ea..bbc50e4a 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "Si vous avez une carte graphique NVIDIA et que la fenêtre distante se ferme immédiatement après la connexion, l'installation du pilote Nouveau et le choix d'utiliser le rendu du logiciel peuvent aider. Un redémarrage du logiciel est requis."), ("Always use software rendering", "Utiliser toujours le rendu logiciel"), ("config_input", "Afin de contrôler le bureau à distance avec le clavier, vous devez accorder à Rustdesk l'autorisation \"Surveillance de l’entrée\"."), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 53369a4b..7a0e0b35 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 32d92099..342a29bc 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index c33cccb6..671c2a8f 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 05ee237b..cd132dc4 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", "Usa sempre il render Software"), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 7dd1640f..4343d5ce 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 66ff3ca9..c9874b2d 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index ac688eb9..049d490a 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index afd6b4b0..5d0d575b 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index bf7954b4..0749678d 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 207be548..f6c43aab 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 43dd1cb0..77f64e75 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "Если у вас видеокарта Nvidia и удалённое окно закрывается сразу после подключения, может помочь установка драйвера Nouveau и выбор использования программной визуализации. Потребуется перезапуск."), ("Always use software rendering", "Использовать программную визуализацию"), ("config_input", "Чтобы управлять удалённым рабочим столом с помощью клавиатуры, необходимо предоставить RustDesk разрешения \"Мониторинг ввода\"."), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 40f19c62..954e3ae9 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 5e8efc17..3b4ee16d 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 0725d02e..804a8879 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 3b7201bb..9ecdd184 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index eeeec80c..ccf1eed8 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index d3be7ba1..f8a7a3bc 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index a4d0a033..5bd969bd 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 2d0fc8c5..ee661d9b 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index a58665a7..aebf8917 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"), ("Always use software rendering", "使用軟件渲染"), ("config_input", ""), + ("request_elevation_tip", "如果對面有人, 也可以請求提升權限。"), + ("Wait","等待"), + ("Elevation Error", "提權失敗"), + ("Ask the remote user for authentication", "請求遠端用戶授權"), + ("Choose this if the remote account is administrator", "當對面電腦是管理員賬號時選擇該選項"), + ("Transmit the username and password of administrator", "發送管理員賬號的用戶名密碼"), + ("still_click_uac_tip", "依然需要被控端用戶在UAC窗口點擊確認。"), + ("Request Elevation", "請求提權"), + ("wait_accept_uac_tip", "請等待遠端用戶確認UAC對話框。"), + ("Elevate successfully", "提權成功"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index fad7a388..784592ff 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 187572c8..ac62631c 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("software_render_tip", ""), ("Always use software rendering", ""), ("config_input", ""), + ("request_elevation_tip", ""), + ("Wait",""), + ("Elevation Error", ""), + ("Ask the remote user for authentication", ""), + ("Choose this if the remote account is administrator", ""), + ("Transmit the username and password of administrator", ""), + ("still_click_uac_tip", ""), + ("Request Elevation", ""), + ("wait_accept_uac_tip", ""), + ("Elevate successfully", ""), ].iter().cloned().collect(); } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index a2a99800..89861a41 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -24,7 +24,7 @@ use winapi::{ minwinbase::STILL_ACTIVE, processthreadsapi::{ GetCurrentProcess, GetCurrentProcessId, GetExitCodeProcess, OpenProcess, - OpenProcessToken, + OpenProcessToken, PROCESS_INFORMATION, STARTUPINFOW, }, securitybaseapi::GetTokenInformation, shellapi::ShellExecuteW, @@ -1714,3 +1714,42 @@ pub fn send_message_to_hnwd( } return true; } + +pub fn create_process_with_logon(user: &str, pwd: &str, exe: &str, arg: &str) -> ResultType<()> { + unsafe { + let wuser = wide_string(user); + let wpc = wide_string(""); + let wpwd = wide_string(pwd); + let cmd = if arg.is_empty() { + format!("\"{}\"", exe) + } else { + format!("\"{}\" {}", exe, arg) + }; + let mut wcmd = wide_string(&cmd); + let mut si: STARTUPINFOW = mem::zeroed(); + si.wShowWindow = SW_HIDE as _; + si.lpDesktop = NULL as _; + si.cb = std::mem::size_of::() as _; + si.dwFlags = STARTF_USESHOWWINDOW; + let mut pi: PROCESS_INFORMATION = mem::zeroed(); + let wexe = wide_string(exe); + if FALSE + == CreateProcessWithLogonW( + wuser.as_ptr(), + wpc.as_ptr(), + wpwd.as_ptr(), + LOGON_WITH_PROFILE, + wexe.as_ptr(), + wcmd.as_mut_ptr(), + CREATE_UNICODE_ENVIRONMENT, + NULL, + NULL as _, + &mut si as *mut STARTUPINFOW, + &mut pi as *mut PROCESS_INFORMATION, + ) + { + bail!("CreateProcessWithLogonW failed, errno={}", GetLastError()); + } + } + return Ok(()); +} diff --git a/src/server/connection.rs b/src/server/connection.rs index 93e90395..a7526c8b 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -101,6 +101,7 @@ pub struct Connection { last_recv_time: Arc>, chat_unanswered: bool, close_manually: bool, + elevation_requested: bool, } impl Subscriber for ConnInner { @@ -196,6 +197,7 @@ impl Connection { last_recv_time: Arc::new(Mutex::new(Instant::now())), chat_unanswered: false, close_manually: false, + elevation_requested: false, }; #[cfg(not(any(target_os = "android", target_os = "ios")))] tokio::spawn(async move { @@ -247,6 +249,8 @@ impl Connection { #[cfg(windows)] let mut last_foreground_window_elevated = false; #[cfg(windows)] + let mut last_portable_service_running = false; + #[cfg(windows)] let is_installed = crate::platform::is_installed(); loop { @@ -353,7 +357,8 @@ impl Connection { } #[cfg(windows)] ipc::Data::DataPortableService(ipc::DataPortableService::RequestStart) => { - if let Err(e) = crate::portable_service::client::start_portable_service() { + use crate::portable_service::client; + if let Err(e) = client::start_portable_service(client::StartPara::Direct) { log::error!("Failed to start portable service from cm:{:?}", e); } } @@ -440,8 +445,18 @@ impl Connection { _ = second_timer.tick() => { #[cfg(windows)] { - if !is_installed { - let portable_service_running = crate::portable_service::client::PORTABLE_SERVICE_RUNNING.lock().unwrap().clone(); + if !is_installed && conn.file_transfer.is_none() && conn.port_forward_socket.is_none(){ + let portable_service_running = crate::portable_service::client::running(); + if portable_service_running != last_portable_service_running { + last_portable_service_running = portable_service_running; + if portable_service_running && conn.elevation_requested { + let mut misc = Misc::new(); + misc.set_portable_service_running(portable_service_running); + let mut msg = Message::new(); + msg.set_misc(misc); + conn.inner.send(msg.into()); + } + } let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone(); if last_uac != uac { last_uac = uac; @@ -1476,6 +1491,51 @@ impl Connection { } } } + Some(misc::Union::ElevationRequest(r)) => match r.union { + Some(elevation_request::Union::Direct(_)) => { + #[cfg(windows)] + { + let mut err = "No need to elevate".to_string(); + if !crate::platform::is_installed() + && !crate::portable_service::client::running() + { + use crate::portable_service::client; + err = client::start_portable_service(client::StartPara::Direct) + .err() + .map_or("".to_string(), |e| e.to_string()); + } + self.elevation_requested = err.is_empty(); + let mut misc = Misc::new(); + misc.set_elevation_response(err); + let mut msg = Message::new(); + msg.set_misc(misc); + self.send(msg).await; + } + } + Some(elevation_request::Union::Logon(r)) => { + #[cfg(windows)] + { + let mut err = "No need to elevate".to_string(); + if !crate::platform::is_installed() + && !crate::portable_service::client::running() + { + use crate::portable_service::client; + err = client::start_portable_service(client::StartPara::Logon( + r.username, r.password, + )) + .err() + .map_or("".to_string(), |e| e.to_string()); + } + self.elevation_requested = err.is_empty(); + let mut misc = Misc::new(); + misc.set_elevation_response(err); + let mut msg = Message::new(); + msg.set_misc(misc); + self.send(msg).await; + } + } + _ => {} + }, _ => {} }, _ => {} diff --git a/src/server/portable_service.rs b/src/server/portable_service.rs index 6b87da21..0651fd4c 100644 --- a/src/server/portable_service.rs +++ b/src/server/portable_service.rs @@ -451,18 +451,24 @@ pub mod server { // functions called in main process. pub mod client { use hbb_common::anyhow::Context; + use std::path::PathBuf; use super::*; lazy_static::lazy_static! { - pub static ref PORTABLE_SERVICE_RUNNING: Arc> = Default::default(); + static ref RUNNING: Arc> = Default::default(); static ref SHMEM: Arc>> = Default::default(); static ref SENDER : Mutex> = Mutex::new(client::start_ipc_server()); } - pub(crate) fn start_portable_service() -> ResultType<()> { + pub enum StartPara { + Direct, + Logon(String, String), + } + + pub(crate) fn start_portable_service(para: StartPara) -> ResultType<()> { log::info!("start portable service"); - if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if RUNNING.lock().unwrap().clone() { bail!("already running"); } if SHMEM.lock().unwrap().is_none() { @@ -491,14 +497,60 @@ pub mod client { unsafe { libc::memset(shmem.as_ptr() as _, 0, shmem.len() as _); } - if crate::platform::run_background( - &std::env::current_exe()?.to_string_lossy().to_string(), - "--portable-service", - ) - .is_err() - { - *SHMEM.lock().unwrap() = None; - bail!("Failed to run portable service process"); + drop(option); + match para { + StartPara::Direct => { + if let Err(e) = crate::platform::run_background( + &std::env::current_exe()?.to_string_lossy().to_string(), + "--portable-service", + ) { + *SHMEM.lock().unwrap() = None; + bail!("Failed to run portable service process:{}", e); + } + } + StartPara::Logon(username, password) => { + #[allow(unused_mut)] + let mut exe = std::env::current_exe()?.to_string_lossy().to_string(); + #[cfg(feature = "flutter")] + { + if let Some(dir) = PathBuf::from(&exe).parent() { + if !set_dir_permission(&PathBuf::from(dir)) { + *SHMEM.lock().unwrap() = None; + bail!("Failed to set permission of {:?}", dir); + } + } + } + #[cfg(not(feature = "flutter"))] + match hbb_common::directories_next::UserDirs::new() { + Some(user_dir) => { + let dir = user_dir + .home_dir() + .join("AppData") + .join("Local") + .join("rustdesk-sciter"); + if std::fs::create_dir_all(&dir).is_ok() { + let dst = dir.join("rustdesk.exe"); + if std::fs::copy(&exe, &dst).is_ok() { + if dst.exists() { + if set_dir_permission(&dir) { + exe = dst.to_string_lossy().to_string(); + } + } + } + } + } + None => {} + } + if let Err(e) = crate::platform::windows::create_process_with_logon( + username.as_str(), + password.as_str(), + &exe, + "--portable-service", + ) { + *SHMEM.lock().unwrap() = None; + bail!("Failed to run portable service process:{}", e); + } + } } let _sender = SENDER.lock().unwrap(); Ok(()) @@ -509,6 +561,16 @@ pub mod client { *SHMEM.lock().unwrap() = None; } + fn set_dir_permission(dir: &PathBuf) -> bool { + // // give Everyone RX permission + std::process::Command::new("icacls") + .arg(dir.as_os_str()) + .arg("/grant") + .arg("Everyone:(OI)(CI)RX") + .arg("/T") + .spawn() + .is_ok() + } pub struct CapturerPortable; impl CapturerPortable { @@ -668,7 +730,7 @@ pub mod client { } Pong => { nack = 0; - *PORTABLE_SERVICE_RUNNING.lock().unwrap() = true; + *RUNNING.lock().unwrap() = true; }, ConnCount(None) => { if !quick_support { @@ -699,7 +761,7 @@ pub mod client { } } } - *PORTABLE_SERVICE_RUNNING.lock().unwrap() = false; + *RUNNING.lock().unwrap() = false; }); } Err(err) => { @@ -752,7 +814,7 @@ pub mod client { use_yuv: bool, portable_service_running: bool, ) -> ResultType> { - if portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if portable_service_running != RUNNING.lock().unwrap().clone() { log::info!("portable service status mismatch"); } if portable_service_running { @@ -767,7 +829,7 @@ pub mod client { } pub fn get_cursor_info(pci: PCURSORINFO) -> BOOL { - if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if RUNNING.lock().unwrap().clone() { get_cursor_info_(&mut SHMEM.lock().unwrap().as_mut().unwrap(), pci) } else { unsafe { winuser::GetCursorInfo(pci) } @@ -775,7 +837,7 @@ pub mod client { } pub fn handle_mouse(evt: &MouseEvent) { - if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if RUNNING.lock().unwrap().clone() { handle_mouse_(evt).ok(); } else { crate::input_service::handle_mouse_(evt); @@ -783,12 +845,16 @@ pub mod client { } pub fn handle_key(evt: &KeyEvent) { - if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if RUNNING.lock().unwrap().clone() { handle_key_(evt).ok(); } else { crate::input_service::handle_key_(evt); } } + + pub fn running() -> bool { + RUNNING.lock().unwrap().clone() + } } #[repr(C)] diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 618b003e..599dfbd5 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -20,14 +20,10 @@ use super::{video_qos::VideoQoS, *}; #[cfg(windows)] -use crate::portable_service::client::PORTABLE_SERVICE_RUNNING; -#[cfg(windows)] use hbb_common::get_version_number; -use hbb_common::{ - tokio::sync::{ - mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, - Mutex as TokioMutex, - }, +use hbb_common::tokio::sync::{ + mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, + Mutex as TokioMutex, }; #[cfg(not(windows))] use scrap::Capturer; @@ -419,7 +415,7 @@ fn run(sp: GenericService) -> ResultType<()> { #[cfg(target_os = "linux")] super::wayland::ensure_inited()?; #[cfg(windows)] - let last_portable_service_running = PORTABLE_SERVICE_RUNNING.lock().unwrap().clone(); + let last_portable_service_running = crate::portable_service::client::running(); #[cfg(not(windows))] let last_portable_service_running = false; @@ -518,14 +514,14 @@ fn run(sp: GenericService) -> ResultType<()> { bail!("SWITCH"); } #[cfg(windows)] - if last_portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() { + if last_portable_service_running != crate::portable_service::client::running() { bail!("SWITCH"); } check_privacy_mode_changed(&sp, c.privacy_mode_id)?; #[cfg(windows)] { if crate::platform::windows::desktop_changed() - && !PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() + && !crate::portable_service::client::running() { bail!("Desktop changed"); } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index a32662d0..551352ff 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -780,11 +780,7 @@ fn cm_inner_send(id: i32, data: Data) { pub fn can_elevate() -> bool { #[cfg(windows)] { - return !crate::platform::is_installed() - && !crate::portable_service::client::PORTABLE_SERVICE_RUNNING - .lock() - .unwrap() - .clone(); + return !crate::platform::is_installed() && !crate::portable_service::client::running(); } #[cfg(not(windows))] return false; diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 46bf39b7..00f1f90c 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -608,6 +608,14 @@ impl Session { } self.update_transfer_list(); } + + pub fn elevate_direct(&self) { + self.send(Data::ElevateDirect); + } + + pub fn elevate_with_logon(&self, username: String, password: String) { + self.send(Data::ElevateWithLogon(username, password)); + } } pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {