Delphi: Работа с устройствами в Windows - Безопасное извлечение устройства

ОГЛАВЛЕНИЕ

Безопасное извлечение устройства

Итак, с включением/отключением устройств мы разобрались. А как безопасно извлекать устройство? Безопасное извлечение устройства осуществляет функция CM_Request_Device_Eject. Вот её описание:

CMAPI CONFIGRET WINAPI
  CM_Request_Device_Eject(
 IN DEVINST dnDevInst,
 OUT PPNP_VETO_TYPE pVetoType,
 OUT LPTSTR pszVetoName,
 IN ULONG ulNameLength,
 IN ULONG ulFlags
 );

Первый параметр это хендл устройства. Второй параметр это указатель на переменную, в которую будет сохранён код причины при неудаче. Третий параметр это указатель на строку, в которую будет сохранена причина неудачи при неудачном вызове. Оба этих параметра опциональны и могут быть равны нулю. Пятый параметр это максимальная длина строки. Шестой не используется. Если pszVetoName равен нулю, то при неудаче сообщение выведет сама система. Вот и сама функция, которая осуществляет безопасное извлечение устройства.

procedure RemoveDrive(index:integer);
var
  DrivesPnPHandle: HDEVINFO;
  DevInfo: SP_DEVINFO_DATA;
  i: Integer;
  Parent: DWORD;
  VetoName:array[0..MAX_PATH] of char;
begin
  DevInfo.cbSize := sizeof(SP_DEVINFO_DATA);
  DrivesPnPHandle := SetupDiGetClassDevsA(@GUID_DEVCLASS_DISKDRIVE, nil, 0, 2);
  if DrivesPnPHandle = INVALID_HANDLE_VALUE then exit;
  if SetupDiEnumDeviceInfo(DrivesPnPHandle, index, DevInfo) then
 begin
   if (IsUSBDevice(DevInfo.DevInst)) and (CM_Get_Parent(Parent, DevInfo.DevInst, 0) = CR_SUCCESS)
     then
       begin
         CM_Request_Device_Eject(Parent, nil, @VetoName, MAX_PATH, 0);
         if VetoName=” then
           ShowMessage(’устройство можно извлечь’)
             else
           ShowMessage(’устройство нельзя извлечь’);
       end
                 else
       ShowMessage(’Не USB устройство’);
 end;
  SetupDiDestroyDeviceInfoList(DrivesPnPHandle);
end;

Единственный параметр передаваемой функции это индекс дискового устройства в списке дисковых устройств. Единственное что модет быть здесь непонятно - это функция CM_Get_Parent. Она получает родитель устройства. Ведь любая «флешка» или внешний дисковый накопитель это составное устройство и отключать надо именно родительское устройство. Код функции IsUSBDevice есть в исходнике, который прилагается к статье.