Title: Drivers Info Dump
Question: this little utility dumps in a memo a lot of information for each driver
in your system
Answer:
unit Unit1;
//Drivers Info Dump
//
// by Gian Paolo Papini
// eMail: gppapini@live.it
//
//this little utility dumps in a memo a lot of information for each driver
//in your system
//
//for instance:
(*
#73
Friendly name:
DevDesc: Intel(R) PRO/1000 PL Network Connection
Driver Key: {4D36E972-E325-11CE-BFC1-08002BE10318}\0008
Class: Net
HardwareID: PCI\VEN_8086&DEV_109A&SUBSYS_81C21043&REV_00
Location: Bus PCI 2, periferica 0, funzione 0
Device Status:
DN_DRIVER_LOADED: Has Register_Device_Driver
DN_STARTED: Is currently configured
DN_DISABLEABLE: Can be rebalanced
Device Problem: No Problems
*)
//SetupApi by Robert Marquardt (Project Jedi)
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
Setupapi //you need this for the Drivers API
;
const
CFGMGR32_DLL = 'cfgmgr32.dll';
CM_GET_DEVNODE_STATUS_NAME = 'CM_Get_DevNode_Status';
CR_SUCCESS = $00000000;
//
// DevInst problem values, returned by call to CM_Get_DevInst_Status
//
CM_PROB_NOT_CONFIGURED = $00000001; // no config for device
CM_PROB_DEVLOADER_FAILED = $00000002; // service load failed
CM_PROB_OUT_OF_MEMORY = $00000003; // out of memory
CM_PROB_ENTRY_IS_WRONG_TYPE = $00000004; // WINDOWS 95 ONLY
CM_PROB_LACKED_ARBITRATOR = $00000005; // WINDOWS 95 ONLY
CM_PROB_BOOT_CONFIG_CONFLICT = $00000006; // boot config conflict
CM_PROB_FAILED_FILTER = $00000007; // WINDOWS 95 ONLY
CM_PROB_DEVLOADER_NOT_FOUND = $00000008; // Devloader not found
CM_PROB_INVALID_DATA = $00000009; // WINDOWS 95 ONLY
CM_PROB_FAILED_START = $0000000A; // WINDOWS 95 ONLY
CM_PROB_LIAR = $0000000B; // ???
CM_PROB_NORMAL_CONFLICT = $0000000C; // config conflict
CM_PROB_NOT_VERIFIED = $0000000D; // WINDOWS 95 ONLY
CM_PROB_NEED_RESTART = $0000000E; // requires restart
CM_PROB_REENUMERATION = $0000000F; // WINDOWS 95 ONLY
CM_PROB_PARTIAL_LOG_CONF = $00000010; // WINDOWS 95 ONLY
CM_PROB_UNKNOWN_RESOURCE = $00000011; // unknown res type
CM_PROB_REINSTALL = $00000012; // WINDOWS 95 ONLY
CM_PROB_REGISTRY = $00000013; // WINDOWS 95 ONLY
CM_PROB_VXDLDR = $00000014; // WINDOWS 95 ONLY
CM_PROB_WILL_BE_REMOVED = $00000015; // devinst will remove
CM_PROB_DISABLED = $00000016; // devinst is disabled
CM_PROB_DEVLOADER_NOT_READY = $00000017; // Devloader not ready
CM_PROB_DEVICE_NOT_THERE = $00000018; // device doesn't exist
CM_PROB_MOVED = $00000019; // WINDOWS 95 ONLY
CM_PROB_TOO_EARLY = $0000001A; // WINDOWS 95 ONLY
CM_PROB_NO_VALID_LOG_CONF = $0000001B; // no valid log config
CM_PROB_FAILED_INSTALL = $0000001C; // install failed
CM_PROB_HARDWARE_DISABLED = $0000001D; // device disabled
CM_PROB_CANT_SHARE_IRQ = $0000001E; // can't share IRQ
NUM_CM_PROB = $0000001F;
//
// Device Instance status flags, returned by call to CM_Get_DevInst_Status
//
DN_ROOT_ENUMERATED = $00000001; // Was enumerated by ROOT
DN_DRIVER_LOADED = $00000002; // Has Register_Device_Driver
DN_ENUM_LOADED = $00000004; // Has Register_Enumerator
DN_STARTED = $00000008; // Is currently configured
DN_MANUAL = $00000010; // Manually installed
DN_NEED_TO_ENUM = $00000020; // May need reenumeration
DN_NOT_FIRST_TIME = $00000040; // Has received a config
DN_HARDWARE_ENUM = $00000080; // Enum generates hardware ID
DN_LIAR = $00000100; // Lied about can reconfig once
DN_HAS_MARK = $00000200; // Not CM_Create_DevInst lately
DN_HAS_PROBLEM = $00000400; // Need device installer
DN_FILTERED = $00000800; // Is filtered
DN_MOVED = $00001000; // Has been moved
DN_DISABLEABLE = $00002000; // Can be rebalanced
DN_REMOVABLE = $00004000; // Can be removed
DN_PRIVATE_PROBLEM = $00008000; // Has a private problem
DN_MF_PARENT = $00010000; // Multi function parent
DN_MF_CHILD = $00020000; // Multi function child
DN_WILL_BE_REMOVED = $00040000; // DevInst is being removed
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function DetectDriversInfo: boolean;
end;
var
Form1: TForm1;
HCfgMgr: THandle;
CM_Get_DevNode_Status: function(pulStatus: PULONG; pulProblemNumber: PULONG; dnDevInst: DWORD; ulFlags: ULONG): DWORD; stdcall;
implementation
{$R *.dfm}
function GetDeviceInstanceStatusProblemMessage(myulProblem: ULONG): string;
//passing a ULONG problem (returned from CM_Get_DevInst_Status)
//returns a corresponding string;
var
msg: string;
begin
case myulProblem of
0:
msg := 'No Problems';
CM_PROB_NOT_CONFIGURED : // no config for device
msg := 'CM_PROB_NOT_CONFIGURED';
CM_PROB_DEVLOADER_FAILED :// service load failed
msg := 'CM_PROB_DEVLOADER_FAILED';
CM_PROB_OUT_OF_MEMORY : // out of memory
msg := 'CM_PROB_OUT_OF_MEMORY';
CM_PROB_ENTRY_IS_WRONG_TYPE : // WINDOWS 95 ONLY
msg := 'CM_PROB_ENTRY_IS_WRONG_TYPE';
CM_PROB_LACKED_ARBITRATOR : // WINDOWS 95 ONLY
msg := 'CM_PROB_LACKED_ARBITRATOR';
CM_PROB_BOOT_CONFIG_CONFLICT : // boot config conflict
msg := 'CM_PROB_BOOT_CONFIG_CONFLICT';
CM_PROB_FAILED_FILTER : // WINDOWS 95 ONLY
msg := 'CM_PROB_FAILED_FILTER';
CM_PROB_DEVLOADER_NOT_FOUND : // Devloader not found
msg := 'CM_PROB_DEVLOADER_NOT_FOUND';
CM_PROB_INVALID_DATA : // WINDOWS 95 ONLY
msg := 'CM_PROB_INVALID_DATA';
CM_PROB_FAILED_START : // WINDOWS 95 ONLY
msg := 'CM_PROB_FAILED_START';
CM_PROB_LIAR : // ???
msg := 'CM_PROB_LIAR';
CM_PROB_NORMAL_CONFLICT : // config conflict
msg := 'CM_PROB_NORMAL_CONFLICT';
CM_PROB_NOT_VERIFIED : // WINDOWS 95 ONLY
msg := 'CM_PROB_NOT_VERIFIED';
CM_PROB_NEED_RESTART : // requires restart
msg := 'CM_PROB_NEED_RESTART';
CM_PROB_REENUMERATION : // WINDOWS 95 ONLY
msg := 'CM_PROB_REENUMERATION';
CM_PROB_PARTIAL_LOG_CONF : // WINDOWS 95 ONLY
msg := 'CM_PROB_PARTIAL_LOG_CONF';
CM_PROB_UNKNOWN_RESOURCE : // unknown res type
msg := 'CM_PROB_UNKNOWN_RESOURCE';
CM_PROB_REINSTALL : // WINDOWS 95 ONLY
msg := 'CM_PROB_REINSTALL';
CM_PROB_REGISTRY : // WINDOWS 95 ONLY
msg := 'CM_PROB_REGISTRY';
CM_PROB_VXDLDR : // WINDOWS 95 ONLY
msg := 'CM_PROB_VXDLDR';
CM_PROB_WILL_BE_REMOVED : // devinst will remove
msg := 'CM_PROB_WILL_BE_REMOVED';
CM_PROB_DISABLED : // devinst is disabled
msg := 'CM_PROB_DISABLED';
CM_PROB_DEVLOADER_NOT_READY : // Devloader not ready
msg := 'CM_PROB_DEVLOADER_NOT_READY';
CM_PROB_DEVICE_NOT_THERE : // device doesn't exist
msg := 'CM_PROB_DEVICE_NOT_THERE';
CM_PROB_MOVED : // WINDOWS 95 ONLY
msg := 'CM_PROB_MOVED';
CM_PROB_TOO_EARLY : // WINDOWS 95 ONLY
msg := 'CM_PROB_TOO_EARLY';
CM_PROB_NO_VALID_LOG_CONF : // no valid log config
msg := 'CM_PROB_NO_VALID_LOG_CONF';
CM_PROB_FAILED_INSTALL : // install failed
msg := 'CM_PROB_FAILED_INSTALL';
CM_PROB_HARDWARE_DISABLED : // device disabled
msg := 'CM_PROB_HARDWARE_DISABLED';
CM_PROB_CANT_SHARE_IRQ : // can't share IRQ
msg := 'CM_PROB_CANT_SHARE_IRQ';
else
msg := 'Undefined Problem';
end;
Result := msg;
end;//function GetDeviceInstanceStatusProblemMessage
function GetDeviceInstanceStatusFlagMessage(myulStatus: ULONG): string;
//passing a ULONG bitmask status (returned from CM_Get_DevInst_Status)
//builds a StringList with every message from every active bit in the mask
var
msg: string;
i: integer;
j: Ulong;
mystrList: TStringList;
begin
if myulStatus = 0 then begin
Result := 'The Device is not installed';
exit;
end;
mystrList := TStringList.Create;
mystrList.Clear;
j := 0;
for i := 0 to 18 do begin //the DN_ consts are 19...
if i = 0 then begin
j := 1;
end else begin
j := j*2;
end;
if ((myulStatus and j) = j) then begin
case j of
DN_ROOT_ENUMERATED:
mystrList.Add('DN_ROOT_ENUMERATED: Was enumerated by ROOT');
DN_DRIVER_LOADED:
mystrList.Add('DN_DRIVER_LOADED: Has Register_Device_Driver');
DN_ENUM_LOADED:
mystrList.Add('DN_ENUM_LOADED: Has Register_Enumerator');
DN_STARTED:
mystrList.Add('DN_STARTED: Is currently configured');
DN_MANUAL:
mystrList.Add('DN_MANUAL: Manually installed');
DN_NEED_TO_ENUM:
mystrList.Add('DN_NEED_TO_ENUM: May need reenumeration');
DN_NOT_FIRST_TIME:
mystrList.Add('DN_NOT_FIRST_TIME: Has received a config');
DN_HARDWARE_ENUM:
mystrList.Add('DN_HARDWARE_ENUM: Enum generates hardware ID');
DN_LIAR:
mystrList.Add('DN_LIAR: Lied about can reconfig once');
DN_HAS_MARK:
mystrList.Add('DN_HAS_MARK: Not CM_Create_DevInst lately');
DN_HAS_PROBLEM:
mystrList.Add('DN_HAS_PROBLEM: Need device installer');
DN_FILTERED:
mystrList.Add('DN_FILTERED: Is filtered');
DN_MOVED:
mystrList.Add('DN_MOVED: Has been moved');
DN_DISABLEABLE:
mystrList.Add('DN_DISABLEABLE: Can be rebalanced');
DN_REMOVABLE:
mystrList.Add('DN_REMOVABLE: Can be removed');
DN_PRIVATE_PROBLEM:
mystrList.Add('DN_PRIVATE_PROBLEM: Has a private problem');
DN_MF_PARENT:
mystrList.Add('DN_MF_PARENT: Multi function parent');
DN_MF_CHILD:
mystrList.Add('DN_MF_CHILD: Multi function child');
DN_WILL_BE_REMOVED:
mystrList.Add('DN_WILL_BE_REMOVED: DevInst is being removed');
else
mystrList.Add('Status undefined');
end;
end;
end;//for i
msg := mystrList.Text;
Result := msg;
FreeAndNil(mystrList);
end;//function GetDeviceInstanceStatusFlagMessage(
function TForm1.DetectDriversInfo: boolean;
var
PnPHandle: HDEVINFO;
DevData: TSPDevInfoData;
mybool: boolean;
Index: DWORD;
msg: string;
ulStatus: ULONG;
ulProblemNumber: ULONG;
DataT: DWORD;
nSize: DWORD;
buf: array[0..MAX_PATH] of char;
begin
Result := false;
Index := 0;
Memo1.Clear;
//Loads the SetupApi for
//SetupDiEnumDeviceInfo
//SetupDiGetDeviceRegistryProperty
LoadSetupApi; //Function in SetupApi
//Loads cfgmgr32.dll for
//CM_Get_DevNode_Status
HCfgMgr := LoadLibrary(CFGMGR32_DLL);
if (HCfgMgr 32) then begin
MessageDlg('Error: could not find Configuration Manager DLL', mtError, [mbOk], 0);
exit;
end;
CM_Get_DevNode_Status := GetProcAddress(HCfgMgr, CM_GET_DEVNODE_STATUS_NAME);
//obtains a pointer to the list of all the drivers
PnPHandle := SetupDiGetClassDevs(nil, nil, 0, DIGCF_ALLCLASSES);
while true do begin
//obtains a SPDevInfoData for each driver
DevData.cbSize := SizeOf(DevData);
mybool := SetupDiEnumDeviceInfo(PnPHandle, Index, DevData);
if not mybool then begin
break;
end else begin
//obtains the status bitmask and the problemNumber for each driver
if not CM_Get_DevNode_Status(@ulStatus, @ulProblemNumber, DevData.DevInst, 0) = CR_SUCCESS then begin
msg := '#' + inttostr(Index);
Memo1.Lines.Add(msg);
Memo1.Lines.Add('DevNode Status error');
Memo1.Lines.Add('__________________');
Memo1.Lines.Add('');
inc(Index);
continue;
end;
//if the driver status =0 --- the driver is "not installed",
//it seems that old drivers garbage remain in the driver list
//you can purge the list through the checkbox if you want to get rid of unused drivers
if ulStatus = 0 then begin
if CheckBox1.Checked then begin
inc(Index);
continue;
end;
end;
nSize := 0;
msg := '';
//obtains several parameters for each driver
//and writes them in the Memo
msg := '#' + inttostr(Index);
Memo1.Lines.Add(msg);
msg := 'Friendly name: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_FRIENDLYNAME, DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
msg := 'DevDesc: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_DEVICEDESC, DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
msg := 'Driver Key: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_DRIVER , DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
msg := 'Class: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_CLASS ,
DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
msg := 'HardwareID: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_HARDWAREID ,
DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
msg := 'Location: ';
if ( SetupDiGetDeviceRegistryProperty(PnPHandle, DevData,
SPDRP_LOCATION_INFORMATION,
DataT, @buf, sizeof(buf), nSize) ) then begin
msg := msg + buf;
end;
Memo1.Lines.Add(msg);
//obtains info strings based on the status and the problemnumber
//of each device
msg := 'Device Status: ';
Memo1.Lines.Add(msg);
//Indeed this function passes a stringList through the Text property
//the text is automatically converted in several lines when you add it to the memo
//cause the stringList and the memo share the same default delimiter for each string
msg := GetDeviceInstanceStatusFlagMessage(ulStatus);
Memo1.Lines.Add(msg);
Memo1.Lines.Add('');
msg := 'Device Problem: ';
msg := msg + GetDeviceInstanceStatusProblemMessage(ulProblemNumber);
Memo1.Lines.Add(msg);
Memo1.Lines.Add('__________________');
Memo1.Lines.Add('');
end;
inc(Index);
end;
//Frees resources
SetupDiDestroyDeviceInfoList(PnPHandle);
FreeLibrary(HCfgMgr);
UnloadSetupApi; //function in Setupapi.pas
end;//function TForm1.DetectDriversInfo: boolean;
procedure TForm1.Button1Click(Sender: TObject);
begin
DetectDriversInfo;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
end;
end.