exerb 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/ChangeLog.ja.rd +305 -0
- data/README.en.txt +12 -0
- data/README.ja.html +143 -0
- data/README.ja.txt +6 -0
- data/README.md +50 -0
- data/Rakefile +205 -0
- data/bin/exerb +185 -0
- data/bin/mkexy +47 -0
- data/doc/LGPL +513 -0
- data/doc/class.ja.html +92 -0
- data/doc/command.ja.html +109 -0
- data/doc/core.ja.html +72 -0
- data/doc/example.ja.html +89 -0
- data/doc/faq.ja.html +59 -0
- data/doc/inside.ja.rd +404 -0
- data/doc/license.ja.html +62 -0
- data/doc/logo.gif +0 -0
- data/doc/misc.ja.html +72 -0
- data/doc/navi.gif +0 -0
- data/doc/recipe.ja.html +317 -0
- data/doc/style.css +187 -0
- data/doc/tutorial.ja.html +182 -0
- data/example/Makefile +54 -0
- data/example/cat_n.rb +14 -0
- data/example/exception.rb +9 -0
- data/example/ext/Win32API.so +0 -0
- data/example/ext/swin.so +0 -0
- data/example/msgbox.rb +14 -0
- data/example/rubytk.rb +22 -0
- data/example/runtime.ico +0 -0
- data/example/runtime.rb +19 -0
- data/example/vr/clipboard.rb +106 -0
- data/example/vr/compat/rubycompat.rb +18 -0
- data/example/vr/compat/vrcomctl.rb +12 -0
- data/example/vr/compat/vrcontrol.rb +50 -0
- data/example/vr/compat/vrmmedia.rb +24 -0
- data/example/vr/contrib/inifile.rb +116 -0
- data/example/vr/contrib/msgboxconst.rb +55 -0
- data/example/vr/contrib/toolbar.rb +371 -0
- data/example/vr/contrib/vrctlcolor.rb +110 -0
- data/example/vr/contrib/vrhotkey.rb +35 -0
- data/example/vr/contrib/vrlistviewex.rb +71 -0
- data/example/vr/contrib/vrstdscrollbar.rb +414 -0
- data/example/vr/contrib/vrwincomponent.rb +54 -0
- data/example/vr/dragdropformat.rb +209 -0
- data/example/vr/rscutil.rb +168 -0
- data/example/vr/sysmod.rb +249 -0
- data/example/vr/vractivex.rb +56 -0
- data/example/vr/vrclipboard.rb +53 -0
- data/example/vr/vrcomctl.rb +1819 -0
- data/example/vr/vrcontrol.rb +1374 -0
- data/example/vr/vrdde.rb +623 -0
- data/example/vr/vrddrop.rb +190 -0
- data/example/vr/vrdialog.rb +406 -0
- data/example/vr/vrhandler.rb +195 -0
- data/example/vr/vrlayout.old.rb +209 -0
- data/example/vr/vrlayout.rb +173 -0
- data/example/vr/vrlayout2.rb +340 -0
- data/example/vr/vrmargin.rb +141 -0
- data/example/vr/vrmgdlayout.rb +381 -0
- data/example/vr/vrmmedia.rb +287 -0
- data/example/vr/vrolednd.rb +192 -0
- data/example/vr/vrowndraw.rb +108 -0
- data/example/vr/vrrichedit.rb +366 -0
- data/example/vr/vrtimer.rb +148 -0
- data/example/vr/vrtooltip.rb +273 -0
- data/example/vr/vrtray.rb +143 -0
- data/example/vr/vrtvitem.rb +118 -0
- data/example/vr/vrtwopane.rb +223 -0
- data/example/vr/vruby.rb +1051 -0
- data/example/vr/winconst.rb +158 -0
- data/example/vruby.rb +38 -0
- data/exerb.gemspec +26 -0
- data/extconf.rb +7 -0
- data/lib/exerb/archive.rb +143 -0
- data/lib/exerb/config.rb +51 -0
- data/lib/exerb/error.rb +15 -0
- data/lib/exerb/executable.rb +68 -0
- data/lib/exerb/file_table.rb +189 -0
- data/lib/exerb/mkexy.rb +81 -0
- data/lib/exerb/name_table.rb +120 -0
- data/lib/exerb/recipe.rb +465 -0
- data/lib/exerb/resource.rb +190 -0
- data/lib/exerb/resource/base.rb +29 -0
- data/lib/exerb/resource/binary.rb +31 -0
- data/lib/exerb/resource/dialog.rb +30 -0
- data/lib/exerb/resource/group_icon.rb +85 -0
- data/lib/exerb/resource/icon.rb +52 -0
- data/lib/exerb/resource/version_info.rb +155 -0
- data/lib/exerb/resource_library.rb +120 -0
- data/lib/exerb/utility.rb +95 -0
- data/lib/exerb/utility2.rb +122 -0
- data/lib/exerb/version.rb +13 -0
- data/lib/exerb/win32/const/resource.rb +51 -0
- data/lib/exerb/win32/icon_file.rb +78 -0
- data/lib/exerb/win32/pe_file.rb +59 -0
- data/lib/exerb/win32/resource_directory.rb +105 -0
- data/lib/exerb/win32/resource_directory_root.rb +67 -0
- data/lib/exerb/win32/resource_entry.rb +98 -0
- data/lib/exerb/win32/struct/base.rb +43 -0
- data/lib/exerb/win32/struct/icon_dir_entry.rb +83 -0
- data/lib/exerb/win32/struct/icon_header.rb +43 -0
- data/lib/exerb/win32/struct/icon_res_entry.rb +48 -0
- data/lib/exerb/win32/struct/image_dos_header.rb +73 -0
- data/lib/exerb/win32/struct/image_file_header.rb +47 -0
- data/lib/exerb/win32/struct/image_nt_headers32.rb +53 -0
- data/lib/exerb/win32/struct/image_optional_header32.rb +107 -0
- data/lib/exerb/win32/struct/image_resource_data_entry.rb +45 -0
- data/lib/exerb/win32/struct/image_resource_directory.rb +47 -0
- data/lib/exerb/win32/struct/image_resource_directory_entry.rb +72 -0
- data/lib/exerb/win32/struct/image_section_header.rb +53 -0
- data/lib/exerb/win32/struct/version_info_block.rb +75 -0
- data/lib/exerb/win32/struct/vs_fixed_file_info.rb +62 -0
- data/src/exerb/cui.c +48 -0
- data/src/exerb/default.rb +1 -0
- data/src/exerb/exerb.c +877 -0
- data/src/exerb/exerb.h +92 -0
- data/src/exerb/gui.c +176 -0
- data/src/exerb/module.c +138 -0
- data/src/exerb/module.h +7 -0
- data/src/exerb/patch.c +27 -0
- data/src/exerb/resource.h +22 -0
- data/src/exerb/resource.rc +121 -0
- data/src/exerb/ruby.ico +0 -0
- data/src/exerb/utility.c +263 -0
- data/src/exerb/utility.h +33 -0
- data/test/alltests.rb +16 -0
- data/test/test-argv.rb +26 -0
- data/test/test-argv/test-argv.rb +9 -0
- data/test/test-argv/test-argv.ret +1 -0
- data/test/test-dollarzero.rb +26 -0
- data/test/test-dollarzero/test-dollarzero.rb +10 -0
- data/test/test-dollarzero/test-dollarzero.ret +2 -0
- data/test/test-dot.rb +26 -0
- data/test/test-dot/dot.dot.dot.rb +9 -0
- data/test/test-dot/dot.dot.rb +9 -0
- data/test/test-dot/test-dot.rb +13 -0
- data/test/test-dot/test-dot.ret +5 -0
- data/test/test-exitcode.rb +28 -0
- data/test/test-exitcode/test-exitcode.rb +9 -0
- data/test/test-kcode.rb +43 -0
- data/test/test-kcode/euc.rb +10 -0
- data/test/test-kcode/euc.ret +2 -0
- data/test/test-kcode/none.rb +10 -0
- data/test/test-kcode/none.ret +2 -0
- data/test/test-kcode/sjis.rb +10 -0
- data/test/test-kcode/sjis.ret +2 -0
- data/test/test-kcode/utf8.rb +10 -0
- data/test/test-kcode/utf8.ret +2 -0
- data/test/test-loadpath.rb +24 -0
- data/test/test-loadpath/test-loadpath.rb +9 -0
- data/test/test-nest.rb +18 -0
- data/test/test-nest/foo.rb +1 -0
- data/test/test-nest/foo/bar.rb +2 -0
- data/test/test-nest/foo/foo.rb +1 -0
- data/test/test-nest/test-nest.rb +1 -0
- data/test/test-nest/test-nest.ret +1 -0
- data/test/test-preload.rb +24 -0
- data/test/test-preload/test-preload.rb +9 -0
- data/test/test-regexp.rb +26 -0
- data/test/test-regexp/test-regexp.rb +23 -0
- data/test/test-regexp/test-regexp.ret +13 -0
- data/test/test-require1.rb +26 -0
- data/test/test-require1/require1.rb +9 -0
- data/test/test-require1/require2.rb +9 -0
- data/test/test-require1/require3.rb +9 -0
- data/test/test-require1/require4.rb +9 -0
- data/test/test-require1/require5.rb +9 -0
- data/test/test-require1/require6.rb +9 -0
- data/test/test-require1/test-require1.rb +41 -0
- data/test/test-require1/test-require1.ret +27 -0
- data/test/test-socket.rb +26 -0
- data/test/test-socket/test-socket.rb +7 -0
- data/test/test-socket/test-socket.ret +1 -0
- data/test/testcase.rb +66 -0
- data/vendor/mkexports.rb +167 -0
- metadata +352 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
#==============================================================================#
|
3
|
+
# $Id: image_resource_directory_entry.rb,v 1.5 2005/04/17 15:56:25 yuya Exp $
|
4
|
+
#==============================================================================#
|
5
|
+
|
6
|
+
require 'exerb/win32/struct/base'
|
7
|
+
require 'exerb/win32/const/resource'
|
8
|
+
|
9
|
+
#==============================================================================#
|
10
|
+
|
11
|
+
module Exerb
|
12
|
+
module Win32
|
13
|
+
module Struct
|
14
|
+
end # Struct
|
15
|
+
end # Win32
|
16
|
+
end # Exerb
|
17
|
+
|
18
|
+
#==============================================================================#
|
19
|
+
|
20
|
+
class Exerb::Win32::Struct::ImageResourceDirectoryEntry < Exerb::Win32::Struct::Base
|
21
|
+
|
22
|
+
FORMAT = 'LL'
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
super()
|
26
|
+
@name = 0
|
27
|
+
@offset_to_data = 0
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :name, :offset_to_data
|
31
|
+
|
32
|
+
def pack
|
33
|
+
return [@name, @offset_to_data].pack(FORMAT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def unpack(bin)
|
37
|
+
@name, @offset_to_data = bin.unpack(FORMAT)
|
38
|
+
return self
|
39
|
+
end
|
40
|
+
|
41
|
+
def id
|
42
|
+
return @name & 0xFFFF
|
43
|
+
end
|
44
|
+
|
45
|
+
def name_is_string?
|
46
|
+
return (@name & Exerb::Win32::Const::IMAGE_RESOURCE_NAME_IS_STRING > 0 ? true : false)
|
47
|
+
end
|
48
|
+
|
49
|
+
def offset_to_string
|
50
|
+
return @name & ~Exerb::Win32::Const::IMAGE_RESOURCE_NAME_IS_STRING
|
51
|
+
end
|
52
|
+
|
53
|
+
def offset_to_string=(value)
|
54
|
+
@name = value | Exerb::Win32::Const::IMAGE_RESOURCE_NAME_IS_STRING
|
55
|
+
end
|
56
|
+
|
57
|
+
def data_is_directory?
|
58
|
+
return (@offset_to_data & Exerb::Win32::Const::IMAGE_RESOURCE_DATA_IS_DIRECTORY > 0 ? true : false)
|
59
|
+
end
|
60
|
+
|
61
|
+
def offset_to_directory
|
62
|
+
return @offset_to_data & ~Exerb::Win32::Const::IMAGE_RESOURCE_DATA_IS_DIRECTORY
|
63
|
+
end
|
64
|
+
|
65
|
+
def offset_to_directory=(value)
|
66
|
+
@offset_to_data = value | Exerb::Win32::Const::IMAGE_RESOURCE_DATA_IS_DIRECTORY
|
67
|
+
end
|
68
|
+
|
69
|
+
end # Exerb::Win32::Struct::ImageResourceDirectoryEntry
|
70
|
+
|
71
|
+
#==============================================================================#
|
72
|
+
#==============================================================================#
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
#==============================================================================#
|
3
|
+
# $Id: image_section_header.rb,v 1.4 2005/04/17 15:56:25 yuya Exp $
|
4
|
+
#==============================================================================#
|
5
|
+
|
6
|
+
require 'exerb/win32/struct/base'
|
7
|
+
|
8
|
+
#==============================================================================#
|
9
|
+
|
10
|
+
module Exerb
|
11
|
+
module Win32
|
12
|
+
module Struct
|
13
|
+
end # Struct
|
14
|
+
end # Win32
|
15
|
+
end # Exerb
|
16
|
+
|
17
|
+
#==============================================================================#
|
18
|
+
|
19
|
+
class Exerb::Win32::Struct::ImageSectionHeader < Exerb::Win32::Struct::Base
|
20
|
+
|
21
|
+
FORMAT = 'Z8LLLLLLSSL'
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@name = ""
|
25
|
+
@virtual_size = 0
|
26
|
+
@virtual_address = 0
|
27
|
+
@size_of_raw_data = 0
|
28
|
+
@pointer_to_raw_data = 0
|
29
|
+
@pointer_to_relocations = 0
|
30
|
+
@pointer_to_linenumbers = 0
|
31
|
+
@number_of_relocations = 0
|
32
|
+
@number_of_linenumbers = 0
|
33
|
+
@characteristics = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :name, :virtual_size, :virtual_address, :size_of_raw_data, :pointer_to_raw_data, :pointer_to_relocations, :pointer_to_linenumbers, :number_of_relocations, :number_of_linenumbers, :characteristics
|
37
|
+
|
38
|
+
def pack
|
39
|
+
return [@name, @virtual_size, @virtual_address, @size_of_raw_data, @pointer_to_raw_data, @pointer_to_relocations, @pointer_to_linenumbers, @number_of_relocations, @number_of_linenumbers, @characteristics].pack(FORMAT)
|
40
|
+
end
|
41
|
+
|
42
|
+
def unpack(bin)
|
43
|
+
@name, @virtual_size, @virtual_address, @size_of_raw_data, @pointer_to_raw_data, @pointer_to_relocations, @pointer_to_linenumbers, @number_of_relocations, @number_of_linenumbers, @characteristics = bin.unpack(FORMAT)
|
44
|
+
return self
|
45
|
+
end
|
46
|
+
|
47
|
+
alias :physical_address :virtual_size
|
48
|
+
alias :physical_address= :virtual_size=
|
49
|
+
|
50
|
+
end # Exerb::Win32::Struct::ImageSectionHeader
|
51
|
+
|
52
|
+
#==============================================================================#
|
53
|
+
#==============================================================================#
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
#==============================================================================#
|
3
|
+
# $Id: version_info_block.rb,v 1.5 2005/04/30 15:16:04 yuya Exp $
|
4
|
+
#==============================================================================#
|
5
|
+
|
6
|
+
require 'exerb/utility'
|
7
|
+
require 'exerb/win32/struct/base'
|
8
|
+
|
9
|
+
#==============================================================================#
|
10
|
+
|
11
|
+
module Exerb
|
12
|
+
module Win32
|
13
|
+
module Struct
|
14
|
+
end # Struct
|
15
|
+
end # Win32
|
16
|
+
end # Exerb
|
17
|
+
|
18
|
+
#==============================================================================#
|
19
|
+
|
20
|
+
class Exerb::Win32::Struct::VersionInfoBlock < Exerb::Win32::Struct::Base
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@total_length = 0
|
24
|
+
@value_length = 0
|
25
|
+
@type = 0
|
26
|
+
@key = ""
|
27
|
+
@data = ""
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :total_length, :value_length, :type, :key, :data
|
31
|
+
|
32
|
+
def pack
|
33
|
+
return Exerb::Utility.alignment(self.pack_header + self.pack_string, 4) + @data.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def pack_header
|
37
|
+
return [@total_length, @value_length, @type].pack('SSS')
|
38
|
+
end
|
39
|
+
|
40
|
+
def pack_string
|
41
|
+
return @key.to_s + "\0\0"
|
42
|
+
end
|
43
|
+
protected :pack_string
|
44
|
+
|
45
|
+
def unpack
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
|
49
|
+
def read(io)
|
50
|
+
@total_length = io.read(2).unpack('S')[0]
|
51
|
+
@value_length = io.read(2).unpack('S')[0]
|
52
|
+
@type = io.read(2).unpack('S')[0]
|
53
|
+
@key = self.read_string(io)
|
54
|
+
@data = io.read(@value_length)
|
55
|
+
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
def read_string(io)
|
60
|
+
str = ''
|
61
|
+
|
62
|
+
while (ch = io.read(2)) != "\0\0"
|
63
|
+
str << ch
|
64
|
+
end
|
65
|
+
|
66
|
+
io.seek((io.pos % 4 == 0 ? 0 : 4 - io.pos % 4), IO::SEEK_CUR)
|
67
|
+
|
68
|
+
return str
|
69
|
+
end
|
70
|
+
protected :read_string
|
71
|
+
|
72
|
+
end # Exerb::Win32::Struct::VersionInfoBlock
|
73
|
+
|
74
|
+
#==============================================================================#
|
75
|
+
#==============================================================================#
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
#==============================================================================#
|
3
|
+
# $Id: vs_fixed_file_info.rb,v 1.3 2005/04/17 15:56:25 yuya Exp $
|
4
|
+
#==============================================================================#
|
5
|
+
|
6
|
+
require 'exerb/win32/struct/base'
|
7
|
+
|
8
|
+
#==============================================================================#
|
9
|
+
|
10
|
+
module Exerb
|
11
|
+
module Win32
|
12
|
+
module Struct
|
13
|
+
end # Struct
|
14
|
+
end # Win32
|
15
|
+
end # Exerb
|
16
|
+
|
17
|
+
#==============================================================================#
|
18
|
+
|
19
|
+
class Exerb::Win32::Struct::VsFixedFileInfo < Exerb::Win32::Struct::Base
|
20
|
+
|
21
|
+
FORMAT = 'LLLLLLLLLLLLL'
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
super()
|
25
|
+
@signature = 0
|
26
|
+
@struct_version = 0
|
27
|
+
@file_version_ms = 0
|
28
|
+
@file_version_ls = 0
|
29
|
+
@product_version_ms = 0
|
30
|
+
@product_version_ls = 0
|
31
|
+
@file_flags_mask = 0
|
32
|
+
@file_flags = 0
|
33
|
+
@file_os = 0
|
34
|
+
@file_type = 0
|
35
|
+
@file_subtype = 0
|
36
|
+
@file_date_ms = 0
|
37
|
+
@file_date_ls = 0
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_accessor :signature, :struct_version, :file_version_ms, :file_version_ls, :product_version_ms, :product_version_ls, :file_flags_mask, :file_flags, :file_os, :file_type, :file_subtype, :file_date_ms, :file_date_ls
|
41
|
+
|
42
|
+
def pack
|
43
|
+
return [@signature, @struct_version, @file_version_ms, @file_version_ls, @product_version_ms, @product_version_ls, @file_flags_mask, @file_flags, @file_os, @file_type, @file_subtype, @file_date_ms, @file_date_ls].pack(FORMAT)
|
44
|
+
end
|
45
|
+
|
46
|
+
def unpack(bin)
|
47
|
+
@signature, @struct_version, @file_version_ms, @file_version_ls, @product_version_ms, @product_version_ls, @file_flags_mask, @file_flags, @file_os, @file_type, @file_subtype, @file_date_ms, @file_date_ls = bin.unpack(FORMAT)
|
48
|
+
return self
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_version
|
52
|
+
return format('%x.%x.%x.%x', @file_version_ms >> 16, @file_version_ms & 0x0000FFFF, @file_version_ls >> 16, @file_version_ls & 0x0000FFFF)
|
53
|
+
end
|
54
|
+
|
55
|
+
def product_version
|
56
|
+
return format('%x.%x.%x.%x', @product_version_ms >> 16, @product_version_ms & 0x0000FFFF, @product_version_ls >> 16, @product_version_ls & 0x0000FFFF)
|
57
|
+
end
|
58
|
+
|
59
|
+
end # Exerb::Win32::Struct::VsFixedFileInfo
|
60
|
+
|
61
|
+
#==============================================================================#
|
62
|
+
#==============================================================================#
|
data/src/exerb/cui.c
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
// $Id: cui.cpp,v 1.10 2005/04/18 14:40:32 yuya Exp $
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
|
5
|
+
////////////////////////////////////////////////////////////////////////////////
|
6
|
+
|
7
|
+
int exerb_main(int argc, char** argv, void (*on_init)(VALUE, VALUE, VALUE), void (*on_fail)(VALUE)); // exerb.cpp
|
8
|
+
|
9
|
+
int main(int argc, char** argv);
|
10
|
+
static void on_fail(VALUE errinfo);
|
11
|
+
|
12
|
+
////////////////////////////////////////////////////////////////////////////////
|
13
|
+
|
14
|
+
int
|
15
|
+
main(int argc, char** argv)
|
16
|
+
{
|
17
|
+
#ifdef _DEBUG
|
18
|
+
__asm { int 3 }
|
19
|
+
#endif
|
20
|
+
return exerb_main(argc, argv, NULL, on_fail);
|
21
|
+
}
|
22
|
+
|
23
|
+
static void
|
24
|
+
on_fail(VALUE errinfo)
|
25
|
+
{
|
26
|
+
const VALUE message = rb_funcall(errinfo, rb_intern("message"), 0);
|
27
|
+
const VALUE backtrace = rb_funcall(errinfo, rb_intern("backtrace"), 0);
|
28
|
+
const VALUE backtrace1 = rb_ary_shift(backtrace);
|
29
|
+
const VALUE backtrace2 = rb_str_concat(rb_str_new2("\tfrom "), rb_ary_join(backtrace, rb_str_new2("\n\tfrom ")));
|
30
|
+
|
31
|
+
#ifdef RUBY19
|
32
|
+
fprintf(stderr, "%s: %s (%s)\n",
|
33
|
+
rb_string_value_ptr((volatile VALUE*) &backtrace1),
|
34
|
+
rb_string_value_ptr((volatile VALUE*) &message),
|
35
|
+
rb_obj_classname(errinfo));
|
36
|
+
#else
|
37
|
+
fprintf(stderr, "%s: %s (%s)\n", STR2CSTR(backtrace1), STR2CSTR(message), rb_obj_classname(errinfo));
|
38
|
+
#endif
|
39
|
+
if ( FIX2INT(rb_funcall(backtrace, rb_intern("size"), 0)) > 0 ) {
|
40
|
+
#ifdef RUBY19
|
41
|
+
fprintf(stderr, "%s\n", rb_string_value_ptr((volatile VALUE*) &backtrace2));
|
42
|
+
#else
|
43
|
+
fprintf(stderr, "%s\n", STR2CSTR(backtrace2));
|
44
|
+
#endif
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
////////////////////////////////////////////////////////////////////////////////
|
@@ -0,0 +1 @@
|
|
1
|
+
raise("please replace an archive.")
|
data/src/exerb/exerb.c
ADDED
@@ -0,0 +1,877 @@
|
|
1
|
+
// $Id: exerb.cpp,v 1.198 2009/09/08 12:25:47 arton Exp $
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
|
5
|
+
/* Use crtdbg with Visual Studio or make it no-op */
|
6
|
+
#ifdef _MSC_VER
|
7
|
+
# include <crtdbg.h>
|
8
|
+
#else
|
9
|
+
# define _CRT_WARN
|
10
|
+
# define _RPT1(...)
|
11
|
+
# define _RPT2(...)
|
12
|
+
# define _RPT3(...)
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#include "exerb.h"
|
16
|
+
#include "config.h"
|
17
|
+
#include "module.h"
|
18
|
+
#include "utility.h"
|
19
|
+
#include "resource.h"
|
20
|
+
|
21
|
+
////////////////////////////////////////////////////////////////////////////////
|
22
|
+
|
23
|
+
typedef struct {
|
24
|
+
char *filepath;
|
25
|
+
HMODULE handle;
|
26
|
+
} LOADED_LIBRARY_ENTRY;
|
27
|
+
|
28
|
+
typedef struct {
|
29
|
+
DWORD base_of_file;
|
30
|
+
IMAGE_DOS_HEADER *dos_header;
|
31
|
+
IMAGE_NT_HEADERS *nt_headers;
|
32
|
+
IMAGE_SECTION_HEADER *section;
|
33
|
+
DWORD base_of_import_table;
|
34
|
+
DWORD delta_of_import_table;
|
35
|
+
DWORD base_of_name_pool;
|
36
|
+
DWORD size_of_name_pool;
|
37
|
+
} IMPORT_TABLE_INFO;
|
38
|
+
|
39
|
+
////////////////////////////////////////////////////////////////////////////////
|
40
|
+
|
41
|
+
VALUE rb_mExerbRuntime = 0;
|
42
|
+
VALUE rb_eExerbRuntimeError = 0;
|
43
|
+
|
44
|
+
ARCHIVE_HEADER *g_archive_header = NULL;
|
45
|
+
NAME_TABLE_HEADER *g_name_table_header = NULL;
|
46
|
+
FILE_TABLE_HEADER *g_file_table_header = NULL;
|
47
|
+
|
48
|
+
int g_loaded_library_count = 0;
|
49
|
+
LOADED_LIBRARY_ENTRY g_loaded_library_table[32] = {0};
|
50
|
+
LOADED_LIBRARY_ENTRY g_pre_loaded_library_table[8] = {0};
|
51
|
+
|
52
|
+
int g_loaded_resource_count = 0;
|
53
|
+
HMODULE g_loaded_resource_table[4] = {0};
|
54
|
+
|
55
|
+
VALUE rb_load_path;
|
56
|
+
VALUE rb_argv0;
|
57
|
+
#ifndef RUBY19
|
58
|
+
VALUE rb_progname;
|
59
|
+
#endif
|
60
|
+
|
61
|
+
////////////////////////////////////////////////////////////////////////////////
|
62
|
+
|
63
|
+
#ifdef RUBY19
|
64
|
+
/* miniprelude.c, prelude.c */
|
65
|
+
void Init_prelude(void);
|
66
|
+
#endif
|
67
|
+
|
68
|
+
#ifdef RUBY19_COMPILED_CODE
|
69
|
+
/* not exposed by Ruby headers (only in iseq.h), so we define it here */
|
70
|
+
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
|
71
|
+
#endif
|
72
|
+
|
73
|
+
////////////////////////////////////////////////////////////////////////////////
|
74
|
+
|
75
|
+
int exerb_main(int argc, char** argv, void (*on_init)(VALUE, VALUE, VALUE), void (*on_fail)(VALUE));
|
76
|
+
static VALUE exerb_main_in_protect(VALUE replace_io);
|
77
|
+
static void exerb_mapping();
|
78
|
+
static void exerb_set_script_name(char* name);
|
79
|
+
static void exerb_setup_kcode();
|
80
|
+
static void exerb_setup_resource_library();
|
81
|
+
static void exerb_execute();
|
82
|
+
static void exerb_cleanup();
|
83
|
+
static int exerb_find_ruby_pre_loaded(const VALUE filename);
|
84
|
+
static int exerb_find_file_pre_loaded(const VALUE filename, VALUE *feature, LOADED_LIBRARY_ENTRY **loaded_library_entry);
|
85
|
+
static int exerb_find_file_inside(const VALUE filename, WORD *id, VALUE *feature, VALUE *realname);
|
86
|
+
static int exerb_find_file_outside(const VALUE filename, VALUE *feature, VALUE *realname);
|
87
|
+
static VALUE exerb_load_ruby_script(const FILE_ENTRY_HEADER *file_entry);
|
88
|
+
static VALUE exerb_load_ruby_script_from_file(const char *filepath);
|
89
|
+
#ifdef RUBY19_COMPILED_CODE
|
90
|
+
static VALUE exerb_load_compiled_script(const FILE_ENTRY_HEADER *file_entry);
|
91
|
+
#endif
|
92
|
+
static void exerb_load_extension_library(const FILE_ENTRY_HEADER *file_entry);
|
93
|
+
static void exerb_load_extension_library_from_file(const char *filepath);
|
94
|
+
static HMODULE exerb_load_library(const FILE_ENTRY_HEADER *file_entry);
|
95
|
+
static HMODULE exerb_load_library_ex(const char *base_of_file, const int size_of_file, const char* filepath, int no_replace_function);
|
96
|
+
static HMODULE exerb_preload_library(const FILE_ENTRY_HEADER *file_entry);
|
97
|
+
static int exerb_replace_import_dll(const char *base_of_file);
|
98
|
+
static void exerb_replace_import_dll_name(IMPORT_TABLE_INFO *info, const char *src_name, const char* new_name);
|
99
|
+
static int exerb_get_import_table_info(const char *base_of_file, IMPORT_TABLE_INFO *info);
|
100
|
+
static IMAGE_SECTION_HEADER* exerb_get_enclosing_section_header(const IMAGE_NT_HEADERS *nt_headers, const DWORD rva);
|
101
|
+
static void exerb_call_initialize_function(const HMODULE handle, const char *filepath);
|
102
|
+
static int exerb_find_resource(const DWORD base_of_image, const int type, const int id, DWORD *base_of_item, DWORD *size_of_item);
|
103
|
+
|
104
|
+
static void exerb_replace_import_function(const HMODULE module);
|
105
|
+
static int exerb_replace_import_function_thunk(const HMODULE module, const FARPROC src_proc, const FARPROC new_proc);
|
106
|
+
static HMODULE WINAPI exerb_hook_load_library(LPCTSTR filename);
|
107
|
+
static HMODULE WINAPI exerb_hook_load_library_ex(LPCTSTR filename, HANDLE file, DWORD flags);
|
108
|
+
static HMODULE WINAPI exerb_hook_get_module_handle(LPCTSTR filename);
|
109
|
+
static FARPROC WINAPI exerb_hook_get_proc_address(HMODULE module, LPCTSTR procname);
|
110
|
+
|
111
|
+
////////////////////////////////////////////////////////////////////////////////
|
112
|
+
|
113
|
+
int
|
114
|
+
exerb_main(int argc, char** argv, void (*on_init)(VALUE, VALUE, VALUE), void (*on_fail)(VALUE))
|
115
|
+
{
|
116
|
+
#ifdef RUBY19
|
117
|
+
ruby_sysinit(&argc, &argv);
|
118
|
+
RUBY_INIT_STACK;
|
119
|
+
ruby_init();
|
120
|
+
#else
|
121
|
+
NtInitialize(&argc, &argv);
|
122
|
+
ruby_init();
|
123
|
+
rb_ary_push(rb_load_path, rb_str_new2("."));
|
124
|
+
#endif
|
125
|
+
// argc = rb_w32_cmdvector(GetCommandLine(), &argv);
|
126
|
+
ruby_set_argv(argc - 1, argv + 1);
|
127
|
+
exerb_set_script_name((char *)"exerb");
|
128
|
+
|
129
|
+
int state = 0, result_code = 0;
|
130
|
+
rb_protect(exerb_main_in_protect, UINT2NUM((DWORD)on_init), &state);
|
131
|
+
|
132
|
+
if ( state ) {
|
133
|
+
#ifdef RUBY19
|
134
|
+
VALUE errinfo = rb_errinfo();
|
135
|
+
#else
|
136
|
+
VALUE errinfo = ruby_errinfo;
|
137
|
+
#endif
|
138
|
+
if ( rb_obj_is_kind_of(errinfo, rb_eSystemExit) ) {
|
139
|
+
result_code = FIX2INT(rb_iv_get(errinfo, "status"));
|
140
|
+
} else {
|
141
|
+
on_fail(errinfo);
|
142
|
+
result_code = 1;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
ruby_finalize();
|
147
|
+
exerb_cleanup();
|
148
|
+
|
149
|
+
return result_code;
|
150
|
+
}
|
151
|
+
|
152
|
+
static VALUE
|
153
|
+
exerb_main_in_protect(VALUE on_init_proc)
|
154
|
+
{
|
155
|
+
Init_ExerbRuntime();
|
156
|
+
|
157
|
+
void (*on_init)(VALUE, VALUE, VALUE) = (void(*)(VALUE, VALUE, VALUE))NUM2UINT(on_init_proc);
|
158
|
+
if ( on_init ) on_init(rb_stdin, rb_stdout, rb_stderr);
|
159
|
+
|
160
|
+
/* Hack require */
|
161
|
+
rb_define_global_function("require", exerb_rb_f_require, 1);
|
162
|
+
|
163
|
+
exerb_mapping();
|
164
|
+
exerb_setup_kcode();
|
165
|
+
exerb_setup_resource_library();
|
166
|
+
exerb_execute();
|
167
|
+
|
168
|
+
return Qnil;
|
169
|
+
}
|
170
|
+
|
171
|
+
static void
|
172
|
+
exerb_mapping()
|
173
|
+
{
|
174
|
+
const DWORD base_of_image = (DWORD)GetModuleHandle(NULL);
|
175
|
+
DWORD base_of_archive = 0, size_of_archive = 0;
|
176
|
+
if ( !exerb_find_resource(base_of_image, RT_EXERB, ID_EXERB, &base_of_archive, &size_of_archive) ) {
|
177
|
+
rb_raise(rb_eExerbRuntimeError, "The executable hasn't an archive.");
|
178
|
+
}
|
179
|
+
|
180
|
+
g_archive_header = (ARCHIVE_HEADER*)base_of_archive;
|
181
|
+
if ( g_archive_header->signature1 != ARCHIVE_HEADER_SIGNATURE1 ||
|
182
|
+
g_archive_header->signature2 != ARCHIVE_HEADER_SIGNATURE2 ) {
|
183
|
+
rb_raise(rb_eExerbRuntimeError, "The executable has invalid signature of archive header.");
|
184
|
+
}
|
185
|
+
if ( g_archive_header->offset_of_name_table == 0 ||
|
186
|
+
g_archive_header->offset_of_file_table == 0 ) {
|
187
|
+
rb_raise(rb_eExerbRuntimeError, "The executable has invalid archive header.");
|
188
|
+
}
|
189
|
+
|
190
|
+
g_name_table_header = (NAME_TABLE_HEADER*)(base_of_archive + g_archive_header->offset_of_name_table);
|
191
|
+
g_file_table_header = (FILE_TABLE_HEADER*)(base_of_archive + g_archive_header->offset_of_file_table);
|
192
|
+
|
193
|
+
if ( g_name_table_header->signature != NAME_TABLE_HEADER_SIGNATURE ) {
|
194
|
+
rb_raise(rb_eExerbRuntimeError, "The executable has invalid signature of the name table header.");
|
195
|
+
}
|
196
|
+
if ( g_file_table_header->signature != FILE_TABLE_HEADER_SIGNATURE ) {
|
197
|
+
rb_raise(rb_eExerbRuntimeError, "The executable has invalid signature of the file table header.");
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
static void
|
202
|
+
exerb_set_script_name(char* name)
|
203
|
+
{
|
204
|
+
ruby_script(name);
|
205
|
+
#ifdef RUBY19
|
206
|
+
rb_argv0 = rb_str_new2(name);
|
207
|
+
#else
|
208
|
+
rb_argv0 = rb_progname;
|
209
|
+
#endif
|
210
|
+
}
|
211
|
+
|
212
|
+
static void
|
213
|
+
exerb_setup_kcode()
|
214
|
+
{
|
215
|
+
#ifndef RUBY19
|
216
|
+
switch ( g_archive_header->kcode ) {
|
217
|
+
case ARCHIVE_HEADER_OPTIONS_KCODE_NONE: rb_set_kcode("n"); break;
|
218
|
+
case ARCHIVE_HEADER_OPTIONS_KCODE_EUC: rb_set_kcode("e"); break;
|
219
|
+
case ARCHIVE_HEADER_OPTIONS_KCODE_SJIS: rb_set_kcode("s"); break;
|
220
|
+
case ARCHIVE_HEADER_OPTIONS_KCODE_UTF8: _from_filerb_set_kcode("u"); break;
|
221
|
+
}
|
222
|
+
#else
|
223
|
+
exerb_require(rb_str_new2("enc/encdb"));
|
224
|
+
exerb_require(rb_str_new2("enc/utf_16le"));
|
225
|
+
exerb_require(rb_str_new2("enc/trans/transdb"));
|
226
|
+
exerb_require(rb_str_new2("enc/trans/utf_16_32"));
|
227
|
+
exerb_require(rb_str_new2("enc/trans/single_byte"));
|
228
|
+
Init_prelude();
|
229
|
+
#endif
|
230
|
+
}
|
231
|
+
|
232
|
+
static void
|
233
|
+
exerb_setup_resource_library()
|
234
|
+
{
|
235
|
+
FILE_ENTRY_HEADER *file_entry = exerb_get_first_file_entry();
|
236
|
+
|
237
|
+
for ( int i = 0; i < g_file_table_header->number_of_headers; i++, file_entry++ ) {
|
238
|
+
if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_RESOURCE_LIBRARY ) {
|
239
|
+
if ( (unsigned int)g_loaded_resource_count > sizeof(g_loaded_resource_table) / sizeof(HMODULE) ) {
|
240
|
+
rb_raise(rb_eExerbRuntimeError, "the loaded recourse table is too big.");
|
241
|
+
}
|
242
|
+
|
243
|
+
g_loaded_resource_table[g_loaded_resource_count] = exerb_load_library(file_entry);
|
244
|
+
g_loaded_resource_count++;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
static void
|
250
|
+
exerb_execute()
|
251
|
+
{
|
252
|
+
FILE_ENTRY_HEADER *file_entry = exerb_get_first_file_entry();
|
253
|
+
|
254
|
+
for ( int i = 0; i < g_file_table_header->number_of_headers; i++, file_entry++ ) {
|
255
|
+
if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_RUBY_SCRIPT ) {
|
256
|
+
exerb_set_script_name(exerb_get_name_from_entry(exerb_find_name_entry(file_entry->id)));
|
257
|
+
exerb_load_ruby_script(file_entry);
|
258
|
+
return;
|
259
|
+
#ifdef RUBY19_COMPILED_CODE
|
260
|
+
} else if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_COMPILED_SCRIPT ) {
|
261
|
+
exerb_set_script_name(exerb_get_name_from_entry(exerb_find_name_entry(file_entry->id)));
|
262
|
+
exerb_load_compiled_script(file_entry);
|
263
|
+
return;
|
264
|
+
#endif
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
rb_raise(rb_eExerbRuntimeError, "The startup script was not found.");
|
269
|
+
}
|
270
|
+
|
271
|
+
static void
|
272
|
+
exerb_cleanup()
|
273
|
+
{
|
274
|
+
for ( int i = g_loaded_library_count; i > 0; i-- ) {
|
275
|
+
const LOADED_LIBRARY_ENTRY *entry = &g_loaded_library_table[i - 1];
|
276
|
+
char filepath[MAX_PATH] = "";
|
277
|
+
GetModuleFileName(entry->handle, filepath, sizeof(filepath));
|
278
|
+
FreeLibrary(entry->handle);
|
279
|
+
DeleteFile(filepath);
|
280
|
+
free(entry->filepath);
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
VALUE
|
285
|
+
exerb_rb_f_require(VALUE obj, VALUE fname)
|
286
|
+
{
|
287
|
+
return exerb_require(fname);
|
288
|
+
}
|
289
|
+
|
290
|
+
VALUE
|
291
|
+
exerb_require(VALUE fname)
|
292
|
+
{
|
293
|
+
#ifdef RUBY19
|
294
|
+
SafeStringValue(fname);
|
295
|
+
#else
|
296
|
+
Check_SafeStr(fname);
|
297
|
+
#endif
|
298
|
+
LOADED_LIBRARY_ENTRY *loaded_library_entry = NULL;
|
299
|
+
WORD id = 0;
|
300
|
+
VALUE feature = Qnil, realname = Qnil;
|
301
|
+
|
302
|
+
if ( exerb_find_ruby_pre_loaded(fname) ) {
|
303
|
+
return Qfalse;
|
304
|
+
}
|
305
|
+
|
306
|
+
if ( exerb_find_file_pre_loaded(fname, &feature, &loaded_library_entry) ) {
|
307
|
+
rb_provide(RSTRING_PTR(feature));
|
308
|
+
exerb_call_initialize_function(loaded_library_entry->handle, loaded_library_entry->filepath);
|
309
|
+
free(loaded_library_entry->filepath);
|
310
|
+
loaded_library_entry->filepath = NULL;
|
311
|
+
loaded_library_entry->handle = NULL;
|
312
|
+
return Qtrue;
|
313
|
+
} else if ( exerb_find_file_inside(fname, &id, &feature, &realname) ) {
|
314
|
+
if ( rb_provided(RSTRING_PTR(feature)) ) return Qfalse;
|
315
|
+
|
316
|
+
FILE_ENTRY_HEADER *file_entry = exerb_find_file_entry(id);
|
317
|
+
|
318
|
+
switch ( file_entry->type_of_file ) {
|
319
|
+
case FILE_ENTRY_HEADER_TYPE_RUBY_SCRIPT:
|
320
|
+
rb_provide(RSTRING_PTR(feature));
|
321
|
+
exerb_load_ruby_script(file_entry);
|
322
|
+
return Qtrue;
|
323
|
+
#ifdef RUBY19_COMPILED_CODE
|
324
|
+
case FILE_ENTRY_HEADER_TYPE_COMPILED_SCRIPT:
|
325
|
+
rb_provide(RSTRING_PTR(feature));
|
326
|
+
exerb_load_compiled_script(file_entry);
|
327
|
+
return Qtrue;
|
328
|
+
#endif
|
329
|
+
case FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY:
|
330
|
+
rb_provide(RSTRING_PTR(feature));
|
331
|
+
exerb_load_extension_library(file_entry);
|
332
|
+
return Qtrue;
|
333
|
+
}
|
334
|
+
} else if ( exerb_find_file_outside(fname, &feature, &realname) ) {
|
335
|
+
if ( rb_provided(RSTRING_PTR(feature)) ) return Qfalse;
|
336
|
+
|
337
|
+
const char *ext = strrchr(RSTRING_PTR(feature), '.');
|
338
|
+
|
339
|
+
if ( stricmp(ext, ".rb") == 0 ) {
|
340
|
+
rb_provide(RSTRING_PTR(feature));
|
341
|
+
exerb_load_ruby_script_from_file(RSTRING_PTR(realname));
|
342
|
+
return Qtrue;
|
343
|
+
} else if ( stricmp(ext, ".so") == 0 ) {
|
344
|
+
rb_provide(RSTRING_PTR(feature));
|
345
|
+
exerb_load_extension_library_from_file(RSTRING_PTR(realname));
|
346
|
+
return Qtrue;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING_PTR(fname));
|
351
|
+
|
352
|
+
return Qfalse;
|
353
|
+
}
|
354
|
+
|
355
|
+
static char* EXTTBL[] = {(char *)"rb", (char *)"so", (char *)"dll" };
|
356
|
+
|
357
|
+
static int
|
358
|
+
exerb_find_ruby_pre_loaded(const VALUE filename)
|
359
|
+
{
|
360
|
+
const char* fname = RSTRING_PTR(filename);
|
361
|
+
if (strchr(fname, '.')) {
|
362
|
+
return rb_provided(fname) != Qfalse ? 1 : 0;
|
363
|
+
} else {
|
364
|
+
char* p = (char*)_alloca(strlen(fname) + 8);
|
365
|
+
for (int i = 0; (unsigned int)i < sizeof(EXTTBL)/sizeof(EXTTBL[0]); i++) {
|
366
|
+
sprintf(p, "%s.%s", fname, EXTTBL[i]);
|
367
|
+
if (rb_provided(p)) {
|
368
|
+
return 1;
|
369
|
+
}
|
370
|
+
}
|
371
|
+
}
|
372
|
+
return 0;
|
373
|
+
}
|
374
|
+
|
375
|
+
static int
|
376
|
+
exerb_find_file_pre_loaded(const VALUE filename, VALUE *feature, LOADED_LIBRARY_ENTRY **loaded_library_entry)
|
377
|
+
{
|
378
|
+
const char *fname = RSTRING_PTR(filename);
|
379
|
+
|
380
|
+
for ( int i = 0; (unsigned int)i < sizeof(g_pre_loaded_library_table) / sizeof(LOADED_LIBRARY_ENTRY); i++ ) {
|
381
|
+
const char *name = g_pre_loaded_library_table[i].filepath;
|
382
|
+
if ( !name ) continue;
|
383
|
+
|
384
|
+
if ( stricmp(name, fname) == 0 ) {
|
385
|
+
*feature = rb_str_new2(name);
|
386
|
+
*loaded_library_entry = &g_pre_loaded_library_table[i];
|
387
|
+
return 1;
|
388
|
+
} else if ( exerb_cmp_filename_with_ext(name, fname, "so") ) {
|
389
|
+
*feature = rb_str_new2(name);
|
390
|
+
*loaded_library_entry = &g_pre_loaded_library_table[i];
|
391
|
+
return 1;
|
392
|
+
} else if ( exerb_cmp_filename_with_ext(name, fname, "dll") ) {
|
393
|
+
*feature = rb_str_concat(rb_str_new2(fname), rb_str_new2(".so"));
|
394
|
+
*loaded_library_entry = &g_pre_loaded_library_table[i];
|
395
|
+
return 1;
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
return 0;
|
400
|
+
}
|
401
|
+
|
402
|
+
static int
|
403
|
+
exerb_find_file_inside(const VALUE filename, WORD *id, VALUE *feature, VALUE *realname)
|
404
|
+
{
|
405
|
+
#ifdef RUBY19
|
406
|
+
const char *fname = rb_string_value_ptr((volatile VALUE*) &filename);
|
407
|
+
#else
|
408
|
+
const char *fname = STR2CSTR(filename);
|
409
|
+
#endif
|
410
|
+
|
411
|
+
NAME_ENTRY_HEADER *name_entry = exerb_get_first_name_entry();
|
412
|
+
|
413
|
+
for ( int i = 0; i < g_name_table_header->number_of_headers; i++, name_entry++ ) {
|
414
|
+
const char *name = exerb_get_name_from_entry(name_entry);
|
415
|
+
|
416
|
+
if ( strcmp(name, fname) == 0 ) {
|
417
|
+
*id = name_entry->id;
|
418
|
+
*feature = rb_str_new2(name);
|
419
|
+
*realname = rb_str_new2(name);
|
420
|
+
return 1;
|
421
|
+
} else if ( exerb_cmp_filename_with_ext(name, fname, "rb") ) {
|
422
|
+
*id = name_entry->id;
|
423
|
+
*feature = rb_str_new2(name);
|
424
|
+
*realname = rb_str_new2(name);
|
425
|
+
return 1;
|
426
|
+
} else if ( exerb_cmp_filename_with_ext(name, fname, "so") ) {
|
427
|
+
*id = name_entry->id;
|
428
|
+
*feature = rb_str_new2(name);
|
429
|
+
*realname = rb_str_new2(name);
|
430
|
+
return 1;
|
431
|
+
} else if ( exerb_cmp_filename_with_ext(name, fname, "dll") ) {
|
432
|
+
FILE_ENTRY_HEADER* file_entry = exerb_find_file_entry(name_entry->id);
|
433
|
+
if (file_entry->type_of_file != FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY) continue;
|
434
|
+
|
435
|
+
*id = name_entry->id;
|
436
|
+
*feature = rb_str_concat(rb_str_new2(fname), rb_str_new2(".so"));
|
437
|
+
*realname = rb_str_new2(name);
|
438
|
+
return 1;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
*id = 0;
|
443
|
+
*feature = Qnil;
|
444
|
+
*realname = Qnil;
|
445
|
+
|
446
|
+
return 0;
|
447
|
+
}
|
448
|
+
|
449
|
+
static int
|
450
|
+
exerb_find_file_outside(const VALUE filename, VALUE *feature, VALUE *realname)
|
451
|
+
{
|
452
|
+
const VALUE filename_rb = rb_str_concat(rb_str_dup(filename), rb_str_new2(".rb"));
|
453
|
+
const VALUE filename_so = rb_str_concat(rb_str_dup(filename), rb_str_new2(".so"));
|
454
|
+
const VALUE filename_dll = rb_str_concat(rb_str_dup(filename), rb_str_new2(".dll"));
|
455
|
+
|
456
|
+
if ( *realname = rb_find_file(*feature = filename) ) return 1;
|
457
|
+
if ( *realname = rb_find_file(*feature = filename_rb) ) return 1;
|
458
|
+
if ( *realname = rb_find_file(*feature = filename_so) ) return 1;
|
459
|
+
if ( *realname = rb_find_file(filename_dll) ) { *feature = filename_so; return 1; }
|
460
|
+
|
461
|
+
*feature = Qnil;
|
462
|
+
*realname = Qnil;
|
463
|
+
|
464
|
+
return 0;
|
465
|
+
}
|
466
|
+
|
467
|
+
static VALUE
|
468
|
+
exerb_load_ruby_script(const FILE_ENTRY_HEADER *file_entry)
|
469
|
+
{
|
470
|
+
ID id_eval = rb_intern("eval");
|
471
|
+
VALUE binding = rb_const_get(rb_mKernel, rb_intern("TOPLEVEL_BINDING"));
|
472
|
+
VALUE lineno = INT2FIX(1);
|
473
|
+
|
474
|
+
const VALUE code = exerb_get_file_from_entry2(file_entry);
|
475
|
+
const VALUE name = rb_str_new2(exerb_get_name_from_entry(exerb_find_name_entry(file_entry->id)));
|
476
|
+
|
477
|
+
return rb_funcall(rb_mKernel, id_eval, 4, code, binding, name, lineno);
|
478
|
+
}
|
479
|
+
|
480
|
+
static VALUE
|
481
|
+
exerb_load_ruby_script_from_file(const char *filepath)
|
482
|
+
{
|
483
|
+
rb_load(rb_str_new2(filepath), 0);
|
484
|
+
return Qnil;
|
485
|
+
}
|
486
|
+
|
487
|
+
#ifdef RUBY19_COMPILED_CODE
|
488
|
+
static VALUE
|
489
|
+
exerb_load_compiled_script(const FILE_ENTRY_HEADER *file_entry)
|
490
|
+
{
|
491
|
+
ID id_eval = rb_intern("eval");
|
492
|
+
const VALUE code = exerb_get_file_from_entry2(file_entry);
|
493
|
+
const VALUE iseq_ary = rb_marshal_load(code);
|
494
|
+
const VALUE iseq = rb_iseq_load(iseq_ary, Qnil, Qnil);
|
495
|
+
|
496
|
+
return rb_funcall(iseq, id_eval, 0);
|
497
|
+
}
|
498
|
+
#endif
|
499
|
+
|
500
|
+
static void
|
501
|
+
exerb_load_extension_library(const FILE_ENTRY_HEADER *file_entry)
|
502
|
+
{
|
503
|
+
const HMODULE handle = exerb_load_library(file_entry);
|
504
|
+
const char *filepath = exerb_get_name_from_entry(exerb_find_name_entry(file_entry->id));
|
505
|
+
exerb_call_initialize_function(handle, filepath);
|
506
|
+
}
|
507
|
+
|
508
|
+
static void
|
509
|
+
exerb_load_extension_library_from_file(const char *filepath)
|
510
|
+
{
|
511
|
+
const HANDLE file = exerb_fopen_for_read(filepath);
|
512
|
+
const DWORD size = exerb_fsize(file);
|
513
|
+
char *buffer = malloc(size);
|
514
|
+
exerb_fread(file, buffer, size);
|
515
|
+
exerb_fclose(file);
|
516
|
+
|
517
|
+
const HMODULE handle = exerb_load_library_ex(buffer, size, filepath, 0);
|
518
|
+
exerb_call_initialize_function(handle, filepath);
|
519
|
+
|
520
|
+
free(buffer);
|
521
|
+
}
|
522
|
+
|
523
|
+
static HMODULE
|
524
|
+
exerb_load_library(const FILE_ENTRY_HEADER *file_entry)
|
525
|
+
{
|
526
|
+
const char *base_of_file = exerb_get_file_from_entry1(file_entry);
|
527
|
+
const char *filepath = exerb_get_name_from_entry(exerb_find_name_entry(file_entry->id));
|
528
|
+
return exerb_load_library_ex(base_of_file, file_entry->size_of_file, filepath, (int)file_entry->flag_no_replace_function);
|
529
|
+
}
|
530
|
+
|
531
|
+
static HMODULE
|
532
|
+
exerb_load_library_ex(const char *base_of_file, const int size_of_file, const char* filepath, int no_replace_function)
|
533
|
+
{
|
534
|
+
if ((unsigned int)g_loaded_library_count > sizeof(g_loaded_library_table) / sizeof(LOADED_LIBRARY_ENTRY) ) {
|
535
|
+
rb_raise(rb_eExerbRuntimeError, "the loaded library table is too big.");
|
536
|
+
}
|
537
|
+
|
538
|
+
DWORD protect = 0, dummy = 0;
|
539
|
+
VirtualProtect((void*)base_of_file, size_of_file, PAGE_READWRITE, &protect);
|
540
|
+
exerb_replace_import_dll(base_of_file);
|
541
|
+
VirtualProtect((void*)base_of_file, size_of_file, protect, &dummy);
|
542
|
+
|
543
|
+
char tmp_filepath[MAX_PATH] = "";
|
544
|
+
exerb_create_tmpfile("exerb", tmp_filepath, base_of_file, size_of_file);
|
545
|
+
|
546
|
+
const HMODULE handle = LoadLibraryEx(tmp_filepath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
547
|
+
if ( !handle ) {
|
548
|
+
DWORD error = GetLastError();
|
549
|
+
DeleteFile(tmp_filepath);
|
550
|
+
exerb_raise_runtime_error(error);
|
551
|
+
}
|
552
|
+
|
553
|
+
g_loaded_library_table[g_loaded_library_count].filepath = exerb_strdup(filepath);
|
554
|
+
g_loaded_library_table[g_loaded_library_count].handle = handle;
|
555
|
+
g_loaded_library_count++;
|
556
|
+
|
557
|
+
if ( !no_replace_function ) exerb_replace_import_function(handle);
|
558
|
+
|
559
|
+
return handle;
|
560
|
+
}
|
561
|
+
|
562
|
+
static HMODULE
|
563
|
+
exerb_preload_library(const FILE_ENTRY_HEADER *file_entry)
|
564
|
+
{
|
565
|
+
NAME_ENTRY_HEADER *name_entry = exerb_find_name_entry(file_entry->id);
|
566
|
+
const char *name = exerb_get_name_from_entry(name_entry);
|
567
|
+
|
568
|
+
for ( int i = 0; i < g_loaded_library_count; i++ ) {
|
569
|
+
if ( g_loaded_library_table[i].filepath && stricmp(g_loaded_library_table[i].filepath, name) == 0 ) {
|
570
|
+
return g_loaded_library_table[i].handle;
|
571
|
+
}
|
572
|
+
}
|
573
|
+
|
574
|
+
HMODULE module = exerb_load_library(file_entry);
|
575
|
+
|
576
|
+
if (file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY ) {
|
577
|
+
for ( int i = 0; (unsigned int)i < sizeof(g_pre_loaded_library_table) / sizeof(LOADED_LIBRARY_ENTRY); i++ ) {
|
578
|
+
if ( !g_pre_loaded_library_table[i].handle ) {
|
579
|
+
g_pre_loaded_library_table[i].filepath = exerb_strdup(name);
|
580
|
+
g_pre_loaded_library_table[i].handle = module;
|
581
|
+
break;
|
582
|
+
}
|
583
|
+
}
|
584
|
+
}
|
585
|
+
|
586
|
+
return module;
|
587
|
+
}
|
588
|
+
|
589
|
+
static int
|
590
|
+
exerb_replace_import_dll(const char *base_of_file)
|
591
|
+
{
|
592
|
+
IMPORT_TABLE_INFO info = {0};
|
593
|
+
if ( !exerb_get_import_table_info(base_of_file, &info) ) return 0;
|
594
|
+
|
595
|
+
char self_filepath[MAX_PATH] = "";
|
596
|
+
const char *self_filename = exerb_get_self_filepath(self_filepath, sizeof(self_filepath));
|
597
|
+
|
598
|
+
exerb_replace_import_dll_name(&info, EXERB_LIBRUBY_SO, self_filename);
|
599
|
+
|
600
|
+
return 1;
|
601
|
+
}
|
602
|
+
|
603
|
+
static void
|
604
|
+
exerb_replace_import_dll_name(IMPORT_TABLE_INFO *info, const char *src_name, const char* new_name)
|
605
|
+
{
|
606
|
+
const DWORD base_of_name = info->base_of_file - info->delta_of_import_table;
|
607
|
+
const DWORD size_of_new_name = strlen(new_name);
|
608
|
+
FILE_ENTRY_HEADER *file_entry;
|
609
|
+
|
610
|
+
IMAGE_IMPORT_DESCRIPTOR *first_descriptor = (IMAGE_IMPORT_DESCRIPTOR*)(info->base_of_file + info->base_of_import_table);
|
611
|
+
|
612
|
+
for ( IMAGE_IMPORT_DESCRIPTOR *descriptor = first_descriptor; descriptor->Name; descriptor++ ) {
|
613
|
+
char *name = (char*)(base_of_name + descriptor->Name);
|
614
|
+
|
615
|
+
if ( stricmp(name, src_name) == 0 ) {
|
616
|
+
int found = 0;
|
617
|
+
for ( IMAGE_IMPORT_DESCRIPTOR *desc = first_descriptor; desc->Name; desc++ ) {
|
618
|
+
if ( strcmp((char*)(base_of_name + desc->Name), new_name) == 0 ) {
|
619
|
+
descriptor->Name = desc->Name;
|
620
|
+
found = 1;
|
621
|
+
break;
|
622
|
+
}
|
623
|
+
}
|
624
|
+
if ( found ) continue;
|
625
|
+
|
626
|
+
if ( strlen(name) >= size_of_new_name ) {
|
627
|
+
strcpy(name, new_name);
|
628
|
+
} else if ( size_of_new_name + 1 <= info->size_of_name_pool ) {
|
629
|
+
DWORD address_of_new_name = info->base_of_name_pool - (size_of_new_name + 1);
|
630
|
+
|
631
|
+
strcpy((char*)(info->base_of_file + address_of_new_name), new_name);
|
632
|
+
descriptor->Name = address_of_new_name + info->delta_of_import_table;
|
633
|
+
|
634
|
+
info->base_of_name_pool -= size_of_new_name + 1;
|
635
|
+
info->size_of_name_pool -= size_of_new_name + 1;
|
636
|
+
} else {
|
637
|
+
rb_raise(rb_eLoadError, "Couldn't modify DLL's name in the import table. The name of the executable file is too long.");
|
638
|
+
}
|
639
|
+
} else if ( file_entry = exerb_find_file_entry_by_filename(name, NULL) ) {
|
640
|
+
if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY ||
|
641
|
+
file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_DYNAMIC_LIBRARY ) {
|
642
|
+
HMODULE module = exerb_preload_library(file_entry);
|
643
|
+
char filepath[MAX_PATH] = "";
|
644
|
+
const char *filename = exerb_get_module_filepath(module, filepath, sizeof(filepath));
|
645
|
+
exerb_replace_import_dll_name(info, name, filename);
|
646
|
+
}
|
647
|
+
}
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
static int
|
652
|
+
exerb_get_import_table_info(const char *base_of_file, IMPORT_TABLE_INFO *info)
|
653
|
+
{
|
654
|
+
info->base_of_file = (DWORD)base_of_file;
|
655
|
+
info->dos_header = (IMAGE_DOS_HEADER*)info->base_of_file;
|
656
|
+
info->nt_headers = (IMAGE_NT_HEADERS*)(info->base_of_file + info->dos_header->e_lfanew);
|
657
|
+
|
658
|
+
const DWORD rva_of_import_table = info->nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
659
|
+
|
660
|
+
info->section = exerb_get_enclosing_section_header(info->nt_headers, rva_of_import_table);
|
661
|
+
if ( !info->section ) return 0;
|
662
|
+
|
663
|
+
info->delta_of_import_table = info->section->VirtualAddress - info->section->PointerToRawData;
|
664
|
+
info->base_of_import_table = rva_of_import_table - info->delta_of_import_table;
|
665
|
+
|
666
|
+
if ( strnicmp((char*)info->section->Name, ".idata", 8) == 0 || // for Boland's Compiler
|
667
|
+
strnicmp((char*)info->section->Name, ".rdata", 8) == 0 ) { // for Microsoft's Compiler
|
668
|
+
info->base_of_name_pool = info->section->PointerToRawData + info->section->SizeOfRawData;
|
669
|
+
info->size_of_name_pool = info->section->SizeOfRawData - info->section->Misc.VirtualSize;
|
670
|
+
} else {
|
671
|
+
info->base_of_name_pool = 0;
|
672
|
+
info->size_of_name_pool = 0;
|
673
|
+
}
|
674
|
+
|
675
|
+
return 1;
|
676
|
+
}
|
677
|
+
|
678
|
+
static IMAGE_SECTION_HEADER*
|
679
|
+
exerb_get_enclosing_section_header(const IMAGE_NT_HEADERS *nt_headers, const DWORD rva)
|
680
|
+
{
|
681
|
+
IMAGE_SECTION_HEADER *section = IMAGE_FIRST_SECTION(nt_headers);
|
682
|
+
|
683
|
+
for ( int i = 0; i < nt_headers->FileHeader.NumberOfSections; i++, section++ ) {
|
684
|
+
if ( (rva >= section->VirtualAddress) && (rva < (section->VirtualAddress + section->Misc.VirtualSize)) ) {
|
685
|
+
return section;
|
686
|
+
}
|
687
|
+
}
|
688
|
+
|
689
|
+
return NULL;
|
690
|
+
}
|
691
|
+
|
692
|
+
static void
|
693
|
+
exerb_call_initialize_function(const HMODULE handle, const char *filepath)
|
694
|
+
{
|
695
|
+
const char *filename = exerb_get_filename(filepath);
|
696
|
+
char funcname[128] = "Init_";
|
697
|
+
strncat(funcname, filename, sizeof(funcname) - strlen(funcname) - 1);
|
698
|
+
|
699
|
+
char *ext = strrchr(funcname, '.');
|
700
|
+
if ( ext && (stricmp(ext, ".so") == 0 || stricmp(ext, ".dll") == 0) ) {
|
701
|
+
*ext = '\0';
|
702
|
+
}
|
703
|
+
|
704
|
+
void (*init_proc)(void) = (void (*)(void))GetProcAddress(handle, funcname);
|
705
|
+
if ( !init_proc ) rb_raise(rb_eExerbRuntimeError, "Couldn't call the initialize function in the extension library. --- %s(%s)", filepath, funcname);
|
706
|
+
|
707
|
+
(*init_proc)();
|
708
|
+
}
|
709
|
+
|
710
|
+
static int
|
711
|
+
exerb_find_resource(const DWORD base_of_image, const int type, const int id, DWORD *base_of_item, DWORD *size_of_item)
|
712
|
+
{
|
713
|
+
const IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)base_of_image;
|
714
|
+
const IMAGE_NT_HEADERS *nt_headers = (IMAGE_NT_HEADERS*)(base_of_image + dos_header->e_lfanew);
|
715
|
+
|
716
|
+
const DWORD base_of_resource = base_of_image + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
|
717
|
+
if ( base_of_resource == base_of_image ) return 0;
|
718
|
+
|
719
|
+
const IMAGE_RESOURCE_DIRECTORY *root_dir = (IMAGE_RESOURCE_DIRECTORY*)base_of_resource;
|
720
|
+
const IMAGE_RESOURCE_DIRECTORY_ENTRY *root_entries = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(root_dir + 1);
|
721
|
+
|
722
|
+
for ( WORD i = 0; i < root_dir->NumberOfNamedEntries + root_dir->NumberOfIdEntries; i++ ) {
|
723
|
+
if ( !root_entries[i].NameIsString && root_entries[i].Id == type ) {
|
724
|
+
const IMAGE_RESOURCE_DIRECTORY *type_dir = (IMAGE_RESOURCE_DIRECTORY*)(base_of_resource + root_entries[i].OffsetToDirectory);
|
725
|
+
const IMAGE_RESOURCE_DIRECTORY_ENTRY *type_entries = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(type_dir + 1);
|
726
|
+
|
727
|
+
for ( WORD j = 0; j < type_dir->NumberOfNamedEntries + type_dir->NumberOfIdEntries; j++ ) {
|
728
|
+
if ( !type_entries[j].NameIsString && type_entries[j].Id == id ) {
|
729
|
+
const IMAGE_RESOURCE_DIRECTORY *item_dir = (IMAGE_RESOURCE_DIRECTORY*)(base_of_resource + type_entries[j].OffsetToDirectory);
|
730
|
+
const IMAGE_RESOURCE_DIRECTORY_ENTRY *item_entries = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(item_dir + 1);
|
731
|
+
const IMAGE_RESOURCE_DATA_ENTRY *data_entry = (IMAGE_RESOURCE_DATA_ENTRY*)(base_of_resource + item_entries[0].OffsetToData);
|
732
|
+
|
733
|
+
if ( base_of_item ) *base_of_item = base_of_image + data_entry->OffsetToData;
|
734
|
+
if ( size_of_item ) *size_of_item = data_entry->Size;
|
735
|
+
|
736
|
+
return 1;
|
737
|
+
}
|
738
|
+
}
|
739
|
+
}
|
740
|
+
}
|
741
|
+
|
742
|
+
return 0;
|
743
|
+
}
|
744
|
+
|
745
|
+
////////////////////////////////////////////////////////////////////////////////
|
746
|
+
static void
|
747
|
+
exerb_replace_import_function(const HMODULE module)
|
748
|
+
{
|
749
|
+
HMODULE kernel32 = GetModuleHandle("kernel32.dll");
|
750
|
+
FARPROC load_library_proc = GetProcAddress(kernel32, "LoadLibraryA");
|
751
|
+
FARPROC load_library_ex_proc = GetProcAddress(kernel32, "LoadLibraryExA");
|
752
|
+
FARPROC get_module_handle = GetProcAddress(kernel32, "GetModuleHandleA");
|
753
|
+
FARPROC get_proc_address_proc = GetProcAddress(kernel32, "GetProcAddress");
|
754
|
+
|
755
|
+
HMODULE self = GetModuleHandle(NULL);
|
756
|
+
FARPROC rb_require_proc = GetProcAddress(self, "rb_require");
|
757
|
+
|
758
|
+
#ifdef RUBY19
|
759
|
+
FARPROC rb_require_safe_proc = GetProcAddress(self, "rb_require_safe");
|
760
|
+
#endif
|
761
|
+
|
762
|
+
exerb_replace_import_function_thunk(module, load_library_proc, (FARPROC)exerb_hook_load_library);
|
763
|
+
exerb_replace_import_function_thunk(module, load_library_ex_proc, (FARPROC)exerb_hook_load_library_ex);
|
764
|
+
exerb_replace_import_function_thunk(module, get_module_handle, (FARPROC)exerb_hook_get_module_handle);
|
765
|
+
exerb_replace_import_function_thunk(module, get_proc_address_proc, (FARPROC)exerb_hook_get_proc_address);
|
766
|
+
|
767
|
+
// replace rb_require and rb_require_safe used by extension with ours
|
768
|
+
exerb_replace_import_function_thunk(module, rb_require_proc, (FARPROC)rb_require);
|
769
|
+
|
770
|
+
#ifdef RUBY19
|
771
|
+
exerb_replace_import_function_thunk(module, rb_require_safe_proc, (FARPROC)rb_require_safe);
|
772
|
+
#endif
|
773
|
+
}
|
774
|
+
|
775
|
+
static int
|
776
|
+
exerb_replace_import_function_thunk(const HMODULE module, const FARPROC src_proc, const FARPROC new_proc)
|
777
|
+
{
|
778
|
+
const DWORD base_of_image = (DWORD)module;
|
779
|
+
const IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER*)base_of_image;
|
780
|
+
const IMAGE_NT_HEADERS *nt_headers = (IMAGE_NT_HEADERS*)(base_of_image + dos_header->e_lfanew);
|
781
|
+
|
782
|
+
const DWORD base_of_import = base_of_image + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
783
|
+
if ( base_of_import == base_of_image ) return 0;
|
784
|
+
|
785
|
+
for ( IMAGE_IMPORT_DESCRIPTOR *desc = (IMAGE_IMPORT_DESCRIPTOR*)base_of_import; desc->Name; desc++ ) {
|
786
|
+
for ( DWORD *thunk = (DWORD*)(base_of_image + desc->FirstThunk); *thunk; thunk++ ) {
|
787
|
+
if ( *thunk == (DWORD)src_proc ) {
|
788
|
+
DWORD protect = 0, dummy = 0;
|
789
|
+
VirtualProtect(thunk, sizeof(DWORD), PAGE_READWRITE, &protect);
|
790
|
+
*thunk = (DWORD)new_proc;
|
791
|
+
VirtualProtect(thunk, sizeof(DWORD), protect, &dummy);
|
792
|
+
return 1;
|
793
|
+
}
|
794
|
+
}
|
795
|
+
}
|
796
|
+
|
797
|
+
return 0;
|
798
|
+
}
|
799
|
+
|
800
|
+
static HMODULE WINAPI
|
801
|
+
exerb_hook_load_library(LPCTSTR filename)
|
802
|
+
{
|
803
|
+
_RPT1(_CRT_WARN, "exerb_hook_load_library('%s')\n", filename);
|
804
|
+
|
805
|
+
FILE_ENTRY_HEADER *file_entry;
|
806
|
+
|
807
|
+
if ( filename ) {
|
808
|
+
if ( stricmp(filename, EXERB_LIBRUBY_NAME) == 0 ||
|
809
|
+
stricmp(filename, EXERB_LIBRUBY_SO) == 0 ) {
|
810
|
+
return GetModuleHandle(NULL);
|
811
|
+
} else if ( file_entry = exerb_find_file_entry_by_filename(filename, "dll") ) {
|
812
|
+
if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY ||
|
813
|
+
file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_DYNAMIC_LIBRARY ) {
|
814
|
+
return exerb_preload_library(file_entry);
|
815
|
+
}
|
816
|
+
}
|
817
|
+
}
|
818
|
+
|
819
|
+
return LoadLibrary(filename);
|
820
|
+
}
|
821
|
+
|
822
|
+
static HMODULE WINAPI
|
823
|
+
exerb_hook_load_library_ex(LPCTSTR filename, HANDLE file, DWORD flags)
|
824
|
+
{
|
825
|
+
_RPT3(_CRT_WARN, "exerb_hook_load_library_ex('%s', %i, %i)\n", filename, file, flags);
|
826
|
+
|
827
|
+
FILE_ENTRY_HEADER *file_entry;
|
828
|
+
|
829
|
+
if ( filename ) {
|
830
|
+
if ( stricmp(filename, EXERB_LIBRUBY_NAME) == 0 ||
|
831
|
+
stricmp(filename, EXERB_LIBRUBY_SO) == 0 ) {
|
832
|
+
return GetModuleHandle(NULL);
|
833
|
+
} else if (file_entry = exerb_find_file_entry_by_filename(filename, "dll") ) {
|
834
|
+
if ( file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_EXTENSION_LIBRARY ||
|
835
|
+
file_entry->type_of_file == FILE_ENTRY_HEADER_TYPE_DYNAMIC_LIBRARY ) {
|
836
|
+
return exerb_preload_library(file_entry);
|
837
|
+
}
|
838
|
+
}
|
839
|
+
}
|
840
|
+
|
841
|
+
return LoadLibraryEx(filename, file, flags);
|
842
|
+
}
|
843
|
+
|
844
|
+
static HMODULE WINAPI
|
845
|
+
exerb_hook_get_module_handle(LPCTSTR filename)
|
846
|
+
{
|
847
|
+
_RPT1(_CRT_WARN, "exerb_hook_get_module_handle('%s')\n", filename);
|
848
|
+
|
849
|
+
if ( filename && (stricmp(filename, EXERB_LIBRUBY_NAME) == 0 ||
|
850
|
+
stricmp(filename, EXERB_LIBRUBY_SO) == 0) ) {
|
851
|
+
return GetModuleHandle(NULL);
|
852
|
+
}
|
853
|
+
|
854
|
+
return GetModuleHandle(filename);
|
855
|
+
}
|
856
|
+
|
857
|
+
static FARPROC WINAPI
|
858
|
+
exerb_hook_get_proc_address(HMODULE module, LPCTSTR procname)
|
859
|
+
{
|
860
|
+
_RPT2(_CRT_WARN, "exerb_hook_get_proc_address(0x%08X, '%s')\n", module, procname);
|
861
|
+
|
862
|
+
HMODULE kernel32 = GetModuleHandle("kernel32.dll");
|
863
|
+
|
864
|
+
// FIXME: �����ɂ��C���|�[�g�ɑΉ�����
|
865
|
+
|
866
|
+
if ( module == kernel32 ) {
|
867
|
+
if ( strcmp(procname, "LoadLibraryA") == 0 ) return (FARPROC)exerb_hook_load_library;
|
868
|
+
else if ( strcmp(procname, "LoadLibraryExA") == 0 ) return (FARPROC)exerb_hook_load_library_ex;
|
869
|
+
else if ( strcmp(procname, "GetModuleHandleA") == 0 ) return (FARPROC)exerb_hook_get_module_handle;
|
870
|
+
else if ( strcmp(procname, "GetProcAddress") == 0 ) return (FARPROC)exerb_hook_get_proc_address;
|
871
|
+
}
|
872
|
+
|
873
|
+
return GetProcAddress(module, procname);
|
874
|
+
}
|
875
|
+
|
876
|
+
|
877
|
+
////////////////////////////////////////////////////////////////////////////////
|