procedure SearchSerialPorts;
const
GUID_DEVINTERFACE_COMPORT: TGUID = '
{86e0d1e0-8089-11d0-9ce4-08003e301f73}';
GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR: TGUID = '
{4D36E978-E325-11CE-BFC1-08002BE10318}';
var
PnPHandle: HDEVINFO;
DevData: TSPDevInfoData;
DeviceInterfaceData: TSPDeviceInterfaceData;
FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
Success: LongBool;
Devn: Integer;
BytesReturned: DWORD;
SerialGUID: TGUID;
Inst: DEVINST;
RegKey: HKEY;
RegBuffer:
array [0..1023]
of Char;
RegSize, RegType: DWORD;
FriendlyName:
string;
PortName:
string;
DeviceDescription:
string;
Bus:
string;
begin
// these API conversions are loaded dynamically by default
LoadSetupApi;
LoadConfigManagerApi;
// enumerate all serial devices (COM port devices)
SerialGUID := GUID_DEVINTERFACE_COMPORT;
// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR;
PnPHandle := SetupDiGetClassDevs(@SerialGUID,
nil, 0, DIGCF_PRESENT
or DIGCF_DEVICEINTERFACE);
if PnPHandle = Pointer(INVALID_HANDLE_VALUE)
then
Exit;
// Combobox klarmachen
portchange.Items.BeginUpdate;
portchange.Items.Clear;
Devn := 0;
repeat
DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
Success := SetupDiEnumDeviceInterfaces(PnPHandle,
nil, SerialGUID, Devn, DeviceInterfaceData);
if Success
then
begin
DevData.cbSize := SizeOf(DevData);
BytesReturned := 0;
// get size required for call
SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
nil, 0, BytesReturned, @DevData);
if (BytesReturned <> 0)
and (GetLastError = ERROR_INSUFFICIENT_BUFFER)
then
begin
// allocate buffer and initialize it for call
FunctionClassDeviceData := AllocMem(BytesReturned);
FunctionClassDeviceData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData)
then
begin
// gives the friendly name of the device as shown in Device Manager
FriendlyName := GetRegistryPropertyString(PnPHandle, DevData, SPDRP_FRIENDLYNAME);
// gives a device description
DeviceDescription := GetRegistryPropertyString(PnPHandle, DevData, SPDRP_DEVICEDESC);
// now try to get the assigned COM port name
RegKey := SetupDiOpenDevRegKey(PnPHandle, DevData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
RegType := REG_SZ;
RegSize := SizeOf(RegBuffer);
RegQueryValueEx(RegKey, '
PortName',
nil, @RegType, @RegBuffer[0], @RegSize);
RegCloseKey(RegKey);
PortName := RegBuffer;
Inst := DevData.DevInst;
CM_Get_Parent(Inst, Inst, 0);
Bus := ExtractBus(GetDeviceID(Inst));
// COM-Ports in Combobox eintragen
portchange.Items.Add(PortName + '
(' + DeviceDescription + '
, ' + Bus+'
)');
end;
FreeMem(FunctionClassDeviceData);
end;
end;
Inc(Devn);
until not Success;
SetupDiDestroyDeviceInfoList(PnPHandle);
// Combobox freigeben
portchange.Items.EndUpdate;
// unload API conversions
UnloadSetupApi;
UnloadConfigManagerApi;
end;