Безопасное извлечение флешки - Free Pascal

Узнай цену своей работы

Формулировка задачи:

Добрый день! Помогите написать программу для безопасного извлечение определенной флешки. Спасибо!

Решение задачи: «Безопасное извлечение флешки»

textual
Листинг программы
program EjectFlesh;
 
{$MODE OBJFPC}
 
 
 
Uses
 
Windows, strings;
 
 
 
Const
 
setupapi = 'SetupApi.dll';
 
GUID_DEVCLASS_DISKDRIVE: TGUID = (D1: $4D36E967; D2: $E325; D3: $11CE; D4: ($BF, $C1, $08, $00, $2B, $E1, $03, $18)); // GUID класса накопителей
 
GUID_DEVCLASS_USB: TGUID = (D1: $36FC9E60; D2: $C465; D3: $11CF; D4: ($44, $45, $53, $54, $00, $00 , $00, $00)); // GUID класса хост-контроллера и USB хабов;
 
 
 
Type
 
HDEVINFO = THandle;
 
 
 
PSP_DEVINFO_DATA = ^SP_DEVINFO_DATA;
 
SP_DEVINFO_DATA = packed record
 
cbSize : DWORD;
 
ClassGuid : TGUID;
 
DevInst : DWORD;
 
Reserved : DWORD;
 
end;
 
 
 
Var
 
q: char;
 
hDevInfoSet: HDEVINFO;
 
DevInfo: SP_DEVINFO_DATA;
 
i: Integer;
 
Parent: DWORD;
 
VetoName: PChar;
 
VetoNameString: String;
 
 
 
// функции из SetupApi.dll
 
function SetupDiGetClassDevsA(ClassGuid: PGUID; Enumerator: PChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external setupapi;
 
 
 
function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; DeviceInfoData: PSP_DEVINFO_DATA): boolean; stdcall; external setupapi;
 
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): boolean; stdcall; external setupapi;
 
function CM_Get_Parent(pdnDevInst: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
 
function CM_Get_Device_ID_Size(pulLen: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
 
function CM_Get_Device_IDA(dnDevInst: DWORD; Buffer: PChar; BufferLen: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
 
function CM_Locate_DevNodeA(pdnDevInst: PDWORD; pDeviceID: PChar; ulFlags: DWORD): DWORD; stdcall; external setupapi;
 
function CM_Request_Device_EjectA(dnDevInst: DWORD; pVetoType: Pointer; pszVetoName: PChar; ulNameLength: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
 
 
 
function CompareMem(p1, p2: Pointer; len: DWORD): boolean;
 
Var
 
i: DWORD;
 
Begin
 
result := false;
 
if len = 0 then exit;
 
for i := 0 to len-1 do
 
if PByte(DWORD(p1) + i)^ <> PByte(DWORD(p2) + i)^ then exit;
 
result := true;
 
End;
 
 
 
function IsUSBDevice(DevInst: DWORD): boolean;
 
Var
 
IDLen: DWORD;
 
ID: PChar;
 
IDString: String;
 
Begin
 
result := false;
 
IDString := '';
 
if (CM_Get_Device_ID_Size(@IDLen, DevInst, 0) <> 0) or (IDLen = 0) then exit;
 
inc(IDLen);
 
ID := GetMemory(IDLen);
 
if ID = nil then exit;
 
if ((CM_Get_Device_IDA(DevInst, ID, IDLen, 0) <> 0) or (not (CompareMem(ID, PChar('USBSTOR'), 7)))) then
 
begin
 
IDString := StrPas(ID);
 
FreeMemory(ID);
 
exit;
 
end;
 
IDString := StrPas(ID);
 
Write('Eject flash-disk?(y - yes; Any other key - no)');
 
ReadLn(q);
 
if q = 'y' then result := true;
 
FreeMemory(ID);
 
End;
 
BEGIN
 
DevInfo.cbSize := sizeof(SP_DEVINFO_DATA);
 
hDevInfoSet := SetupDiGetClassDevsA(@GUID_DEVCLASS_DISKDRIVE, nil, 0, 2);
 
 
 
if hDevInfoSet = INVALID_HANDLE_VALUE then exit;
 
i := 0;
 
while (SetupDiEnumDeviceInfo(hDevInfoSet, i, @DevInfo)) do
 
begin
 
if IsUSBDevice(DevInfo.DevInst) then
 
begin
 
if CM_Get_Parent(@Parent, DevInfo.DevInst, 0) = 0 then
 
begin
 
VetoName := GetMemory(260);
 
if (CM_Request_Device_EjectA(Parent, nil, VetoName, 260, 0) <> 0) then
 
begin
 
if (CM_Locate_DevNodeA(@Parent, VetoName, 0) <> 0) then
 
begin
 
FreeMemory(VetoName);
 
continue;
 
end;
 
FreeMemory(VetoName);
 
if (CM_Request_Device_EjectA(Parent, nil, nil, 0, 0) <> 0) then continue;
 
end;
 
VetoNameString := StrPas(VetoName);
 
FreeMemory(VetoName);
 
break;
 
end;
 
end;
 
inc(i);
 
end;
 
SetupDiDestroyDeviceInfoList(hDevInfoSet);
 
END.

Объяснение кода листинга программы

  1. В коде используется язык программирования Free Pascal.
  2. Задача программы - безопасное извлечение флешки.
  3. В коде используются следующие константы:
    • GUID_DEVCLASS_DISKDRIVE: GUID класса накопителей.
    • GUID_DEVCLASS_USB: GUID класса хост-контроллера и USB хабов.
  4. Типы данных, используемые в коде:
    • HDEVINFO: THandle.
    • PSP_DEVINFO_DATA: ^SP_DEVINFO_DATA.
    • SP_DEVINFO_DATA: packed record.
  5. Переменные, используемые в коде:
    • q: char.
    • hDevInfoSet: HDEVINFO.
    • DevInfo: SP_DEVINFO_DATA.
    • i: Integer.
    • Parent: DWORD.
    • VetoName: PChar.
    • VetoNameString: String.
  6. В коде используются функции из SetupApi.dll:
    • SetupDiGetClassDevsA.
    • SetupDiEnumDeviceInfo.
    • SetupDiDestroyDeviceInfoList.
    • CM_Get_Parent.
    • CM_Get_Device_ID_Size.
    • CM_Get_Device_IDA.
    • CM_Locate_DevNodeA.
    • CM_Request_Device_EjectA.
  7. В функции CompareMem сравниваются две памяти, начиная с указанных адресов и длиной в указанное количество байт.
  8. Функция IsUSBDevice проверяет, является ли устройство USB-накопителем.
  9. В основном цикле программы происходит перебор всех устройств выбранного класса.
  10. Если устройство является USB-накопителем, то выполняется запрос на безопасное извлечение устройства.
  11. Если устройство не может быть безопасно извлечено, то программа продолжает работу до тех пор, пока не будет получен другой ввод пользователя.
  12. Ввод пользователя запрашивается с помощью функции ReadLn.
  13. Если пользователь вводит 'y', то выполняется запрос на безопасное извлечение устройства.
  14. Если пользователь вводит любой другой символ, то запрос на безопасное извлечение устройства не выполняется.
  15. В конце программы выполняется функция SetupDiDestroyDeviceInfoList для освобождения ресурсов.

Оцени полезность:

9   голосов , оценка 3.778 из 5
Похожие ответы