Files
umbrix/lib/features/connection/data/connection_platform_source.dart
2026-01-15 12:28:40 +03:00

70 lines
2.0 KiB
Dart

import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'package:hiddify/core/utils/ffi_utils.dart';
import 'package:hiddify/utils/custom_loggers.dart';
import 'package:hiddify/utils/utils.dart';
import 'package:posix/posix.dart';
import 'package:win32/win32.dart';
abstract interface class ConnectionPlatformSource {
Future<bool> checkPrivilege();
}
class ConnectionPlatformSourceImpl
with InfraLogger
implements ConnectionPlatformSource {
@override
Future<bool> checkPrivilege() async {
try {
if (Platform.isWindows) {
bool isElevated = false;
withMemory<void, Uint32>(sizeOf<Uint32>(), (phToken) {
withMemory<void, Uint32>(sizeOf<Uint32>(), (pReturnedSize) {
withMemory<void, _TokenElevation>(sizeOf<_TokenElevation>(),
(pElevation) {
if (OpenProcessToken(
GetCurrentProcess(),
TOKEN_ACCESS_MASK.TOKEN_QUERY,
phToken.cast(),
) ==
1) {
if (GetTokenInformation(
phToken.value,
TOKEN_INFORMATION_CLASS.TokenElevation,
pElevation,
sizeOf<_TokenElevation>(),
pReturnedSize,
) ==
1) {
isElevated = pElevation.ref.tokenIsElevated != 0;
}
}
if (phToken.value != 0) {
CloseHandle(phToken.value);
}
});
});
});
return isElevated;
} else if (Platform.isLinux || Platform.isMacOS) {
final euid = geteuid();
return euid == 0;
} else {
return true;
}
} catch (e) {
loggy.warning("error checking privilege", e);
return true; // return true so core handles it
}
}
}
sealed class _TokenElevation extends Struct {
/// A nonzero value if the token has elevated privileges;
/// otherwise, a zero value.
@Int32()
external int tokenIsElevated;
}