31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/aibika/library_detector.rb', line 31
def self.loaded_dlls
require 'fiddle'
psapi = Fiddle.dlopen('psapi')
enumprocessmodules = Fiddle::Function.new(
psapi['EnumProcessModules'],
[Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG
)
kernel32 = Fiddle.dlopen('kernel32')
getcurrentprocess = Fiddle::Function.new(kernel32['GetCurrentProcess'], [], Fiddle::TYPE_LONG)
getmodulefilename = Fiddle::Function.new(
kernel32['GetModuleFileNameW'],
[Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG], Fiddle::TYPE_LONG
)
getlasterror = Fiddle::Function.new(kernel32['GetLastError'], [], Fiddle::TYPE_LONG)
if Fiddle::SIZEOF_VOIDP == 8
f_single = 'Q'
f_array = 'Q*'
else
f_single = 'I'
f_array = 'I*'
end
bytes_needed = Fiddle::SIZEOF_VOIDP * 32
module_handle_buffer = nil
process_handle = getcurrentprocess.call
loop do
module_handle_buffer = "\x00" * bytes_needed
bytes_needed_buffer = [0].pack(f_single)
enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size,
bytes_needed_buffer)
bytes_needed = bytes_needed_buffer.unpack1(f_single)
break if bytes_needed <= module_handle_buffer.size
end
handles = module_handle_buffer.unpack(f_array)
handles.select(&:positive?).map do |handle|
str = "\x00\x00" * 256
modulefilename_length = getmodulefilename.call(handle, str, str.size)
unless modulefilename_length.positive?
errorcode = getlasterror.call
Aibika.fatal_error "LibraryDetector: GetModuleFileNameW failed with error code 0x#{errorcode.to_s(16)}"
end
modulefilename = str[0, modulefilename_length * 2].force_encoding('UTF-16LE').encode('UTF-8')
Aibika.Pathname(modulefilename)
end
end
|