Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dcom/oaut.py : 72%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Author: Alberto Solino (@agsolino)
8#
9# Description:
10# [MS-OAUT]: OLE Automation Protocol Implementation
11# This was used as a way to test the DCOM runtime. Further
12# testing is needed to verify it is working as expected
13#
14# Best way to learn how to use these calls is to grab the protocol standard
15# so you understand what the call does, and then read the test case located
16# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC
17#
18# Since DCOM is like an OO RPC, instead of helper functions you will see the
19# classes described in the standards developed.
20# There are test cases for them too.
21#
22from __future__ import division
23from __future__ import print_function
24import random
25from struct import pack, unpack
27from impacket import LOG
28from impacket import hresult_errors
29from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown2, PMInterfacePointer, INTERFACE, \
30 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer
31from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, DWORD, SHORT, GUID, USHORT, LONG, WSTR, BYTE, LONGLONG, FLOAT, \
32 DOUBLE, HRESULT, PSHORT, PLONG, PLONGLONG, PFLOAT, PDOUBLE, PHRESULT, CHAR, ULONGLONG, INT, UINT, PCHAR, PUSHORT, \
33 PULONG, PULONGLONG, PINT, PUINT, NULL
34from impacket.dcerpc.v5.enum import Enum
35from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantArray, NDRPOINTER, NDRENUM, NDRUSHORT, NDRUNION, \
36 NDRUniConformantVaryingArray, NDR
37from impacket.dcerpc.v5.rpcrt import DCERPCException
38from impacket.uuid import string_to_bin
40class DCERPCSessionError(DCERPCException):
41 def __init__(self, error_string=None, error_code=None, packet=None):
42 DCERPCException.__init__(self, error_string, error_code, packet)
44 def __str__( self ):
45 if self.error_code in hresult_errors.ERROR_MESSAGES:
46 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0]
47 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1]
48 return 'OAUT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
49 else:
50 return 'OAUT SessionError: unknown error code: 0x%x' % (self.error_code)
52################################################################################
53# CONSTANTS
54################################################################################
55# 1.9 Standards Assignments
56IID_IDispatch = string_to_bin('00020400-0000-0000-C000-000000000046')
57IID_ITypeInfo = string_to_bin('00020401-0000-0000-C000-000000000046')
58IID_ITypeComp = string_to_bin('00020403-0000-0000-C000-000000000046')
59IID_NULL = string_to_bin('00000000-0000-0000-0000-000000000000')
61error_status_t = ULONG
63LCID = DWORD
64WORD = NDRUSHORT
66# 2.2.2 IID
67IID = GUID
69# 2.2.3 LPOLESTR
70LPOLESTR = LPWSTR
71OLESTR = WSTR
73# 2.2.4 REFIID
74REFIID = IID
76# 2.2.25 DATE
77DATE = DOUBLE
78class PDATE(NDRPOINTER):
79 referent = (
80 ('Data', DATE),
81 )
83# 2.2.27 VARIANT_BOOL
84VARIANT_BOOL = USHORT
86class PVARIANT_BOOL(NDRPOINTER):
87 referent = (
88 ('Data', VARIANT_BOOL),
89 )
91# 3.1.4.4 IDispatch::Invoke (Opnum 6)
92# dwFlags
93DISPATCH_METHOD = 0x00000001
94DISPATCH_PROPERTYGET = 0x00000002
95DISPATCH_PROPERTYPUT = 0x00000004
96DISPATCH_PROPERTYPUTREF = 0x00000008
97DISPATCH_zeroVarResult = 0x00020000
98DISPATCH_zeroExcepInfo = 0x00040000
99DISPATCH_zeroArgErr = 0x00080000
101################################################################################
102# STRUCTURES
103################################################################################
104# 2.2.26 DECIMAL
105class DECIMAL(NDRSTRUCT):
106 structure = (
107 ('wReserved',WORD),
108 ('scale',BYTE),
109 ('sign',BYTE),
110 ('Hi32',ULONG),
111 ('Lo64',ULONGLONG),
112 )
114class PDECIMAL(NDRPOINTER):
115 referent = (
116 ('Data', DECIMAL),
117 )
119# 2.2.7 VARIANT Type Constants
120class VARENUM(NDRENUM):
121 class enumItems(Enum):
122 VT_EMPTY = 0
123 VT_NULL = 1
124 VT_I2 = 2
125 VT_I4 = 3
126 VT_R4 = 4
127 VT_R8 = 5
128 VT_CY = 6
129 VT_DATE = 7
130 VT_BSTR = 8
131 VT_DISPATCH = 9
132 VT_ERROR = 0xa
133 VT_BOOL = 0xb
134 VT_VARIANT = 0xc
135 VT_UNKNOWN = 0xd
136 VT_DECIMAL = 0xe
137 VT_I1 = 0x10
138 VT_UI1 = 0x11
139 VT_UI2 = 0x12
140 VT_UI4 = 0x13
141 VT_I8 = 0x14
142 VT_UI8 = 0x15
143 VT_INT = 0x16
144 VT_UINT = 0x17
145 VT_VOID = 0x18
146 VT_HRESULT = 0x19
147 VT_PTR = 0x1a
148 VT_SAFEARRAY = 0x1b
149 VT_CARRAY = 0x1c
150 VT_USERDEFINED = 0x1d
151 VT_LPSTR = 0x1e
152 VT_LPWSTR = 0x1f
153 VT_RECORD = 0x24
154 VT_INT_PTR = 0x25
155 VT_UINT_PTR = 0x26
156 VT_ARRAY = 0x2000
157 VT_BYREF = 0x4000
158 VT_RECORD_OR_VT_BYREF = VT_RECORD | VT_BYREF
159 VT_UI1_OR_VT_BYREF = VT_UI1 | VT_BYREF
160 VT_I2_OR_VT_BYREF = VT_I2 | VT_BYREF
161 VT_I4_OR_VT_BYREF = VT_I4 | VT_BYREF
162 VT_I8_OR_VT_BYREF = VT_I8 | VT_BYREF
163 VT_R4_OR_VT_BYREF = VT_R4 | VT_BYREF
164 VT_R8_OR_VT_BYREF = VT_R8 | VT_BYREF
165 VT_BOOL_OR_VT_BYREF = VT_BOOL | VT_BYREF
166 VT_ERROR_OR_VT_BYREF = VT_ERROR | VT_BYREF
167 VT_CY_OR_VT_BYREF = VT_CY | VT_BYREF
168 VT_DATE_OR_VT_BYREF = VT_DATE | VT_BYREF
169 VT_BSTR_OR_VT_BYREF = VT_BSTR | VT_BYREF
170 VT_UNKNOWN_OR_VT_BYREF = VT_UNKNOWN | VT_BYREF
171 VT_DISPATCH_OR_VT_BYREF = VT_DISPATCH | VT_BYREF
172 VT_ARRAY_OR_VT_BYREF = VT_ARRAY | VT_BYREF
173 VT_VARIANT_OR_VT_BYREF = VT_VARIANT| VT_BYREF
174 VT_I1_OR_VT_BYREF = VT_I1 | VT_BYREF
175 VT_UI2_OR_VT_BYREF = VT_UI2 | VT_BYREF
176 VT_UI4_OR_VT_BYREF = VT_UI4 | VT_BYREF
177 VT_UI8_OR_VT_BYREF = VT_UI8 | VT_BYREF
178 VT_INT_OR_VT_BYREF = VT_INT | VT_BYREF
179 VT_UINT_OR_VT_BYREF = VT_UINT | VT_BYREF
180 VT_DECIMAL_OR_VT_BYREF = VT_DECIMAL | VT_BYREF
182# 2.2.8 SAFEARRAY Feature Constants
183class SF_TYPE(NDRENUM):
184 # [v1_enum] type
185 structure = (
186 ('Data', '<L'),
187 )
188 class enumItems(Enum):
189 SF_ERROR = VARENUM.VT_ERROR
190 SF_I1 = VARENUM.VT_I1
191 SF_I2 = VARENUM.VT_I2
192 SF_I4 = VARENUM.VT_I4
193 SF_I8 = VARENUM.VT_I8
194 SF_BSTR = VARENUM.VT_BSTR
195 SF_UNKNOWN = VARENUM.VT_UNKNOWN
196 SF_DISPATCH = VARENUM.VT_DISPATCH
197 SF_VARIANT = VARENUM.VT_VARIANT
198 SF_RECORD = VARENUM.VT_RECORD
199 SF_HAVEIID = VARENUM.VT_UNKNOWN | 0x8000
201# 2.2.10 CALLCONV Calling Convention Constants
202class CALLCONV(NDRENUM):
203 # [v1_enum] type
204 structure = (
205 ('Data', '<L'),
206 )
207 class enumItems(Enum):
208 CC_CDECL = 1
209 CC_PASCAL = 2
210 CC_STDCALL = 4
213# 2.2.12 FUNCKIND Function Access Constants
214class FUNCKIND(NDRENUM):
215 # [v1_enum] type
216 structure = (
217 ('Data', '<L'),
218 )
219 class enumItems(Enum):
220 FUNC_PUREVIRTUAL = 1
221 FUNC_STATIC = 3
222 FUNC_DISPATCH = 4
224# 2.2.14 INVOKEKIND Function Invocation Constants
225class INVOKEKIND(NDRENUM):
226 # [v1_enum] type
227 structure = (
228 ('Data', '<L'),
229 )
230 class enumItems(Enum):
231 INVOKE_FUNC = 1
232 INVOKE_PROPERTYGET = 2
233 INVOKE_PROPERTYPUT = 4
234 INVOKE_PROPERTYPUTREF = 8
236# 2.2.17 TYPEKIND Type Kind Constants
237class TYPEKIND(NDRENUM):
238 # [v1_enum] type
239 structure = (
240 ('Data', '<L'),
241 )
242 class enumItems(Enum):
243 TKIND_ENUM = 0
244 TKIND_RECORD = 1
245 TKIND_MODULE = 2
246 TKIND_INTERFACE = 3
247 TKIND_DISPATCH = 4
248 TKIND_COCLASS = 5
249 TKIND_ALIAS = 6
250 TKIND_UNION = 7
252# 2.2.23 BSTR
253# 2.2.23.1 FLAGGED_WORD_BLOB
254class USHORT_ARRAY(NDRUniConformantArray):
255 item = '<H'
257class FLAGGED_WORD_BLOB(NDRSTRUCT):
258 structure = (
259 ('cBytes',ULONG),
260 ('clSize',ULONG),
261 ('asData',USHORT_ARRAY),
262 )
263 def __setitem__(self, key, value):
264 if key == 'asData':
265 value = value #+ '\x00'
266 array = list()
267 for letter in value:
268 encoded = letter.encode('utf-16le')
269 array.append(unpack('<H', encoded)[0])
270 self.fields[key]['Data'] = array
271 self['cBytes'] = len(value)*2
272 self['clSize'] = len(value)
273 self.data = None # force recompute
274 else:
275 return NDRSTRUCT.__setitem__(self, key, value)
277 def __getitem__(self, key):
278 if key == 'asData':
279 value = ''
280 for letter in self.fields['asData']['Data']:
281 value += pack('<H', letter).decode('utf-16le')
282 return value
283 else:
284 return NDRSTRUCT.__getitem__(self,key)
286 def dump(self, msg = None, indent = 0):
287 if msg is None: msg = self.__class__.__name__
288 ind = ' '*indent
289 if msg != '':
290 print("%s" % (msg))
291 value = ''
292 print('%sasData: %s' % (ind,self['asData']), end=' ')
294# 2.2.23.2 BSTR Type Definition
295class BSTR(NDRPOINTER):
296 referent = (
297 ('Data', FLAGGED_WORD_BLOB),
298 )
300class PBSTR(NDRPOINTER):
301 referent = (
302 ('Data', BSTR),
303 )
305# 2.2.24 CURRENCY
306class CURRENCY(NDRSTRUCT):
307 structure = (
308 ('int64', LONGLONG),
309 )
311class PCURRENCY(NDRPOINTER):
312 referent = (
313 ('Data', CURRENCY),
314 )
316# 2.2.28.2 BRECORD
317# 2.2.28.2.1 _wireBRECORD
318class _wireBRECORD(NDRSTRUCT):
319 structure = (
320 ('fFlags', LONGLONG),
321 ('clSize', LONGLONG),
322 ('pRecInfo', MInterfacePointer),
323 ('pRecord', BYTE_ARRAY),
324 )
326class BRECORD(NDRPOINTER):
327 referent = (
328 ('Data', _wireBRECORD),
329 )
331# 2.2.30 SAFEARRAY
332# 2.2.30.1 SAFEARRAYBOUND
333class SAFEARRAYBOUND(NDRSTRUCT):
334 structure = (
335 ('cElements', ULONG),
336 ('lLbound', LONG),
337 )
339class PSAFEARRAYBOUND(NDRPOINTER):
340 referent = (
341 ('Data', SAFEARRAYBOUND),
342 )
344# 2.2.30.2 SAFEARR_BSTR
345class BSTR_ARRAY(NDRUniConformantArray):
346 item = BSTR
348class PBSTR_ARRAY(NDRPOINTER):
349 referent = (
350 ('Data', BSTR_ARRAY),
351 )
353class SAFEARR_BSTR(NDRSTRUCT):
354 structure = (
355 ('Size', ULONG),
356 ('aBstr', PBSTR_ARRAY),
357 )
359# 2.2.30.3 SAFEARR_UNKNOWN
360class SAFEARR_UNKNOWN(NDRSTRUCT):
361 structure = (
362 ('Size', ULONG),
363 ('apUnknown', MInterfacePointer_ARRAY),
364 )
366# 2.2.30.4 SAFEARR_DISPATCH
367class SAFEARR_DISPATCH(NDRSTRUCT):
368 structure = (
369 ('Size', ULONG),
370 ('apDispatch', MInterfacePointer_ARRAY),
371 )
373# 2.2.30.6 SAFEARR_BRECORD
374class BRECORD_ARRAY(NDRUniConformantArray):
375 item = BRECORD
377class SAFEARR_BRECORD(NDRSTRUCT):
378 structure = (
379 ('Size', ULONG),
380 ('aRecord', BRECORD_ARRAY),
381 )
383# 2.2.30.7 SAFEARR_HAVEIID
384class SAFEARR_HAVEIID(NDRSTRUCT):
385 structure = (
386 ('Size', ULONG),
387 ('apUnknown', MInterfacePointer_ARRAY),
388 ('iid', IID),
389 )
391# 2.2.30.8 Scalar-Sized Arrays
392# 2.2.30.8.1 BYTE_SIZEDARR
393class BYTE_SIZEDARR(NDRSTRUCT):
394 structure = (
395 ('clSize', ULONG),
396 ('pData', BYTE_ARRAY),
397 )
399# 2.2.30.8.2 WORD_SIZEDARR
400class WORD_ARRAY(NDRUniConformantArray):
401 item = '<H'
403class WORD_SIZEDARR(NDRSTRUCT):
404 structure = (
405 ('clSize', ULONG),
406 ('pData', WORD_ARRAY),
407 )
409# 2.2.30.8.3 DWORD_SIZEDARR
410class DWORD_ARRAY(NDRUniConformantArray):
411 item = '<L'
413class DWORD_SIZEDARR(NDRSTRUCT):
414 structure = (
415 ('clSize', ULONG),
416 ('pData', DWORD_ARRAY),
417 )
419# 2.2.30.8.4 HYPER_SIZEDARR
420class HYPER_ARRAY(NDRUniConformantArray):
421 item = '<Q'
423class HYPER_SIZEDARR(NDRSTRUCT):
424 structure = (
425 ('clSize', ULONG),
426 ('pData', HYPER_ARRAY),
427 )
430# 2.2.36 HREFTYPE
431HREFTYPE = DWORD
433# 2.2.30.5 SAFEARR_VARIANT
434class VARIANT_ARRAY(NDRUniConformantArray):
435 # In order to avoid the lack of forward declarations in Python
436 # I declare the item in the constructor
437 #item = VARIANT
438 def __init__(self, data = None, isNDR64 = False):
439 NDRUniConformantArray.__init__(self, data, isNDR64)
440 self.item = VARIANT
442class PVARIANT_ARRAY(NDRPOINTER):
443 referent = (
444 ('Data', VARIANT_ARRAY),
445 )
447class PVARIANT(NDRPOINTER):
448 # In order to avoid the lack of forward declarations in Python
449 # I declare the item in the constructor
450 #referent = (
451 # ('Data', VARIANT),
452 #)
453 def __init__(self, data = None, isNDR64 = False):
454 NDRPOINTER.__init__(self, data, isNDR64)
455 self.referent = ( ('Data', VARIANT),)
458class SAFEARR_VARIANT(NDRSTRUCT):
459 structure = (
460 ('Size', ULONG),
461 ('aVariant', VARIANT_ARRAY),
462 )
464# 2.2.30.9 SAFEARRAYUNION
465class SAFEARRAYUNION(NDRUNION):
466 commonHdr = (
467 ('tag', ULONG),
468 )
469 union = {
470 SF_TYPE.SF_BSTR : ('BstrStr', SAFEARR_BSTR),
471 SF_TYPE.SF_UNKNOWN : ('UnknownStr', SAFEARR_UNKNOWN),
472 SF_TYPE.SF_DISPATCH : ('DispatchStr', SAFEARR_DISPATCH),
473 SF_TYPE.SF_VARIANT : ('VariantStr', SAFEARR_VARIANT),
474 SF_TYPE.SF_RECORD : ('RecordStr', SAFEARR_BRECORD),
475 SF_TYPE.SF_HAVEIID : ('HaveIidStr', SAFEARR_HAVEIID),
476 SF_TYPE.SF_I1 : ('ByteStr', BYTE_SIZEDARR),
477 SF_TYPE.SF_I2 : ('WordStr', WORD_SIZEDARR),
478 SF_TYPE.SF_I4 : ('LongStr', DWORD_SIZEDARR),
479 SF_TYPE.SF_I8 : ('HyperStr', HYPER_SIZEDARR),
480 }
482# 2.2.30.10 SAFEARRAY
483class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray):
484 item = SAFEARRAYBOUND
486class PSAFEARRAYBOUND_ARRAY(NDRPOINTER):
487 referent = (
488 ('Data', SAFEARRAYBOUND_ARRAY),
489 )
491class SAFEARRAY(NDRSTRUCT):
492 structure = (
493 ('cDims', USHORT),
494 ('fFeatures', USHORT),
495 ('cbElements', ULONG),
496 ('cLocks', ULONG),
497 ('uArrayStructs', SAFEARRAYUNION),
498 ('rgsabound', SAFEARRAYBOUND_ARRAY),
499 )
501class PSAFEARRAY(NDRPOINTER):
502 referent = (
503 ('Data', SAFEARRAY),
504 )
506# 2.2.29 VARIANT
507# 2.2.29.1 _wireVARIANT
508class EMPTY(NDR):
509 align = 0
510 structure = (
511 )
513class varUnion(NDRUNION):
514 commonHdr = (
515 ('tag', ULONG),
516 )
517 union = {
518 VARENUM.VT_I8 : ('llVal', LONGLONG),
519 VARENUM.VT_I4 : ('lVal', LONG),
520 VARENUM.VT_UI1 : ('bVal', BYTE),
521 VARENUM.VT_I2 : ('iVal', SHORT),
522 VARENUM.VT_R4 : ('fltVal', FLOAT),
523 VARENUM.VT_R8 : ('dblVal', DOUBLE),
524 VARENUM.VT_BOOL : ('boolVal', VARIANT_BOOL),
525 VARENUM.VT_ERROR : ('scode', HRESULT),
526 VARENUM.VT_CY : ('cyVal', CURRENCY),
527 VARENUM.VT_DATE : ('date', DATE),
528 VARENUM.VT_BSTR : ('bstrVal', BSTR),
529 VARENUM.VT_UNKNOWN : ('punkVal', PMInterfacePointer),
530 VARENUM.VT_DISPATCH : ('pdispVal', PMInterfacePointer),
531 VARENUM.VT_ARRAY : ('parray', SAFEARRAY),
532 VARENUM.VT_RECORD : ('brecVal', BRECORD),
533 VARENUM.VT_RECORD_OR_VT_BYREF : ('brecVal', BRECORD),
534 VARENUM.VT_UI1_OR_VT_BYREF : ('pbVal', BYTE),
535 VARENUM.VT_I2_OR_VT_BYREF : ('piVal', PSHORT),
536 VARENUM.VT_I4_OR_VT_BYREF : ('plVal', PLONG),
537 VARENUM.VT_I8_OR_VT_BYREF : ('pllVal', PLONGLONG),
538 VARENUM.VT_R4_OR_VT_BYREF : ('pfltVal', PFLOAT),
539 VARENUM.VT_R8_OR_VT_BYREF : ('pdblVal', PDOUBLE),
540 VARENUM.VT_BOOL_OR_VT_BYREF : ('pboolVal', PVARIANT_BOOL),
541 VARENUM.VT_ERROR_OR_VT_BYREF : ('pscode', PHRESULT),
542 VARENUM.VT_CY_OR_VT_BYREF : ('pcyVal', PCURRENCY),
543 VARENUM.VT_DATE_OR_VT_BYREF : ('pdate', PDATE),
544 VARENUM.VT_BSTR_OR_VT_BYREF : ('pbstrVal', PBSTR),
545 VARENUM.VT_UNKNOWN_OR_VT_BYREF : ('ppunkVal', PPMInterfacePointer),
546 VARENUM.VT_DISPATCH_OR_VT_BYREF: ('ppdispVal', PPMInterfacePointer),
547 VARENUM.VT_ARRAY_OR_VT_BYREF : ('pparray', PSAFEARRAY),
548 VARENUM.VT_VARIANT_OR_VT_BYREF : ('pvarVal', PVARIANT),
549 VARENUM.VT_I1 : ('cVal', CHAR),
550 VARENUM.VT_UI2 : ('uiVal', USHORT),
551 VARENUM.VT_UI4 : ('ulVal', ULONG),
552 VARENUM.VT_UI8 : ('ullVal', ULONGLONG),
553 VARENUM.VT_INT : ('intVal', INT),
554 VARENUM.VT_UINT : ('uintVal', UINT),
555 VARENUM.VT_DECIMAL : ('decVal', DECIMAL),
556 VARENUM.VT_I1_OR_VT_BYREF : ('pcVal', PCHAR),
557 VARENUM.VT_UI2_OR_VT_BYREF : ('puiVal', PUSHORT),
558 VARENUM.VT_UI4_OR_VT_BYREF : ('pulVal', PULONG),
559 VARENUM.VT_UI8_OR_VT_BYREF : ('pullVal', PULONGLONG),
560 VARENUM.VT_INT_OR_VT_BYREF : ('pintVal', PINT),
561 VARENUM.VT_UINT_OR_VT_BYREF : ('puintVal', PUINT),
562 VARENUM.VT_DECIMAL_OR_VT_BYREF : ('pdecVal', PDECIMAL),
563 VARENUM.VT_EMPTY : ('empty', EMPTY),
564 VARENUM.VT_NULL : ('null', EMPTY),
565 }
567class wireVARIANTStr(NDRSTRUCT):
568 structure = (
569 ('clSize',DWORD),
570 ('rpcReserved',DWORD),
571 ('vt',USHORT),
572 ('wReserved1',USHORT),
573 ('wReserved2',USHORT),
574 ('wReserved3',USHORT),
575 ('_varUnion',varUnion),
576 )
578 def getAlignment(self):
579 return 8
581class VARIANT(NDRPOINTER):
582 referent = (
583 ('Data', wireVARIANTStr),
584 )
586class PVARIANT(NDRPOINTER):
587 referent = (
588 ('Data', VARIANT),
589 )
591# 2.2.32 DISPID
592DISPID = LONG
594# 2.2.33 DISPPARAMS
595class DISPID_ARRAY(NDRUniConformantArray):
596 item = '<L'
598class PDISPID_ARRAY(NDRPOINTER):
599 referent = (
600 ('Data', DISPID_ARRAY),
601 )
603class DISPPARAMS(NDRSTRUCT):
604 structure = (
605 ('rgvarg',PVARIANT_ARRAY),
606 ('rgdispidNamedArgs', PDISPID_ARRAY),
607 ('cArgs', UINT),
608 ('cNamedArgs', UINT),
609 )
611# 2.2.34 EXCEPINFO
612class EXCEPINFO(NDRSTRUCT):
613 structure = (
614 ('wCode',WORD),
615 ('wReserved', WORD),
616 ('bstrSource', BSTR),
617 ('bstrDescription', BSTR),
618 ('bstrHelpFile', BSTR),
619 ('dwHelpContext', DWORD),
620 ('pvReserved', ULONG),
621 ('pfnDeferredFillIn', ULONG),
622 ('scode', HRESULT),
623 )
625# 2.2.35 MEMBERID
626MEMBERID = DISPID
628# 2.2.38 ARRAYDESC
629class ARRAYDESC(NDRSTRUCT):
630 # In order to avoid the lack of forward declarations in Python
631 # I declare the item in the constructor
632 #structure = (
633 # ('tdescElem',TYPEDESC),
634 # ('cDims',USHORT),
635 # ('rgbounds',SAFEARRAYBOUND_ARRAY),
636 #)
637 def __init__(self, data = None, isNDR64 = False):
638 NDRSTRUCT.__init__(self, data, isNDR64)
639 self.structure = (
640 ('tdescElem',TYPEDESC),
641 ('cDims',USHORT),
642 ('rgbounds',SAFEARRAYBOUND_ARRAY),
643 )
645# 2.2.37 TYPEDESC
646class tdUnion(NDRUNION):
647 notAlign = True
648 commonHdr = (
649 ('tag', USHORT),
650 )
651 # In order to avoid the lack of forward declarations in Python
652 # I declare the item in the constructor
653 #union = {
654 # VARENUM.VT_PTR: ('lptdesc', tdUnion),
655 # VARENUM.VT_SAFEARRAY: ('lptdesc', tdUnion),
656 # VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),
657 # VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),
658 #}
659 def __init__(self, data = None, isNDR64=False, topLevel = False):
660 NDRUNION.__init__(self,None, isNDR64=isNDR64, topLevel=topLevel)
661 self.union = {
662 VARENUM.VT_PTR: ('lptdesc', PTYPEDESC),
663 VARENUM.VT_SAFEARRAY: ('lptdesc', PTYPEDESC),
664 VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),
665 VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),
666 'default': None,
667 }
669class TYPEDESC(NDRSTRUCT):
670 structure = (
671 ('vtType',tdUnion),
672 ('vt', VARENUM),
673 )
675 def getAlignment(self):
676 return 4
678class PTYPEDESC(NDRPOINTER):
679 referent = (
680 ('Data', TYPEDESC),
681 )
682 def __init__(self, data = None, isNDR64=False, topLevel = False):
683 ret = NDRPOINTER.__init__(self,None, isNDR64=isNDR64, topLevel = False)
684 # We're forcing the pointer not to be topLevel
685 if data is None:
686 self.fields['ReferentID'] = random.randint(1,65535)
687 else:
688 self.fromString(data)
691# 2.2.48 SCODE
692SCODE = LONG
694class SCODE_ARRAY(NDRUniConformantArray):
695 item = SCODE
697class PSCODE_ARRAY(NDRPOINTER):
698 referent = (
699 ('Data', SCODE_ARRAY),
700 )
702# 2.2.39 PARAMDESCEX
703class PARAMDESCEX(NDRSTRUCT):
704 structure = (
705 ('cBytes',ULONG),
706 ('varDefaultValue',VARIANT),
707 )
709class PPARAMDESCEX(NDRPOINTER):
710 referent = (
711 ('Data', PARAMDESCEX),
712 )
715# 2.2.40 PARAMDESC
716class PARAMDESC(NDRSTRUCT):
717 structure = (
718 ('pparamdescex',PPARAMDESCEX),
719 ('wParamFlags',USHORT),
720 )
722# 2.2.41 ELEMDESC
723class ELEMDESC(NDRSTRUCT):
724 structure = (
725 ('tdesc',TYPEDESC),
726 ('paramdesc',PARAMDESC),
727 )
729class ELEMDESC_ARRAY(NDRUniConformantArray):
730 item = ELEMDESC
732class PELEMDESC_ARRAY(NDRPOINTER):
733 referent = (
734 ('Data', ELEMDESC_ARRAY),
735 )
737# 2.2.42 FUNCDESC
738class FUNCDESC(NDRSTRUCT):
739 structure = (
740 ('memid',MEMBERID),
741 ('lReserved1',PSCODE_ARRAY),
742 ('lprgelemdescParam',PELEMDESC_ARRAY),
743 ('funckind',FUNCKIND),
744 ('invkind',INVOKEKIND),
745 ('callconv',CALLCONV),
746 ('cParams',SHORT),
747 ('cParamsOpt',SHORT),
748 ('oVft',SHORT),
749 ('cReserved2',SHORT),
750 ('elemdescFunc',ELEMDESC),
751 ('wFuncFlags',WORD),
752 )
754class LPFUNCDESC(NDRPOINTER):
755 referent = (
756 ('Data', FUNCDESC),
757 )
758# 2.2.44 TYPEATTR
759class TYPEATTR(NDRSTRUCT):
760 structure = (
761 ('guid',GUID),
762 ('lcid',LCID),
763 ('dwReserved1',DWORD),
764 ('dwReserved2',DWORD),
765 ('dwReserved3',DWORD),
766 ('lpstrReserved4',LPOLESTR),
767 ('cbSizeInstance',ULONG),
768 ('typeKind',TYPEKIND),
769 ('cFuncs',WORD),
770 ('cVars',WORD),
771 ('cImplTypes',WORD),
772 ('cbSizeVft',WORD),
773 ('cbAlignment',WORD),
774 ('wTypeFlags',WORD),
775 ('wMajorVerNum',WORD),
776 ('wMinorVerNum',WORD),
777 ('tdescAlias',TYPEDESC),
778 ('dwReserved5',DWORD),
779 ('dwReserved6',WORD),
780 )
782class PTYPEATTR(NDRPOINTER):
783 referent = (
784 ('Data', TYPEATTR),
785 )
787class BSTR_ARRAY_CV(NDRUniConformantVaryingArray):
788 item = BSTR
790class UINT_ARRAY(NDRUniConformantArray):
791 item = '<L'
793class OLESTR_ARRAY(NDRUniConformantArray):
794 item = LPOLESTR
797################################################################################
798# RPC CALLS
799################################################################################
800# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3)
801class IDispatch_GetTypeInfoCount(DCOMCALL):
802 opnum = 3
803 structure = (
804 ('pwszMachineName', LPWSTR),
805 )
807class IDispatch_GetTypeInfoCountResponse(DCOMANSWER):
808 structure = (
809 ('pctinfo', ULONG),
810 ('ErrorCode', error_status_t),
811 )
813# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4)
814class IDispatch_GetTypeInfo(DCOMCALL):
815 opnum = 4
816 structure = (
817 ('iTInfo', ULONG),
818 ('lcid', DWORD),
819 )
821class IDispatch_GetTypeInfoResponse(DCOMANSWER):
822 structure = (
823 ('ppTInfo', PMInterfacePointer),
824 ('ErrorCode', error_status_t),
825 )
827# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5)
828class IDispatch_GetIDsOfNames(DCOMCALL):
829 opnum = 5
830 structure = (
831 ('riid', REFIID),
832 ('rgszNames', OLESTR_ARRAY),
833 ('cNames', UINT),
834 ('lcid', LCID),
835 )
837class IDispatch_GetIDsOfNamesResponse(DCOMANSWER):
838 structure = (
839 ('rgDispId', DISPID_ARRAY),
840 ('ErrorCode', error_status_t),
841 )
843# 3.1.4.4 IDispatch::Invoke (Opnum 6)
844class IDispatch_Invoke(DCOMCALL):
845 opnum = 6
846 structure = (
847 ('dispIdMember', DISPID),
848 ('riid', REFIID),
849 ('lcid', LCID),
850 ('dwFlags', DWORD),
851 ('pDispParams', DISPPARAMS),
852 ('cVarRef', UINT),
853 ('rgVarRefIdx', UINT_ARRAY),
854 ('rgVarRef', VARIANT_ARRAY),
855 )
857class IDispatch_InvokeResponse(DCOMANSWER):
858 structure = (
859 ('pVarResult', VARIANT),
860 ('pExcepInfo', EXCEPINFO),
861 ('pArgErr', UINT),
862 ('ErrorCode', error_status_t),
863 )
865# 3.7.4.1 ITypeInfo::GetTypeAttr (Opnum 3)
866class ITypeInfo_GetTypeAttr(DCOMCALL):
867 opnum = 3
868 structure = (
869 )
871class ITypeInfo_GetTypeAttrResponse(DCOMANSWER):
872 structure = (
873 ('ppTypeAttr', PTYPEATTR),
874 ('pReserved', DWORD),
875 ('ErrorCode', error_status_t),
876 )
878# 3.7.4.2 ITypeInfo::GetTypeComp (Opnum 4)
879class ITypeInfo_GetTypeComp(DCOMCALL):
880 opnum = 4
881 structure = (
882 )
884class ITypeInfo_GetTypeCompResponse(DCOMANSWER):
885 structure = (
886 ('ppTComp', PMInterfacePointer),
887 ('ErrorCode', error_status_t),
888 )
890# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5)
891class ITypeInfo_GetFuncDesc(DCOMCALL):
892 opnum = 5
893 structure = (
894 ('index', UINT),
895 )
897class ITypeInfo_GetFuncDescResponse(DCOMANSWER):
898 structure = (
899 ('ppFuncDesc', LPFUNCDESC),
900 ('pReserved', DWORD),
901 ('ErrorCode', error_status_t),
902 )
904# 3.7.4.5 ITypeInfo::GetNames (Opnum 7)
905class ITypeInfo_GetNames(DCOMCALL):
906 opnum = 7
907 structure = (
908 ('memid', MEMBERID),
909 ('cMaxNames', UINT),
910 )
912class ITypeInfo_GetNamesResponse(DCOMANSWER):
913 structure = (
914 ('rgBstrNames', BSTR_ARRAY_CV),
915 ('pcNames', UINT),
916 ('ErrorCode', error_status_t),
917 )
919# 3.7.4.8 ITypeInfo::GetDocumentation (Opnum 12)
920class ITypeInfo_GetDocumentation(DCOMCALL):
921 opnum = 12
922 structure = (
923 ('memid', MEMBERID),
924 ('refPtrFlags', DWORD),
925 )
927class ITypeInfo_GetDocumentationResponse(DCOMANSWER):
928 structure = (
929 ('pBstrName', BSTR),
930 ('pBstrDocString', BSTR),
931 ('pdwHelpContext', DWORD),
932 ('ErrorCode', error_status_t),
933 )
936################################################################################
937# OPNUMs and their corresponding structures
938################################################################################
939OPNUMS = {
940}
942################################################################################
943# HELPER FUNCTIONS AND INTERFACES
944################################################################################
945# 4.8.5 Enumerating All Methods in an Interface
946# INPUT: IDispatch pointer from the automation server
947# CALL IDispatch::GetTypeInfoCount and OBTAIN pcTInfo
948# COMMENT see Section 3.1.4.1 for information on pcTInfo i
949# IF pcTInfo = 0 THEN
950# PRINT Automation Server does not support type information for this object
951# ELSE
952# CALL IDispatch::GetTypeInfo with correct LocaleID and OBTAIN ITypeInfo pointer
953# CALL ITypeInfo::GetDocumentation(MEMBERID_NIL, 1, &BstrName, NULL, NULL, NULL)
954# PRINT Name of the Interface is BstrName
955# CALL ITypeInfo::GetTypeAttr and OBTAIN TYPEATTR pointer
956#
957# FOR X = 0 to TYPEATTR:: cFuncs -1
958# CALL ITypeInfo::GetFuncDesc with X and OBTAIN FUNCDESC pointer
959# CALL ITypeInfo::GetNames with FUNCDESC::memid and appropriate values for
960# rgBstrNames, cMaxNames and pcNames
961# COMMENT see Section 3.7.4.5 for more information regarding the parameters
962# to ITypeinfo::GetNames
963# IF pcNames > 0 THEN
964# PRINT Name of the method is rgBstrNames[0]
965# PRINT Parameters to above method are following
966# FOR Y = 1 to pcNames -1
967# PRINT rgBstrNames[Y]
968# END FOR
969# END IF
970# END FOR i
971# ENDIF
972def enumerateMethods(iInterface):
973 methods = dict()
974 typeInfoCount = iInterface.GetTypeInfoCount()
975 if typeInfoCount['pctinfo'] == 0:
976 LOG.error('Automation Server does not support type information for this object')
977 return {}
978 iTypeInfo = iInterface.GetTypeInfo()
979 iTypeAttr = iTypeInfo.GetTypeAttr()
980 for x in range(iTypeAttr['ppTypeAttr']['cFuncs']):
981 funcDesc = iTypeInfo.GetFuncDesc(x)
982 names = iTypeInfo.GetNames(funcDesc['ppFuncDesc']['memid'], 255)
983 print(names['rgBstrNames'][0]['asData'])
984 funcDesc.dump()
985 print('='*80)
986 if names['pcNames'] > 0:
987 name = names['rgBstrNames'][0]['asData']
988 methods[name] = {}
989 for param in range(1, names['pcNames']):
990 methods[name][names['rgBstrNames'][param]['asData']] = ''
991 if funcDesc['ppFuncDesc']['elemdescFunc'] != NULL:
992 methods[name]['ret'] = funcDesc['ppFuncDesc']['elemdescFunc']['tdesc']['vt']
994 return methods
996def checkNullString(string):
997 if string == NULL:
998 return string
1000 if string[-1:] != '\x00':
1001 return string + '\x00'
1002 else:
1003 return string
1005class ITypeComp(IRemUnknown2):
1006 def __init__(self, interface):
1007 IRemUnknown2.__init__(self,interface)
1008 self._iid = IID_ITypeComp
1010class ITypeInfo(IRemUnknown2):
1011 def __init__(self, interface):
1012 IRemUnknown2.__init__(self,interface)
1013 self._iid = IID_ITypeInfo
1015 def GetTypeAttr(self):
1016 request = ITypeInfo_GetTypeAttr()
1017 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1018 return resp
1020 def GetTypeComp(self):
1021 request = ITypeInfo_GetTypeComp()
1022 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1023 return ITypeComp(INTERFACE(self.get_cinstance(), ''.join(resp['ppTComp']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))
1025 def GetFuncDesc(self, index):
1026 request = ITypeInfo_GetFuncDesc()
1027 request['index'] = index
1028 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1029 return resp
1031 def GetNames(self, memid, cMaxNames=10):
1032 request = ITypeInfo_GetNames()
1033 request['memid'] = memid
1034 request['cMaxNames'] = cMaxNames
1035 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1036 return resp
1038 def GetDocumentation(self, memid, refPtrFlags=15):
1039 request = ITypeInfo_GetDocumentation()
1040 request['memid'] = memid
1041 request['refPtrFlags'] = refPtrFlags
1042 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1043 return resp
1046class IDispatch(IRemUnknown2):
1047 def __init__(self, interface):
1048 IRemUnknown2.__init__(self,interface)
1049 self._iid = IID_IDispatch
1051 def GetTypeInfoCount(self):
1052 request = IDispatch_GetTypeInfoCount()
1053 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1054 return resp
1056 def GetTypeInfo(self):
1057 request = IDispatch_GetTypeInfo()
1058 request['iTInfo'] = 0
1059 request['lcid'] = 0
1060 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1061 return ITypeInfo(INTERFACE(self.get_cinstance(), ''.join(resp['ppTInfo']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))
1063 def GetIDsOfNames(self, rgszNames, lcid = 0):
1064 request = IDispatch_GetIDsOfNames()
1065 request['riid'] = IID_NULL
1066 for name in rgszNames:
1067 tmpName = LPOLESTR()
1068 tmpName['Data'] = checkNullString(name)
1069 request['rgszNames'].append(tmpName)
1070 request['cNames'] = len(rgszNames)
1071 request['lcid'] = lcid
1072 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1073 IDs = list()
1074 for id in resp['rgDispId']:
1075 IDs.append(id)
1077 return IDs
1079 def Invoke(self, dispIdMember, lcid, dwFlags, pDispParams, cVarRef, rgVarRefIdx, rgVarRef):
1080 request = IDispatch_Invoke()
1081 request['dispIdMember'] = dispIdMember
1082 request['riid'] = IID_NULL
1083 request['lcid'] = lcid
1084 request['dwFlags'] = dwFlags
1085 request['pDispParams'] = pDispParams
1086 request['cVarRef'] = cVarRef
1087 request['rgVarRefIdx'] = rgVarRefIdx
1088 request['rgVarRef'] = rgVarRefIdx
1089 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1090 return resp