user2667489
user2667489

Reputation:

Ruby FFI: Pointer to an array of unsigned integer

I am trying to use EnumProcesses in my ruby program:

BOOL WINAPI EnumProcesses(
  _Out_  DWORD *pProcessIds,
  _In_   DWORD cb,
  _Out_  DWORD *pBytesReturned
);

I need to define a pointer to an array of unsigned integers, I am doing that in following way:

require 'ffi'

module Win32
  extend FFI::Library
  ffi_lib 'Psapi'
  ffi_convention :stdcall
  attach_function :EnumProcesses,  [:pointer, :uint, :pointer], :int
end

process_ids    = FFI::MemoryPointer.new(:uint, 1024)
bytes_returned = FFI::MemoryPointer.new(:uint)

if Win32.EnumProcesses(process_ids, process_ids.size, bytes_returned) != 0
  puts bytes_returned.read_string
end

The output of above bytes returned is a kind of junk characters like x☺

Let me know where am I doing wrong?

Upvotes: 0

Views: 1175

Answers (1)

WickedTribe
WickedTribe

Reputation: 11

You were very close. The primary issue is interpreting the data coming back from Microsoft. It isn't a string. Its an array of DWORDs or uint32s.

Give the following a go:

require 'ffi'

module Win32

  extend FFI::Library
  ffi_lib 'Psapi'
  ffi_convention :stdcall

=begin
  BOOL WINAPI EnumProcesses(
    _Out_  DWORD *pProcessIds,
    _In_   DWORD cb,
    _Out_  DWORD *pBytesReturned
  );
=end
  attach_function :EnumProcesses, [:pointer, :uint32, :pointer], :int

end

# Allocate room for the windows process ids.
process_ids = FFI::MemoryPointer.new(:uint32, 1024)

# Allocate room for windows to tell us how many process ids there were.
bytes_returned = FFI::MemoryPointer.new(:uint32)

# Ask for the process ids
if Win32.EnumProcesses(process_ids, process_ids.size, bytes_returned) != 0

  # Determine the number of ids we were given
  process_ids_returned = bytes_returned.read_int / bytes_returned.size

  # Pull all the ids out of the raw memory and into a local ruby array.
  ids = process_ids.read_array_of_type(:uint32, :read_uint32, process_ids_returned)

  puts ids.sort
end

Upvotes: 1

Related Questions