Class: FFI::Pointer

Inherits:
Object show all
Defined in:
lib/puppet/util/windows/api_types.rb

Constant Summary collapse

NULL_HANDLE =
0
WCHAR_NULL =
"\0\0".encode('UTF-16LE').freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_string_to_wide_string(str, &block) ⇒ Object


24
25
26
27
28
29
30
# File 'lib/puppet/util/windows/api_types.rb', line 24

def self.from_string_to_wide_string(str, &block)
  str = Puppet::Util::Windows::String.wide_string(str)
  FFI::MemoryPointer.from_wide_string(str, &block)

  # ptr has already had free called, so nothing to return
  nil
end

Instance Method Details

#read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {}) ⇒ Object

Parameters:

  • max_char_length (Integer) (defaults to: 512)

    Maximum number of wide chars to return (typically excluding NULLs), not bytes

  • null_terminator (Symbol) (defaults to: :single_null)

    Number of number of null wchar characters, not bytes, that determine the end of the string null_terminator = :single_null, then the terminating sequence is two bytes of zero. This is UNIT16 = 0 null_terminator = :double_null, then the terminating sequence is four bytes of zero. This is UNIT32 = 0

  • encode_options (Hash) (defaults to: {})

    Accepts the same option hash that may be passed to String#encode in Ruby


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/puppet/util/windows/api_types.rb', line 72

def read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {})
  idx = case null_terminator
        when :single_null
          # find index of wide null between 0 and max (exclusive)
          (0...max_char_length).find do |i|
            get_uint16(i * 2) == 0
          end
        when :double_null
          # find index of double-wide null between 0 and max - 1 (exclusive)
          (0...max_char_length - 1).find do |i|
            get_uint32(i * 2) == 0
          end
        else
          raise _("Unable to read wide strings with %{null_terminator} terminal nulls") % { null_terminator: null_terminator }
        end

  read_wide_string(idx || max_char_length, Encoding::UTF_8, false, encode_options)
end

#read_com_memory_pointer(&block) ⇒ Object


105
106
107
108
109
110
111
112
113
114
115
# File 'lib/puppet/util/windows/api_types.rb', line 105

def read_com_memory_pointer(&block)
  ptr = read_pointer
  begin
    yield ptr
  ensure
    FFI::WIN32::CoTaskMemFree(ptr) unless ptr.null?
  end

  # ptr has already had CoTaskMemFree called, so nothing to return
  nil
end

#read_handleObject


44
45
46
# File 'lib/puppet/util/windows/api_types.rb', line 44

def read_handle
  type_size == 4 ? read_uint32 : read_uint64
end

#read_wide_string(char_length, dst_encoding = Encoding::UTF_8, strip = false, encode_options = {}) ⇒ Object


52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/puppet/util/windows/api_types.rb', line 52

def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, strip = false, encode_options = {})
  # char_length is number of wide chars (typically excluding NULLs), *not* bytes
  str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')

  if strip
    i = str.index(WCHAR_NULL)
    str = str[0, i] if i
  end

  str.encode(dst_encoding, str.encoding, encode_options)
rescue EncodingError => e
  Puppet.debug { "Unable to convert value #{str.nil? ? 'nil' : str.dump} to encoding #{dst_encoding} due to #{e.inspect}" }
  raise
end

#read_win32_boolObject


32
33
34
35
36
# File 'lib/puppet/util/windows/api_types.rb', line 32

def read_win32_bool
  # BOOL is always a 32-bit integer in Win32
  # some Win32 APIs return 1 for true, while others are non-0
  read_int32 != FFI::WIN32_FALSE
end

#read_win32_local_pointer(&block) ⇒ Object


91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/puppet/util/windows/api_types.rb', line 91

def read_win32_local_pointer(&block)
  ptr = read_pointer
  begin
    yield ptr
  ensure
    if !ptr.null? && FFI::WIN32::LocalFree(ptr.address) != FFI::Pointer::NULL_HANDLE
      Puppet.debug "LocalFree memory leak"
    end
  end

  # ptr has already had LocalFree called, so nothing to return
  nil
end