此部分代码请大家给加上注释。
const
DEV_CLASS_NAME = 'Net';
DEM_CLASS_NAME = 'MEDIA';
DEC_CLASS_NAME = 'CDROM';
DEU_CLASS_NAME = 'USB';
DEP_CLASS_NAMW = 'ports';
UNKNOWN_DEVICE = '<未知设备>';
private
{ Private declarations }
DevState: Array of Boolean;
procedure RefreshDevState;
procedure EnumNetDevice; //获得网卡 信息
function IsClassHidden(const ClassGUID: PGUID): Boolean; //被EnumNetDevice调用
function ConstructDeviceName(DeviceInfoSet: HDEVINFO; //被EnumNetDevice调用
DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar; Length: ULONG): Boolean;
function GetRegistryProperty(DeviceInfoSet: HDEVINFO; //被EnumNetDevice调用
DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
Length: ULONG): Boolean;
function IsDevDisable(DevIndex: DWORD; hDevInfo: HDEVINFO): Boolean; //被EnumNetDevice调用
function ChangeDevState(DevIndex, NewState: DWORD): BOOL; //改变网卡状态
public
{ Public declarations }
end;
var
DevForm: TDevForm;
implementation
{$R *.dfm}
procedure TDevForm.EnumNetDevice; //获得网卡信息
var
DeviceInfoSet: HDEVINFO;
DeviceInfoData: SP_DEVINFO_DATA;
i: Integer;
Status, Problem: DWORD;
ClassName: PChar;
ClassSize, ReqClassSize: DWORD;
DeviceName: PChar;
begin
clbDevList.Clear;
DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT);
if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
Exit;
ClassSize:=255;
GetMem(ClassName,256);
try
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA); //枚举硬件,获得需要的接口
i:=0;
while SetupDiEnumDeviceInfo(DeviceInfoSet,i,@DeviceInfoData) do
begin
Inc(i);
if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
@ReqClassSize) then
begin
if ReqClassSize>ClassSize then
begin
FreeMem(ClassName);
ClassSize:=ReqClassSize;
GetMem(ClassName,ClassSize+1);
if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
@ReqClassSize) then
Exit;
end
else
Exit;
end;
if not SameText(ClassName,DEV_CLASS_NAME) and not SameText(ClassName,DEM_CLASS_NAME) and
not SameText(ClassName,DEC_CLASS_NAME) and not SameText(ClassName,DEU_CLASS_NAME) and
not SameText(ClassName,DEP_CLASS_NAMW) then
Continue;
if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst,0)
<> CR_SUCCESS then
Exit;
if ((Status and DN_NO_SHOW_IN_DM)<>0) or
IsClassHidden(@DeviceInfoData.ClassGuid) then
Continue;
GetMem(DeviceName,256); //给DeviceName变量分配 256 的内存
ZeroMemory(DeviceName,256); //给DeviceName的每个单元赋值 值为 零
ConstructDeviceName(DeviceInfoSet,@DeviceInfoData,DeviceName,255); //获得了 DeviceName的值
if IsDevDisable(i-1,DeviceInfoSet) then
begin
clbDevList.Items.AddObject(StrPas(DeviceName)+'-----'+classname,TObject(i-1)); //把DeviceName的值加入到列表中i-1行
clbDevList.Checked[clbDevList.Count-1]:= IsDevDisable(i-1,DeviceInfoSet); // Checked的值为true
end;
FreeMem(DeviceName); //释放DeviceName所占的内存
end;
finally
FreeMem(ClassName);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
end;
end;
function TDevForm.ConstructDeviceName(DeviceInfoSet: HDEVINFO; //构造 DeviceName 的值
DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar;
Length: ULONG): Boolean;
begin
Result:=True;
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_FRIENDLYNAME,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_DEVICEDESC,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASS,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASSGUID,
Buffer,Length) then
begin
StrCopy(Buffer,UNKNOWN_DEVICE); //获得 DeviceName 的值 为‘未知设备’
end
else
Result:=False;
end;
end;
end;
end;
function TDevForm.GetRegistryProperty(DeviceInfoSet: HDEVINFO;
DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
Length: ULONG): Boolean;
var
ReqLen: DWORD;
begin
Result:=False;
while not SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,
AProperty,Nil,Buffer,Length,@ReqLen) do
begin
if GetLastError() = ERROR_INVALID_DATA then
break
else
if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
begin
if Assigned(Buffer) then
FreeMem(Buffer);
Length:=ReqLen;
GetMem(Buffer,Length+1);
end
else
Exit;
end;
Result:=Buffer^<>#0;
end;
function TDevForm.IsClassHidden(const ClassGUID: PGUID): Boolean;
var
hKeyClass: HKEY;
begin
Result:=False;
hKeyClass := SetupDiOpenClassRegKey(ClassGuid,KEY_READ); //获得KEY值
if hKeyClass<>0 then
begin
Result:= RegQueryValueEx(hKeyClass,REGSTR_VAL_NODISPLAYCLASS,Nil,Nil,NIl,Nil) = ERROR_SUCCESS; //查找KEY值,返回值为布尔型
RegCloseKey(hKeyClass);
end;
end;
function TDevForm.IsDevDisable(DevIndex: DWORD;
hDevInfo: HDEVINFO): Boolean;
var
DeviceInfoData: SP_DEVINFO_DATA;
Status, Problem: DWORD;
begin
Result:=False;
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
if not SetupDiEnumDeviceInfo(hDevInfo,DevIndex,@DeviceInfoData) then
Exit;
if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS then
Exit;
Result:=((Status and DN_DISABLEABLE)<>0) and (CM_PROB_HARDWARE_DISABLED <> Problem);
end;
function TDevForm.ChangeDevState(DevIndex, NewState: DWORD): BOOL; // 改变驱动器的状态
var //devindex : 驱动器索引 newstate : 网卡 的新状态 enable ;启用
DeviceInfoSet: HDEVINFO; // disable ;禁用
DeviceInfoData: SP_DEVINFO_DATA;
PropChangeParams: SP_PROPCHANGE_PARAMS;
Cursor: HCURSOR;
begin
Result:=False;
DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT); //获得当前驱动器的指针
if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
Exit;
try
PropChangeParams.ClassInstallHeader.cbSize:=SizeOf(SP_CLASSINSTALL_HEADER);
DeviceInfoData.cbSize:=SizeOf(SP_DEVINFO_DATA);
Cursor := SetCursor(LoadCursor(0, IDC_WAIT));
if not SetupDiEnumDeviceInfo(DeviceInfoSet,DevIndex,@DeviceInfoData) then
Exit;
/////可以对设备进行重启,停止,启动等操作
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
PropChangeParams.StateChange := NewState;
if not SetupDiSetClassInstallParams(DeviceInfoSet,@DeviceInfoData,
@PropChangeParams,Sizeof(PropChangeParams)) then
Exit;
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,DeviceInfoSet,
@DeviceInfoData) then
Exit;
SetCursor(Cursor);
Result:=True;
finally
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
end;
end;
procedure TDevForm.FormCreate(Sender: TObject);
begin
btRefresh.Click;
end;
procedure TDevForm.btExitClick(Sender: TObject);
begin
Close;
end;
procedure TDevForm.btApplyClick(Sender: TObject); //应用 设置
var
i: Integer;
begin
for i:=0 to clbDevList.Count-1 do
begin
if clbDevList.Checked[i] <> DevState[i] then //网卡的新状态和原来不一致就判断网卡的新状态是否被选中
begin
if clbDevList.Checked[i] then
ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_ENABLE) //启用网卡(cardinal 32位无符号数)
else
ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_DISABLE); //禁用网卡
end;
end;
RefreshDevState;
end;
procedure TDevForm.RefreshDevState;
var
i: Integer;
begin
SetLength(DevState,clbDevList.Count);
for i:=0 to clbDevList.Count-1 do
DevState[i]:=clbDevList.Checked[i];
end;
procedure TDevForm.btRefreshClick(Sender: TObject); //获得网卡信息并且存入 D E V S T A T E的布尔型数组里
begin
EnumNetDevice;
RefreshDevState;
end;
end.
const
DEV_CLASS_NAME = 'Net';
DEM_CLASS_NAME = 'MEDIA';
DEC_CLASS_NAME = 'CDROM';
DEU_CLASS_NAME = 'USB';
DEP_CLASS_NAMW = 'ports';
UNKNOWN_DEVICE = '<未知设备>';
private
{ Private declarations }
DevState: Array of Boolean;
procedure RefreshDevState;
procedure EnumNetDevice; //获得网卡 信息
function IsClassHidden(const ClassGUID: PGUID): Boolean; //被EnumNetDevice调用
function ConstructDeviceName(DeviceInfoSet: HDEVINFO; //被EnumNetDevice调用
DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar; Length: ULONG): Boolean;
function GetRegistryProperty(DeviceInfoSet: HDEVINFO; //被EnumNetDevice调用
DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
Length: ULONG): Boolean;
function IsDevDisable(DevIndex: DWORD; hDevInfo: HDEVINFO): Boolean; //被EnumNetDevice调用
function ChangeDevState(DevIndex, NewState: DWORD): BOOL; //改变网卡状态
public
{ Public declarations }
end;
var
DevForm: TDevForm;
implementation
{$R *.dfm}
procedure TDevForm.EnumNetDevice; //获得网卡信息
var
DeviceInfoSet: HDEVINFO;
DeviceInfoData: SP_DEVINFO_DATA;
i: Integer;
Status, Problem: DWORD;
ClassName: PChar;
ClassSize, ReqClassSize: DWORD;
DeviceName: PChar;
begin
clbDevList.Clear;
DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT);
if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
Exit;
ClassSize:=255;
GetMem(ClassName,256);
try
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA); //枚举硬件,获得需要的接口
i:=0;
while SetupDiEnumDeviceInfo(DeviceInfoSet,i,@DeviceInfoData) do
begin
Inc(i);
if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
@ReqClassSize) then
begin
if ReqClassSize>ClassSize then
begin
FreeMem(ClassName);
ClassSize:=ReqClassSize;
GetMem(ClassName,ClassSize+1);
if not SetupDiClassNameFromGuid(@DeviceInfoData.ClassGuid,ClassName,ClassSize,
@ReqClassSize) then
Exit;
end
else
Exit;
end;
if not SameText(ClassName,DEV_CLASS_NAME) and not SameText(ClassName,DEM_CLASS_NAME) and
not SameText(ClassName,DEC_CLASS_NAME) and not SameText(ClassName,DEU_CLASS_NAME) and
not SameText(ClassName,DEP_CLASS_NAMW) then
Continue;
if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst,0)
<> CR_SUCCESS then
Exit;
if ((Status and DN_NO_SHOW_IN_DM)<>0) or
IsClassHidden(@DeviceInfoData.ClassGuid) then
Continue;
GetMem(DeviceName,256); //给DeviceName变量分配 256 的内存
ZeroMemory(DeviceName,256); //给DeviceName的每个单元赋值 值为 零
ConstructDeviceName(DeviceInfoSet,@DeviceInfoData,DeviceName,255); //获得了 DeviceName的值
if IsDevDisable(i-1,DeviceInfoSet) then
begin
clbDevList.Items.AddObject(StrPas(DeviceName)+'-----'+classname,TObject(i-1)); //把DeviceName的值加入到列表中i-1行
clbDevList.Checked[clbDevList.Count-1]:= IsDevDisable(i-1,DeviceInfoSet); // Checked的值为true
end;
FreeMem(DeviceName); //释放DeviceName所占的内存
end;
finally
FreeMem(ClassName);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
end;
end;
function TDevForm.ConstructDeviceName(DeviceInfoSet: HDEVINFO; //构造 DeviceName 的值
DeviceInfoData: PSP_DEVINFO_DATA; Buffer: PAnsiChar;
Length: ULONG): Boolean;
begin
Result:=True;
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_FRIENDLYNAME,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_DEVICEDESC,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASS,
Buffer,Length) then
begin
if not GetRegistryProperty(DeviceInfoSet,DeviceInfoData,SPDRP_CLASSGUID,
Buffer,Length) then
begin
StrCopy(Buffer,UNKNOWN_DEVICE); //获得 DeviceName 的值 为‘未知设备’
end
else
Result:=False;
end;
end;
end;
end;
function TDevForm.GetRegistryProperty(DeviceInfoSet: HDEVINFO;
DeviceInfoData: PSP_DEVINFO_DATA; AProperty: ULONG; Buffer: PAnsiChar;
Length: ULONG): Boolean;
var
ReqLen: DWORD;
begin
Result:=False;
while not SetupDiGetDeviceRegistryProperty(DeviceInfoSet,DeviceInfoData,
AProperty,Nil,Buffer,Length,@ReqLen) do
begin
if GetLastError() = ERROR_INVALID_DATA then
break
else
if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
begin
if Assigned(Buffer) then
FreeMem(Buffer);
Length:=ReqLen;
GetMem(Buffer,Length+1);
end
else
Exit;
end;
Result:=Buffer^<>#0;
end;
function TDevForm.IsClassHidden(const ClassGUID: PGUID): Boolean;
var
hKeyClass: HKEY;
begin
Result:=False;
hKeyClass := SetupDiOpenClassRegKey(ClassGuid,KEY_READ); //获得KEY值
if hKeyClass<>0 then
begin
Result:= RegQueryValueEx(hKeyClass,REGSTR_VAL_NODISPLAYCLASS,Nil,Nil,NIl,Nil) = ERROR_SUCCESS; //查找KEY值,返回值为布尔型
RegCloseKey(hKeyClass);
end;
end;
function TDevForm.IsDevDisable(DevIndex: DWORD;
hDevInfo: HDEVINFO): Boolean;
var
DeviceInfoData: SP_DEVINFO_DATA;
Status, Problem: DWORD;
begin
Result:=False;
DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
if not SetupDiEnumDeviceInfo(hDevInfo,DevIndex,@DeviceInfoData) then
Exit;
if CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS then
Exit;
Result:=((Status and DN_DISABLEABLE)<>0) and (CM_PROB_HARDWARE_DISABLED <> Problem);
end;
function TDevForm.ChangeDevState(DevIndex, NewState: DWORD): BOOL; // 改变驱动器的状态
var //devindex : 驱动器索引 newstate : 网卡 的新状态 enable ;启用
DeviceInfoSet: HDEVINFO; // disable ;禁用
DeviceInfoData: SP_DEVINFO_DATA;
PropChangeParams: SP_PROPCHANGE_PARAMS;
Cursor: HCURSOR;
begin
Result:=False;
DeviceInfoSet:=SetupDiGetClassDevs(Nil,Nil,0,DIGCF_ALLCLASSES or DIGCF_PRESENT); //获得当前驱动器的指针
if DeviceInfoSet = Pointer(INVALID_HANDLE_VALUE) then
Exit;
try
PropChangeParams.ClassInstallHeader.cbSize:=SizeOf(SP_CLASSINSTALL_HEADER);
DeviceInfoData.cbSize:=SizeOf(SP_DEVINFO_DATA);
Cursor := SetCursor(LoadCursor(0, IDC_WAIT));
if not SetupDiEnumDeviceInfo(DeviceInfoSet,DevIndex,@DeviceInfoData) then
Exit;
/////可以对设备进行重启,停止,启动等操作
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
PropChangeParams.StateChange := NewState;
if not SetupDiSetClassInstallParams(DeviceInfoSet,@DeviceInfoData,
@PropChangeParams,Sizeof(PropChangeParams)) then
Exit;
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,DeviceInfoSet,
@DeviceInfoData) then
Exit;
SetCursor(Cursor);
Result:=True;
finally
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
end;
end;
procedure TDevForm.FormCreate(Sender: TObject);
begin
btRefresh.Click;
end;
procedure TDevForm.btExitClick(Sender: TObject);
begin
Close;
end;
procedure TDevForm.btApplyClick(Sender: TObject); //应用 设置
var
i: Integer;
begin
for i:=0 to clbDevList.Count-1 do
begin
if clbDevList.Checked[i] <> DevState[i] then //网卡的新状态和原来不一致就判断网卡的新状态是否被选中
begin
if clbDevList.Checked[i] then
ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_ENABLE) //启用网卡(cardinal 32位无符号数)
else
ChangeDevState(Cardinal(clbDevList.Items.Objects[i]),DICS_DISABLE); //禁用网卡
end;
end;
RefreshDevState;
end;
procedure TDevForm.RefreshDevState;
var
i: Integer;
begin
SetLength(DevState,clbDevList.Count);
for i:=0 to clbDevList.Count-1 do
DevState[i]:=clbDevList.Checked[i];
end;
procedure TDevForm.btRefreshClick(Sender: TObject); //获得网卡信息并且存入 D E V S T A T E的布尔型数组里
begin
EnumNetDevice;
RefreshDevState;
end;
end.