Форум программистов, компьютерный форум, киберфорум
QWIPQ
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

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

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

вообщем есть сказка про репку... ну и в итоге главные герои эту репку вытянули...
вот чтобы и нам нашу репку отключить нужно следующее...
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. надеюсь что смог помочь кодом рассчитываю на ваши плюшки в этой теме)))))
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Мульти-тенантные БД с PostgreSQL Row Security
Codd 23.04.2025
Современные облачные сервисы и бизнес-приложения всё чаще обслуживают множество клиентов в рамках единой программной инфраструктуры. Эта архитектурная модель, известная как мульти-тенантность, стала. . .
Реализация конвейеров машинного обучения с Python и Scikit-learn
AI_Generated 23.04.2025
Мир данных вокруг нас растёт с каждым днём, и умение эффективно обрабатывать информацию стало необходимым навыком. Специалисты по машинному обучению ежедневно сталкиваются с задачами предобработки. . .
Контроллеры Kubernetes Ingress: Сравнительный анализ
Mr. Docker 23.04.2025
В Kubernetes управление входящим трафиком представляет собой одну из ключевых задач при построении масштабируемых и отказоустойчивых приложений. Ingress — это API-объект, который служит вратами. . .
Оптимизация кода Python с Cython и Numba
py-thonny 23.04.2025
Python прочно обосновался в топе языков программирования благодаря своей простоте и гибкости. Разработчики любят его за читабельность кода и богатую экосистему библиотек. Но у этой медали есть и. . .
Микросервис на Python с FastAPI и Docker
ArchitectMsa 23.04.2025
В эпоху облачных вычислений и растущей сложности программных продуктов классическая монолитная архитектура всё чаще уступает место новым подходам. Микросервисная архитектура становится фаворитом. . .
Создаем веб-приложение на Vue.js и Laravel
Reangularity 23.04.2025
Выбор правильного технологического стека определяет успех веб-проекта. Laravel и Vue. js формируют отличную комбинацию для создания современных приложений. Laravel — это PHP-фреймворк с элегантным. . .
Максимальная производительность C#: Span<T> и Memory<T>
stackOverflow 22.04.2025
Мир высоконагруженных приложений безжалостен к неэффективному коду. Каждая миллисекунда на счету, каждый выделенный байт памяти может стать причиной падения производительности. Разработчики на C#. . .
JWT аутентификация в Java
Javaican 21.04.2025
JWT (JSON Web Token) представляет собой открытый стандарт (RFC 7519), который определяет компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Эта информация. . .
Спринты Agile: Планирование, выполнение, ревью и ретроспектива
EggHead 21.04.2025
Спринты — сердцевина Agile-методологии, позволяющая командам создавать работающий продукт итерационно, с постоянной проверкой гипотез и адаптацией к изменениям. В основе концепции спринтов лежит. . .
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров
Programma_Boinc 21.04.2025
Очередные открытия мега простых чисел, сделанные добровольцами с помощью домашних компьютеров. 3 марта 2025 года, в результате обобщенного поиска простых чисел Ферма в PrimeGrid был найден. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер