Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

universal.py 8.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. # Code that packs and unpacks the Univgw structures.
  2. # See if we have a special directory for the binaries (for developers)
  3. import pythoncom
  4. from win32com.client import gencache
  5. com_error = pythoncom.com_error
  6. _univgw = pythoncom._univgw
  7. def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names=None):
  8. ret = [] # return a list of (dispid, funcname for our policy's benefit
  9. # First see if we have makepy support. If so, we can probably satisfy the request without loading the typelib.
  10. try:
  11. mod = gencache.GetModuleForTypelib(typelibGUID, lcid, major, minor)
  12. except ImportError:
  13. mod = None
  14. if mod is None:
  15. import win32com.client.build
  16. # Load up the typelib and build (but don't cache) it now
  17. tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid)
  18. typecomp_lib = tlb.GetTypeComp()
  19. if interface_names is None:
  20. interface_names = []
  21. for i in range(tlb.GetTypeInfoCount()):
  22. info = tlb.GetTypeInfo(i)
  23. doc = tlb.GetDocumentation(i)
  24. attr = info.GetTypeAttr()
  25. if attr.typekind == pythoncom.TKIND_INTERFACE or (
  26. attr.typekind == pythoncom.TKIND_DISPATCH
  27. and attr.wTypeFlags & pythoncom.TYPEFLAG_FDUAL
  28. ):
  29. interface_names.append(doc[0])
  30. for name in interface_names:
  31. type_info, type_comp = typecomp_lib.BindType(
  32. name,
  33. )
  34. # Not sure why we don't get an exception here - BindType's C
  35. # impl looks correct..
  36. if type_info is None:
  37. raise ValueError("The interface '%s' can not be located" % (name,))
  38. # If we got back a Dispatch interface, convert to the real interface.
  39. attr = type_info.GetTypeAttr()
  40. if attr.typekind == pythoncom.TKIND_DISPATCH:
  41. refhtype = type_info.GetRefTypeOfImplType(-1)
  42. type_info = type_info.GetRefTypeInfo(refhtype)
  43. attr = type_info.GetTypeAttr()
  44. item = win32com.client.build.VTableItem(
  45. type_info, attr, type_info.GetDocumentation(-1)
  46. )
  47. _doCreateVTable(
  48. item.clsid, item.python_name, item.bIsDispatch, item.vtableFuncs
  49. )
  50. for info in item.vtableFuncs:
  51. names, dispid, desc = info
  52. invkind = desc[4]
  53. ret.append((dispid, invkind, names[0]))
  54. else:
  55. # Cool - can used cached info.
  56. if not interface_names:
  57. interface_names = list(mod.VTablesToClassMap.values())
  58. for name in interface_names:
  59. try:
  60. iid = mod.NamesToIIDMap[name]
  61. except KeyError:
  62. raise ValueError(
  63. "Interface '%s' does not exist in this cached typelib" % (name,)
  64. )
  65. # print "Processing interface", name
  66. sub_mod = gencache.GetModuleForCLSID(iid)
  67. is_dispatch = getattr(sub_mod, name + "_vtables_dispatch_", None)
  68. method_defs = getattr(sub_mod, name + "_vtables_", None)
  69. if is_dispatch is None or method_defs is None:
  70. raise ValueError("Interface '%s' is IDispatch only" % (name,))
  71. # And create the univgw defn
  72. _doCreateVTable(iid, name, is_dispatch, method_defs)
  73. for info in method_defs:
  74. names, dispid, desc = info
  75. invkind = desc[4]
  76. ret.append((dispid, invkind, names[0]))
  77. return ret
  78. def _doCreateVTable(iid, interface_name, is_dispatch, method_defs):
  79. defn = Definition(iid, is_dispatch, method_defs)
  80. vtbl = _univgw.CreateVTable(defn, is_dispatch)
  81. _univgw.RegisterVTable(vtbl, iid, interface_name)
  82. def _CalcTypeSize(typeTuple):
  83. t = typeTuple[0]
  84. if t & (pythoncom.VT_BYREF | pythoncom.VT_ARRAY):
  85. # Its a pointer.
  86. cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  87. elif t == pythoncom.VT_RECORD:
  88. # Just because a type library uses records doesn't mean the user
  89. # is trying to. We need to better place to warn about this, but it
  90. # isn't here.
  91. # try:
  92. # import warnings
  93. # warnings.warn("warning: records are known to not work for vtable interfaces")
  94. # except ImportError:
  95. # print "warning: records are known to not work for vtable interfaces"
  96. cb = _univgw.SizeOfVT(pythoncom.VT_PTR)[1]
  97. # cb = typeInfo.GetTypeAttr().cbSizeInstance
  98. else:
  99. cb = _univgw.SizeOfVT(t)[1]
  100. return cb
  101. class Arg:
  102. def __init__(self, arg_info, name=None):
  103. self.name = name
  104. self.vt, self.inOut, self.default, self.clsid = arg_info
  105. self.size = _CalcTypeSize(arg_info)
  106. # Offset from the beginning of the arguments of the stack.
  107. self.offset = 0
  108. class Method:
  109. def __init__(self, method_info, isEventSink=0):
  110. all_names, dispid, desc = method_info
  111. name = all_names[0]
  112. names = all_names[1:]
  113. invkind = desc[4]
  114. arg_defs = desc[2]
  115. ret_def = desc[8]
  116. self.dispid = dispid
  117. self.invkind = invkind
  118. # We dont use this ATM.
  119. # self.ret = Arg(ret_def)
  120. if isEventSink and name[:2] != "On":
  121. name = "On%s" % name
  122. self.name = name
  123. cbArgs = 0
  124. self.args = []
  125. for argDesc in arg_defs:
  126. arg = Arg(argDesc)
  127. arg.offset = cbArgs
  128. cbArgs = cbArgs + arg.size
  129. self.args.append(arg)
  130. self.cbArgs = cbArgs
  131. self._gw_in_args = self._GenerateInArgTuple()
  132. self._gw_out_args = self._GenerateOutArgTuple()
  133. def _GenerateInArgTuple(self):
  134. # Given a method, generate the in argument tuple
  135. l = []
  136. for arg in self.args:
  137. if arg.inOut & pythoncom.PARAMFLAG_FIN or arg.inOut == 0:
  138. l.append((arg.vt, arg.offset, arg.size))
  139. return tuple(l)
  140. def _GenerateOutArgTuple(self):
  141. # Given a method, generate the out argument tuple
  142. l = []
  143. for arg in self.args:
  144. if (
  145. arg.inOut & pythoncom.PARAMFLAG_FOUT
  146. or arg.inOut & pythoncom.PARAMFLAG_FRETVAL
  147. or arg.inOut == 0
  148. ):
  149. l.append((arg.vt, arg.offset, arg.size, arg.clsid))
  150. return tuple(l)
  151. class Definition:
  152. def __init__(self, iid, is_dispatch, method_defs):
  153. self._iid = iid
  154. self._methods = []
  155. self._is_dispatch = is_dispatch
  156. for info in method_defs:
  157. entry = Method(info)
  158. self._methods.append(entry)
  159. def iid(self):
  160. return self._iid
  161. def vtbl_argsizes(self):
  162. return [m.cbArgs for m in self._methods]
  163. def vtbl_argcounts(self):
  164. return [len(m.args) for m in self._methods]
  165. def dispatch(
  166. self,
  167. ob,
  168. index,
  169. argPtr,
  170. ReadFromInTuple=_univgw.ReadFromInTuple,
  171. WriteFromOutTuple=_univgw.WriteFromOutTuple,
  172. ):
  173. "Dispatch a call to an interface method."
  174. meth = self._methods[index]
  175. # Infer S_OK if they don't return anything bizarre.
  176. hr = 0
  177. args = ReadFromInTuple(meth._gw_in_args, argPtr)
  178. # If ob is a dispatcher, ensure a policy
  179. ob = getattr(ob, "policy", ob)
  180. # Ensure the correct dispid is setup
  181. ob._dispid_to_func_[meth.dispid] = meth.name
  182. retVal = ob._InvokeEx_(meth.dispid, 0, meth.invkind, args, None, None)
  183. # None is an allowed return value stating that
  184. # the code doesn't want to touch any output arguments.
  185. if type(retVal) == tuple: # Like pythoncom, we special case a tuple.
  186. # However, if they want to return a specific HRESULT,
  187. # then they have to return all of the out arguments
  188. # AND the HRESULT.
  189. if len(retVal) == len(meth._gw_out_args) + 1:
  190. hr = retVal[0]
  191. retVal = retVal[1:]
  192. else:
  193. raise TypeError(
  194. "Expected %s return values, got: %s"
  195. % (len(meth._gw_out_args) + 1, len(retVal))
  196. )
  197. else:
  198. retVal = [retVal]
  199. retVal.extend([None] * (len(meth._gw_out_args) - 1))
  200. retVal = tuple(retVal)
  201. WriteFromOutTuple(retVal, meth._gw_out_args, argPtr)
  202. return hr