Главная страница
Навигация по странице:

  • 4.1. Почему не желательно вынимать USB-накопитель из разъёма без использования безопасного отключения

  • 4.2. Какой формат имеет PnP -идентификатор USB-устройств

  • 4.3. Какой формат имеет идентификатор экземпляра устройства USB-накопителя Идентификатор оборудования имеет следующий форматUSBSTOR\t*v(8)p(16)r(4)

  • 4.4. Что делает и какой формат имеет функция SetupDiGetDeviceRegistryProperty позволяет получить PnP свойства устройства.SetupDiGetDeviceRegistryProperty

  • 4.5. Что делает и какой формат имеет функция CM _ Get _ Device _ ID Функция CM _ Get _ Device _

  • 4.6. Какие функции из SetupAPI . dll используются для нахождения и отключения устройства Функция CM _ Get _ Device _ ID

  • CM_Request_Device_Eject

  • Программное извлечение флешдиска


    Скачать 265.52 Kb.
    НазваниеПрограммное извлечение флешдиска
    Дата09.12.2022
    Размер265.52 Kb.
    Формат файлаdocx
    Имя файла5lab.docx
    ТипЛабораторная работа
    #836044

    Федеральное агентство связи
    Федеральное государственное бюджетное образовательное

    учреждение высшего образования
    Поволжский государственный университет

    телекоммуникаций и информатики
    Кафедра Информационных систем и технологий


    Лабораторная работа №5

    По дисциплине «Инструментальные средства информационных систем»

    Тема: «Программное извлечение флеш-диска»

    Руководитель доцент к. т. н.

    __________________ Никитин К.А.


    Самара 2018




    Используя среду программирования Free Pascal разработать программу, останавливающую только Вашу флешку для безопасного извлечения её из разъёма.
    Листинг

    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_DEVCLASS_USB: TGUID = (D1: $36FC9E60; D2: $C465; D3: $11CF; D4: ($44, $45, $53, $54, $00, $00 , $00, $00));
    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;
    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;

    IDString2: 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);

    IDString2:='USBSTOR\DISK&VEN_KINGSTON&PROD_DATATRAVELER_3.0&REV_\002618525DD3F18197452D9E&0';

    if (IDString=IDString2) then

    begin

    //IDString := StrPas(ID);

    Write('Eject flash-disk?(y - yes; Any other key - no)');

    ReadLn(q);

    if q = 'y' then result := true;

    end;

    FreeMemory(ID);
    // if(IDString<>IDString2) then
    exit;

    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.

    Выполнение программы:








    К.В.


    4.1. Почему не желательно вынимать USB-накопитель из разъёма без использования безопасного отключения?

    Предусмотрены 2 политики удаления: по умолчанию включен режим быстрого удаления, который подразумевает извлечение устройства в любой момент времени без необходимости использования опции безопасного удаления. Второй режим использует кэширование данных перед записью, что увеличивает производительность, то есть в данном случае скорость записи на устройство, но требует обязательного использования безопасного извлечения. Выходит, что если не менять политику извлечения, то можно вынимать флешки без дополнительных манипуляций. На самом деле — нет. Дело в том, что флеш-карта может работать в разных режимах. К примеру, вы просто копируете какие-либо файлы с компьютера на съёмный носитель. В этом случае обращение к флешке прекратится после завершения копирования, но бывают и ситуации, когда вы работаете непосредственно с флеш-карты.

    В любом случае, независимо от используемой политики рекомендуется извлекать флешку безопасно. Это позволит избежать повреждения данных.

    4.2. Какой формат имеет PnP-идентификатор USB-устройств?

    Каждое USB-устройство, спроектированное по спецификации PnP, должно иметь идентификатор, который однозначно определяет модель данного устройства. Для USB-устройства идентификатор имеет следующий формат:

    USB\Vid_vvvv&Pid_dddd&Rev_rrrr,

    где vvvv – код идентификатора производителя, зарегистрированного в Комитете USB-производителей;

    dddd – идентификатор, присвоенный производителем данный модели USB-устройства;

    rrrr – номер версии разработки.

    Все эти поля вводятся как шестнадцатеричные числа.

    При идентификации USB-накопителя драйвером порта, последний создаёт новый идентификатор устройства (device ID) и набор идентификаторов оборудования (hardware ID). Первая строка идентификатора оборудования должна совпадать с идентификатором устройства.

    4.3. Какой формат имеет идентификатор экземпляра устройства USB-накопителя?

    Идентификатор оборудования имеет следующий формат

    USBSTOR\t*v(8)p(16)r(4)

    где t* – тип устройства (для USB-накопителей DISK);

    v(8) – идентификатор производителя из 8 символов;

    p(16) – идентификатор продукта;

    r(4) – идентификатор версии разработки.

    Идентификатор оборудования необходим для точного подбора драйвера для устройства.

    Кроме идентификатора устройства (device ID) каждый накопитель имеет идентификатор экземпляра (instance ID), который отличает устройство от других устройств того же типа. Идентификатор экземпляра может определять устройство относительно шины (например, учитывать USB-порт, к которому подключено устройство) или представлять глобально уникальный дескриптор (например, серийный номер устройства). Идентификаторы устройства и экземпляра дают идентификатор экземпляра устройства (device instance ID, DIID или код экземпляра устройства), который однозначно идентифицирует экземпляр устройства в системе.

    4.4. Что делает и какой формат имеет функция SetupDiGetDeviceRegistryProperty?

    позволяет получить PnP свойства устройства.

    SetupDiGetDeviceRegistryProperty (hDeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize),

    где hDeviceInfoSetдескриптор класса устройств;

    DeviceInfoData – указатель на структуру с информацией об устройстве;

    Property – параметр, указывающий какое именно свойство требуется получить. Для получения строки с описанием устройства необходимо указать константу или SPDRP_DEVICEDESC (0x00000000) или SPDRP_FRIENDLYNAME (0х0000000С). Для получения идентификатора оборудования (HardwareID) необходимо указать константу SPDRP_HARDWAREID (0x00000001);

    PropertyRegDataType – указатель на переменную, в которую помещается тип возвращаемых функцией данных;

    PropertyBuffer – указатель на буфер, в который возвращается значение указанного свойства. Если этот параметр указа как null и PropertyBufferSize указан как 0, то функция возвращает в RequiredSize необходимый размер буфера;

    PropertyBufferSize – размер буфера для получения значения свойства;

    RequiredSize – дополнительный параметр для получения размера буфера, если не используется, то null.

    4.5. Что делает и какой формат имеет функция CM_Get_Device_ID?

    Функция CM_Get_Device_ID_Size возвращает размер строки идентификатора устройства.

    CM_Get_Device_ID_Size (pulLen, dnDevInst, ulFlags),

    где pulLen – указатель на переменную для записи длины строки;

    dnDevInst – идентификатор устройства;

    ulFlags – не используется, должен быть нулем.

    4.6. Какие функции из SetupAPI.dll используются для нахождения и отключения устройства?

    Функция CM_Get_Device_ID возвращает текстовый идентификатор экземпляра устройства ID.

    CM_Get_Device_ID (dnDevInst, Buffer, BufferLen, ulFlags),

    где dnDevInst – дескриптор устройства;

    Buffer – указатель на буфер для записи строки идентификатора устройства;

    BufferLen – длина строки идентификатора устройства;

    ulFlags – не используется, должен быть нулем.

    Функция CM_Request_Device_Eject выполняет безопасное извлечение устройства, а если это не возможно, то возвращает информацию об ошибке.

    CM_Request_Device_Eject (dnDevInst, pVetoType, pszVetoName, ulNameLength, ulFlags),

    где dnDevInst – дескриптор устройства;

    pVetoType – дополнительный параметр для возвращения кода ошибки, если отказано в извлечении устройства;

    pszVetoName – дополнительный параметр для возвращения текстового описания ошибки, в случае отказа в извлечении устройства;

    ulNameLength – максимальная длина текстового описания ошибки;

    ulFlagsне используется, должен быть нулем.


    написать администратору сайта