turborex 0.1.1

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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +38 -0
  4. data/README.rdoc +19 -0
  5. data/examples/alpc_client.rb +15 -0
  6. data/examples/alpc_server.rb +14 -0
  7. data/examples/com_client.rb +19 -0
  8. data/examples/com_finder.rb +39 -0
  9. data/examples/create_instance.rb +15 -0
  10. data/examples/cstruct.rb +19 -0
  11. data/examples/find_com_client_calls.rb +16 -0
  12. data/examples/find_rpc_security_callback.rb +12 -0
  13. data/examples/rpc_finder.rb +117 -0
  14. data/examples/scan_exports.rb +5 -0
  15. data/examples/scan_imports.rb +5 -0
  16. data/examples/tinysdk.rb +17 -0
  17. data/lib/turborex.rb +21 -0
  18. data/lib/turborex/cstruct.rb +565 -0
  19. data/lib/turborex/cstruct/struct_helper.rb +7 -0
  20. data/lib/turborex/exception.rb +65 -0
  21. data/lib/turborex/fuzzer.rb +204 -0
  22. data/lib/turborex/fuzzer/containers.rb +115 -0
  23. data/lib/turborex/fuzzer/coverage.rb +67 -0
  24. data/lib/turborex/fuzzer/mutators.rb +25 -0
  25. data/lib/turborex/fuzzer/seed.rb +30 -0
  26. data/lib/turborex/monkey.rb +11 -0
  27. data/lib/turborex/msrpc.rb +14 -0
  28. data/lib/turborex/msrpc/decompiler.rb +244 -0
  29. data/lib/turborex/msrpc/midl.rb +747 -0
  30. data/lib/turborex/msrpc/ndrtype.rb +167 -0
  31. data/lib/turborex/msrpc/rpcbase.rb +777 -0
  32. data/lib/turborex/msrpc/rpcfinder.rb +1426 -0
  33. data/lib/turborex/msrpc/utils.rb +70 -0
  34. data/lib/turborex/pefile.rb +8 -0
  35. data/lib/turborex/pefile/pe.rb +61 -0
  36. data/lib/turborex/pefile/scanner.rb +82 -0
  37. data/lib/turborex/utils.rb +321 -0
  38. data/lib/turborex/windows.rb +402 -0
  39. data/lib/turborex/windows/alpc.rb +844 -0
  40. data/lib/turborex/windows/com.rb +266 -0
  41. data/lib/turborex/windows/com/client.rb +84 -0
  42. data/lib/turborex/windows/com/com_finder.rb +330 -0
  43. data/lib/turborex/windows/com/com_registry.rb +100 -0
  44. data/lib/turborex/windows/com/interface.rb +522 -0
  45. data/lib/turborex/windows/com/utils.rb +210 -0
  46. data/lib/turborex/windows/constants.rb +82 -0
  47. data/lib/turborex/windows/process.rb +56 -0
  48. data/lib/turborex/windows/security.rb +12 -0
  49. data/lib/turborex/windows/security/ace.rb +76 -0
  50. data/lib/turborex/windows/security/acl.rb +25 -0
  51. data/lib/turborex/windows/security/security_descriptor.rb +118 -0
  52. data/lib/turborex/windows/tinysdk.rb +89 -0
  53. data/lib/turborex/windows/utils.rb +138 -0
  54. data/resources/headers/alpc/ntdef.h +72 -0
  55. data/resources/headers/alpc/ntlpcapi.h +1014 -0
  56. data/resources/headers/rpc/common.h +162 -0
  57. data/resources/headers/rpc/guiddef.h +191 -0
  58. data/resources/headers/rpc/internal_ndrtypes.h +262 -0
  59. data/resources/headers/rpc/rpc.h +10 -0
  60. data/resources/headers/rpc/rpcdce.h +266 -0
  61. data/resources/headers/rpc/rpcdcep.h +187 -0
  62. data/resources/headers/rpc/rpcndr.h +39 -0
  63. data/resources/headers/rpc/v4_x64/rpcinternals.h +154 -0
  64. data/resources/headers/rpc/wintype.h +517 -0
  65. data/resources/headers/tinysdk/tinysdk.h +5 -0
  66. data/resources/headers/tinysdk/tinysdk/comdef.h +645 -0
  67. data/resources/headers/tinysdk/tinysdk/dbghelp.h +118 -0
  68. data/resources/headers/tinysdk/tinysdk/guiddef.h +194 -0
  69. data/resources/headers/tinysdk/tinysdk/memoryapi.h +12 -0
  70. data/resources/headers/tinysdk/tinysdk/poppack.h +12 -0
  71. data/resources/headers/tinysdk/tinysdk/pshpack4.h +13 -0
  72. data/resources/headers/tinysdk/tinysdk/winnt.h +1059 -0
  73. data/resources/headers/tinysdk/tinysdk/wintype.h +326 -0
  74. metadata +290 -0
@@ -0,0 +1,100 @@
1
+ require 'win32/registry'
2
+
3
+ module TurboRex
4
+ class Windows < Metasm::WinOS
5
+ module COM
6
+ class COMRegistry
7
+
8
+ class CLSIDEntry
9
+ attr_reader :clsid
10
+ attr_accessor :inproc_server
11
+ attr_accessor :inproc_server32
12
+ attr_accessor :inproc_handler
13
+ attr_accessor :inproc_handler32
14
+ attr_accessor :local_server
15
+ attr_accessor :local_server32
16
+ attr_accessor :prog_id
17
+ attr_accessor :treat_as
18
+ attr_accessor :typelib
19
+
20
+ InprocHandler = Struct.new(:path, :threading_model)
21
+ InprocHandler32 = Struct.new(:path, :threading_model)
22
+ InprocServer32 = Struct.new(:path, :threading_model)
23
+ InprocServer = Struct.new(:path)
24
+ LocalServer = Struct.new(:path, :server_executable)
25
+ LocalServer32 = Struct.new(:path, :server_executable)
26
+
27
+ def initialize(clsid)
28
+ @clsid = clsid
29
+ end
30
+
31
+ def self.from_registry(reg_key)
32
+ return unless reg_key.keyname =~ /^\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}$/i
33
+ clsid_entry = new(reg_key.keyname.delete('{}'))
34
+ reg_key.each_key do |k|
35
+ reg_key.open(k) do |sub_key|
36
+ case k.downcase
37
+ when 'inprocserver32'
38
+ clsid_entry.inproc_server32 = InprocServer32.new
39
+ clsid_entry.inproc_server32.path = sub_key[''] rescue nil
40
+ clsid_entry.inproc_server32.threading_model = (sub_key['ThreadingModel'] rescue 'sta')
41
+ when 'localserver32'
42
+ clsid_entry.local_server32 = LocalServer32.new
43
+ clsid_entry.local_server32.path = sub_key[''] rescue nil
44
+ clsid_entry.local_server32.server_executable = sub_key['ServerExecutable'] rescue nil
45
+ when 'progid'
46
+ @progid = sub_key[''] rescue nil
47
+ when 'treatas'
48
+ @treat_as = sub_key[''] rescue nil
49
+ when 'typelib'
50
+ @typelib = sub_key[''] rescue nil
51
+ end
52
+ end
53
+ end
54
+
55
+ clsid_entry
56
+ end
57
+ end
58
+
59
+ class AppIDEntry
60
+ attr_accessor :appid_guid
61
+ attr_accessor :executable_name
62
+ attr_accessor :launch_permission
63
+ attr_accessor :access_permission
64
+ attr_accessor :local_service
65
+
66
+ def self.from_registry(reg_key)
67
+ appid_entry = AppIDEntry.new
68
+ if reg_key.keyname =~ /^\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}$/i
69
+ appid_entry.appid_guid = reg_key.keyname
70
+ if (raw = reg_key.read('LaunchPermission').last rescue nil)
71
+ sd = TurboRex::Windows::Win32API.alloc_c_ary('BYTE', raw.bytesize)
72
+ sd.str = raw
73
+ lpbDaclPresent = TurboRex::Windows::Win32API.alloc_c_ptr('BOOL')
74
+ pdacl = TurboRex::Windows::Win32API.alloc_c_ptr('PVOID')
75
+ lpbDaclDefaulted = TurboRex::Windows::Win32API.alloc_c_ptr('BOOL')
76
+
77
+ TurboRex::Windows::Win32API.getsecuritydescriptordacl(sd, lpbDaclPresent, pdacl, lpbDaclDefaulted)
78
+ appid_entry.launch_permission = TurboRex::Windows::Security::SecurityDescriptor.from_raw(raw)
79
+ end
80
+
81
+ if (raw = reg_key.read('AccessPermission').last rescue nil)
82
+ sd = TurboRex::Windows::Win32API.alloc_c_ary('BYTE', raw.bytesize)
83
+ sd.str = raw
84
+ lpbDaclPresent = TurboRex::Windows::Win32API.alloc_c_ptr('BOOL')
85
+ pdacl = TurboRex::Windows::Win32API.alloc_c_ptr('PVOID')
86
+ lpbDaclDefaulted = TurboRex::Windows::Win32API.alloc_c_ptr('BOOL')
87
+
88
+ TurboRex::Windows::Win32API.getsecuritydescriptordacl(sd, lpbDaclPresent, pdacl, lpbDaclDefaulted)
89
+ appid_entry.access_permission = TurboRex::Windows::Security::SecurityDescriptor.from_raw(raw)
90
+ end
91
+ else
92
+ appid_entry.executable_name = reg_key.keyname
93
+ end
94
+
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,522 @@
1
+ module TurboRex
2
+ class Windows < Metasm::WinOS
3
+ module COM
4
+ class Interface
5
+ include WellKnownIID
6
+
7
+ attr_accessor :this
8
+ attr_reader :iid
9
+ attr_reader :vtbl
10
+ attr_reader :pvtbl
11
+ attr_reader :parent
12
+ attr_reader :methods
13
+
14
+ class IUnknown < Interface
15
+ METHOD_DEFS =<<-EOS
16
+ HRESULT STDMETHODCALLTYPE QueryInterface(
17
+ IUnknown * This,
18
+ REFIID riid,
19
+ void **ppvObject);
20
+
21
+ ULONG STDMETHODCALLTYPE AddRef(IUnknown * This);
22
+
23
+ ULONG STDMETHODCALLTYPE Release(IUnknown * This);
24
+ EOS
25
+
26
+ apiproxy = Windows::Win32API.dup
27
+ apiproxy.parse_c(METHOD_DEFS)
28
+ _symbol = apiproxy.cp.toplevel.symbol
29
+
30
+ METHODS = [
31
+ _symbol['QueryInterface'],
32
+ _symbol['AddRef'],
33
+ _symbol['Release']
34
+ ]
35
+
36
+ def initialize
37
+ methods = METHODS
38
+ parent = nil
39
+ super(IID_IUnknown, methods, parent)
40
+ end
41
+
42
+ def name
43
+ self.class.to_s
44
+ end
45
+ end
46
+
47
+ class IClassFactory < Interface
48
+ METHOD_DEFS =<<-EOS
49
+ HRESULT STDMETHODCALLTYPE QueryInterface(
50
+ IClassFactory * This,
51
+ REFIID riid,
52
+ void **ppvObject);
53
+
54
+ ULONG STDMETHODCALLTYPE AddRef(IClassFactory * This);
55
+
56
+ ULONG STDMETHODCALLTYPE Release(IClassFactory * This);
57
+
58
+ HRESULT STDMETHODCALLTYPE CreateInstance(
59
+ IClassFactory * This,
60
+ void *pUnkOuter,
61
+ REFIID riid,
62
+ void **ppvObject);
63
+
64
+ HRESULT STDMETHODCALLTYPE LockServer(
65
+ IClassFactory * This,
66
+ BOOL fLock);
67
+ EOS
68
+
69
+ apiproxy = Windows::Win32API.dup
70
+ apiproxy.parse_c(METHOD_DEFS)
71
+ _symbol = apiproxy.cp.toplevel.symbol
72
+ METHODS = [
73
+ _symbol['QueryInterface'],
74
+ _symbol['AddRef'],
75
+ _symbol['Release'],
76
+ _symbol['CreateInstance'],
77
+ _symbol['LockServer']
78
+ ]
79
+
80
+ def initialize
81
+ methods = METHODS
82
+ parent = nil
83
+ super(IID_IClassFactory, methods, parent)
84
+ end
85
+
86
+ def name
87
+ self.class.to_s
88
+ end
89
+ end
90
+
91
+ class IRpcStubBuffer < Interface
92
+ METHOD_DEFS =<<-EOS
93
+ HRESULT STDMETHODCALLTYPE QueryInterface(
94
+ IRpcStubBuffer * This,
95
+ REFIID riid,
96
+ void **ppvObject);
97
+
98
+ ULONG STDMETHODCALLTYPE AddRef(
99
+ IRpcStubBuffer * This);
100
+
101
+ ULONG STDMETHODCALLTYPE Release(
102
+ IRpcStubBuffer * This);
103
+
104
+ HRESULT STDMETHODCALLTYPE Connect(
105
+ IRpcStubBuffer * This,
106
+ IUnknown *pUnkServer);
107
+
108
+ void STDMETHODCALLTYPE Disconnect(
109
+ IRpcStubBuffer * This);
110
+
111
+ HRESULT STDMETHODCALLTYPE Invoke (
112
+ IRpcStubBuffer * This,
113
+ RPCOLEMESSAGE *_prpcmsg,
114
+ IRpcChannelBuffer *_pRpcChannelBuffer);
115
+
116
+ IRpcStubBuffer * STDMETHODCALLTYPE IsIIDSupported(
117
+ IRpcStubBuffer * This,
118
+ REFIID riid);
119
+
120
+ ULONG STDMETHODCALLTYPE CountRefs(
121
+ IRpcStubBuffer * This);
122
+
123
+ HRESULT STDMETHODCALLTYPE DebugServerQueryInterface(
124
+ IRpcStubBuffer * This,
125
+ void **ppv);
126
+
127
+ void STDMETHODCALLTYPE DebugServerRelease(
128
+ IRpcStubBuffer * This,
129
+ void *pv);
130
+ EOS
131
+
132
+ def initialize
133
+ methods = METHODS
134
+ parent = nil
135
+ super(IID_IRpcStubBuffer, methods, parent)
136
+ end
137
+ end
138
+
139
+ class IRpcProxyBuffer < Interface
140
+ METHOD_DEFS = <<-EOS
141
+ HRESULT STDMETHODCALLTYPE QueryInterface(
142
+ IRpcProxyBuffer * This,
143
+ REFIID riid,
144
+ void **ppvObject);
145
+
146
+ ULONG STDMETHODCALLTYPE AddRef(
147
+ IRpcProxyBuffer * This);
148
+
149
+ ULONG STDMETHODCALLTYPE Release(
150
+ IRpcProxyBuffer * This);
151
+
152
+ HRESULT STDMETHODCALLTYPE Connect(
153
+ IRpcProxyBuffer * This,
154
+ IRpcChannelBuffer *pRpcChannelBuffer);
155
+
156
+ void STDMETHODCALLTYPE Disconnect(
157
+ IRpcProxyBuffer * This);
158
+ EOS
159
+
160
+ apiproxy = Windows::Win32API.dup
161
+ apiproxy.parse_c(METHOD_DEFS)
162
+ _symbol = apiproxy.cp.toplevel.symbol
163
+ METHODS = [
164
+ _symbol['QueryInterface'],
165
+ _symbol['AddRef'],
166
+ _symbol['Release'],
167
+ _symbol['Connect'],
168
+ _symbol['Disconnect']
169
+ ]
170
+
171
+ def initialize
172
+ methods = METHODS
173
+ parent = nil
174
+ super(IID_IRpcProxyBuffer, methods, parent)
175
+ end
176
+
177
+ def name
178
+ self.class.to_s
179
+ end
180
+ end
181
+
182
+ class IPSFactoryBuffer < Interface
183
+ METHOD_DEFS = <<-EOS
184
+ HRESULT STDMETHODCALLTYPE QueryInterface(
185
+ IPSFactoryBuffer * This,
186
+ REFIID riid,
187
+ void **ppvObject);
188
+
189
+ ULONG STDMETHODCALLTYPE AddRef(
190
+ IPSFactoryBuffer * This);
191
+
192
+ ULONG STDMETHODCALLTYPE Release(
193
+ IPSFactoryBuffer * This);
194
+
195
+ HRESULT STDMETHODCALLTYPE CreateProxy(
196
+ IPSFactoryBuffer * This,
197
+ IUnknown *pUnkOuter,
198
+ REFIID riid,
199
+ IRpcProxyBuffer **ppProxy,
200
+ void **ppv);
201
+
202
+ HRESULT STDMETHODCALLTYPE CreateStub(
203
+ IPSFactoryBuffer * This,
204
+ REFIID riid,
205
+ IUnknown *pUnkServer,
206
+ IRpcStubBuffer **ppStub);
207
+ EOS
208
+
209
+ apiproxy = Windows::Win32API.dup
210
+ apiproxy.parse_c(METHOD_DEFS)
211
+ _symbol = apiproxy.cp.toplevel.symbol
212
+ METHODS = [
213
+ _symbol['QueryInterface'],
214
+ _symbol['AddRef'],
215
+ _symbol['Release'],
216
+ _symbol['CreateProxy'],
217
+ _symbol['CreateStub']
218
+ ]
219
+
220
+ def initialize
221
+ methods = METHODS
222
+ parent = nil
223
+ super(IID_IPSFactoryBuffer, methods, parent)
224
+ end
225
+
226
+ def name
227
+ self.class.to_s
228
+ end
229
+ end
230
+
231
+ class IStream < Interface
232
+ METHOD_DEFS =<<-EOS
233
+ HRESULT STDMETHODCALLTYPE QueryInterface(
234
+ IStream * This,
235
+ REFIID riid,
236
+ void **ppvObject);
237
+
238
+ ULONG STDMETHODCALLTYPE AddRef(IStream * This);
239
+
240
+ ULONG STDMETHODCALLTYPE Release(IStream * This);
241
+
242
+ HRESULT STDMETHODCALLTYPE Read(
243
+ IStream * This,
244
+ void *pv,
245
+ ULONG cb,
246
+ ULONG *pcbRead);
247
+
248
+ HRESULT STDMETHODCALLTYPE Write(
249
+ IStream * This,
250
+ const void *pv,
251
+ ULONG cb,
252
+ ULONG *pcbWritten);
253
+
254
+ HRESULT STDMETHODCALLTYPE Seek(
255
+ IStream * This,
256
+ LARGE_INTEGER dlibMove,
257
+ DWORD dwOrigin,
258
+ ULARGE_INTEGER *plibNewPosition);
259
+
260
+ HRESULT STDMETHODCALLTYPE SetSize(
261
+ IStream * This,
262
+ ULARGE_INTEGER libNewSize);
263
+
264
+ HRESULT STDMETHODCALLTYPE CopyTo(
265
+ IStream * This,
266
+ void *pstm,
267
+ ULARGE_INTEGER cb,
268
+ ULARGE_INTEGER *pcbRead,
269
+ ULARGE_INTEGER *pcbWritten);
270
+
271
+ HRESULT STDMETHODCALLTYPE Commit(
272
+ IStream * This,
273
+ DWORD grfCommitFlags);
274
+
275
+ HRESULT STDMETHODCALLTYPE Revert(
276
+ IStream * This);
277
+
278
+ HRESULT STDMETHODCALLTYPE LockRegion(
279
+ IStream * This,
280
+ ULARGE_INTEGER libOffset,
281
+ ULARGE_INTEGER cb,
282
+ DWORD dwLockType);
283
+
284
+ HRESULT STDMETHODCALLTYPE UnlockRegion(
285
+ IStream * This,
286
+ ULARGE_INTEGER libOffset,
287
+ ULARGE_INTEGER cb,
288
+ DWORD dwLockType);
289
+
290
+ HRESULT STDMETHODCALLTYPE Stat(
291
+ IStream * This,
292
+ STATSTG *pstatstg,
293
+ DWORD grfStatFlag);
294
+
295
+ HRESULT STDMETHODCALLTYPE Clone(
296
+ IStream * This,
297
+ void **ppstm);
298
+ EOS
299
+
300
+ apiproxy = Windows::Win32API.dup
301
+ apiproxy.parse_c(METHOD_DEFS)
302
+ _symbol = apiproxy.cp.toplevel.symbol
303
+ METHODS = [_symbol['QueryInterface'],
304
+ _symbol['AddRef'],
305
+ _symbol['Release'],
306
+ _symbol['Read'],
307
+ _symbol['Write'],
308
+ _symbol['Seek'],
309
+ _symbol['SetSize'],
310
+ _symbol['CopyTo'],
311
+ _symbol['Commit'],
312
+ _symbol['Revert'],
313
+ _symbol['LockRegion'],
314
+ _symbol['UnlockRegion'],
315
+ _symbol['Stat'],
316
+ _symbol['Clone']
317
+ ]
318
+
319
+ def initialize
320
+ methods = METHODS
321
+ parent = nil
322
+ super(IID_IStream, methods, parent)
323
+ end
324
+
325
+ def name
326
+ self.class.to_s
327
+ end
328
+ end
329
+
330
+ class IStorage < Interface
331
+ METHOD_DEFS =<<-EOS
332
+ HRESULT STDMETHODCALLTYPE QueryInterface(
333
+ IUnknown * This,
334
+ REFIID riid,
335
+ void **ppvObject);
336
+
337
+ ULONG STDMETHODCALLTYPE AddRef(IUnknown * This);
338
+
339
+ ULONG STDMETHODCALLTYPE Release(IUnknown * This);
340
+
341
+ HRESULT STDMETHODCALLTYPE CreateStream(
342
+ IStorage * This,
343
+ const OLECHAR *pwcsName,
344
+ DWORD grfMode,
345
+ DWORD reserved1,
346
+ DWORD reserved2,
347
+ IStream **ppstm);
348
+
349
+ HRESULT STDMETHODCALLTYPE OpenStream(
350
+ IStorage * This,
351
+ const OLECHAR *pwcsName,
352
+ void *reserved1,
353
+ DWORD grfMode,
354
+ DWORD reserved2,
355
+ IStream **ppstm);
356
+
357
+ HRESULT STDMETHODCALLTYPE CreateStorage(
358
+ IStorage * This,
359
+ const OLECHAR *pwcsName,
360
+ DWORD grfMode,
361
+ DWORD reserved1,
362
+ DWORD reserved2,
363
+ IStorage **ppstg);
364
+
365
+ HRESULT STDMETHODCALLTYPE OpenStorage(
366
+ IStorage * This,
367
+ const OLECHAR *pwcsName,
368
+ IStorage *pstgPriority,
369
+ DWORD grfMode,
370
+ SNB snbExclude,
371
+ DWORD reserved,
372
+ IStorage **ppstg);
373
+
374
+ HRESULT STDMETHODCALLTYPE CopyTo(
375
+ IStorage * This,
376
+ DWORD ciidExclude,
377
+ const IID *rgiidExclude,
378
+ SNB snbExclude,
379
+ IStorage *pstgDest);
380
+
381
+ HRESULT STDMETHODCALLTYPE MoveElementTo (
382
+ IStorage * This,
383
+ const OLECHAR *pwcsName,
384
+ IStorage *pstgDest,
385
+ const OLECHAR *pwcsNewName,
386
+ DWORD grfFlags);
387
+
388
+ HRESULT STDMETHODCALLTYPE Commit(
389
+ IStorage * This,
390
+ DWORD grfCommitFlags);
391
+
392
+ HRESULT STDMETHODCALLTYPE Revert(
393
+ IStorage * This);
394
+
395
+ HRESULT STDMETHODCALLTYPE EnumElements(
396
+ IStorage * This,
397
+ DWORD reserved1,
398
+ void *reserved2,
399
+ DWORD reserved3,
400
+ IEnumSTATSTG **ppenum);
401
+
402
+ HRESULT STDMETHODCALLTYPE DestroyElement(
403
+ IStorage * This,
404
+ const OLECHAR *pwcsName);
405
+
406
+ HRESULT STDMETHODCALLTYPE RenameElement(
407
+ IStorage * This,
408
+ const OLECHAR *pwcsOldName,
409
+ const OLECHAR *pwcsNewName);
410
+
411
+ HRESULT STDMETHODCALLTYPE SetElementTimes(
412
+ IStorage * This,
413
+ const OLECHAR *pwcsName,
414
+ const FILETIME *pctime,
415
+ const FILETIME *patime,
416
+ const FILETIME *pmtime);
417
+
418
+ HRESULT STDMETHODCALLTYPE SetClass(
419
+ IStorage * This,
420
+ REFCLSID clsid);
421
+
422
+ HRESULT STDMETHODCALLTYPE SetStateBits(
423
+ IStorage * This,
424
+ DWORD grfStateBits,
425
+ DWORD grfMask);
426
+
427
+ HRESULT STDMETHODCALLTYPE Stat(
428
+ IStorage * This,
429
+ STATSTG *pstatstg,
430
+ DWORD grfStatFlag);
431
+ EOS
432
+
433
+ apiproxy = Windows::Win32API.dup
434
+ apiproxy.parse_c(METHOD_DEFS)
435
+ _symbol = apiproxy.cp.toplevel.symbol
436
+
437
+ METHODS = [
438
+ _symbol['QueryInterface'],
439
+ _symbol['AddRef'],
440
+ _symbol['Release'],
441
+ _symbol['CreateStream'],
442
+ _symbol['OpenStream'],
443
+ _symbol['CreateStorage'],
444
+ _symbol['OpenStorage'],
445
+ _symbol['CopyTo'],
446
+ _symbol['MoveElementTo'],
447
+ _symbol['Commit'],
448
+ _symbol['Revert'],
449
+ _symbol['EnumElements'],
450
+ _symbol['DestroyElement'],
451
+ _symbol['RenameElement'],
452
+ _symbol['SetElementTimes'],
453
+ _symbol['SetClass'],
454
+ _symbol['SetStateBits'],
455
+ _symbol['Stat']
456
+ ]
457
+
458
+ def initialize
459
+ methods = METHODS
460
+ parent = nil
461
+ super(IID_IStorage, methods, parent)
462
+ end
463
+
464
+ def name
465
+ self.class.to_s
466
+ end
467
+ end
468
+
469
+ def initialize(iid, methods, parent=IUnknown)
470
+ @iid = iid
471
+ @methods = methods
472
+ @parent = parent
473
+ @api_proxy = Win32API.dup
474
+
475
+ @methods.freeze
476
+ definie_rb_proxy
477
+ end
478
+
479
+ def this=(ptr)
480
+ @this = ptr
481
+ ptr_len = @api_proxy.host_cpu.size / 8
482
+ format = ptr_len == 8 ? 'Q' : 'L'
483
+
484
+ pvtbl = @api_proxy.memory_read(@this, ptr_len).unpack(format).first
485
+ vtbl = @api_proxy.memory_read(pvtbl, ptr_len*@methods.count).unpack(format*@methods.count)
486
+ @pvtbl = pvtbl
487
+ @vtbl = vtbl
488
+
489
+ @vtbl.each_with_index {|addr, i| @api_proxy.new_caller_for(@methods[i], @methods[i].name, addr)}
490
+ end
491
+
492
+ def marshal_to_string(mshctx=MSHCTX_DIFFERENTMACHINE, mshlflags=MSHLFLAGS_NORMAL)
493
+ Utils.marshal_interface_to_string(self, mshctx, mshlflags)
494
+ end
495
+
496
+ def self.define_interface(iid, method_defs={}, parent=IUnknown)
497
+ api_proxy = Win32API.dup
498
+ methods = [*parent::METHODS]
499
+ method_defs.each_value {|v| api_proxy.parse_c(v) }
500
+ method_defs.each_key {|k| methods<<api_proxy.cp.toplevel.symbol[k.to_s]}
501
+ methods.compact!
502
+
503
+ new(iid, methods, parent)
504
+ end
505
+
506
+ def name
507
+ self.class.to_s
508
+ end
509
+
510
+ private
511
+
512
+ def definie_rb_proxy
513
+ @methods.each do |m|
514
+ self.define_singleton_method(m.name) do |*args|
515
+ @api_proxy.send m.name, @this, *args
516
+ end
517
+ end
518
+ end
519
+ end
520
+ end
521
+ end
522
+ end