mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-18 13:37:52 +08:00
check super permission: win && linux
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
123a7aa17b
commit
4faf0a3d35
@ -52,6 +52,8 @@ class MyTheme {
|
|||||||
static const Color darkGray = Color(0xFFB9BABC);
|
static const Color darkGray = Color(0xFFB9BABC);
|
||||||
static const Color cmIdColor = Color(0xFF21790B);
|
static const Color cmIdColor = Color(0xFF21790B);
|
||||||
static const Color dark = Colors.black87;
|
static const Color dark = Colors.black87;
|
||||||
|
static const Color disabledTextLight = Color(0xFF888888);
|
||||||
|
static const Color disabledTextDark = Color(0xFF777777);
|
||||||
|
|
||||||
static ThemeData lightTheme = ThemeData(
|
static ThemeData lightTheme = ThemeData(
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
|
@ -253,28 +253,47 @@ class _Safety extends StatefulWidget {
|
|||||||
class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => true;
|
bool get wantKeepAlive => true;
|
||||||
|
bool locked = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return ListView(
|
return ListView(
|
||||||
children: [
|
children: [
|
||||||
permissions(),
|
Column(
|
||||||
password(),
|
children: [
|
||||||
whitelist(),
|
_lock(locked, 'Unlock Security Settings', () {
|
||||||
|
locked = false;
|
||||||
|
setState(() => {});
|
||||||
|
}),
|
||||||
|
AbsorbPointer(
|
||||||
|
absorbing: locked,
|
||||||
|
child: Column(children: [
|
||||||
|
permissions(),
|
||||||
|
password(),
|
||||||
|
whitelist(),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
],
|
],
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
).marginOnly(bottom: _kListViewBottomMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget permissions() {
|
Widget permissions() {
|
||||||
|
bool enabled = !locked;
|
||||||
return _Card(title: 'Permissions', children: [
|
return _Card(title: 'Permissions', children: [
|
||||||
_OptionCheckBox('Enable Keyboard/Mouse', 'enable-keyboard'),
|
_OptionCheckBox('Enable Keyboard/Mouse', 'enable-keyboard',
|
||||||
_OptionCheckBox('Enable Clipboard', 'enable-clipboard'),
|
enabled: enabled),
|
||||||
_OptionCheckBox('Enable File Transfer', 'enable-file-transfer'),
|
_OptionCheckBox('Enable Clipboard', 'enable-clipboard', enabled: enabled),
|
||||||
_OptionCheckBox('Enable Audio', 'enable-audio'),
|
_OptionCheckBox('Enable File Transfer', 'enable-file-transfer',
|
||||||
_OptionCheckBox('Enable Remote Restart', 'enable-remote-restart'),
|
enabled: enabled),
|
||||||
|
_OptionCheckBox('Enable Audio', 'enable-audio', enabled: enabled),
|
||||||
|
_OptionCheckBox('Enable Remote Restart', 'enable-remote-restart',
|
||||||
|
enabled: enabled),
|
||||||
_OptionCheckBox('Enable remote configuration modification',
|
_OptionCheckBox('Enable remote configuration modification',
|
||||||
'allow-remote-config-modification'),
|
'allow-remote-config-modification',
|
||||||
|
enabled: enabled),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,15 +316,17 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
String currentValue = values[keys.indexOf(model.verificationMethod)];
|
String currentValue = values[keys.indexOf(model.verificationMethod)];
|
||||||
List<Widget> radios = values
|
List<Widget> radios = values
|
||||||
.map((value) => _Radio<String>(
|
.map((value) => _Radio<String>(
|
||||||
value: value,
|
value: value,
|
||||||
groupValue: currentValue,
|
groupValue: currentValue,
|
||||||
label: value,
|
label: value,
|
||||||
onChanged: ((value) {
|
onChanged: ((value) {
|
||||||
model.verificationMethod = keys[values.indexOf(value)];
|
model.verificationMethod = keys[values.indexOf(value)];
|
||||||
})))
|
}),
|
||||||
|
enabled: !locked,
|
||||||
|
))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
var onChanged = tmp_enabled
|
var onChanged = tmp_enabled && !locked
|
||||||
? (value) {
|
? (value) {
|
||||||
if (value != null)
|
if (value != null)
|
||||||
model.temporaryPasswordLength = value.toString();
|
model.temporaryPasswordLength = value.toString();
|
||||||
@ -319,7 +340,11 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
value: value,
|
value: value,
|
||||||
groupValue: model.temporaryPasswordLength,
|
groupValue: model.temporaryPasswordLength,
|
||||||
onChanged: onChanged),
|
onChanged: onChanged),
|
||||||
Text(value),
|
Text(
|
||||||
|
value,
|
||||||
|
style: TextStyle(
|
||||||
|
color: _disabledTextColor(onChanged != null)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
).paddingSymmetric(horizontal: 10),
|
).paddingSymmetric(horizontal: 10),
|
||||||
onTap: () => onChanged?.call(value),
|
onTap: () => onChanged?.call(value),
|
||||||
@ -335,10 +360,10 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
...lengthRadios,
|
...lengthRadios,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
enabled: tmp_enabled),
|
enabled: tmp_enabled && !locked),
|
||||||
radios[1],
|
radios[1],
|
||||||
_SubButton(
|
_SubButton('Set permanent password', setPasswordDialog,
|
||||||
'Set permanent password', setPasswordDialog, perm_enabled),
|
perm_enabled && !locked),
|
||||||
radios[2],
|
radios[2],
|
||||||
]);
|
]);
|
||||||
})));
|
})));
|
||||||
@ -346,7 +371,8 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
|
|
||||||
Widget whitelist() {
|
Widget whitelist() {
|
||||||
return _Card(title: 'IP Whitelisting', children: [
|
return _Card(title: 'IP Whitelisting', children: [
|
||||||
_Button('IP Whitelisting', changeWhiteList, tip: 'whitelist_tip')
|
_Button('IP Whitelisting', changeWhiteList,
|
||||||
|
tip: 'whitelist_tip', enabled: !locked)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,31 +388,46 @@ class _ConnectionState extends State<_Connection>
|
|||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => true;
|
bool get wantKeepAlive => true;
|
||||||
|
bool locked = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
return ListView(
|
bool enabled = !locked;
|
||||||
children: [
|
return ListView(children: [
|
||||||
_Card(title: 'Server', children: [
|
Column(
|
||||||
_Button('ID/Relay Server', changeServer),
|
children: [
|
||||||
]),
|
_lock(locked, 'Unlock Connection Settings', () {
|
||||||
_Card(title: 'Service', children: [
|
locked = false;
|
||||||
_OptionCheckBox('Enable Service', 'stop-service', reverse: true),
|
setState(() => {});
|
||||||
// TODO: Not implemented
|
}),
|
||||||
// _option_check('Always connected via relay', 'allow-always-relay'),
|
AbsorbPointer(
|
||||||
// _option_check('Start ID/relay service', 'stop-rendezvous-service',
|
absorbing: locked,
|
||||||
// reverse: true),
|
child: Column(children: [
|
||||||
]),
|
_Card(title: 'Server', children: [
|
||||||
_Card(title: 'TCP Tunneling', children: [
|
_Button('ID/Relay Server', changeServer, enabled: enabled),
|
||||||
_OptionCheckBox('Enable TCP Tunneling', 'enable-tunnel'),
|
]),
|
||||||
]),
|
_Card(title: 'Service', children: [
|
||||||
direct_ip(),
|
_OptionCheckBox('Enable Service', 'stop-service',
|
||||||
_Card(title: 'Proxy', children: [
|
reverse: true, enabled: enabled),
|
||||||
_Button('Socks5 Proxy', changeSocks5Proxy),
|
// TODO: Not implemented
|
||||||
]),
|
// _option_check('Always connected via relay', 'allow-always-relay', enabled: enabled),
|
||||||
],
|
// _option_check('Start ID/relay service', 'stop-rendezvous-service',
|
||||||
).marginOnly(bottom: _kListViewBottomMargin);
|
// reverse: true, enabled: enabled),
|
||||||
|
]),
|
||||||
|
_Card(title: 'TCP Tunneling', children: [
|
||||||
|
_OptionCheckBox('Enable TCP Tunneling', 'enable-tunnel',
|
||||||
|
enabled: enabled),
|
||||||
|
]),
|
||||||
|
direct_ip(),
|
||||||
|
_Card(title: 'Proxy', children: [
|
||||||
|
_Button('Socks5 Proxy', changeSocks5Proxy, enabled: enabled),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]).marginOnly(bottom: _kListViewBottomMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget direct_ip() {
|
Widget direct_ip() {
|
||||||
@ -395,7 +436,7 @@ class _ConnectionState extends State<_Connection>
|
|||||||
RxBool apply_enabled = false.obs;
|
RxBool apply_enabled = false.obs;
|
||||||
return _Card(title: 'Direct IP Access', children: [
|
return _Card(title: 'Direct IP Access', children: [
|
||||||
_OptionCheckBox('Enable Direct IP Access', 'direct-server',
|
_OptionCheckBox('Enable Direct IP Access', 'direct-server',
|
||||||
update: update),
|
update: update, enabled: !locked),
|
||||||
_futureBuilder(
|
_futureBuilder(
|
||||||
future: () async {
|
future: () async {
|
||||||
String enabled = await bind.mainGetOption(key: 'direct-server');
|
String enabled = await bind.mainGetOption(key: 'direct-server');
|
||||||
@ -414,7 +455,7 @@ class _ConnectionState extends State<_Connection>
|
|||||||
width: 80,
|
width: 80,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
enabled: enabled,
|
enabled: enabled && !locked,
|
||||||
onChanged: (_) => apply_enabled.value = true,
|
onChanged: (_) => apply_enabled.value = true,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.allow(RegExp(
|
FilteringTextInputFormatter.allow(RegExp(
|
||||||
@ -429,10 +470,10 @@ class _ConnectionState extends State<_Connection>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabled: enabled,
|
enabled: enabled && !locked,
|
||||||
),
|
).marginOnly(left: 5),
|
||||||
Obx(() => ElevatedButton(
|
Obx(() => ElevatedButton(
|
||||||
onPressed: apply_enabled.value && enabled
|
onPressed: apply_enabled.value && enabled && !locked
|
||||||
? () async {
|
? () async {
|
||||||
apply_enabled.value = false;
|
apply_enabled.value = false;
|
||||||
await bind.mainSetOption(
|
await bind.mainSetOption(
|
||||||
@ -440,7 +481,9 @@ class _ConnectionState extends State<_Connection>
|
|||||||
value: controller.text);
|
value: controller.text);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(translate('Apply')),
|
child: Text(
|
||||||
|
translate('Apply'),
|
||||||
|
),
|
||||||
).marginOnly(left: 20))
|
).marginOnly(left: 20))
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@ -700,8 +743,16 @@ Widget _Card({required String title, required List<Widget> children}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color? _disabledTextColor(bool enabled) {
|
||||||
|
return enabled
|
||||||
|
? null
|
||||||
|
: isDarkTheme()
|
||||||
|
? MyTheme.disabledTextDark
|
||||||
|
: MyTheme.disabledTextLight;
|
||||||
|
}
|
||||||
|
|
||||||
Widget _OptionCheckBox(String label, String key,
|
Widget _OptionCheckBox(String label, String key,
|
||||||
{Function()? update = null, bool reverse = false}) {
|
{Function()? update = null, bool reverse = false, bool enabled = true}) {
|
||||||
return _futureBuilder(
|
return _futureBuilder(
|
||||||
future: bind.mainGetOption(key: key),
|
future: bind.mainGetOption(key: key),
|
||||||
hasData: (data) {
|
hasData: (data) {
|
||||||
@ -721,9 +772,14 @@ Widget _OptionCheckBox(String label, String key,
|
|||||||
child: Obx(
|
child: Obx(
|
||||||
() => Row(
|
() => Row(
|
||||||
children: [
|
children: [
|
||||||
Checkbox(value: ref.value, onChanged: onChanged)
|
Checkbox(
|
||||||
|
value: ref.value, onChanged: enabled ? onChanged : null)
|
||||||
.marginOnly(right: 10),
|
.marginOnly(right: 10),
|
||||||
Expanded(child: Text(translate(label)))
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
translate(label),
|
||||||
|
style: TextStyle(color: _disabledTextColor(enabled)),
|
||||||
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
).marginOnly(left: _kCheckBoxLeftMargin),
|
).marginOnly(left: _kCheckBoxLeftMargin),
|
||||||
@ -734,29 +790,33 @@ Widget _OptionCheckBox(String label, String key,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _Radio<T>({
|
Widget _Radio<T>(
|
||||||
required T value,
|
{required T value,
|
||||||
required T groupValue,
|
required T groupValue,
|
||||||
required String label,
|
required String label,
|
||||||
required Function(T value) onChanged,
|
required Function(T value) onChanged,
|
||||||
}) {
|
bool enabled = true}) {
|
||||||
var on_change = (T? value) {
|
var on_change = enabled
|
||||||
if (value != null) {
|
? (T? value) {
|
||||||
onChanged(value);
|
if (value != null) {
|
||||||
}
|
onChanged(value);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
: null;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Radio<T>(value: value, groupValue: groupValue, onChanged: on_change),
|
Radio<T>(value: value, groupValue: groupValue, onChanged: on_change),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(translate(label),
|
child: Text(translate(label),
|
||||||
style: TextStyle(fontSize: _kContentFontSize))
|
style: TextStyle(
|
||||||
|
fontSize: _kContentFontSize,
|
||||||
|
color: _disabledTextColor(enabled)))
|
||||||
.marginOnly(left: 5),
|
.marginOnly(left: 5),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).marginOnly(left: _kRadioLeftMargin),
|
).marginOnly(left: _kRadioLeftMargin),
|
||||||
onTap: () => on_change(value),
|
onTap: () => on_change?.call(value),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,19 +868,19 @@ Widget _SubLabeledWidget(String label, Widget child, {bool enabled = true}) {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: hover.value && enabled
|
color: hover.value && enabled
|
||||||
? Colors.grey.withOpacity(0.8)
|
? Color(0xFFD7D7D7)
|
||||||
: Colors.grey.withOpacity(0.5),
|
: Color(0xFFCBCBCB),
|
||||||
width: hover.value && enabled ? 2 : 1)),
|
width: hover.value && enabled ? 2 : 1)),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
height: 28,
|
height: 28,
|
||||||
color: (hover.value && enabled)
|
color: (hover.value && enabled)
|
||||||
? Colors.grey.withOpacity(0.8)
|
? Color(0xFFD7D7D7)
|
||||||
: Colors.grey.withOpacity(0.5),
|
: Color(0xFFCBCBCB),
|
||||||
child: Text(
|
child: Text(
|
||||||
label + ': ',
|
label + ': ',
|
||||||
style: TextStyle(),
|
style: TextStyle(fontWeight: FontWeight.w300),
|
||||||
),
|
),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding:
|
padding:
|
||||||
@ -851,6 +911,43 @@ Widget _futureBuilder(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _lock(
|
||||||
|
bool locked,
|
||||||
|
String label,
|
||||||
|
Function() onUnlock,
|
||||||
|
) {
|
||||||
|
return Offstage(
|
||||||
|
offstage: !locked,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: _kCardFixedWidth,
|
||||||
|
child: Card(
|
||||||
|
child: ElevatedButton(
|
||||||
|
child: Container(
|
||||||
|
height: 25,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.security_sharp,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
Text(translate(label)).marginOnly(left: 5),
|
||||||
|
]).marginSymmetric(vertical: 2)),
|
||||||
|
onPressed: () async {
|
||||||
|
bool checked = await bind.mainCheckSuperUserPermission();
|
||||||
|
if (checked) {
|
||||||
|
onUnlock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).marginSymmetric(horizontal: 2, vertical: 4),
|
||||||
|
).marginOnly(left: _kCardLeftMargin),
|
||||||
|
).marginOnly(top: 10),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class _ComboBox extends StatelessWidget {
|
class _ComboBox extends StatelessWidget {
|
||||||
late final List<String> keys;
|
late final List<String> keys;
|
||||||
|
@ -70,7 +70,6 @@ class DesktopTabBar extends StatelessWidget {
|
|||||||
super(key: key) {
|
super(key: key) {
|
||||||
scrollController.itemCount = tabs.length;
|
scrollController.itemCount = tabs.length;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
debugPrint("callback");
|
|
||||||
scrollController.scrollToItem(selected.value,
|
scrollController.scrollToItem(selected.value,
|
||||||
center: true, animate: true);
|
center: true, animate: true);
|
||||||
});
|
});
|
||||||
|
@ -22,12 +22,12 @@ use crate::ui_interface;
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
use crate::ui_interface::{change_id, check_connect_status, is_ok_change_id};
|
use crate::ui_interface::{change_id, check_connect_status, is_ok_change_id};
|
||||||
use crate::ui_interface::{
|
use crate::ui_interface::{
|
||||||
discover, forget_password, get_api_server, get_app_name, get_async_job_status,
|
check_super_user_permission, discover, forget_password, get_api_server, get_app_name,
|
||||||
get_connect_status, get_fav, get_id, get_lan_peers, get_langs, get_license, get_local_option,
|
get_async_job_status, get_connect_status, get_fav, get_id, get_lan_peers, get_langs,
|
||||||
get_option, get_options, get_peer, get_peer_option, get_socks, get_sound_inputs, get_uuid,
|
get_license, get_local_option, get_option, get_options, get_peer, get_peer_option, get_socks,
|
||||||
get_version, has_hwcodec, has_rendezvous_service, post_request, set_local_option, set_option,
|
get_sound_inputs, get_uuid, get_version, has_hwcodec, has_rendezvous_service, post_request,
|
||||||
set_options, set_peer_option, set_permanent_password, set_socks, store_fav,
|
set_local_option, set_option, set_options, set_peer_option, set_permanent_password, set_socks,
|
||||||
test_if_valid_server, update_temporary_password, using_public_server,
|
store_fav, test_if_valid_server, update_temporary_password, using_public_server,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn initialize(app_dir: &str) {
|
fn initialize(app_dir: &str) {
|
||||||
@ -735,6 +735,10 @@ pub fn main_set_permanent_password(password: String) {
|
|||||||
set_permanent_password(password);
|
set_permanent_password(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main_check_super_user_permission() -> bool {
|
||||||
|
check_super_user_permission()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cm_send_chat(conn_id: i32, msg: String) {
|
pub fn cm_send_chat(conn_id: i32, msg: String) {
|
||||||
connection_manager::send_chat(conn_id, msg);
|
connection_manager::send_chat(conn_id, msg);
|
||||||
}
|
}
|
||||||
|
@ -629,3 +629,9 @@ extern "C" {
|
|||||||
pub fn quit_gui() {
|
pub fn quit_gui() {
|
||||||
unsafe { gtk_main_quit() };
|
unsafe { gtk_main_quit() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_super_user_permission() -> ResultType<bool> {
|
||||||
|
// TODO: replace echo with a rustdesk's program, which is location-fixed and non-gui.
|
||||||
|
let status = std::process::Command::new("pkexec").arg("echo").status()?;
|
||||||
|
Ok(status.success() && status.code() == Some(0))
|
||||||
|
}
|
||||||
|
@ -8,7 +8,7 @@ use hbb_common::{
|
|||||||
};
|
};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsString,
|
ffi::{CString, OsString},
|
||||||
fs, io, mem,
|
fs, io, mem,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
@ -17,7 +17,8 @@ use winapi::{
|
|||||||
shared::{minwindef::*, ntdef::NULL, windef::*},
|
shared::{minwindef::*, ntdef::NULL, windef::*},
|
||||||
um::{
|
um::{
|
||||||
errhandlingapi::GetLastError, handleapi::CloseHandle, minwinbase::STILL_ACTIVE,
|
errhandlingapi::GetLastError, handleapi::CloseHandle, minwinbase::STILL_ACTIVE,
|
||||||
processthreadsapi::GetExitCodeProcess, winbase::*, wingdi::*, winnt::HANDLE, winuser::*,
|
processthreadsapi::GetExitCodeProcess, shellapi::ShellExecuteA, winbase::*, wingdi::*,
|
||||||
|
winnt::HANDLE, winuser::*,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use windows_service::{
|
use windows_service::{
|
||||||
@ -1418,3 +1419,17 @@ pub fn get_user_token(session_id: u32, as_user: bool) -> HANDLE {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_super_user_permission() -> ResultType<bool> {
|
||||||
|
unsafe {
|
||||||
|
let ret = ShellExecuteA(
|
||||||
|
NULL as _,
|
||||||
|
CString::new("runas")?.as_ptr() as _,
|
||||||
|
CString::new("cmd")?.as_ptr() as _,
|
||||||
|
CString::new("/c /q")?.as_ptr() as _,
|
||||||
|
NULL as _,
|
||||||
|
SW_SHOWNORMAL,
|
||||||
|
);
|
||||||
|
return Ok(ret as i32 > 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -676,6 +676,13 @@ pub fn has_hwcodec() -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_super_user_permission() -> bool {
|
||||||
|
#[cfg(any(windows, target_os = "linux"))]
|
||||||
|
return crate::platform::check_super_user_permission().unwrap_or(false);
|
||||||
|
#[cfg(not(any(windows, target_os = "linux")))]
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_zombie(childs: Childs) {
|
pub fn check_zombie(childs: Childs) {
|
||||||
let mut deads = Vec::new();
|
let mut deads = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
Loading…
Reference in New Issue
Block a user