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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#
# (C) Copyright 2015 Enthought, Inc., Austin, TX
# All right reserved.
#
# This file is open source software distributed according to the terms in
# LICENSE.txt
#
 
""" Utility functions to help with cffi wrapping.
"""
from __future__ import absolute_import
 
from win32ctypes.core.compat import is_bytes, is_integer, text_type
from cffi import FFI
 
ffi = FFI()
ffi.set_unicode(True)
 
 
def HMODULE(cdata):
    return int(ffi.cast("intptr_t", cdata))
 
 
def PVOID(x):
    return ffi.cast("void *", x)
 
 
def IS_INTRESOURCE(x):
    """ Check if x is an index into the id list.
 
    """
    return int(ffi.cast("uintptr_t", x)) >> 16 == 0
 
 
def RESOURCE(resource):
    """ Convert a resource into a compatible input for cffi.
 
    """
    if is_integer(resource):
        resource = ffi.cast('wchar_t *', resource)
    elif is_bytes(resource):
        resource = text_type(resource)
    return resource
 
 
def resource(lpRESOURCEID):
    """ Convert the windows RESOURCE into a python friendly object.
    """
    if IS_INTRESOURCE(lpRESOURCEID):
        resource = int(ffi.cast("uintptr_t", lpRESOURCEID))
    else:
        resource = ffi.string(lpRESOURCEID)
    return resource
 
 
class ErrorWhen(object):
    """ Callable factory for raising errors when calling cffi functions.
 
    """
 
    def __init__(self, check, raise_on_zero=True):
        """ Constructor
 
        Parameters
        ----------
        check :
            The return value that designates that an error has taken place.
 
        raise_on_zero : bool
            When set any error will be raised. When false the winerror
            is checked and only non-zero win errors are raised. Currently
            this parameters is used to workaround issues with the win32
            implementation in ``wine``.
 
        """
        self._check = check
        self._raise_on_zero = raise_on_zero
 
    def __call__(self, value, function_name=''):
        if value == self._check:
            self._raise_error(function_name)
        else:
            return value
 
    def _raise_error(self, function_name=''):
        code, message = ffi.getwinerror()
        exception = WindowsError()
        exception.errno = ffi.errno
        exception.winerror = code
        exception.strerror = message
        exception.function = function_name
        raise exception
 
 
check_null = ErrorWhen(ffi.NULL)
check_zero = ErrorWhen(0)
check_false = ErrorWhen(False)
 
 
class Libraries(object):
 
    def __getattr__(self, name):
        library = ffi.dlopen('{}.dll'.format(name))
        self.__dict__[name] = library
        return library
 
 
dlls = Libraries()