mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-27 23:09:12 +08:00
Merge branch 'master' into keyboard
This commit is contained in:
commit
47658667d6
4
.github/workflows/flutter-nightly.yml
vendored
4
.github/workflows/flutter-nightly.yml
vendored
@ -47,8 +47,8 @@ jobs:
|
||||
run: |
|
||||
flutter doctor -v
|
||||
flutter precache --windows
|
||||
Invoke-WebRequest -Uri https://github.com/Kingtous/engine/releases/download/v3.0.5-rustdesk/windows-x64-release-flutter.zip -OutFile windows-x64-release-flutter.zip
|
||||
Expand-Archive windows-x64-release-flutter.zip -DestinationPath engine
|
||||
Invoke-WebRequest -Uri https://github.com/Kingtous/engine/releases/download/v3.0.5-rustdesk.2/windows-x64-flutter-release.zip -OutFile windows-x64-flutter-release.zip
|
||||
Expand-Archive windows-x64-flutter-release.zip -DestinationPath engine
|
||||
mv -Force engine/* C:/hostedtoolcache/windows/flutter/stable-3.0.5-x64/bin/cache/artifacts/engine/windows-x64-release/
|
||||
|
||||
- name: Install Rust toolchain
|
||||
|
408
Cargo.lock
generated
408
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -47,7 +47,7 @@ libc = "0.2"
|
||||
parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" }
|
||||
flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] }
|
||||
runas = "0.2"
|
||||
magnum-opus = { git = "https://github.com/SoLongAndThanksForAllThePizza/magnum-opus" }
|
||||
magnum-opus = { git = "https://github.com/rustdesk/magnum-opus" }
|
||||
dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true }
|
||||
rubato = { version = "0.12", optional = true }
|
||||
samplerate = { version = "0.2", optional = true }
|
||||
@ -118,6 +118,7 @@ dbus = "0.9"
|
||||
dbus-crossroads = "0.5"
|
||||
gtk = "0.15"
|
||||
libappindicator = "0.7"
|
||||
glib = "0.16.5"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android_logger = "0.11"
|
||||
|
@ -5,6 +5,8 @@ import 'dart:ui' as ui;
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_custom_cursor/cursor_manager.dart'
|
||||
as custom_cursor_manager;
|
||||
import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
@ -109,17 +111,17 @@ class _RemotePageState extends State<RemotePage>
|
||||
id: widget.id, arg: 'show-remote-cursor');
|
||||
_zoomCursor.value =
|
||||
bind.sessionGetToggleOptionSync(id: widget.id, arg: 'zoom-cursor');
|
||||
if (!_isCustomCursorInited) {
|
||||
customCursorController.registerNeedUpdateCursorCallback(
|
||||
(String? lastKey, String? currentKey) async {
|
||||
if (_firstEnterImage.value) {
|
||||
_firstEnterImage.value = false;
|
||||
return true;
|
||||
}
|
||||
return lastKey == null || lastKey != currentKey;
|
||||
});
|
||||
_isCustomCursorInited = true;
|
||||
}
|
||||
// if (!_isCustomCursorInited) {
|
||||
// customCursorController.registerNeedUpdateCursorCallback(
|
||||
// (String? lastKey, String? currentKey) async {
|
||||
// if (_firstEnterImage.value) {
|
||||
// _firstEnterImage.value = false;
|
||||
// return true;
|
||||
// }
|
||||
// return lastKey == null || lastKey != currentKey;
|
||||
// });
|
||||
// _isCustomCursorInited = true;
|
||||
// }
|
||||
}
|
||||
|
||||
@override
|
||||
@ -366,15 +368,23 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||
return MouseCursor.defer;
|
||||
} else {
|
||||
final key = cache.updateGetKey(scale, zoomCursor.value);
|
||||
cursor.addKey(key);
|
||||
return FlutterCustomMemoryImageCursor(
|
||||
pixbuf: cache.data,
|
||||
key: key,
|
||||
hotx: cache.hotx,
|
||||
hoty: cache.hoty,
|
||||
imageWidth: (cache.width * cache.scale).toInt(),
|
||||
imageHeight: (cache.height * cache.scale).toInt(),
|
||||
);
|
||||
if (!cursor.cachedKeys.contains(key)) {
|
||||
debugPrint("Register custom cursor with key $key");
|
||||
// [Safety]
|
||||
// It's ok to call async registerCursor in current synchronous context,
|
||||
// because activating the cursor is also an async call and will always
|
||||
// be executed after this.
|
||||
custom_cursor_manager.CursorManager.instance
|
||||
.registerCursor(custom_cursor_manager.CursorData()
|
||||
..buffer = cache.data!
|
||||
..height = (cache.height * cache.scale).toInt()
|
||||
..width = (cache.width * cache.scale).toInt()
|
||||
..hotX = cache.hotx
|
||||
..hotY = cache.hoty
|
||||
..name = key);
|
||||
cursor.addKey(key);
|
||||
}
|
||||
return FlutterCustomMemoryImageCursor(key: key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import 'package:flutter_hbb/common/shared_state.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:image/image.dart' as img2;
|
||||
import 'package:flutter_custom_cursor/flutter_custom_cursor.dart';
|
||||
import 'package:flutter_custom_cursor/cursor_manager.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
import '../common.dart';
|
||||
@ -1113,7 +1113,8 @@ class CursorModel with ChangeNotifier {
|
||||
_clearCache() {
|
||||
final keys = {...cachedKeys};
|
||||
for (var k in keys) {
|
||||
customCursorController.freeCache(k);
|
||||
debugPrint("deleting cursor with key $k");
|
||||
CursorManager.instance.deleteCursor(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ packages:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "49.0.0"
|
||||
version: "50.0.0"
|
||||
after_layout:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -21,7 +21,7 @@ packages:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
version: "5.2.0"
|
||||
animations:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -352,7 +352,7 @@ packages:
|
||||
name: file_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
version: "5.2.3"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -389,12 +389,10 @@ packages:
|
||||
flutter_custom_cursor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "74b1b314142b6775c1243067a3503ac568ebc74b"
|
||||
resolved-ref: "74b1b314142b6775c1243067a3503ac568ebc74b"
|
||||
url: "https://github.com/Kingtous/rustdesk_flutter_custom_cursor"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
name: flutter_custom_cursor
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.2"
|
||||
flutter_improved_scrolling:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -455,14 +453,14 @@ packages:
|
||||
name: freezed
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.3.2"
|
||||
freezed_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: freezed_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.2.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -637,7 +635,7 @@ packages:
|
||||
name: mime
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
version: "1.0.3"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1106,7 +1104,7 @@ packages:
|
||||
name: video_player
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.7"
|
||||
version: "2.4.9"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -65,10 +65,7 @@ dependencies:
|
||||
url: https://github.com/Kingtous/rustdesk_desktop_multi_window
|
||||
ref: 82f9eab81cb2c7bfb938def7a1b399a6279bbc75
|
||||
freezed_annotation: ^2.0.3
|
||||
flutter_custom_cursor:
|
||||
git:
|
||||
url: https://github.com/Kingtous/rustdesk_flutter_custom_cursor
|
||||
ref: 74b1b314142b6775c1243067a3503ac568ebc74b
|
||||
flutter_custom_cursor: ^0.0.2
|
||||
window_size:
|
||||
git:
|
||||
url: https://github.com/google/flutter-desktop-embedding.git
|
||||
|
@ -66,6 +66,21 @@ macro_rules! allow_err {
|
||||
} else {
|
||||
}
|
||||
};
|
||||
|
||||
($e:expr, $($arg:tt)*) => {
|
||||
if let Err(err) = $e {
|
||||
log::debug!(
|
||||
"{:?}, {}, {}:{}:{}:{}",
|
||||
err,
|
||||
format_args!($($arg)*),
|
||||
module_path!(),
|
||||
file!(),
|
||||
line!(),
|
||||
column!()
|
||||
);
|
||||
} else {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -250,4 +265,10 @@ mod tests {
|
||||
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116));
|
||||
assert_eq!(addr, AddrMangle::decode(&AddrMangle::encode(addr)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_allow_err() {
|
||||
allow_err!(Err("test err") as Result<(), &str>);
|
||||
allow_err!(Err("test err with msg") as Result<(), &str>, "prompt {}", "failed");
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ impl Encoder {
|
||||
#[inline]
|
||||
pub fn current_hw_encoder_name() -> Option<String> {
|
||||
#[cfg(feature = "hwcodec")]
|
||||
if check_hwcodec_config() {
|
||||
if enable_hwcodec_option() {
|
||||
return HwEncoder::current_name().lock().unwrap().clone();
|
||||
} else {
|
||||
return None;
|
||||
@ -229,7 +229,7 @@ impl Encoder {
|
||||
|
||||
pub fn supported_encoding() -> (bool, bool) {
|
||||
#[cfg(feature = "hwcodec")]
|
||||
if check_hwcodec_config() {
|
||||
if enable_hwcodec_option() {
|
||||
let best = HwEncoder::best();
|
||||
(
|
||||
best.h264.as_ref().map_or(false, |c| c.score > 0),
|
||||
@ -246,7 +246,7 @@ impl Encoder {
|
||||
impl Decoder {
|
||||
pub fn video_codec_state(_id: &str) -> VideoCodecState {
|
||||
#[cfg(feature = "hwcodec")]
|
||||
if check_hwcodec_config() {
|
||||
if enable_hwcodec_option() {
|
||||
let best = HwDecoder::best();
|
||||
return VideoCodecState {
|
||||
score_vpx: SCORE_VPX,
|
||||
@ -257,7 +257,7 @@ impl Decoder {
|
||||
};
|
||||
}
|
||||
#[cfg(feature = "mediacodec")]
|
||||
if check_hwcodec_config() {
|
||||
if enable_hwcodec_option() {
|
||||
let score_h264 = if H264_DECODER_SUPPORT.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
92
|
||||
} else {
|
||||
@ -287,11 +287,19 @@ impl Decoder {
|
||||
Decoder {
|
||||
vpx,
|
||||
#[cfg(feature = "hwcodec")]
|
||||
hw: HwDecoder::new_decoders(),
|
||||
hw: if enable_hwcodec_option() {
|
||||
HwDecoder::new_decoders()
|
||||
} else {
|
||||
HwDecoders::default()
|
||||
},
|
||||
#[cfg(feature = "hwcodec")]
|
||||
i420: vec![],
|
||||
#[cfg(feature = "mediacodec")]
|
||||
media_codec: MediaCodecDecoder::new_decoders(),
|
||||
media_codec: if enable_hwcodec_option() {
|
||||
MediaCodecDecoder::new_decoders()
|
||||
} else {
|
||||
MediaCodecDecoders::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +423,7 @@ impl Decoder {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
|
||||
fn check_hwcodec_config() -> bool {
|
||||
fn enable_hwcodec_option() -> bool {
|
||||
if let Some(v) = Config2::get().options.get("enable-hwcodec") {
|
||||
return v != "N";
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ impl EncoderApi for HwEncoder {
|
||||
frames.push(EncodedVideoFrame {
|
||||
data: Bytes::from(frame.data),
|
||||
pts: frame.pts as _,
|
||||
key:frame.key == 1,
|
||||
key: frame.key == 1,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
@ -175,6 +175,7 @@ pub struct HwDecoder {
|
||||
pub info: CodecInfo,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HwDecoders {
|
||||
pub h264: Option<HwDecoder>,
|
||||
pub h265: Option<HwDecoder>,
|
||||
|
@ -37,6 +37,7 @@ impl Deref for MediaCodecDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MediaCodecDecoders {
|
||||
pub h264: Option<MediaCodecDecoder>,
|
||||
pub h265: Option<MediaCodecDecoder>,
|
||||
|
@ -173,7 +173,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
crate::start_os_service();
|
||||
return None;
|
||||
} else if args[0] == "--server" {
|
||||
log::info!("start --server");
|
||||
log::info!("start --server with user {}", crate::username());
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
crate::start_server(true);
|
||||
|
@ -56,7 +56,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Too frequent", "Zu häufig"),
|
||||
("Cancel", "Abbrechen"),
|
||||
("Skip", "Überspringen"),
|
||||
("Close", "Sitzung beenden"),
|
||||
("Close", "Schließen"),
|
||||
("Retry", "Erneut versuchen"),
|
||||
("OK", "OK"),
|
||||
("Password Required", "Passwort erforderlich"),
|
||||
@ -358,7 +358,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Unpin menubar", "Menüleiste lösen"),
|
||||
("Recording", "Aufnahme"),
|
||||
("Directory", "Verzeichnis"),
|
||||
("Automatically record incoming sessions", "Automatische Aufzeichnung eingehender Sitzungen"),
|
||||
("Automatically record incoming sessions", "Eingehende Sitzungen automatisch aufzeichnen"),
|
||||
("Change", "Ändern"),
|
||||
("Start session recording", "Sitzungsaufzeichnung starten"),
|
||||
("Stop session recording", "Sitzungsaufzeichnung beenden"),
|
||||
@ -398,7 +398,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
|
||||
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Right click to select tabs", "Register mit rechtem Mausklick auswählen"),
|
||||
("Add to Address Book", "Zum Adressbuch hinzufügen"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Transfer File", "Transferir archivo"),
|
||||
("Connect", "Conectar"),
|
||||
("Recent Sessions", "Sesiones recientes"),
|
||||
("Address Book", "Directorio"),
|
||||
("Address Book", "Libreta de direcciones"),
|
||||
("Confirmation", "Confirmación"),
|
||||
("TCP Tunneling", "Túnel TCP"),
|
||||
("Remove", "Quitar"),
|
||||
|
@ -179,7 +179,8 @@ fn set_x11_env(uid: &str) {
|
||||
log::info!("uid of seat0: {}", uid);
|
||||
let gdm = format!("/run/user/{}/gdm/Xauthority", uid);
|
||||
let mut auth = get_env_tries("XAUTHORITY", uid, 10);
|
||||
if auth.is_empty() {
|
||||
// auth is another user's when uid = 0, https://github.com/rustdesk/rustdesk/issues/2468
|
||||
if auth.is_empty() || uid == "0" {
|
||||
auth = if std::path::Path::new(&gdm).exists() {
|
||||
gdm
|
||||
} else {
|
||||
|
@ -439,6 +439,7 @@ extern "C" {
|
||||
fn win32_disable_lowlevel_keyboard(hwnd: HWND);
|
||||
fn win_stop_system_key_propagate(v: BOOL);
|
||||
fn is_win_down() -> BOOL;
|
||||
fn is_local_system() -> BOOL;
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
@ -718,10 +719,10 @@ pub fn set_share_rdp(enable: bool) {
|
||||
}
|
||||
|
||||
pub fn get_active_username() -> String {
|
||||
let name = crate::username();
|
||||
if name != "SYSTEM" {
|
||||
return name;
|
||||
if !is_root() {
|
||||
return crate::username();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn get_active_user(path: *mut u16, n: u32, rdp: BOOL) -> u32;
|
||||
}
|
||||
@ -757,7 +758,8 @@ pub fn is_prelogin() -> bool {
|
||||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
crate::username() == "SYSTEM"
|
||||
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||
unsafe { is_local_system() == TRUE }
|
||||
}
|
||||
|
||||
pub fn lock_screen() {
|
||||
|
@ -379,7 +379,9 @@ impl RendezvousMediator {
|
||||
)
|
||||
.await?;
|
||||
let local_addr = socket.local_addr();
|
||||
allow_err!(socket_client::connect_tcp(peer_addr, local_addr, 300).await);
|
||||
// key important here for punch hole to tell my gateway incoming peer is safe.
|
||||
// it can not be async here, because local_addr can not be reused, we must close the connection before use it again.
|
||||
allow_err!(socket_client::connect_tcp(peer_addr, local_addr, 30).await);
|
||||
socket
|
||||
};
|
||||
let mut msg_out = Message::new();
|
||||
|
42
src/tray.rs
42
src/tray.rs
@ -88,6 +88,9 @@ pub fn start_tray() {
|
||||
/// This function will block current execution, show the tray icon and handle events.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn start_tray() {
|
||||
use std::time::Duration;
|
||||
|
||||
use glib::{clone, Continue};
|
||||
use gtk::traits::{GtkMenuItemExt, MenuShellExt, WidgetExt};
|
||||
|
||||
info!("configuring tray");
|
||||
@ -106,9 +109,9 @@ pub fn start_tray() {
|
||||
crate::client::translate("Stop service".to_owned())
|
||||
};
|
||||
let menu_item_service = gtk::MenuItem::with_label(label.as_str());
|
||||
menu_item_service.connect_activate(move |item| {
|
||||
menu_item_service.connect_activate(move |_| {
|
||||
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||
update_tray_service_item(item);
|
||||
change_service_state();
|
||||
});
|
||||
menu.append(&menu_item_service);
|
||||
// show tray item
|
||||
@ -116,6 +119,16 @@ pub fn start_tray() {
|
||||
appindicator.set_menu(&mut menu);
|
||||
// start event loop
|
||||
info!("Setting tray event loop");
|
||||
// check the connection status for every second
|
||||
glib::timeout_add_local(
|
||||
Duration::from_secs(1),
|
||||
clone!(@strong menu_item_service as item => move || {
|
||||
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||
update_tray_service_item(&item);
|
||||
// continue to trigger the next status check
|
||||
Continue(true)
|
||||
}),
|
||||
);
|
||||
gtk::main();
|
||||
} else {
|
||||
error!("Tray process exit now");
|
||||
@ -123,17 +136,25 @@ pub fn start_tray() {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn change_service_state() {
|
||||
if is_service_stoped() {
|
||||
debug!("Now try to start service");
|
||||
crate::ipc::set_option("stop-service", "");
|
||||
} else {
|
||||
debug!("Now try to stop service");
|
||||
crate::ipc::set_option("stop-service", "Y");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[inline]
|
||||
fn update_tray_service_item(item: >k::MenuItem) {
|
||||
use gtk::traits::GtkMenuItemExt;
|
||||
|
||||
if is_service_stoped() {
|
||||
debug!("Now try to start service");
|
||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "");
|
||||
} else {
|
||||
debug!("Now try to stop service");
|
||||
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "Y");
|
||||
} else {
|
||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,10 +210,10 @@ pub fn make_tray() {
|
||||
match mode {
|
||||
dark_light::Mode::Dark => {
|
||||
icon_path = "mac-tray-light.png";
|
||||
},
|
||||
}
|
||||
dark_light::Mode::Light => {
|
||||
icon_path = "mac-tray-dark.png";
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Ok(mut tray) = TrayItem::new(&crate::get_app_name(), icon_path) {
|
||||
tray.add_label(&format!(
|
||||
@ -211,4 +232,3 @@ pub fn make_tray() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,4 +588,44 @@ extern "C"
|
||||
stop_system_key_propagate = v;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||
BOOL is_local_system()
|
||||
{
|
||||
HANDLE hToken;
|
||||
UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];
|
||||
PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser;
|
||||
ULONG cbTokenUser;
|
||||
SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
|
||||
PSID pSystemSid;
|
||||
BOOL bSystem;
|
||||
|
||||
// open process token
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
TOKEN_QUERY,
|
||||
&hToken))
|
||||
return FALSE;
|
||||
|
||||
// retrieve user SID
|
||||
if (!GetTokenInformation(hToken, TokenUser, pTokenUser,
|
||||
sizeof(bTokenUser), &cbTokenUser))
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
|
||||
// allocate LocalSystem well-known SID
|
||||
if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
||||
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
|
||||
return FALSE;
|
||||
|
||||
// compare the user SID from the token with the LocalSystem SID
|
||||
bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid);
|
||||
|
||||
FreeSid(pSystemSid);
|
||||
|
||||
return bSystem;
|
||||
}
|
||||
|
||||
} // end of extern "C"
|
Loading…
Reference in New Issue
Block a user