forked from nvaccess/nvda
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomHelper.py
81 lines (73 loc) · 2.29 KB
/
comHelper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# comHelper.py
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2013 NV Access Limited
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
"""Utilities to help with issues related to COM."""
import subprocess
import ctypes
import comtypes.client.dynamic
from comtypes import IUnknown
from comtypes.automation import IDispatch
import oleacc
import config
MK_E_UNAVAILABLE = -2147221021
CO_E_CLASSSTRING = -2147221005
def _lresultFromGetActiveObject(progid, dynamic):
o = comtypes.client.GetActiveObject(progid, dynamic=dynamic)
if not isinstance(o, IUnknown):
o = o._comobj
return oleacc.LresultFromObject(0, o)
def getActiveObject(progid, dynamic=False, appModule=None):
"""Get an active COM object, handling privilege issues.
This is similar to comtypes.client.GetActiveObject
except that it can retrieve objects from normal processes when NVDA is running with uiAccess.
"""
if appModule:
if not appModule.helperLocalBindingHandle:
raise ValueError("appModule does not have a binding handle")
import NVDAHelper
p = ctypes.POINTER(comtypes.IUnknown)()
res = NVDAHelper.localLib.nvdaInProcUtils_getActiveObject(
appModule.helperLocalBindingHandle,
progid,
ctypes.byref(p),
)
if res != 0:
raise ctypes.WinError(res)
if not p:
raise RuntimeError("NULL IUnknown pointer")
if dynamic:
return comtypes.client.dynamic.Dispatch(p.QueryInterface(IDispatch))
else:
return comtypes.client.GetBestInterface(p)
try:
return comtypes.client.GetActiveObject(progid, dynamic=dynamic)
except WindowsError as e:
if e.winerror not in (MK_E_UNAVAILABLE, CO_E_CLASSSTRING):
# This isn't related to privileges.
raise
p = subprocess.Popen(
(config.SLAVE_FILENAME, "comGetActiveObject", progid, "%d" % dynamic),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
try:
try:
lres = int(p.stdout.readline())
except ValueError:
raise RuntimeError("Helper process unable to get object; see log for details")
o = oleacc.ObjectFromLresult(
lres,
0,
IDispatch if dynamic else IUnknown,
)
if dynamic:
o = comtypes.client.dynamic.Dispatch(o)
return o
finally:
# This will cause EOF for the waiting process, which will then exit.
p.stdin.close()
p.wait()
p.stdout.close()