вообщем есть сказка про репку... ну и в итоге главные герои эту репку вытянули...
вот чтобы и нам нашу репку отключить нужно следующее...
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. надеюсь что смог помочь кодом рассчитываю на ваши плюшки в этой теме)))))
|