winpnp 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
winpnp/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from . import info, properties
winpnp/_setupapi.py ADDED
@@ -0,0 +1,208 @@
1
+ from ctypes import (
2
+ POINTER,
3
+ Structure,
4
+ c_bool,
5
+ c_ubyte,
6
+ c_uint16,
7
+ c_uint32,
8
+ c_void_p,
9
+ c_wchar_p,
10
+ windll,
11
+ )
12
+ from enum import IntFlag
13
+ from uuid import UUID
14
+
15
+ INVALID_HANDLE_VALUE = -1
16
+
17
+ HDEVINFO = c_void_p
18
+
19
+
20
+ class DIGCF(IntFlag):
21
+ DEFAULT = 0x00000001
22
+ PRESENT = 0x00000002
23
+ ALLCLASSES = 0x00000004
24
+ PROFILE = 0x00000008
25
+ DEVICEINTERFACE = 0x00000010
26
+
27
+
28
+ class DICLASSPROP(IntFlag):
29
+ INSTALLER = 0x00000001
30
+ INTERFACE = 0x00000002
31
+
32
+
33
+ class GUID(Structure):
34
+ _fields_ = (
35
+ ("Data1", c_uint32),
36
+ ("Data2", c_uint16),
37
+ ("Data3", c_uint16),
38
+ ("Data4", c_ubyte * 8),
39
+ )
40
+
41
+ def __str__(self) -> str:
42
+ return str(self.to_uuid())
43
+
44
+ def __repr__(self) -> str:
45
+ return f"{type(self).__name__}({{{str(self.to_uuid())}}})"
46
+
47
+ @classmethod
48
+ def from_uuid(cls, guid: UUID) -> "GUID":
49
+ return cls.from_buffer_copy(guid.bytes_le)
50
+
51
+ def to_uuid(self) -> UUID:
52
+ return UUID(bytes_le=bytes(self))
53
+
54
+
55
+ class SP_DEVINFO_DATA(Structure):
56
+ _fields_ = (
57
+ ("cbSize", c_uint32),
58
+ ("ClassGuid", GUID),
59
+ ("DevInst", c_uint32),
60
+ ("Reserved", c_void_p),
61
+ )
62
+
63
+
64
+ class DEVPROPKEY(Structure):
65
+ _fields_ = (
66
+ ("fmtid", GUID),
67
+ ("pid", c_uint32),
68
+ )
69
+
70
+
71
+ class DEVPROP_TYPEMOD(IntFlag):
72
+ NONE = 0x00000000
73
+ ARRAY = 0x00001000 # array of fixed-sized data elements
74
+ LIST = 0x00002000 # list of variable-sized data elements
75
+
76
+
77
+ class DEVPROP_TYPE(IntFlag):
78
+ EMPTY = 0x00000000 # nothing, no property data
79
+ NULL = 0x00000001 # null property data
80
+ SBYTE = 0x00000002 # 8-bit signed int (SBYTE)
81
+ BYTE = 0x00000003 # 8-bit unsigned int (BYTE)
82
+ INT16 = 0x00000004 # 16-bit signed int (SHORT)
83
+ UINT16 = 0x00000005 # 16-bit unsigned int (USHORT)
84
+ INT32 = 0x00000006 # 32-bit signed int (LONG)
85
+ UINT32 = 0x00000007 # 32-bit unsigned int (ULONG)
86
+ INT64 = 0x00000008 # 64-bit signed int (LONG64)
87
+ UINT64 = 0x00000009 # 64-bit unsigned int (ULONG64)
88
+ FLOAT = 0x0000000A # 32-bit floating-point (FLOAT)
89
+ DOUBLE = 0x0000000B # 64-bit floating-point (DOUBLE)
90
+ DECIMAL = 0x0000000C # 128-bit data (DECIMAL)
91
+ GUID = 0x0000000D # 128-bit unique identifier (GUID)
92
+ CURRENCY = 0x0000000E # 64 bit signed int currency value (CURRENCY)
93
+ DATE = 0x0000000F # date (DATE)
94
+ FILETIME = 0x00000010 # file time (FILETIME)
95
+ BOOLEAN = 0x00000011 # 8-bit boolean (DEVPROP_BOOLEAN)
96
+ STRING = 0x00000012 # null-terminated string
97
+ STRING_LIST = STRING | DEVPROP_TYPEMOD.LIST # multi-sz string list
98
+ SECURITY_DESCRIPTOR = 0x00000013 # self-relative binary SECURITY_DESCRIPTOR
99
+ SECURITY_DESCRIPTOR_STRING = 0x00000014 # security descriptor string (SDDL format)
100
+ DEVPROPKEY = 0x00000015 # device property key (DEVPROPKEY)
101
+ DEVPROPTYPE = 0x00000016 # device property type (DEVPROPTYPE)
102
+ BINARY = BYTE | DEVPROP_TYPEMOD.ARRAY # custom binary data
103
+ ERROR = 0x00000017 # 32-bit Win32 system error code
104
+ NTSTATUS = 0x00000018 # 32-bit NTSTATUS code
105
+ STRING_INDIRECT = 0x00000019 # string resource (@[path\]<dllname>,-<strId>)
106
+
107
+
108
+ SetupDiCreateDeviceInfoList = windll.setupapi.SetupDiCreateDeviceInfoList
109
+ SetupDiCreateDeviceInfoList.restype = HDEVINFO
110
+ SetupDiCreateDeviceInfoList.argtypes = (
111
+ POINTER(GUID), # [in, optional] ClassGuid
112
+ c_void_p, # [in, optional] hwndParent
113
+ )
114
+
115
+ SetupDiDestroyDeviceInfoList = windll.setupapi.SetupDiDestroyDeviceInfoList
116
+ SetupDiDestroyDeviceInfoList.restype = c_bool
117
+ SetupDiDestroyDeviceInfoList.argtypes = (HDEVINFO,) # [in] DeviceInfoSet
118
+
119
+ SetupDiGetClassDevsW = windll.setupapi.SetupDiGetClassDevsW
120
+ SetupDiGetClassDevsW.restype = HDEVINFO
121
+ SetupDiGetClassDevsW.argtypes = (
122
+ POINTER(GUID), # [in, optional] ClassGuid
123
+ c_wchar_p, # [in, optional] Enumerator
124
+ c_void_p, # [in, optional] hwndParent
125
+ c_uint32, # [in] Flags
126
+ )
127
+
128
+ SetupDiEnumDeviceInfo = windll.setupapi.SetupDiEnumDeviceInfo
129
+ SetupDiEnumDeviceInfo.restype = c_bool
130
+ SetupDiEnumDeviceInfo.argtypes = (
131
+ HDEVINFO, # [in] DeviceInfoSet
132
+ c_uint32, # [in] MemberIndex
133
+ POINTER(SP_DEVINFO_DATA), # [out] DeviceInfoData
134
+ )
135
+
136
+ SetupDiOpenDeviceInfoW = windll.setupapi.SetupDiOpenDeviceInfoW
137
+ SetupDiOpenDeviceInfoW.restype = c_bool
138
+ SetupDiOpenDeviceInfoW.argtypes = (
139
+ HDEVINFO, # [in] DeviceInfoSet
140
+ c_wchar_p, # [in] DeviceInstanceId
141
+ c_void_p, # [in, optional] hwndParent
142
+ c_uint32, # [in] OpenFlags
143
+ POINTER(SP_DEVINFO_DATA), # [out, optional] DeviceInfoData
144
+ )
145
+
146
+ SetupDiGetDevicePropertyW = windll.setupapi.SetupDiGetDevicePropertyW
147
+ SetupDiGetDevicePropertyW.restype = c_bool
148
+ SetupDiGetDevicePropertyW.argtypes = (
149
+ HDEVINFO, # [in] DeviceInfoSet
150
+ POINTER(SP_DEVINFO_DATA), # [in] DeviceInfoData
151
+ POINTER(DEVPROPKEY), # [in] PropertyKey
152
+ POINTER(c_uint32), # [out] PropertyType
153
+ POINTER(c_ubyte), # [out, optional] PropertyBuffer
154
+ c_uint32, # [in] PropertyBufferSize
155
+ POINTER(c_uint32), # [out, optional] RequiredSize
156
+ c_uint32, # [in] Flags
157
+ )
158
+
159
+ SetupDiGetDevicePropertyKeys = windll.setupapi.SetupDiGetDevicePropertyKeys
160
+ SetupDiGetDevicePropertyKeys.restype = c_bool
161
+ SetupDiGetDevicePropertyKeys.argtypes = (
162
+ HDEVINFO, # [in] DeviceInfoSet
163
+ POINTER(SP_DEVINFO_DATA), # [in] DeviceInfoData
164
+ POINTER(DEVPROPKEY), # [out, optional] PropertyKeyArray
165
+ c_uint32, # [in] PropertyKeyCount
166
+ POINTER(c_uint32), # [out, optional] RequiredPropertyKeyCount
167
+ c_uint32, # [in] Flags
168
+ )
169
+
170
+ SetupDiBuildClassInfoList = windll.setupapi.SetupDiBuildClassInfoList
171
+ SetupDiBuildClassInfoList.restype = c_bool
172
+ SetupDiBuildClassInfoList.argtypes = (
173
+ c_uint32, # [in] Flags
174
+ POINTER(GUID), # [out, optional] ClassGuidList
175
+ c_uint32, # [in] ClassGuidListSize
176
+ POINTER(c_uint32), # [out] RequiredSize
177
+ )
178
+
179
+ SetupDiClassGuidsFromNameW = windll.setupapi.SetupDiClassGuidsFromNameW
180
+ SetupDiClassGuidsFromNameW.restype = c_bool
181
+ SetupDiClassGuidsFromNameW.argtypes = (
182
+ c_wchar_p, # [in] ClassName,
183
+ POINTER(GUID), # [out] ClassGuidList,
184
+ c_uint32, # [in] ClassGuidListSize,
185
+ POINTER(c_uint32), # [out] RequiredSize
186
+ )
187
+
188
+ SetupDiGetClassPropertyW = windll.setupapi.SetupDiGetClassPropertyW
189
+ SetupDiGetClassPropertyW.restype = c_bool
190
+ SetupDiGetClassPropertyW.argtypes = (
191
+ POINTER(GUID), # [in] ClassGuid,
192
+ POINTER(DEVPROPKEY), # [in] PropertyKey,
193
+ POINTER(c_uint32), # [out] PropertyType,
194
+ POINTER(c_ubyte), # [out] PropertyBuffer,
195
+ c_uint32, # [in] PropertyBufferSize,
196
+ POINTER(c_uint32), # [out, optional] RequiredSize,
197
+ c_uint32, # [in] Flags
198
+ )
199
+
200
+ SetupDiGetClassPropertyKeys = windll.setupapi.SetupDiGetClassPropertyKeys
201
+ SetupDiGetClassPropertyKeys.restype = c_bool
202
+ SetupDiGetClassPropertyKeys.argtypes = (
203
+ POINTER(GUID), # [in] ClassGuid,
204
+ POINTER(DEVPROPKEY), # [out, optional] PropertyKeyArray,
205
+ c_uint32, # [in] PropertyKeyCount,
206
+ POINTER(c_uint32), # [out, optional] RequiredPropertyKeyCount,
207
+ c_uint32, # [in] Flags
208
+ )
@@ -0,0 +1 @@
1
+ from . import device, setup_class
@@ -0,0 +1,126 @@
1
+ from collections.abc import Mapping
2
+ from ctypes import (
3
+ POINTER,
4
+ GetLastError,
5
+ WinError,
6
+ byref,
7
+ c_ubyte,
8
+ c_uint32,
9
+ cast,
10
+ create_string_buffer,
11
+ )
12
+ from typing import Any, Iterator, Protocol, TypeVar
13
+
14
+ from winerror import ERROR_INSUFFICIENT_BUFFER, ERROR_NOT_FOUND
15
+
16
+ from winpnp._setupapi import DEVPROPKEY, GUID
17
+ from winpnp.properties.pnp_property import PnpProperty, PnpPropertyKey, PnpPropertyType
18
+
19
+ T = TypeVar("T")
20
+
21
+
22
+ class QueryValueFunc(Protocol):
23
+ def __call__(
24
+ self,
25
+ PropertyKey,
26
+ PropertyType,
27
+ PropertyBuffer,
28
+ PropertyBufferSize,
29
+ RequiredSize,
30
+ ) -> bool: ...
31
+
32
+
33
+ class QueryKeysFunc(Protocol):
34
+ def __call__(
35
+ self, PropertyKeyArray, PropertyKeyCount, RequiredPropertyKeyCount
36
+ ) -> bool: ...
37
+
38
+
39
+ class PnpPropertyMapping(Mapping[PnpPropertyKey[T], PnpProperty[T]]):
40
+ def __init__(
41
+ self,
42
+ description: str,
43
+ query_value_func: QueryValueFunc,
44
+ query_keys_func: QueryKeysFunc,
45
+ ) -> None:
46
+ super().__init__()
47
+
48
+ self.description = description
49
+ self.query_value = query_value_func
50
+ self.query_keys = query_keys_func
51
+
52
+ def __getitem__(self, key: PnpPropertyKey[T]) -> PnpProperty[T]:
53
+ if not isinstance(key, PnpPropertyKey):
54
+ raise KeyError(key)
55
+
56
+ win_prop_key = DEVPROPKEY(GUID.from_uuid(key.category), key.property_id)
57
+ type_id = c_uint32()
58
+ required_size = c_uint32()
59
+
60
+ if self.query_value(
61
+ byref(win_prop_key),
62
+ byref(type_id),
63
+ None,
64
+ 0,
65
+ byref(required_size),
66
+ ):
67
+ return self.__build_property(key, PnpPropertyType(type_id.value), b"")
68
+
69
+ error = GetLastError()
70
+ if error == ERROR_NOT_FOUND:
71
+ raise KeyError(key)
72
+ if error != ERROR_INSUFFICIENT_BUFFER:
73
+ raise WinError(error)
74
+
75
+ value_buffer = create_string_buffer(required_size.value)
76
+ if not self.query_value(
77
+ byref(win_prop_key),
78
+ byref(type_id),
79
+ cast(value_buffer, POINTER(c_ubyte)),
80
+ required_size,
81
+ None,
82
+ ):
83
+ raise WinError()
84
+
85
+ return self.__build_property(
86
+ key, PnpPropertyType(type_id.value), value_buffer.raw
87
+ )
88
+
89
+ def __len__(self) -> int:
90
+ required_count = c_uint32()
91
+ if self.query_keys(None, 0, byref(required_count)):
92
+ return 0
93
+
94
+ error = GetLastError()
95
+ if error != ERROR_INSUFFICIENT_BUFFER:
96
+ raise WinError(error)
97
+
98
+ return required_count.value
99
+
100
+ def __iter__(self) -> Iterator[PnpPropertyKey[T]]:
101
+ keys = (DEVPROPKEY * len(self))()
102
+ if not self.query_keys(keys, len(keys), None):
103
+ raise WinError()
104
+
105
+ for key in keys:
106
+ yield PnpPropertyKey(key.fmtid.to_uuid(), key.pid)
107
+
108
+ def __build_property(
109
+ self,
110
+ key: PnpPropertyKey[T],
111
+ actual_type: PnpPropertyType[Any],
112
+ data: bytes,
113
+ ) -> PnpProperty[T]:
114
+ if (
115
+ key.allowed_types is not None
116
+ and actual_type.type_id not in key.allowed_types
117
+ ):
118
+ raise ValueError(
119
+ f"Property {key} of {self.description} has type {actual_type}, which is not expected."
120
+ )
121
+
122
+ if key.allowed_types is not None:
123
+ # Prefer key from allowed_types over original actual_type in case the one from allowed_types has a custom decoder
124
+ actual_type = key.allowed_types[actual_type.type_id]
125
+
126
+ return PnpProperty(actual_type.decode(data), actual_type)
winpnp/info/device.py ADDED
@@ -0,0 +1,171 @@
1
+ from collections.abc import Mapping
2
+ from contextlib import contextmanager
3
+ from ctypes import GetLastError, WinError, byref, create_unicode_buffer, sizeof
4
+ from typing import Any, Iterable, Iterator, TypeVar
5
+
6
+ from winerror import ERROR_NO_MORE_ITEMS
7
+
8
+ from winpnp._setupapi import (
9
+ DIGCF,
10
+ HDEVINFO,
11
+ INVALID_HANDLE_VALUE,
12
+ SP_DEVINFO_DATA,
13
+ SetupDiCreateDeviceInfoList,
14
+ SetupDiDestroyDeviceInfoList,
15
+ SetupDiEnumDeviceInfo,
16
+ SetupDiGetClassDevsW,
17
+ SetupDiGetDevicePropertyKeys,
18
+ SetupDiGetDevicePropertyW,
19
+ SetupDiOpenDeviceInfoW,
20
+ )
21
+ from winpnp.properties import keys
22
+ from winpnp.properties.pnp_property import PnpProperty, PnpPropertyKey
23
+
24
+ from ._pnp_property_mapping import PnpPropertyMapping
25
+
26
+ T = TypeVar("T")
27
+
28
+
29
+ class DeviceInfo(Mapping[PnpPropertyKey[Any], PnpProperty[Any]]):
30
+ """
31
+ Represents information about a single PnP device node.
32
+
33
+ This class should not be instantiated directly. Instead, use one of the factory methods: `of_instance_id`, `of_all_devices`, `of_present_devices`:
34
+
35
+ Can be used as a `Mapping`, with `PnpPropertyKey`s as keys and `PnpProperty` as values.
36
+
37
+ For example:
38
+ >>> from winpnp.properties.keys.device import INSTANCE_ID
39
+ ...
40
+ >>> with DeviceInfo.of_instance_id("HTREE\\ROOT\\0") as device:
41
+ ... instance_id = device[INSTANCE_ID]
42
+ ...
43
+ >>> instance_id
44
+ PnpProperty(value='HTREE\\ROOT\\0', kind=PnpPropertyType(type_id=18, name='STRING'))
45
+ """
46
+
47
+ __init_token = object()
48
+
49
+ def __init__(self, handle: HDEVINFO, data: SP_DEVINFO_DATA, *, _token=None) -> None:
50
+ """
51
+ This function should not be called directly, instead use one of the factory methods: `of_instance_id`, `of_all_devices`, `of_present_devices`.
52
+ """
53
+ if _token is not self.__init_token:
54
+ raise TypeError(
55
+ f"{type(self).__name__} should not be instantiated directly. You should use one of the factory methods: `of_instance_id`, `of_all_devices`, `of_present_devices`"
56
+ )
57
+
58
+ super().__init__()
59
+
60
+ self._handle = handle
61
+ self._data = data
62
+
63
+ self._properties: PnpPropertyMapping[Any] = PnpPropertyMapping(
64
+ description="<uninitialized DeviceInfo>",
65
+ query_value_func=lambda PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize: SetupDiGetDevicePropertyW(
66
+ self._handle,
67
+ byref(self._data),
68
+ PropertyKey,
69
+ PropertyType,
70
+ PropertyBuffer,
71
+ PropertyBufferSize,
72
+ RequiredSize,
73
+ 0,
74
+ ),
75
+ query_keys_func=lambda PropertyKeyArray, PropertyKeyCount, RequiredPropertyKeyCount: SetupDiGetDevicePropertyKeys(
76
+ self._handle,
77
+ byref(self._data),
78
+ PropertyKeyArray,
79
+ PropertyKeyCount,
80
+ RequiredPropertyKeyCount,
81
+ 0,
82
+ ),
83
+ )
84
+
85
+ self._instance_id: str = self._properties[keys.device.INSTANCE_ID].value
86
+ # Update description now that instance_id is known
87
+ self._properties.description = repr(self)
88
+
89
+ def __repr__(self) -> str:
90
+ return f"{type(self).__name__}(instance_id={repr(self._instance_id)})"
91
+
92
+ def __getitem__(self, key: PnpPropertyKey[T]) -> PnpProperty[T]:
93
+ return self._properties[key]
94
+
95
+ def __len__(self) -> int:
96
+ return len(self._properties)
97
+
98
+ def __iter__(self) -> Iterator[PnpPropertyKey[Any]]:
99
+ return iter(self._properties)
100
+
101
+ @classmethod
102
+ def __enumerate_device_info_set(cls, handle: HDEVINFO) -> Iterator["DeviceInfo"]:
103
+ index = 0
104
+ data = SP_DEVINFO_DATA()
105
+ data.cbSize = sizeof(data)
106
+
107
+ while SetupDiEnumDeviceInfo(handle, index, byref(data)):
108
+ yield cls(
109
+ handle, SP_DEVINFO_DATA.from_buffer_copy(data), _token=cls.__init_token
110
+ )
111
+ index += 1
112
+
113
+ error = GetLastError()
114
+ if error != ERROR_NO_MORE_ITEMS:
115
+ raise WinError(error)
116
+
117
+ @classmethod
118
+ @contextmanager
119
+ def __create_using_SetupDiGetClassDevsW(
120
+ cls, flags: DIGCF
121
+ ) -> Iterator[Iterable["DeviceInfo"]]:
122
+ handle: HDEVINFO = SetupDiGetClassDevsW(None, None, None, flags)
123
+ if handle == INVALID_HANDLE_VALUE:
124
+ raise WinError()
125
+
126
+ try:
127
+ yield cls.__enumerate_device_info_set(handle)
128
+ finally:
129
+ SetupDiDestroyDeviceInfoList(handle)
130
+
131
+ @classmethod
132
+ @contextmanager
133
+ def of_instance_id(cls, instance_id: str) -> Iterator["DeviceInfo"]:
134
+ """
135
+ Opens information of the device with the specified instance id.
136
+ """
137
+ handle: HDEVINFO = SetupDiCreateDeviceInfoList(None, None)
138
+ if handle == INVALID_HANDLE_VALUE:
139
+ raise WinError()
140
+
141
+ try:
142
+ data = SP_DEVINFO_DATA()
143
+ data.cbSize = sizeof(data)
144
+ if not SetupDiOpenDeviceInfoW(
145
+ handle, create_unicode_buffer(instance_id), None, 0, byref(data)
146
+ ):
147
+ raise WinError()
148
+
149
+ yield cls(handle, data, _token=cls.__init_token)
150
+ finally:
151
+ SetupDiDestroyDeviceInfoList(handle)
152
+
153
+ @classmethod
154
+ @contextmanager
155
+ def of_all_devices(cls) -> Iterator[Iterable["DeviceInfo"]]:
156
+ """
157
+ Opens information of all devices known to Windows, including ones that are no longer present.
158
+ """
159
+ with cls.__create_using_SetupDiGetClassDevsW(DIGCF.ALLCLASSES) as devices:
160
+ yield devices
161
+
162
+ @classmethod
163
+ @contextmanager
164
+ def of_present_devices(cls) -> Iterator[Iterable["DeviceInfo"]]:
165
+ """
166
+ Opens information of all devices that are currently present.
167
+ """
168
+ with cls.__create_using_SetupDiGetClassDevsW(
169
+ DIGCF.ALLCLASSES | DIGCF.PRESENT
170
+ ) as devices:
171
+ yield devices
@@ -0,0 +1,110 @@
1
+ from collections.abc import Mapping
2
+ from ctypes import WinError, byref, c_uint32, create_unicode_buffer
3
+ from typing import Any, Iterator, TypeVar
4
+ from uuid import UUID
5
+
6
+ from winpnp._setupapi import (
7
+ DICLASSPROP,
8
+ GUID,
9
+ SetupDiBuildClassInfoList,
10
+ SetupDiClassGuidsFromNameW,
11
+ SetupDiGetClassPropertyKeys,
12
+ SetupDiGetClassPropertyW,
13
+ )
14
+ from winpnp.properties import keys
15
+ from winpnp.properties.pnp_property import PnpProperty, PnpPropertyKey
16
+
17
+ from ._pnp_property_mapping import PnpPropertyMapping
18
+
19
+ T = TypeVar("T")
20
+
21
+
22
+ class SetupClassInfo(Mapping[PnpPropertyKey[Any], PnpProperty[Any]]):
23
+ """
24
+ Represents information about a single PnP setup class.
25
+
26
+ Can be used as a `Mapping`, with `PnpPropertyKey`s as keys and `PnpProperty` as values.
27
+
28
+ For example:
29
+ >>> from uuid import UUID
30
+ >>> from winpnp.properties.keys.device_class import CLASS_NAME
31
+ ...
32
+ >>> SetupClassInfo(UUID("36fc9e60-c465-11cf-8056-444553540000"))[CLASS_NAME]
33
+ PnpProperty(value='USB', kind=PnpPropertyType(type_id=18, name='STRING'))
34
+ """
35
+
36
+ def __init__(self, guid: UUID) -> None:
37
+ super().__init__()
38
+
39
+ self._guid = guid
40
+
41
+ self._properties: PnpPropertyMapping[Any] = PnpPropertyMapping(
42
+ description="<uninitialized SetupClassInfo>",
43
+ query_value_func=lambda PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize: SetupDiGetClassPropertyW(
44
+ byref(GUID.from_uuid(self._guid)),
45
+ PropertyKey,
46
+ PropertyType,
47
+ PropertyBuffer,
48
+ PropertyBufferSize,
49
+ RequiredSize,
50
+ DICLASSPROP.INSTALLER,
51
+ ),
52
+ query_keys_func=lambda PropertyKeyArray, PropertyKeyCount, RequiredPropertyKeyCount: SetupDiGetClassPropertyKeys(
53
+ byref(GUID.from_uuid(self._guid)),
54
+ PropertyKeyArray,
55
+ PropertyKeyCount,
56
+ RequiredPropertyKeyCount,
57
+ DICLASSPROP.INSTALLER,
58
+ ),
59
+ )
60
+
61
+ self._name: str = self._properties[keys.device_class.CLASS_NAME].value
62
+ # Update description now that instance_id is known
63
+ self._properties.description = repr(self)
64
+
65
+ def __repr__(self) -> str:
66
+ return (
67
+ f"{type(self).__name__}(guid={repr(self._guid)}, name={repr(self._name)})"
68
+ )
69
+
70
+ def __getitem__(self, key: PnpPropertyKey[T]) -> PnpProperty[T]:
71
+ return self._properties[key]
72
+
73
+ def __len__(self) -> int:
74
+ return len(self._properties)
75
+
76
+ def __iter__(self) -> Iterator[PnpPropertyKey]:
77
+ return iter(self._properties)
78
+
79
+ @property
80
+ def guid(self) -> UUID:
81
+ return self._guid
82
+
83
+ @classmethod
84
+ def of_class_name(cls, name: str) -> Iterator["SetupClassInfo"]:
85
+ name_buffer = create_unicode_buffer(name)
86
+ required_size = c_uint32()
87
+ if SetupDiClassGuidsFromNameW(name_buffer, None, 0, byref(required_size)):
88
+ return
89
+
90
+ guids = (GUID * required_size.value)()
91
+ if not SetupDiClassGuidsFromNameW(
92
+ name_buffer, guids, required_size, byref(required_size)
93
+ ):
94
+ raise WinError()
95
+
96
+ for guid in guids:
97
+ yield cls(guid.to_uuid())
98
+
99
+ @classmethod
100
+ def of_all_classes(cls) -> Iterator["SetupClassInfo"]:
101
+ required_size = c_uint32()
102
+ if SetupDiBuildClassInfoList(0, None, 0, byref(required_size)):
103
+ return
104
+
105
+ guids = (GUID * required_size.value)()
106
+ if not SetupDiBuildClassInfoList(0, guids, required_size, byref(required_size)):
107
+ raise WinError()
108
+
109
+ for guid in guids:
110
+ yield cls(guid.to_uuid())
@@ -0,0 +1 @@
1
+ from . import keys, kinds, pnp_property