undll32 0.2.0 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79d24bcf938e3a23a7e87f932a6189c7248b690a1fc5766e7907cf056b0967e6
4
- data.tar.gz: 29faa69356a53024534261b815fa3f7c3bfd5d01f429877fe5c6f1f5da273572
3
+ metadata.gz: 59acbe9b221095472b7f22916b35b3b1c704248c8c89a0434322e59f20d05435
4
+ data.tar.gz: 0dcb7e45987554109eb5160d22f93f974264df6e2d0296c37f586cddfc414523
5
5
  SHA512:
6
- metadata.gz: f336b0b7936b6e1dd2d744126263e00869a68500e8346ce971393f8dfbc7520d4068b70cc7c3c3cc3187a5ae809b9b934f2a6c56724fcf6919284ae046736230
7
- data.tar.gz: 490a671e93edc615934ae0372731aebec5d6978c54d2e4ffba85cfd978ab7f5ccf562e42d0ac9c44b15aada37e34c24bf6ec9c455039266de5f58f19d9956c82
6
+ metadata.gz: 04f13a36ca8ac4eaeb8aa391e99dfd955ddff22b9a506af1ec2a591137ce7ec4ee85f7e8985bd37f7626111cf511af327d24850e2775f51236712dcf67890731
7
+ data.tar.gz: 37acf71e14b0eabcf9408d9c3ccc889891cf5a133c52123b1765f77fbac6ed76c3fc58fe7c3340bdc2e1c4f81e747e2540ee28687f681abb71262affabaf9407
data/Gemfile.lock CHANGED
@@ -1,20 +1,21 @@
1
- PATH
2
- remote: .
3
- specs:
4
- undll32 (0.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- rake (10.5.0)
10
-
11
- PLATFORMS
12
- x64-mingw32
13
-
14
- DEPENDENCIES
15
- bundler (~> 1.16)
16
- rake (~> 10.0)
17
- undll32!
18
-
19
- BUNDLED WITH
20
- 1.16.2
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ undll32 (0.3.4)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (13.0.3)
10
+
11
+ PLATFORMS
12
+ ruby
13
+ x64-mingw32
14
+
15
+ DEPENDENCIES
16
+ bundler (~> 2.2.9)
17
+ rake (~> 13.0)
18
+ undll32!
19
+
20
+ BUNDLED WITH
21
+ 2.2.9
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 hyrious
3
+ Copyright (c) 2019 hyrious
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -22,9 +22,15 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- - `undll32`: `undll32 User32,MessageBox 0 hello world 0`
26
- - `ruby -r`: `ruby -rundll32 -e Undll32.exe -- User32,MessageBox 0 hello world 0`
27
- - Program: `Undll32.run('User32', 'MessageBox', 0, 'hello', 'world', 0)`
25
+ - Command line:
26
+ ```
27
+ undll32 User32,MessageBox 0 hello world 0
28
+ ruby -rundll32 -e Undll32.exe -- User32,MessageBox 0 hello world 0
29
+ ```
30
+ - Program:
31
+ ```ruby
32
+ Undll32.run('User32', 'MessageBox', 0, 'hello', 'world', 0)
33
+ ```
28
34
 
29
35
  ## Development
30
36
 
data/lib/undll32.rb CHANGED
@@ -1,13 +1,57 @@
1
1
  require "undll32/version"
2
- require 'win32api'
2
+ require 'fiddle/import'
3
3
 
4
4
  ##
5
5
  # Undll32
6
6
  # replacement of Windows' rundll32.exe
7
7
  module Undll32
8
8
 
9
+ class Win32API
10
+ DLL = {}
11
+ TYPEMAP = {
12
+ '0' => Fiddle::TYPE_VOID,
13
+ 'S' => Fiddle::TYPE_VOIDP,
14
+ 'I' => Fiddle::TYPE_LONG,
15
+ }
16
+ POINTER_TYPE =
17
+ Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
18
+ WIN32_TYPES = 'VPpNnLlIi'
19
+ DL_TYPES = '0SSI'
20
+
21
+ def initialize(dllname, func, import, export = '0', calltype = :stdcall)
22
+ @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
23
+ import = @proto.chars.map { |e| TYPEMAP[e.tr(WIN32_TYPES, DL_TYPES)] }
24
+ export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
25
+ calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
26
+ handle = DLL[dllname] ||=
27
+ begin
28
+ Fiddle.dlopen(dllname)
29
+ rescue Fiddle::DLError
30
+ raise unless File.extname(dllname).empty?
31
+ Fiddle.dlopen("#{dllname}.dll")
32
+ end
33
+ @func = Fiddle::Function.new(handle[func], import, export, calltype)
34
+ rescue Fiddle::DLError => e
35
+ raise LoadError, e.message, e.backtrace
36
+ end
37
+
38
+ def call(*args)
39
+ import = @proto.split('')
40
+ args.each_with_index do |x, i|
41
+ if import[i] == 'S'
42
+ args[i], = [x == 0 ? nil : x].pack('p').unpack(POINTER_TYPE)
43
+ end
44
+ args[i], = [x].pack('I').unpack('i') if import[i] == 'I'
45
+ end
46
+ ret, = @func.call(*args)
47
+ ret || 0
48
+ end
49
+
50
+ alias Call call
51
+ end
52
+
9
53
  ##
10
- # represents a string/struct
54
+ # represents a string/struct.
11
55
  # Buffer.new({ :x => :L, :y => 4 })
12
56
  # Buffer.new([ :L, 4 ])
13
57
  # Buffer.new(:L)
@@ -15,6 +59,8 @@ module Undll32
15
59
  # buffer.buffer => "\0\0\0\0"
16
60
  # buffer.unpack => 0
17
61
  class Buffer
62
+ attr_accessor :struct
63
+
18
64
  def initialize struct
19
65
  case struct
20
66
  when Hash, Array, Symbol, Integer
@@ -33,22 +79,63 @@ module Undll32
33
79
  _unpack @struct
34
80
  end
35
81
 
36
- def _unpack x
82
+ def load v
83
+ @_i = 0
84
+ _load @struct, v
85
+ unpack
86
+ end
87
+
88
+ def _load x, v
37
89
  case x
38
90
  when Integer
39
- buffer[(@_i += x) - x, x].sub(/\0+$/, '')
91
+ return @_i += x if v.nil?
92
+ unless String === v
93
+ raise ArgumentError, "expected str, got #{v}"
94
+ end
95
+ x = [x, v.length].min
96
+ buffer[(@_i += x) - x, x] = v[0, x]
40
97
  when Symbol
41
98
  n = { C: 1, S: 2, L: 4, Q: 8 }[x]
42
99
  if n.nil?
43
100
  raise ArgumentError, "expected CSLQ, got #{x}"
44
101
  end
102
+ return @_i += n if v.nil?
103
+ unless Integer === v
104
+ raise ArgumentError, "expected int, got #{v}"
105
+ end
106
+ buffer[(@_i += n) - n, n] = [v].pack("#{x}")
107
+ when Array
108
+ return x.each { |a| _load a, nil } if v.nil?
109
+ unless Array === v and v.size == x.size
110
+ raise ArgumentError, "expected array[#{x.size}], got #{v}"
111
+ end
112
+ x.zip(v) { |a, b| _load a, b }
113
+ when Hash
114
+ return x.each { |k, y| _load y, nil } if v.nil?
115
+ unless Hash === v
116
+ raise ArgumentError, "expected hash, got #{v}"
117
+ end
118
+ x.each { |k, y| _load y, v[k] }
119
+ else
120
+ raise ArgumentError, "expected hash, array, sym, int, got #{x}"
121
+ end
122
+ ensure
123
+ $@.shift if $@
124
+ end
125
+
126
+ def _unpack x
127
+ case x
128
+ when Integer
129
+ buffer[(@_i += x) - x, x].sub(/\0+$/, '')
130
+ when Symbol
131
+ n = { C: 1, S: 2, L: 4, Q: 8 }[x]
45
132
  buffer[(@_i += n) - n, n].unpack1("#{x}")
46
133
  when Array
47
134
  x.map { |e| _unpack e }
48
135
  when Hash
49
136
  Hash[x.map { |k, v| [k, _unpack(v)] }]
50
137
  else
51
- raise ArgumentError, "expected hash, array, sym, int, got #{struct}"
138
+ raise ArgumentError, "expected hash, array, sym, int, got #{x}"
52
139
  end
53
140
  ensure
54
141
  $@.shift if $@
@@ -69,50 +156,135 @@ module Undll32
69
156
  when Hash
70
157
  _buffer x.values
71
158
  else
72
- raise ArgumentError, "expected hash, array, sym, int, got #{struct}"
159
+ raise ArgumentError, "expected hash, array, sym, int, got #{x}"
73
160
  end
74
161
  ensure
75
162
  $@.shift if $@
76
163
  end
164
+
165
+ def self.from_array code
166
+ unless code =~ /^\[[CSLQ]+\]$/
167
+ raise ArgumentError, "expected [CSLQ], got #{code}"
168
+ end
169
+ return new(code[1..-2].chars.map(&:to_sym))
170
+ end
171
+
172
+ def self.from_size code
173
+ m = code.match(/^\:(?<size>[^=]+)=?(?<value>.+)?$/)
174
+ if m.nil?
175
+ raise ArgumentError, "expected <number> or CSLQ, got #{code}"
176
+ end
177
+ if m[:size] =~ /^[CSLQ]+$/
178
+ s = m[:size].chars.map(&:to_sym)
179
+ if s.size == 1
180
+ return new(s[0]).tap { |b| b.load(m[:value].to_i) if m[:value] }
181
+ else
182
+ b = new(s)
183
+ b.load(m[:value].split(':').map(&:to_i)) if m[:value]
184
+ return b
185
+ end
186
+ end
187
+ if (n = m[:size].to_i)
188
+ return new(n).tap { |b| b.load(m[:value]) if m[:value] }
189
+ end
190
+ raise ArgumentError, "expected <number> or CSLQ, got #{code}"
191
+ end
192
+
193
+ def self.next_placeholder
194
+ @_placeholder_counter ||= 0
195
+ "__#{@_placeholder_counter += 1}__"
196
+ end
197
+
198
+ def self.from_struct code
199
+ default = {}
200
+ # code := '{' [name] [:type] [=value] [,...] '}'
201
+ env, keys, key = [], [], ''
202
+ seq = code.scan /\w+|\:[[:digit:]]+|\:[CSLQ:]+|=[^,\}]+|./
203
+ ret = while (token = seq.shift)
204
+ case token[0]
205
+ when '{'
206
+ keys.push(key.to_sym) unless key.empty?
207
+ env.push({})
208
+ key = ''
209
+ when '}'
210
+ env[-1][key.to_sym] = :L unless key.empty?
211
+ x = env.pop
212
+ break x if env.empty?
213
+ env[-1][keys.pop] = x
214
+ key = ''
215
+ when ':'
216
+ token << seq.shift if seq.first&.start_with?('=')
217
+ b = from_size(token)
218
+ key = next_placeholder if key.empty?
219
+ env[-1][key.to_sym] = b.struct
220
+ d = default
221
+ keys.each { |k| d[k] ||= {}; d = d[k] }
222
+ d[key.to_sym] = b.unpack
223
+ key = ''
224
+ when '='
225
+ e = token[1..-1]
226
+ e = Integer(e) rescue nil
227
+ type = Integer === e ? :L : (e.length + 1)
228
+ env[-1][key.to_sym] = type
229
+ d = default
230
+ keys.each { |k| d[k] ||= {}; d = d[k] }
231
+ if Integer === type
232
+ e = "\"#{e}\"".undump rescue e.undump
233
+ end
234
+ d[key.to_sym] = e
235
+ key = ''
236
+ when ','
237
+ next if key.empty?
238
+ env[-1][key.to_sym] = :L
239
+ key = ''
240
+ else
241
+ key << token
242
+ end
243
+ end
244
+ if ret.nil?
245
+ raise ArgumentError, 'expected }, got end-of-input'
246
+ end
247
+ new(ret).tap { |b| b.load(default) }
248
+ end
249
+
250
+ def self.from code
251
+ return from_array(code) if code.start_with?('[')
252
+ return from_size(code) if code.start_with?(':')
253
+ code = "{#{code}}" unless code.start_with?('{')
254
+ return from_struct(code)
255
+ end
77
256
  end
78
257
 
79
258
  # Undll32.run 'user32', 'MessageBox', 0, 'hello', 'world', 0
259
+ # Undll32.run 'user32', 'GetCursorPos', Buffer.new({:x => :L, :y => :L})
260
+ # Undll32.run 'user32', 'GetCursorPos', Buffer.from('x,y')
80
261
  def self.run(dll, func, *args)
81
262
  types = args.map { |e| Integer === e ? 'L' : 'p' }
82
263
  input = args.map { |e| Buffer === e ? e.buffer : e }
83
264
  Win32API.new(dll, func, types, 'i').call(*input)
84
265
  end
85
266
 
86
- def self.parse xs
87
- case x = xs.shift
88
- when ':' then Buffer.new xs.shift.to_i
89
- when '[' then Buffer.new xs.shift.chars.map(&:to_sym)
90
- when '{'
91
- x = Hash[xs.each_slice(4).map { |k, _, v, _| [k.to_sym, v.to_sym] }]
92
- Buffer.new x
93
- else
94
- raise ArgumentError, "expected : [ {, got #{x}"
95
- end
96
- end
97
-
98
267
  def self.exe(argv=ARGV)
99
268
  return help if ARGV.include? '-h' or ARGV.include? '--help'
100
269
  dllfunc, *args = argv
101
270
  return help if dllfunc.nil?
102
271
  dll, func = dllfunc.split(',')
103
272
  return help if func.nil?
104
- args.map! { |e|
273
+ dll += '.dll' unless dll.end_with? '.dll'
274
+ realpath = File.expand_path dll
275
+ dll = realpath if File.exist? realpath
276
+ args.map! do |e|
105
277
  e = e.dup
106
278
  if e.start_with?('+')
107
279
  e.slice!(0)
108
280
  next e if e.start_with?('+')
109
- parse e.scan(/\w+|./)
281
+ Buffer.from(e)
110
282
  else
111
283
  n = Integer(e) rescue nil
112
284
  next n if n
113
285
  e
114
286
  end
115
- }
287
+ end
116
288
  ret = run(dll, func, *args)
117
289
  args.each { |e| pp e.unpack if Buffer === e }
118
290
  ret
@@ -126,10 +298,10 @@ module Undll32
126
298
  EXAMPLE
127
299
  undll32 user32,MessageBox 0 hello world 0
128
300
  undll32 user32,GetCursorPos +[LL]
129
- undll32 user32,GetCursorPos +{x:L,y:L}
301
+ undll32 user32,GetCursorPos +x,y
130
302
  undll32 user32,GetCursorPos +:8 # will be converted to string
131
303
 
132
- EXPLAIN
304
+ ARGUMENTS
133
305
  0 => (Integer) 0
134
306
  str => 'str'
135
307
  +0 => '0'
@@ -138,6 +310,9 @@ module Undll32
138
310
  +{x:L,y:L} => Buffer.new({:x => :L, :y => :L})
139
311
  +:256 => Buffer.new(256)
140
312
 
313
+ VERSION
314
+ #{VERSION}
315
+
141
316
  USAGE
142
317
  end
143
318
  end
@@ -1,3 +1,3 @@
1
1
  module Undll32
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.4"
3
3
  end
data/undll32.gemspec CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
- spec.add_development_dependency "bundler", "~> 1.16"
27
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "bundler", "~> 2.2.9"
27
+ spec.add_development_dependency "rake", "~> 13.0"
28
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undll32
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - hyrious
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-01 00:00:00.000000000 Z
11
+ date: 2021-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: 2.2.9
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: 2.2.9
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  description: undll32 User32,MessageBoxA 0 hello world 0
42
42
  email:
43
43
  - hyrious@outlook.com
@@ -62,7 +62,7 @@ homepage: https://github.com/hyrious/undll32
62
62
  licenses:
63
63
  - MIT
64
64
  metadata: {}
65
- post_install_message:
65
+ post_install_message:
66
66
  rdoc_options: []
67
67
  require_paths:
68
68
  - lib
@@ -77,9 +77,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
77
  - !ruby/object:Gem::Version
78
78
  version: '0'
79
79
  requirements: []
80
- rubyforge_project:
81
- rubygems_version: 2.7.6
82
- signing_key:
80
+ rubygems_version: 3.2.9
81
+ signing_key:
83
82
  specification_version: 4
84
83
  summary: Windows rundll32 replacement.
85
84
  test_files: []