def read(key, name_ptr, *rtype)
      result = nil

      query_value_ex(key, name_ptr) do |type, data_ptr, byte_length|
        unless rtype.empty? or rtype.include?(type)
          raise TypeError, _("Type mismatch (expect %{rtype} but %{type} present)") % { rtype: rtype.inspect, type: type }
        end

        string_length = 0
        # buffer is raw bytes, *not* chars - less a NULL terminator
        string_length = (byte_length / FFI.type_size(:wchar)) - 1 if byte_length > 0

        begin
          case type
            when Win32::Registry::REG_SZ, Win32::Registry::REG_EXPAND_SZ
              result = [ type, data_ptr.read_wide_string(string_length) ]
            when Win32::Registry::REG_MULTI_SZ
              result = [ type, data_ptr.read_wide_string(string_length).split(/\0/) ]
            when Win32::Registry::REG_BINARY
              result = [ type, data_ptr.read_bytes(byte_length) ]
            when Win32::Registry::REG_DWORD
              result = [ type, data_ptr.read_dword ]
            when Win32::Registry::REG_DWORD_BIG_ENDIAN
              result = [ type, data_ptr.order(:big).read_dword ]
            when Win32::Registry::REG_QWORD
              result = [ type, data_ptr.read_qword ]
            else
              raise TypeError, _("Type %{type} is not supported.") % { type: type }
          end
        rescue IndexError => ex
          raise if (ex.message !~ /^Memory access .* is out of bounds$/i)
          parent_key_name = key.parent ? "#{key.parent.keyname}\\" : ""
          Puppet.warning _("A value in the registry key %{parent_key_name}%{key} is corrupt or invalid") % { parent_key_name: parent_key_name, key: key.keyname }
        end
      end

      result
    end
def read(key, name_ptr, *rtype)
      result = nil

      query_value_ex(key, name_ptr) do |type, data_ptr, byte_length|
        unless rtype.empty? or rtype.include?(type)
          raise TypeError, _("Type mismatch (expect %{rtype} but %{type} present)") % { rtype: rtype.inspect, type: type }
        end

        string_length = 0
        # buffer is raw bytes, *not* chars - less a NULL terminator
        string_length = (byte_length / FFI.type_size(:wchar)) - 1 if byte_length > 0

        begin
          case type
            when Win32::Registry::REG_SZ, Win32::Registry::REG_EXPAND_SZ
              result = [ type, data_ptr.read_wide_string(string_length) ]
            when Win32::Registry::REG_MULTI_SZ
              result = [ type, data_ptr.read_wide_string(string_length).split(/\0/) ]
            when Win32::Registry::REG_BINARY
              result = [ type, data_ptr.read_bytes(byte_length) ]
            when Win32::Registry::REG_DWORD
              result = [ type, data_ptr.read_dword ]
            when Win32::Registry::REG_DWORD_BIG_ENDIAN
              result = [ type, data_ptr.order(:big).read_dword ]
            when Win32::Registry::REG_QWORD
              result = [ type, data_ptr.read_qword ]
            else
              raise TypeError, _("Type %{type} is not supported.") % { type: type }
          end
        rescue IndexError => ex
          raise if (ex.message !~ /^Memory access .* is out of bounds$/i)
          parent_key_name = key.parent ? "#{key.parent.keyname}\\" : ""
          Puppet.warning _("A value in the registry key %{parent_key_name}%{key} is corrupt or invalid") % { parent_key_name: parent_key_name, key: key.keyname }
        end
      end

      result
    end
Read a registry value named name and return array of
 [ type, data ].
 When name is nil, the `default' value is read.
 type is value type. (see Win32::Registry::Constants module)
 data is value data, its class is:
 :REG_SZ, REG_EXPAND_SZ
    String
 :REG_MULTI_SZ
    Array of String
 :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
    Integer
 :REG_BINARY
    String (contains binary data)

 When rtype is specified, the value type must be included by
 rtype array, or TypeError is raised.