machine_guid_windows.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. });
  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.lookupFunction<
  28. Int32 Function(IntPtr, Pointer<Utf8>, Uint32, Uint32, Pointer<IntPtr>),
  29. int Function(
  30. int, Pointer<Utf8>, int, int, Pointer<IntPtr>)>('RegOpenKeyExA');
  31. // Define the RegCloseKey function signature
  32. static final _RegCloseKey = _advapi32
  33. .lookupFunction<Int32 Function(IntPtr), int Function(int)>('RegCloseKey');
  34. // Define the RegQueryValueExW function signature
  35. static final _RegQueryValueExA = _advapi32.lookupFunction<
  36. Int32 Function(IntPtr, Pointer<Utf8>, Pointer<IntPtr>, Pointer<Uint32>,
  37. Pointer<Uint8>, Pointer<Uint32>),
  38. int Function(int, Pointer<Utf8>, Pointer<IntPtr>, Pointer<Uint32>,
  39. Pointer<Uint8>, Pointer<Uint32>)>('RegQueryValueExA');
  40. // Define the HKEY_LOCAL_MACHINE constant
  41. static const _HKEY_LOCAL_MACHINE = 0x80000002;
  42. static const _KEY_QUERY_VALUE = 0x0001;
  43. static const _KEY_WOW64_64KEY = 0x0100;
  44. static const kSuccess = 0;
  45. static const kRegKey = "SOFTWARE\\Microsoft\\Cryptography";
  46. static const kValueKey = "MachineGuid";
  47. static void RegOpenKeyEx(Pointer<IntPtr> hkey) {
  48. final res = _RegOpenKeyExA(
  49. _HKEY_LOCAL_MACHINE,
  50. kRegKey.toNativeUtf8(),
  51. 0,
  52. _KEY_QUERY_VALUE | _KEY_WOW64_64KEY,
  53. hkey,
  54. );
  55. if (res != _Native.kSuccess) {
  56. throw Exception('Failed to open registry: $res');
  57. }
  58. }
  59. static void RegCloseKey(Pointer<IntPtr> hkey) {
  60. _RegCloseKey(hkey.value);
  61. }
  62. static String RegQueryValueEx(Arena alloc, Pointer<IntPtr> hkey) {
  63. final dataTypePtr = alloc<Uint32>();
  64. dataTypePtr.value = 0;
  65. final dataSizePtr = alloc<Uint32>();
  66. var res = _RegQueryValueExA(
  67. hkey.value,
  68. kValueKey.toNativeUtf8(),
  69. nullptr,
  70. dataTypePtr,
  71. nullptr,
  72. dataSizePtr,
  73. );
  74. if (kSuccess != res) {
  75. throw Exception('Failed to get registry value size: $res');
  76. }
  77. final data = alloc<Uint8>(dataSizePtr.value);
  78. res = _RegQueryValueExA(
  79. hkey.value,
  80. kValueKey.toNativeUtf8(),
  81. nullptr,
  82. dataTypePtr,
  83. data,
  84. dataSizePtr,
  85. );
  86. if (kSuccess != res) {
  87. throw Exception('Failed to get registry value: $res');
  88. }
  89. return utf8.decode(data.asTypedList(dataSizePtr.value));
  90. }
  91. }