This is the part 2 of the Exploring Delphi XE3 – WinApi Additions – Winapi.Functiondiscovery Article
One of the nice features of the Function Discovery API is the posibility of filter the results for device enumeration, for this you must use the CreateInstanceCollectionQuery method and then add the conditions for the query using the AddPropertyConstraint method.
Try this sample Delphi code which enumerates all the processors devices where the manufacturer is Intel.
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.Win.ComObj,
Winapi.Windows,
Winapi.Activex,
Winapi.PropSys,
Winapi.Functiondiscovery,
System.SysUtils;
procedure Enumerate;
var
LFunctionDiscovery : IFunctionDiscovery;
LFunctionInstance : IFunctionInstance;
ppIFunctionInstanceCollection: IFunctionInstanceCollection;
ppIFunctionInstanceCollectionQuery: IFunctionInstanceCollectionQuery;
ppIPropertyStore : IPropertyStore;
pv : TPropVariant;
pdwCount : DWORD;
pszCategory: PWCHAR;
hr : HResult;
i : integer;
begin
//create an instance to the IFunctionDiscovery interface
LFunctionDiscovery := CreateComObject(CLSID_FunctionDiscovery) as IFunctionDiscovery;
try
//set the provider to search
pszCategory:=FCTN_CATEGORY_PNP;
//get the devices collection
hr := LFunctionDiscovery.CreateInstanceCollectionQuery(pszCategory, nil, false, nil, nil, ppIFunctionInstanceCollectionQuery);
if Succeeded(hr) then
begin
PropVariantClear(pv);
pv.vt:=VT_LPWSTR;
pv.pwszVal:='Intel';
hr := ppIFunctionInstanceCollectionQuery.AddPropertyConstraint(PKEY_Device_Manufacturer, pv, QC_EQUALS);
if not Succeeded(hr) then RaiseLastOSError;
PropVariantClear(pv);
pv.vt:=VT_LPWSTR;
pv.pwszVal:='Processor';
hr := ppIFunctionInstanceCollectionQuery.AddPropertyConstraint(PKEY_Device_Class, pv, QC_EQUALS);
if not Succeeded(hr) then RaiseLastOSError;
hr := ppIFunctionInstanceCollectionQuery.Execute(ppIFunctionInstanceCollection);
if Succeeded(hr) then
begin
//get the collection count
ppIFunctionInstanceCollection.GetCount(pdwCount);
if pdwCount=0 then
Writeln(Format('No items was found for the %s category',[pszCategory]))
else
for i := 0 to pdwCount - 1 do begin
//get the n Item of the collection
if Succeeded(ppIFunctionInstanceCollection.Item(i, LFunctionInstance)) then
begin
//init the propertiess store
LFunctionInstance.OpenPropertyStore(STGM_READ, ppIPropertyStore);
//read the properties values
if Succeeded(ppIPropertyStore.GetValue(PKEY_NAME, pv)) then
Writeln(Format('Name %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_InstanceId, pv)) then
Writeln(Format('Instance Id %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_Driver, pv)) then
Writeln(Format('Device Driver %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_Model, pv)) then
Writeln(Format('Model %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_Manufacturer, pv)) then
Writeln(Format('Manufacturer %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_LocationInfo, pv)) then
Writeln(Format('Location %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_Class, pv)) then
Writeln(Format('Class %s',[pv.pwszVal]));
if Succeeded(ppIPropertyStore.GetValue(PKEY_Device_ClassGuid, pv)) then
Writeln(Format('Class Guid %s',[pv.puuid^.ToString]));
Writeln;
end
else
RaiseLastOSError;
end;
end;
end
else
RaiseLastOSError;
finally
LFunctionDiscovery:=nil;
end;
end;
begin
try
ReportMemoryLeaksOnShutdown:=True;
if (Win32MajorVersion >= 6) then // available on Vista (or later)
begin
if Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED)) then
try
Enumerate;
finally
CoUninitialize;
end;
end
else
Writeln('Windows version not compatible');
except
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
December 24, 2013 at 12:05 pm
Doesn’t give PNP ID GUIDs; but this will
//depending of the type of the property display the info
case pv.vt of
VT_BOOL : Writeln(Format(‘%-40s %s’,[KeyName , BoolToStr(pv.boolVal, True)]));
VT_UINT : Writeln(Format(‘%-40s %d’,[KeyName ,pv.ulVal]));
VT_INT : Writeln(Format(‘%-40s %d’,[KeyName ,pv.iVal]));
VT_I4,
VT_UI4 : Writeln(Format(‘%-40s %d’,[KeyName ,pv.ulVal]));
VT_EMPTY : Writeln(Format(‘%-40s %s’,[KeyName ,'(Empty)’]));
VT_LPWSTR : Writeln(Format(‘%-40s %s’,[KeyName ,pv.pwszVal]));
VT_CLSID : Writeln(Format(‘%-40s %s’,[KeyName ,pv.puuid^.ToString]));
VT_VECTOR or VT_LPWSTR :
try
k := 0;
while PropVariantGetElem(pv,k,ps)=0 do
begin
case ps.vt of
VT_LPWSTR : Writeln(Format(‘%-40s %s’,[KeyName ,ps.pwszVal]));
else
Writeln(Format(‘%-40s %s’,[KeyName ,'(Type Unk)’+IntToStr(pv.vt) ]));
end;
Inc(k);
end;
except
end;
else
Writeln(Format(‘%-40s %s’,[KeyName ,'(Type Unknow)’+IntToStr(pv.vt) ]));
end;