Class: FFI::Pointer

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_string_to_wide_string(str, &_block) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/pdk/util/windows/api_types.rb', line 13

def self.from_string_to_wide_string(str, &_block)
  str = PDK::Util::Windows::String.wide_string(str)
  FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr|
    # uchar here is synonymous with byte
    ptr.put_array_of_uchar(0, str.bytes.to_a)

    yield ptr
  end

  # 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



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pdk/util/windows/api_types.rb', line 39

def read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {})
  unless [:single_null, :double_null].include?(null_terminator)
    raise ArgumentError, _(
      '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 the null_terminator; if found, read up to that null
  # (exclusive)
  (0...max_char_length - terminator_width).each do |i|
    return read_wide_string(i, Encoding::UTF_8, encode_options) if send(reader_method, (i * 2)).zero?
  end

  # String is longer than the max, read just up to the max
  read_wide_string(max_char_length, Encoding::UTF_8, encode_options)
end

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



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/pdk/util/windows/api_types.rb', line 26

def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, 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')
  str.encode(dst_encoding, str.encoding, encode_options)
rescue StandardError => e
  PDK.logger.debug _('Unable to convert value %{string} to encoding %{encoding} due to %{error}') % {
    string:   str.dump,
    encoding: dst_encoding,
    error:    e.inspect,
  }
  raise
end