machine_guid_windows.dart 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // ignore_for_file: unused_import, non_constant_identifier_names, unused_field
  2. // ignore_for_file: constant_identifier_names
  3. import 'dart:convert';
  4. import 'dart:ffi';
  5. import 'dart:io';
  6. import 'package:ffi/ffi.dart';
  7. String getMachineGuid() {
  8. if (!Platform.isWindows) {
  9. throw Exception('"getMachineGuid" only supports Windows.');
  10. }
  11. return using<String>((alloc) {
  12. final hkey = calloc<IntPtr>();
  13. _Native.RegOpenKeyEx(hkey);
  14. try {
  15. return _Native.RegQueryValueEx(alloc, hkey);
  16. } catch (e) {
  17. rethrow;
  18. } finally {
  19. _Native.RegCloseKey(hkey);
  20. }
  21. }).replaceAll(RegExp(r'[\u0000-\u001F\u007F]'), '').trim();
  22. }
  23. class _Native {
  24. // Load the advapi32.dll library
  25. static final _advapi32 = DynamicLibrary.open('Advapi32.dll');
  26. // Define the RegOpenKeyExW function signature
  27. static final _RegOpenKeyExA = _advapi32
  28. .lookupFunction<
  29. Int32 Function(IntPtr, Pointer<Utf8>, Uint32, Uint32, Pointer<IntPtr>),
  30. int Function(int, Pointer<Utf8>, int, int, Pointer<IntPtr>)
  31. >('RegOpenKeyExA');
  32. // Define the RegCloseKey function signature
  33. static final _RegCloseKey = _advapi32
  34. .lookupFunction<Int32 Function(IntPtr), int Function(int)>('RegCloseKey');
  35. // Define the RegQueryValueExW function signature
  36. static final _RegQueryValueExA = _advapi32
  37. .lookupFunction<
  38. Int32 Function(
  39. IntPtr,
  40. Pointer<Utf8>,
  41. Pointer<IntPtr>,
  42. Pointer<Uint32>,
  43. Pointer<Uint8>,
  44. Pointer<Uint32>,
  45. ),
  46. int Function(
  47. int,
  48. Pointer<Utf8>,
  49. Pointer<IntPtr>,
  50. Pointer<Uint32>,
  51. Pointer<Uint8>,
  52. Pointer<Uint32>,
  53. )
  54. >('RegQueryValueExA');
  55. // Define the HKEY_LOCAL_MACHINE constant
  56. static const _HKEY_LOCAL_MACHINE = 0x80000002;
  57. static const _KEY_QUERY_VALUE = 0x0001;
  58. static const _KEY_WOW64_64KEY = 0x0100;
  59. static const kSuccess = 0;
  60. static const kRegKey = "SOFTWARE\\Microsoft\\Cryptography";
  61. static const kValueKey = "MachineGuid";
  62. static void RegOpenKeyEx(Pointer<IntPtr> hkey) {
  63. final res = _RegOpenKeyExA(
  64. _HKEY_LOCAL_MACHINE,
  65. kRegKey.toNativeUtf8(),
  66. 0,
  67. _KEY_QUERY_VALUE | _KEY_WOW64_64KEY,
  68. hkey,
  69. );
  70. if (res != _Native.kSuccess) {
  71. throw Exception('Failed to open registry: $res');
  72. }
  73. }
  74. static void RegCloseKey(Pointer<IntPtr> hkey) {
  75. _RegCloseKey(hkey.value);
  76. }
  77. static String RegQueryValueEx(Arena alloc, Pointer<IntPtr> hkey) {
  78. final dataTypePtr = alloc<Uint32>();
  79. dataTypePtr.value = 0;
  80. final dataSizePtr = alloc<Uint32>();
  81. var res = _RegQueryValueExA(
  82. hkey.value,
  83. kValueKey.toNativeUtf8(),
  84. nullptr,
  85. dataTypePtr,
  86. nullptr,
  87. dataSizePtr,
  88. );
  89. if (kSuccess != res) {
  90. throw Exception('Failed to get registry value size: $res');
  91. }
  92. final data = alloc<Uint8>(dataSizePtr.value);
  93. res = _RegQueryValueExA(
  94. hkey.value,
  95. kValueKey.toNativeUtf8(),
  96. nullptr,
  97. dataTypePtr,
  98. data,
  99. dataSizePtr,
  100. );
  101. if (kSuccess != res) {
  102. throw Exception('Failed to get registry value: $res');
  103. }
  104. return utf8.decode(data.asTypedList(dataSizePtr.value));
  105. }
  106. }