turborex 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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