Class: Facter::Util::Windows::FFI

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

Defined Under Namespace

Modules: WIN32

Constant Summary collapse

WIN32_FALSE =

standard Win32 error codes

0
ERROR_SUCCESS =
0
NULL_HANDLE =
0

Class Method Summary collapse

Class Method Details

.read_arbitrary_wide_string_up_to(ffi_pointer, max_char_length = 512, null_terminator = :single_null) ⇒ 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



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/facter/util/windows/api_types.rb', line 35

def self.read_arbitrary_wide_string_up_to(ffi_pointer, max_char_length = 512, null_terminator = :single_null)
  if null_terminator != :single_null && null_terminator != :double_null
    raise _("Unable to read wide strings with %{null_terminator} terminal nulls") % { null_terminator: null_terminator }
  end

  terminator_width = null_terminator == :single_null ? 1 : 2
  reader_method = null_terminator == :single_null ? :get_uint16 : :get_uint32

  # Look for a null terminating characters; if found, read up to that null (exclusive)
  (0...max_char_length - terminator_width).each do |i|
    return read_wide_string(ffi_pointer, i) if ffi_pointer.send(reader_method, (i * 2)) == 0
  end

  # String is longer than the max; read just to the max
  read_wide_string(ffi_pointer, max_char_length)
end

.read_dword(ffi_pointer) ⇒ Object



17
18
19
# File 'lib/facter/util/windows/api_types.rb', line 17

def self.read_dword(ffi_pointer)
  ffi_pointer.read_uint32
end

.read_handle(ffi_pointer) ⇒ Object



21
22
23
# File 'lib/facter/util/windows/api_types.rb', line 21

def self.read_handle(ffi_pointer)
  ffi_pointer.type_size == 4 ? ffi_pointer.read_uint32 : ffi_pointer.read_uint64
end

.read_wide_string(ffi_pointer, char_length, dst_encoding = Encoding::UTF_8) ⇒ Object



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

def self.read_wide_string(ffi_pointer, char_length, dst_encoding = Encoding::UTF_8)
  # char_length is number of wide chars (typically excluding NULLs), *not* bytes
  str = ffi_pointer.get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
  str.encode(dst_encoding)
end

.read_win32_bool(ffi_pointer) ⇒ Object



11
12
13
14
15
# File 'lib/facter/util/windows/api_types.rb', line 11

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

.read_win32_local_pointer(ffi_pointer, &block) ⇒ Object



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

def self.read_win32_local_pointer(ffi_pointer, &block)
  ptr = nil
  begin
    ptr = ffi_pointer.read_pointer
    yield ptr
  ensure
    if ptr && ! ptr.null?
      if WIN32.LocalFree(ptr.address) != NULL_HANDLE
        Puppet.debug "LocalFree memory leak"
      end
    end
  end

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