Форум программистов, компьютерный форум, киберфорум
Наши страницы
QWIPQ
Войти
Регистрация
Восстановить пароль
Рейтинг: 3.00. Голосов: 1.

Безопасное извлечение флешек из системы

Запись от QWIPQ размещена 09.05.2012 в 18:05

вообщем есть сказка про репку... ну и в итоге главные герои эту репку вытянули...
вот чтобы и нам нашу репку отключить нужно следующее...
C++
1
2
3
4
#include <Cfgmgr32.h>
#include <Setupapi.h>
#include <winioctl.h>
#include <devguid.h>
ниже появится возможно вопрос что це таке и почему оно не объявлено:
C++
1
2
DEFINE_GUID( GUID_DEVCLASS_USB,0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 );
DEFINE_GUID( GUID_DEVCLASS_DISKDRIVE,0x4d36e967L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 );
объясняю:GUID_DEVCLASS_DISKDRIVE и GUID_DEVCLASS_USB - это класс наших устройств в ПК которые прописаны в devguid.h и объявлять их совсем необязательно главн подключить библиотечку хотя некоторые и отдельно объявляют...

здесь приведен код результат которого нам потребуется для безопасного отключения флешек...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
////////////////////////////////////////////////////////////////////////////
////////////////////////////Список физ. дисков///////////////////////////
////////////////////////////////////////////////////////////////////////////
bool GetDeviceName(HDEVINFO PnPHandle, SP_DEVINFO_DATA DevData)
{
  DWORD BytesReturned;
  DWORD RegDataType;
  char Buffer[256];
////////////////////////
  BytesReturned = 0;
  RegDataType = 0;
  Buffer[0] = 0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, &DevData, SPDRP_FRIENDLYNAME,
    NULL, &Buffer[0], sizeof(Buffer), NULL);
  Result = Buffer;
  if (Result == "") exit(1);
  Result+=" - ";
  BytesReturned = 0;
  RegDataType = 0;
  Buffer[0] = 0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, &DevData, SPDRP_DEVICEDESC,
    NULL, &Buffer[0], sizeof(Buffer), NULL);
  Result+=Buffer;
}
bool FizicheskieYstroistva()
{
  Form1->DrivesListBox->Clear();
  HDEVINFO DrivePnPHandle;
  DWORD DeviceNumber;
  SP_DEVINFO_DATA DevData;
  BOOL RES;
  //запуск
  Form1->DrivesListBox->Clear();
  DrivePnPHandle = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT);
  if (DrivePnPHandle == INVALID_HANDLE_VALUE)exit(1);
  DeviceNumber = 0;
  while(true)
  {
   DevData.cbSize = sizeof(SP_DEVINFO_DATA);
   RES = SetupDiEnumDeviceInfo(DrivePnPHandle, DeviceNumber, &DevData);
   if (RES)
   {
        Result=NULL;
        GetDeviceName(DrivePnPHandle, DevData);
        Form1->DrivesListBox->Items->Add(Result);
   }
   else break;
   DeviceNumber++;
  }
   SetupDiDestroyDeviceInfoList(DrivePnPHandle);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
результатом его выполнения выполнения является заполнение ListBox нашими физическими дисками и флешками, данные устройства находятся в классе GUID_DEVCLASS_DISKDRIVE и соответствующий номер в этом классе является номером нашего диска или флешки в ListBox, это сделано для удобства извлечения флеш носителей

ниже приведен код безопасного извлечения флеш носителей
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
////////////////////////////////////////////////////////////////////////////
//////////////////////////Безопасно удалить флеху///////////////////////////
////////////////////////////////////////////////////////////////////////////
BOOL IsUSBDevice(DWORD DevInst)
{
    DWORD size;
    LPBYTE pData;
    BOOL usb = FALSE;
    if (CM_Get_Device_ID_Size(&size, DevInst, 0) == CR_SUCCESS)
    {
        if (size)
        {
            pData = (LPBYTE)GlobalAlloc(GPTR, size + 1);
            if (pData)
            {
                if (CM_Get_Device_ID(DevInst, (PCHAR)pData, size + 1,0) == CR_SUCCESS)
                {
                    *(pData + 7) = 0x00;
                    if (!strcmp((char*)pData, "USBSTOR"))
                        usb = TRUE;
                }
                GlobalFree(pData);
            }
        }
    }
    return usb;
}
 
BOOL RemoveUSBDevice(int index)
{
    //объявляем переменные
    HDEVINFO DrivesPnPHandle;
    SP_DEVINFO_DATA DevInfo;
    DWORD Parent;
    //вызываем функции
    DrivesPnPHandle = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, 2); //DIGCF_ALLCLASSES  DIGCF_PRESENT DIGCF_INTERFACEDEVICE
    if(DrivesPnPHandle == INVALID_HANDLE_VALUE)
    {
        exit(1);//вообще ни к чему
    }
    DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
    if(SetupDiEnumDeviceInfo(DrivesPnPHandle, index, &DevInfo))
    {
        if (IsUSBDevice(DevInfo.DevInst) && (CM_Get_Parent(&Parent, DevInfo.DevInst,0) == CR_SUCCESS))
        {
            CM_Request_Device_Eject(Parent, NULL, NULL, NULL, NULL);
        }
    }
    return FALSE;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
все функции в кодах описывать нет смысла т.к. все есть в MSDN, хочу лишь отметить главной здесь является функция CM_Request_Device_Eject так она объявлена в MSDN:
C++
1
2
3
4
5
6
7
8
9
CMAPI
CONFIGRET
WINAPI CM_Request_Device_Eject(
  __in       DEVINST dnDevInst,
  __out_opt  PPNP_VETO_TYPE pVetoType,
  __out_opt  LPTSTR pszVetoName,
  __in       ULONG ulNameLength,
  __in       ULONG ulFlags
);
Первый параметр это хендл устройства. Второй параметр это указатель на переменную, в которую будет сохранён код причины при неудаче. Третий параметр это указатель на строку, в которую будет сохранена причина неудачи при неудачном вызове. Оба этих параметра опциональны и могут быть равны нулю. Пятый параметр это максимальная длина строки. Шестой не используется. Если pszVetoName равен нулю, то при неудаче сообщение выведет сама система. В принципе нам необходим только первый параметр а все остальные могут быть NULL. Ведь любая «флешка» или внешний дисковый накопитель это составное устройство и отключать надо именно родительское устройство, для этих целий служит функция CM_Get_Parent которая получает хендл родительского устройства.

чтобы нам вызвать это все нам надо указать в ListBox то устройство какое хотим удалить и передать его индекс по нажатию кнопки, также необходимо обновить сразу ListBox
C++
1
2
3
4
5
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
    RemoveUSBDevice(DrivesListBox->ItemIndex);
    FizicheskieYstroistva();
}
ListBox необходимо обновлять будет в 3х местах:
1. подключение флешки
2. по получению сообщения об отключению флешки (небезопасному - просто выдернуть из порта)
3. по безопасному отключению
таким способом сможем осуществить динамику наших устройств и эффективное их отключение.
Хочу также добавить что в ListBox выводится ваш жесткий диск, а его можите даже не стараться отключать

P.S. надеюсь что смог помочь кодом рассчитываю на ваши плюшки в этой теме)))))
Размещено в Без категории
Просмотров 798 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru