-
Notifications
You must be signed in to change notification settings - Fork 44
/
DeviceHelper.pas
327 lines (295 loc) · 9.95 KB
/
DeviceHelper.pas
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
unit DeviceHelper;
interface
uses
Windows,
SetupApi,
Common;
type
TDeviceHelper = class
private
FDeviceInfoData: SP_DEVINFO_DATA;
FDeviceListHandle: HDEVINFO;
protected
function GetBinary(PropertyCode: Integer;
pData: Pointer; dwSize: DWORD): Boolean; virtual;
function GetDWORD(PropertyCode: Integer): DWORD; virtual;
function GetGuid(PropertyCode: Integer): TGUID; virtual;
function GetString(PropertyCode: Integer): String; virtual;
function GetPolicy(PropertyCode: Integer): String; virtual;
public
function Capabilities: String;
function Characteristics: String;
function ConfigFlags: String;
function DeviceClassDescription: String; overload;
function DeviceClassDescription(DeviceTypeGUID: TGUID): String; overload;
function InstallState: String;
function PowerData: String;
function LegacyBusType: String;
public
property Address: DWORD index SPDRP_ADDRESS read GetDWORD;
property BusTypeGUID: TGUID index SPDRP_BUSTYPEGUID read GetGuid;
property BusNumber: DWORD index SPDRP_BUSNUMBER read GetDWORD;
property ClassGUID: TGUID index SPDRP_CLASSGUID read GetGuid;
property CompatibleIDS: String index SPDRP_COMPATIBLEIDS read GetString;
property DeviceClassName: String index SPDRP_CLASS read GetString;
//property DeviceType: xxx index SPDRP_DEVTYPE read xxx;
property DriverName: String index SPDRP_DRIVER read GetString;
property Description: String index SPDRP_DEVICEDESC read GetString;
property Enumerator: String index SPDRP_ENUMERATOR_NAME read GetString;
//property Exclusive: xxx index SPDRP_EXCLUSIVE read xxx;
property FriendlyName: String index SPDRP_FRIENDLYNAME read GetString;
property HardwareID: String index SPDRP_HARDWAREID read GetString;
property Service: String index SPDRP_SERVICE read GetString;
//property Security: xxx index SPDRP_SECURITY read xxx;
//property SecuritySDS: xxx index SPDRP_SECURITY_SDS read xxx;
property Location: String index SPDRP_LOCATION_INFORMATION read GetString;
property LowerFilters: String index SPDRP_LOWERFILTERS read GetString;
property Manufacturer: String index SPDRP_MFG read GetString;
property PhisicalDriverName: String
index SPDRP_PHYSICAL_DEVICE_OBJECT_NAME read GetString;
property RemovalPolicy: String index SPDRP_REMOVAL_POLICY
read GetPolicy;
property RemovalPolicyHWDefault: String
index SPDRP_REMOVAL_POLICY_HW_DEFAULT read GetPolicy;
property RemovalPolicyOverride: String index SPDRP_REMOVAL_POLICY_OVERRIDE
read GetPolicy;
property UINumber: DWORD index SPDRP_UI_NUMBER read GetDWORD;
property UINumberDecription: String index SPDRP_UI_NUMBER_DESC_FORMAT
read GetString;
property UpperFilters: String index SPDRP_UPPERFILTERS read GetString;
public
property DeviceInfoData: SP_DEVINFO_DATA read FDeviceInfoData
write FDeviceInfoData;
property DeviceListHandle: HDEVINFO read FDeviceListHandle
write FDeviceListHandle;
end;
procedure CoTaskMemFree(pv: Pointer); stdcall; external 'ole32.dll' name 'CoTaskMemFree';
function StringFromCLSID(const clsid: TGUID; out psz: PWideChar): HResult; stdcall; external 'ole32.dll' name 'StringFromCLSID';
function CLSIDFromString(psz: PWideChar; out clsid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CLSIDFromString';
implementation
uses
ListarDispositivos;
{ TDeviceHelper }
function HasFlag(const Value, dwFlag: DWORD): Boolean;
begin
Result := (Value and dwFlag) = dwFlag;
end;
procedure AddToResult(var AResult: String; const Value: String);
begin
if AResult = '' then
AResult := Value
else
AResult := AResult + ', ' + Value;
end;
function ExtractMultiString(const Value: String): String;
var
P: PChar;
begin
P := @Value[1];
while P^ <> #0 do
begin
if Result <> '' then
Result := Result + ', ';
Result := Result + P;
Inc(P, lstrlen(P) + 1);
end;
end;
function TDeviceHelper.Capabilities: String;
var
I: Integer;
dwCapabilities: DWORD;
begin
Result := '';
dwCapabilities := GetDWORD(SPDRP_CAPABILITIES);
for I := 0 to 9 do
if HasFlag(dwCapabilities, CapabilitiesRelationships[I].Flag) then
AddToResult(Result, CapabilitiesRelationships[I].Desc);
end;
function TDeviceHelper.Characteristics: String;
var
dwCharacteristics: DWORD;
begin
dwCharacteristics := GetDWORD(SPDRP_CHARACTERISTICS);
//if dwCharacteristics <> 0 then Beep;
end;
function TDeviceHelper.ConfigFlags: String;
var
I: Integer;
dwConfigFlags: DWORD;
begin
Result := '';
dwConfigFlags := GetDWORD(SPDRP_CONFIGFLAGS);
for I := 0 to 15 do
if HasFlag(dwConfigFlags, ConfigFlagRelationships[I].Flag) then
AddToResult(Result, ConfigFlagRelationships[I].Desc);
end;
function TDeviceHelper.DeviceClassDescription(DeviceTypeGUID: TGUID): String;
var
dwRequiredSize: DWORD;
begin
Result := '';
dwRequiredSize := 0;
SetupDiGetClassDescriptionW(DeviceTypeGUID, nil, 0, dwRequiredSize);
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
SetLength(Result, dwRequiredSize * 2);
SetupDiGetClassDescriptionW(DeviceTypeGUID, @Result[1], dwRequiredSize, dwRequiredSize);
end;
Result := PChar(Result);
end;
function TDeviceHelper.DeviceClassDescription: String;
var
AGUID: TGUID;
begin
AGUID := ClassGUID;
Result := DeviceClassDescription(AGUID);
end;
function TDeviceHelper.GetBinary(PropertyCode: Integer; pData: Pointer;
dwSize: DWORD): Boolean;
var
dwPropertyRegDataType, dwRequiredSize: DWORD;
begin
dwRequiredSize := 0;
dwPropertyRegDataType := REG_BINARY;
Result := SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, pData,
dwSize, dwRequiredSize);
end;
function TDeviceHelper.GetDWORD(PropertyCode: Integer): DWORD;
var
dwPropertyRegDataType, dwRequiredSize: DWORD;
begin
Result := 0;
dwRequiredSize := 4;
dwPropertyRegDataType := REG_DWORD;
SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, @Result,
dwRequiredSize, dwRequiredSize);
end;
function StringToGUID(const S: string): TGUID;
begin
Succeeded(CLSIDFromString(PWideChar(WideString(S)), Result))
end;
function TDeviceHelper.GetGuid(PropertyCode: Integer): TGUID;
var
dwPropertyRegDataType, dwRequiredSize: DWORD;
StringGUID: String;
begin
ZeroMemory(@Result, SizeOf(TGUID));
StringGUID := GetString(PropertyCode);
if StringGUID = '' then
begin
dwRequiredSize := 0;
dwPropertyRegDataType := REG_BINARY;
SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, nil, 0, dwRequiredSize);
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, @Result,
dwRequiredSize, dwRequiredSize);
end;
end
else
Result := StringToGUID(StringGUID);
end;
function TDeviceHelper.GetPolicy(PropertyCode: Integer): String;
var
dwPolicy: DWORD;
begin
dwPolicy := GetDWORD(PropertyCode);
if dwPolicy > 0 then
case dwPolicy of
CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL:
Result := 'CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL';
CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL:
Result := 'CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL';
CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL:
Result := 'CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL';
else
Result := 'unknown 0x' + IntToHex(dwPolicy, 8);
end;
end;
function TDeviceHelper.GetString(PropertyCode: Integer): String;
var
dwPropertyRegDataType, dwRequiredSize: DWORD;
begin
Result := '';
dwRequiredSize := 0;
dwPropertyRegDataType := REG_SZ;
SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, nil, 0, dwRequiredSize);
if not (dwPropertyRegDataType in [REG_SZ, REG_MULTI_SZ]) then Exit;
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
SetLength(Result, dwRequiredSize * 2);
SetupDiGetDeviceRegistryPropertyW(DeviceListHandle, DeviceInfoData,
PropertyCode, dwPropertyRegDataType, @Result[1],
dwRequiredSize, dwRequiredSize);
end;
case dwPropertyRegDataType of
REG_SZ: Result := PChar(Result);
REG_MULTI_SZ: Result := ExtractMultiString(Result);
end;
end;
function TDeviceHelper.InstallState: String;
var
dwInstallState: DWORD;
begin
dwInstallState := GetDWORD(SDRP_INSTALL_STATE);
case dwInstallState of
CM_INSTALL_STATE_INSTALLED:
Result := 'CM_INSTALL_STATE_INSTALLED';
CM_INSTALL_STATE_NEEDS_REINSTALL:
Result := 'CM_INSTALL_STATE_NEEDS_REINSTALL';
CM_INSTALL_STATE_FAILED_INSTALL:
Result := 'CM_INSTALL_STATE_FAILED_INSTALL';
CM_INSTALL_STATE_FINISH_INSTALL:
Result := 'CM_INSTALL_STATE_FINISH_INSTALL';
else
Result := 'unknown 0x' + IntToHex(dwInstallState, 8);
end;
end;
function TDeviceHelper.LegacyBusType: String;
var
BusType: Integer;
begin
BusType := Integer(GetDWORD(SPDRP_LEGACYBUSTYPE));
case BusType of
-1: Result := 'InterfaceTypeUndefined';
00: Result := 'Internal';
01: Result := 'Isa';
02: Result := 'Eisa';
03: Result := 'MicroChannel';
04: Result := 'TurboChannel';
05: Result := 'PCIBus';
06: Result := 'VMEBus';
07: Result := 'NuBus';
08: Result := 'PCMCIABus';
09: Result := 'CBus';
10: Result := 'MPIBus';
11: Result := 'MPSABus';
12: Result := 'ProcessorInternal';
13: Result := 'InternalPowerBus';
14: Result := 'PNPISABus';
15: Result := 'PNPBus';
16: Result := 'MaximumInterfaceType';
else
Result := 'unknown 0x' + IntToHex(BusType, 8);
end;
end;
function TDeviceHelper.PowerData: String;
var
I: Integer;
pPowerData: TCM_Power_Data;
begin
Result := '';
if GetBinary(SPDRP_DEVICE_POWER_DATA, @pPowerData,
SizeOf(TCM_Power_Data)) then
begin
for I := 0 to 8 do
if HasFlag(pPowerData.PD_Capabilities, PDCAPRelationships[I].Flag) then
AddToResult(Result, PDCAPRelationships[I].Desc);
end;
end;
end.