-
Notifications
You must be signed in to change notification settings - Fork 8
/
api.py
77 lines (60 loc) · 2.22 KB
/
api.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
import json
import six
from pywinauto.backend import Singleton
from pywinauto.actionlogger import ActionLogger
from .injector import Injector
from .channel import Pipe
# backend exit codes enum
OK = 0
PARSE_ERROR = 1
UNSUPPORTED_ACTION = 2
MISSING_PARAM = 3
RUNTIME_ERROR = 4
NOT_FOUND = 5
UNSUPPORTED_TYPE = 6
INVALID_VALUE = 7
class InjectedBaseError(Exception):
"""Base class for exceptions based on errors returned from injected DLL side"""
pass
class InjectedUnsupportedActionError(InjectedBaseError):
"""The specified action is not supported"""
pass
class InjectedRuntimeError(InjectedBaseError):
"""Runtime exception during code execution inside injected target"""
pass
class InjectedNotFoundError(InjectedBaseError):
"""Requested item not found: control element, property, ..."""
pass
@six.add_metaclass(Singleton)
class ConnectionManager(object):
def __init__(self):
self._pipes = {}
def _get_pipe(self, pid):
if pid not in self._pipes:
self._pipes[pid] = self._create_pipe(pid)
return self._pipes[pid]
def _create_pipe(self, pid):
pipe_name = 'pywinauto_{}'.format(pid)
pipe = Pipe(pipe_name)
if pipe.connect(n_attempts=1):
ActionLogger().log('Pipe {} found, looks like dll has been injected already'.format(pipe_name))
return pipe
else:
ActionLogger().log('Pipe {} not found, injecting dll to the process'.format(pipe_name))
Injector(pid, 'dotnet', 'bootstrap')
pipe.connect()
return pipe
def call_action(self, action_name, pid, **params):
command = {'action': action_name}
command.update(params)
reply = self._get_pipe(pid).transact(json.dumps(command))
reply = json.loads(reply)
if reply['status_code'] == UNSUPPORTED_ACTION:
raise InjectedUnsupportedActionError(reply['message'])
elif reply['status_code'] == RUNTIME_ERROR:
raise InjectedRuntimeError(reply['message'])
elif reply['status_code'] == NOT_FOUND:
raise InjectedNotFoundError(reply['message'])
elif reply['status_code'] != OK:
raise InjectedBaseError()
return reply