readAllRegistryValues static method

Future<Map<String, String>> readAllRegistryValues(
  1. String keyPath
)

Read all registry values from a given key path

keyPath - Registry key path (e.g., r'.DEFAULT\Software\HaloAgent') Returns a map of registry value names to their values

Implementation

static Future<Map<String, String>> readAllRegistryValues(
  String keyPath,
) async {
  DebugLogger.log('[WindowsRegistry] === readAllRegistryValues() called ===');
  DebugLogger.log('[WindowsRegistry] Key path: $keyPath');

  final hKey = calloc<IntPtr>();
  final subKeyPtr = keyPath.toNativeUtf16();
  final nameBuffer = calloc<Uint16>(256); // Allocate buffer for name (WCHAR)
  final valueBuffer = calloc<Uint8>(1024); // Allocate buffer for value (BYTE)
  final nameLengthPtr = calloc<DWORD>();
  final valueLengthPtr = calloc<DWORD>();
  final typePtr = calloc<DWORD>();

  final values = <String, String>{};

  try {
    // Open the registry key
    DebugLogger.log('[WindowsRegistry] Opening registry key...');
    final openResult = RegOpenKeyEx(
      HKEY_USERS,
      subKeyPtr,
      0,
      REG_SAM_FLAGS.KEY_READ,
      hKey,
    );

    if (openResult != WIN32_ERROR.ERROR_SUCCESS) {
      DebugLogger.log(
        '[WindowsRegistry] ❌ Failed to open registry key. Error code: $openResult',
      );
      return values;
    }

    DebugLogger.log('[WindowsRegistry] ✅ Registry key opened successfully');

    int index = 0;
    while (true) {
      // Reset lengths for each iteration
      nameLengthPtr.value = 256; // Name buffer length in WCHARs
      valueLengthPtr.value = 1024; // Value buffer length in bytes

      final enumResult = RegEnumValue(
        hKey.value,
        index,
        nameBuffer as Pointer<Utf16>,
        nameLengthPtr,
        nullptr,
        typePtr,
        valueBuffer,
        valueLengthPtr,
      );

      if (enumResult == WIN32_ERROR.ERROR_NO_MORE_ITEMS) {
        DebugLogger.log('[WindowsRegistry] No more items to enumerate');
        break; // No more items to enumerate
      }

      if (enumResult != WIN32_ERROR.ERROR_SUCCESS) {
        DebugLogger.log(
          '[WindowsRegistry] ❌ Error enumerating values. Error code: $enumResult',
        );
        break;
      }

      // Decode the name (UTF-16) to Dart String
      final name = _decodeUtf16(nameBuffer, nameLengthPtr.value);
      DebugLogger.log('[WindowsRegistry] Found registry value: $name');

      // Decode the value buffer based on the type
      String value;
      switch (typePtr.value) {
        case REG_VALUE_TYPE.REG_SZ: // String
          value = _decodeUtf16(
            valueBuffer.cast<Uint16>(),
            valueLengthPtr.value,
          );
          DebugLogger.log('[WindowsRegistry] Value type: REG_SZ, Value: $value');
          break;
        case REG_VALUE_TYPE.REG_DWORD: // DWORD (integer)
          value = valueBuffer.cast<Uint32>().value.toString();
          DebugLogger.log('[WindowsRegistry] Value type: REG_DWORD, Value: $value');
          break;
        default:
          value = 'Unsupported value type: ${typePtr.value}';
          DebugLogger.log(
            '[WindowsRegistry] ⚠️ Unsupported value type: ${typePtr.value}',
          );
          break;
      }

      // Add to the map
      values[name] = value;
      index++;
    }

    DebugLogger.log('[WindowsRegistry] ✅ Read ${values.length} registry values');
  } catch (e) {
    DebugLogger.log('[WindowsRegistry] ❌ Exception reading registry: $e');
  } finally {
    // Free allocated memory
    calloc.free(hKey);
    calloc.free(subKeyPtr);
    calloc.free(nameBuffer);
    calloc.free(valueBuffer);
    calloc.free(nameLengthPtr);
    calloc.free(valueLengthPtr);
    calloc.free(typePtr);
  }

  return values;
}