uses
......, ComCtrls, StdCtrls, SetupAPI, ExtCtrls, Menus;
const
SetupApiModuleName = 'cfgmgr32.dll';
REGSTR_VAL_NODISPLAYCLASS = 'NoDisplayClass';
CR_SUCCESS = $00000000;
DN_HAS_PROBLEM = $00000400;
DN_DISABLEABLE = $00002000;
DN_NO_SHOW_IN_DM = $40000000;
CM_PROB_DISABLED = $00000016;
CM_PROB_HARDWARE_DISABLED = $0000001D;
function CM_Get_DevNode_Status(pulStatus: PULong; pulProblemNumber: PULong;
dnDevInst: DWord; ulFlags: ULong): DWord; stdcall;
external SetupApiModuleName name 'CM_Get_DevNode_Status';
type
TForm1 = class(TForm)
TreeView: TTreeView;
ImageList: TImageList;
MainMenu: TMainMenu;
mFile: TMenuItem;
mExit: TMenuItem;
mChange: TMenuItem;
mEnableDevice: TMenuItem;
mDisableDevice: TMenuItem;
mOptions: TMenuItem;
mRefreshDisplay: TMenuItem;
mShowHiddenDevices: TMenuItem;
mN: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure mExitClick(Sender: TObject);
procedure mRefreshDisplayClick(Sender: TObject);
procedure mShowHiddenDevicesClick(Sender: TObject);
procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
procedure TreeViewDblClick(Sender: TObject);
procedure ChangeEnableDevice(Sender: TObject);
procedure ChangeDisableDevice(Sender: TObject);
private
{ Private declarations }
DevInfo: hDevInfo;
ClassImageListData: TSPClassImageListData;
ShowHidden: Boolean;
function IsDisableable(SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
function IsDisabled(SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
function StateChange(NewState: DWord; SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
function GetRegistryProperty(PnPHandle: HDEVINFO;DevData: TSPDevInfoData;
Prop: DWORD; Buffer: PChar; dwLength: DWord): Boolean;
function ConstructDeviceName(DeviceInfoSet: hDevInfo;
DeviceInfoData: TSPDevInfoData; Buffer: PChar; dwLength: DWord): Boolean;
function IsClassHidden(ClassGuid: TGuid): Boolean;
function EnumAddDevices(ShowHidden: Boolean; hwndTree: TTreeView; DevInfo: hDevInfo): Boolean;
function GetClassImageIndex(ClassGuid: TGuid; Index: PInt): Boolean;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function TForm1.IsDisableable(SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
var
DeviceInfoData: TSPDevInfoData;
Status, Problem: DWord;
begin
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
exit;
end;
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
Result := false;
exit;
end;
Result := ((Status and DN_DISABLEABLE = DN_DISABLEABLE) and not (CM_PROB_HARDWARE_DISABLED = Problem));
end;
function TForm1.IsDisabled(SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
var
DeviceInfoData: TSPDevInfoData;
Status, Problem: DWord;
begin
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
exit;
end;
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
Result := false;
exit;
end;
Result := ((Status and DN_HAS_PROBLEM = DN_HAS_PROBLEM) and (CM_PROB_DISABLED = Problem));
end;
function TForm1.StateChange(NewState: DWord; SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
var
PropChangeParams: TSPPropChangeParams;
DeviceInfoData: TSPDevInfoData;
begin
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
ShowMessage('EnumDeviceInfo');
exit;
end;
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
PropChangeParams.StateChange := NewState;
if (not SetupDiSetClassInstallParams(hDevInfo, @DeviceInfoData,
PSPClassInstallHeader(@PropChangeParams), SizeOf(PropChangeParams))) then
begin
Result := false;
ShowMessage('SetClassInstallParams');
exit;
end;
if (not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DeviceInfoData)) then
begin
Result := false;
ShowMessage('SetClassInstallParams');
exit;
end;
Result := true;
end;
function TForm1.GetClassImageIndex(ClassGuid: TGuid; Index: PInt): Boolean;
begin
Result := SetupDiGetClassImageIndex(ClassImageListData, ClassGuid, Index^);
end;
function TForm1.GetRegistryProperty(PnPHandle: hDevInfo; DevData: TSPDevInfoData; Prop: DWord; Buffer: PChar; dwLength: DWord): Boolean;
var
aBuffer: array[0..256] of Char;
begin
dwLength := 0;
aBuffer[0] := #0;
SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, Prop, PBYTE(@aBuffer[0]), SizeOf(aBuffer), dwLength);
StrCopy(Buffer, aBuffer);
Result := Buffer^ <> #0;
end;
function TForm1.ConstructDeviceName(DeviceInfoSet: hDevInfo;
DeviceInfoData: TSPDevInfoData; Buffer: PChar; dwLength: DWord): Boolean;
const
UnknownDevice = '<Unknown Device>';
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASS, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASSGUID, Buffer, dwLength)) then
begin
dwLength := DWord(SizeOf(UnknownDevice));
Buffer := Pointer(LocalAlloc(LPTR, Cardinal(dwLength)));
StrCopy(Buffer, UnknownDevice);
end;
end;
end;
end;
Result := true;
end;
function TForm1.IsClassHidden(ClassGuid: TGuid): Boolean;
var
bHidden: Boolean;
hKeyClass: HKey;
begin
bHidden := false;
hKeyClass := SetupDiOpenClassRegKey(@ClassGuid, KEY_READ);
if (hKeyClass <> 0) then
begin
bHidden := (RegQueryValueEx(hKeyClass, REGSTR_VAL_NODISPLAYCLASS, nil, nil, nil, nil) = ERROR_SUCCESS);
RegCloseKey(hKeyClass);
end;
Result := bHidden;
end;
function TForm1.EnumAddDevices(ShowHidden: Boolean; hwndTree: TTreeView; DevInfo: hDevInfo): Boolean;
var
i, Status, Problem: DWord;
pszText: PChar;
DeviceInfoData: TSPDevInfoData;
iImage: Integer;
begin
TTreeView(hWndTree).Items.BeginUpdate;
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
TTreeView(hWndTree).Items.Clear;
i := 0;
while SetupDiEnumDeviceInfo(DevInfo, i, DeviceInfoData) do
begin
inc(i);
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
ShowMessage('CM_Get_DevNode_Status :: uenable.pas');
break;
end;
if (not (ShowHidden or not(Boolean(Status and DN_NO_SHOW_IN_DM) or IsClassHidden(DeviceInfoData.ClassGuid)))) then
begin
break;
end;
GetMem(pszText, 256);
try
ConstructDeviceName(DevInfo, DeviceInfoData, pszText, DWord(nil));
if (GetClassImageIndex(DeviceInfoData.ClassGuid, @iImage)) then
begin
with TTreeView(hWndTree).Items.AddObject(nil, pszText, nil) do
begin
TTreeView(hWndTree).Items[i-1].ImageIndex := iImage;
TTreeView(hWndTree).Items[i-1].SelectedIndex := iImage;
end;
if (Problem = CM_PROB_DISABLED) then // Красный (X)
begin
TTreeView(hWndTree).Items[i-1].OverlayIndex := IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST;
end else
begin
if (Boolean(Problem)) then // Желтый (!)
begin
TTreeView(hWndTree).Items[i-1].OverlayIndex := IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST;
end;
end;
if (Status and DN_NO_SHOW_IN_DM = DN_NO_SHOW_IN_DM) then
begin
TTreeView(hWndTree).Items[i-1].Cut := true;
end;
end;
finally
FreeMem(pszText);
end;
end;
TTreeView(hWndTree).Items.EndUpdate;
Result := true;
end;