How do I detect that a drive is internal or connected to a USB port?
For example I now the letter of a partition from that drive. If I use GetDriveType on one connected to USB it says that it is fixed not removable.
I found some code with witch you can get informations from registry when such a device is connected to the computer. But it doesn't help me if the device is already connected when the program starts.
It is doable because there are programs (like WinSetupFromUsb) which detects them correctly.

Thank you in advance for any help.

Oh, I already found how to do it:

type
   STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined);
   TStorageQueryType = STORAGE_QUERY_TYPE;

   STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty);
   TStoragePropertyID = STORAGE_PROPERTY_ID;

   STORAGE_PROPERTY_QUERY = packed record
      PropertyId: STORAGE_PROPERTY_ID;
      QueryType: STORAGE_QUERY_TYPE;
      AdditionalParameters: array[0..9] of AnsiChar;
   end;
   TStoragePropertyQuery = STORAGE_PROPERTY_QUERY;

   STORAGE_BUS_TYPE = (BusTypeUnknown = 0, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre,
      BusTypeUsb, BusTypeRAID, BusTypeiScsi, BusTypeSas, BusTypeSata, BusTypeMaxReserved = $7F);
   TStorageBusType = STORAGE_BUS_TYPE;

   STORAGE_DEVICE_DESCRIPTOR = packed record
      Version: DWORD;
      Size: DWORD;
      DeviceType: Byte;
      DeviceTypeModifier: Byte;
      RemovableMedia: Boolean;
      CommandQueueing: Boolean;
      VendorIdOffset: DWORD;
      ProductIdOffset: DWORD;
      ProductRevisionOffset: DWORD;
      SerialNumberOffset: DWORD;
      BusType: STORAGE_BUS_TYPE;
      RawPropertiesLength: DWORD;
      RawDeviceProperties: array[0..0] of AnsiChar;
   end;
   TStorageDeviceDescriptor = STORAGE_DEVICE_DESCRIPTOR;

const
    IOCTL_STORAGE_QUERY_PROPERTY = $002D1400;

function IsOnUsb(Drive: AnsiChar): Boolean;
var
   H: THandle;
   Query: TStoragePropertyQuery;
   dwBytesReturned: DWORD;
   Buffer: array[0..1023] of Byte;
   sdd: TStorageDeviceDescriptor absolute Buffer;
   OldMode: UINT;
begin
   Result := False;

   OldMode := SetErrorMode(SEM_FAILCRITICALERRORS);
   try
      H := CreateFile(PChar(Format('\\.\%s:', [AnsiLowerCase(string(Drive))])), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
         OPEN_EXISTING, 0, 0);
      if H <> INVALID_HANDLE_VALUE then
      begin
         try
            dwBytesReturned := 0;
            FillChar(Query, SizeOf(Query), 0);
            FillChar(Buffer, SizeOf(Buffer), 0);
            sdd.Size := SizeOf(Buffer);
            Query.PropertyId := StorageDeviceProperty;
            Query.QueryType := PropertyStandardQuery;
            if DeviceIoControl(H, IOCTL_STORAGE_QUERY_PROPERTY, @Query, SizeOf(Query), @Buffer, SizeOf(Buffer), dwBytesReturned, nil) then
               Result := (sdd.BusType = BusTypeUsb){ and sdd.RemovableMedia};
         finally
            CloseHandle(H);
         end;
      end;
   finally
      SetErrorMode(OldMode);
   end;
end;

Sorry, I was very busy and I forgot to post it...

Comments
Thanks for sharing.
This article has been dead for over six months. Start a new discussion instead.