| 42 | sentinel = object() |
| 43 | |
| 44 | class ApiProxy(object): |
| 45 | APIDLL = None |
| 46 | """Create a python wrapper around a kernel32 function""" |
| 47 | def __init__(self, func_name=None, error_check=sentinel, deffunc_module=None): |
| 48 | self.deffunc_module = deffunc_module if deffunc_module is not None else gdef.winfuncs |
| 49 | self.func_name = func_name |
| 50 | if error_check is sentinel: |
| 51 | error_check = self.default_error_check |
| 52 | |
| 53 | self.error_check = error_check |
| 54 | self._cprototyped = None |
| 55 | |
| 56 | def __call__(self, python_proxy): |
| 57 | # Use the name of the sub-function if None was given |
| 58 | if self.func_name is None: |
| 59 | self.func_name = python_proxy.__name__ |
| 60 | |
| 61 | errchk = None |
| 62 | if self.error_check is not None: |
| 63 | errchk = functools.wraps(self.error_check)(functools.partial(self.error_check, self.func_name)) |
| 64 | |
| 65 | prototype = getattr(self.deffunc_module, self.func_name + "Prototype") |
| 66 | params = getattr(self.deffunc_module, self.func_name + "Params") |
| 67 | python_proxy.prototype = prototype |
| 68 | python_proxy.params = params |
| 69 | python_proxy.errcheck = errchk |
| 70 | python_proxy.target_dll = self.APIDLL |
| 71 | python_proxy.target_func = self.func_name |
| 72 | # Give access to the 'ApiProxy' object from the function |
| 73 | python_proxy.proxy = self |
| 74 | params_name = [param[1] for param in params] |
| 75 | if (self.error_check.__doc__): |
| 76 | doc = python_proxy.__doc__ |
| 77 | doc = doc if doc else "" |
| 78 | python_proxy.__doc__ = doc + "\nErrcheck:\n " + self.error_check.__doc__ |
| 79 | |
| 80 | def generate_ctypes_function(): |
| 81 | try: |
| 82 | api_dll = ctypes.windll[self.APIDLL] |
| 83 | except WindowsError as e: |
| 84 | if e.winerror == gdef.ERROR_BAD_EXE_FORMAT: |
| 85 | e.strerror = e.strerror.replace("%1", "<{0}>".format(self.APIDLL)) |
| 86 | raise |
| 87 | try: |
| 88 | c_prototyped = prototype((self.func_name, api_dll), params) |
| 89 | except (AttributeError, WindowsError): |
| 90 | raise ExportNotFound(self.func_name, self.APIDLL) |
| 91 | if errchk is not None: |
| 92 | c_prototyped.errcheck = errchk |
| 93 | self._cprototyped = c_prototyped |
| 94 | |
| 95 | def perform_call(*args): |
| 96 | if self._cprototyped is None: |
| 97 | generate_ctypes_function() |
| 98 | try: |
| 99 | return self._cprototyped(*args) |
| 100 | except ctypes.ArgumentError as e: |
| 101 | # We just add a conversion ctypes argument fail |
nothing calls this directly
no outgoing calls
no test coverage detected