unit deviceId;

interface

uses SysUtils, ActiveX, WbemScripting_TLB;

function getDeviceId(driveLetter: string):string;

implementation

function wmiEscapePath(path: string):string;
begin
    Result:=StringReplace(path,'\','\\', [rfReplaceAll]);
end;

function wmiGetPropertyValue(propName: string; wmiObject:ISWbemObject):oleVariant;
var
    props: ISWbemPropertySet;
    prop: ISWbemProperty;
    propsEnum: IEnumVariant;
    tmpObject: oleVariant;
    value: cardinal;
begin
    Result:='';
    props := wmiObject.Properties_;
    propsEnum := (props._NewEnum) as IEnumVariant;
    while (propsEnum.Next(1, tmpObject, value) = S_OK) do begin
        prop := IUnknown(tmpObject) as SWBemProperty;
        if (prop.Name = propName) then begin
            Result:=prop.Get_Value;
            exit;
        end;
    end;
end;

function getDeviceId(driveLetter: string):string;
var
  wmiServices: ISWbemServices;
  wmiDiskDrive, wmiDiskPartition, wmiLogicalDisk: ISWbemObject;
  wmiDiskDrivesEnum, wmiDiskPartsEnum, wmiLogicalDisksEnum: IEnumVariant;
  wmiDiskDeviceId, wmiDiskPartitionDeviceID, wmiLogicalDiskDeviceID: OleVariant;
  tmpObject: OleVariant;
  Value: Cardinal;
  wmiLocator: TSWbemLocator;

begin
  Result:='';
  try
  wmiLocator := TSWbemLocator.Create(nil);
  wmiServices := wmiLocator.ConnectServer('.', 'root\CIMV2', '', '', '', '', 0, nil);
  // Получение всех дисковых накопителей
  wmiDiskDrivesEnum := wmiServices.ExecQuery('select * from Win32_DiskDrive', 'WQL', wbemFlagBidirectional, nil)._NewEnum as IEnumVariant;
  while (wmiDiskDrivesEnum.Next(1, tmpObject, Value) = S_OK) do begin
      wmiDiskDrive := IUnknown(tmpObject) as SWBemObject;
      wmiDiskDeviceId := wmiGetPropertyValue('DeviceID',wmiDiskDrive);
      wmiDiskDeviceId := wmiEscapePath(wmiDiskDeviceId);
      // Получение физических разделов на диске
      wmiDiskPartsEnum := wmiServices.ExecQuery('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="'+wmiDiskDeviceId+'"} WHERE AssocClass = Win32_DiskDriveToDiskPartition', 'WQL', wbemFlagBidirectional, nil)._NewEnum as IEnumVariant;
      while (wmiDiskPartsEnum.Next(1, tmpObject, Value) = S_OK) do begin
          wmiDiskPartition := IUnknown(tmpObject) as SWBemObject;
          wmiDiskPartitionDeviceID := wmiGetPropertyValue('DeviceID',wmiDiskPartition);
          // Получение логических дисков
          wmiLogicalDisksEnum := wmiServices.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+ wmiDiskPartitionDeviceID +'"} WHERE AssocClass = Win32_LogicalDiskToPartition', 'WQL', wbemFlagBidirectional, nil)._NewEnum as IEnumVariant;
          while (wmiLogicalDisksEnum.Next(1, tmpObject, Value) = S_OK) do begin
              wmiLogicalDisk := IUnknown(tmpObject) as SWBemObject;
              wmiLogicalDiskDeviceID := wmiGetPropertyValue('DeviceID',wmiLogicalDisk);
              if wmiLogicalDiskDeviceID = driveLetter then begin
                  Result:= wmiGetPropertyValue('PNPDeviceID',wmiDiskDrive);
              end;
          end;
      end;
  end;
  except
  end;
end;


end.
