summaryrefslogtreecommitdiffstats
path: root/debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py
diff options
context:
space:
mode:
authorJeremy Morse <jeremy.morse@sony.com>2019-10-31 16:51:53 +0000
committerJeremy Morse <jeremy.morse@sony.com>2019-10-31 16:51:53 +0000
commit984fad243d179564df31c5f9531a52442e24581a (patch)
treeaba85a27f1596d456079f6f5eb69e09408730b49 /debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py
parent34f3c0fc44a5fd8a0f9186002749336e398837cf (diff)
downloadbcm5719-llvm-984fad243d179564df31c5f9531a52442e24581a.tar.gz
bcm5719-llvm-984fad243d179564df31c5f9531a52442e24581a.zip
Reapply "Import Dexter to debuginfo-tests""
This reverts commit cb935f345683194e42e6e883d79c5a16479acd74. Discussion in D68708 advises that green dragon is being briskly refurbished, and it's good to have this patch up testing it.
Diffstat (limited to 'debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py')
-rw-r--r--debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py119
1 files changed, 119 insertions, 0 deletions
diff --git a/debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py b/debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py
new file mode 100644
index 00000000000..0bce5b533e7
--- /dev/null
+++ b/debuginfo-tests/dexter/dex/debugger/visualstudio/windows/ComInterface.py
@@ -0,0 +1,119 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~ ~ ~~ ~ ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""Communication via the Windows COM interface."""
+
+import inspect
+import time
+import sys
+
+# pylint: disable=import-error
+import win32com.client as com
+import win32api
+# pylint: enable=import-error
+
+from dex.utils.Exceptions import LoadDebuggerException
+
+_com_error = com.pywintypes.com_error # pylint: disable=no-member
+
+
+def get_file_version(file_):
+ try:
+ info = win32api.GetFileVersionInfo(file_, '\\')
+ ms = info['FileVersionMS']
+ ls = info['FileVersionLS']
+ return '.'.join(
+ str(s) for s in [
+ win32api.HIWORD(ms),
+ win32api.LOWORD(ms),
+ win32api.HIWORD(ls),
+ win32api.LOWORD(ls)
+ ])
+ except com.pywintypes.error: # pylint: disable=no-member
+ return 'no versioninfo present'
+
+
+def _handle_com_error(e):
+ exc = sys.exc_info()
+ msg = win32api.FormatMessage(e.hresult)
+ try:
+ msg = msg.decode('CP1251')
+ except AttributeError:
+ pass
+ msg = msg.strip()
+ return msg, exc
+
+
+class ComObject(object):
+ """Wrap a raw Windows COM object in a class that implements auto-retry of
+ failed calls.
+ """
+
+ def __init__(self, raw):
+ assert not isinstance(raw, ComObject), raw
+ self.__dict__['raw'] = raw
+
+ def __str__(self):
+ return self._call(self.raw.__str__)
+
+ def __getattr__(self, key):
+ if key in self.__dict__:
+ return self.__dict__[key]
+ return self._call(self.raw.__getattr__, key)
+
+ def __setattr__(self, key, val):
+ if key in self.__dict__:
+ self.__dict__[key] = val
+ self._call(self.raw.__setattr__, key, val)
+
+ def __getitem__(self, key):
+ return self._call(self.raw.__getitem__, key)
+
+ def __setitem__(self, key, val):
+ self._call(self.raw.__setitem__, key, val)
+
+ def __call__(self, *args):
+ return self._call(self.raw, *args)
+
+ @classmethod
+ def _call(cls, fn, *args):
+ """COM calls tend to randomly fail due to thread sync issues.
+ The Microsoft recommended solution is to set up a message filter object
+ to automatically retry failed calls, but this seems prohibitively hard
+ from python, so this is a custom solution to do the same thing.
+ All COM accesses should go through this function.
+ """
+ ex = AssertionError("this should never be raised!")
+
+ assert (inspect.isfunction(fn) or inspect.ismethod(fn)
+ or inspect.isbuiltin(fn)), (fn, type(fn))
+ retries = ([0] * 50) + ([1] * 5)
+ for r in retries:
+ try:
+ try:
+ result = fn(*args)
+ if inspect.ismethod(result) or 'win32com' in str(
+ result.__class__):
+ result = ComObject(result)
+ return result
+ except _com_error as e:
+ msg, _ = _handle_com_error(e)
+ e = WindowsError(msg) # pylint: disable=undefined-variable
+ raise e
+ except (AttributeError, TypeError, OSError) as e:
+ ex = e
+ time.sleep(r)
+ raise ex
+
+
+class DTE(ComObject):
+ def __init__(self, class_string):
+ try:
+ super(DTE, self).__init__(com.DispatchEx(class_string))
+ except _com_error as e:
+ msg, exc = _handle_com_error(e)
+ raise LoadDebuggerException(
+ '{} [{}]'.format(msg, class_string), orig_exception=exc)
OpenPOWER on IntegriCloud