Привязка к железу

Тема в разделе "Корзина", создана пользователем Tema_zzz, 4 фев 2018.

Статус темы:
Закрыта.
  1. Tema_zzz
    ▪ Привязка к железу

    Иногда в программах необходимо использовать возможность проверки типа носителя или его серийный номер. Причины могут быть разными от банального контроля устройств в системе до средств защит использующих привязку к железу. Сейчас я вам покажу как с помощью API реализовать эту простую задачу.

    Нам понадобится всего 2 API - функции:
    • GetDriveType - определяет и возвращает тип носителя;
    • GetVolumeInformation - определяет информацию о носителе, среди которой содержится серийный номер.

    Рассмотрим описание этих функций для С++ и Delphi На ответах мэйл.ру!

    Первой будет функция GetDriveType, она очень простая и использует всего один параметр - указатель на том. Например “c:”,”a:” и т.д. Функция возвращает одно из следующих значений:
    DRIVE_UNKNOWN - 0 : диск неопределен/не существует
    DRIVE_NO_ROOT_DIR - 1 : неверный путь/ путь не указывает на том
    DRIVE_REMOVABLE - 2 : тип устройства определяется как съемный (дискета, флешка и т.д.)
    DRIVE_FIXED - 3 : тип устройства - фиксированный диск (жесткий диск)
    DRIVE_REMOTE - 4 : тип устройства - удаленный(сетевой) диск
    DRIVE_CDROM - 5 : это устройство CD-ROM
    DRIVE_RAMDISK - 6 : виртуальный диск, созданный в оперативной памяти
    C/C++

    UINT WINAPI GetDriveType(
    LPCTSTR lpRootPathName //путь к диску
    );


    Delphi

    function GetDriveType(
    lpRootPathName: PChar //путь к диску
    ): UINT; stdcall;


    Замечание: Если в качестве параметра указать для С/С++ NULL, а для Delphi - nil то тип устройства будет определяться для текущего диска (с которого была запущена программа).
    А теперь взглянем на функцию GetVolumeInformation. Тоже достаточно простая функция, однако использует параметров значительно больше.
    C/C++

    BOOL WINAPI GetVolumeInformation(
    LPCTSTR lpRootPathName, //путь к сетевому или локальному
    // тому (пример: "MyServerMyShare" или "C:".
    LPTSTR lpVolumeNameBuffer, //буфер - в котором будет храниться
    // имя тома
    DWORD nVolumeNameSize, //размер буфера
    LPDWORD lpVolumeSerialNumber, //серийный номер тома
    LPDWORD lpMaximumComponentLength, //размер тома
    LPDWORD lpFileSystemFlags, //тип файловой системы
    LPTSTR lpFileSystemNameBuffer, //название файловой системы
    DWORD nFileSystemNameSize //размер буфера под название ФС
    );


    Delphi

    function GetVolumeInformation(
    lpRootPathName: PChar; //путь к сетевому или локальному
    //тому (пример: "MyServerMyShare" или "C:".
    lpVolumeNameBuffer: PChar; //буфер - в котором будет храниться
    // имя тома
    nVolumeNameSize: DWORD; //размер буфера
    lpVolumeSerialNumber: PDWORD; //серийный номер тома
    var lpMaximumComponentLength, lpFileSystemFlags: DWORD; //размер
    // тома и тип файловой системы
    lpFileSystemNameBuffer: PChar; //название файловой системы
    nFileSystemNameSize: DWORD //размер буфера под название ФС
    ): BOOL; stdcall;


    Замечание: Если в качестве первого параметра указать для С/С++ NULL, а для Delphi - nil то функция будет выполняется для текущего диска (с которого была запущена программа).
    Ну а теперь собственно для пущего интересу приведу пример, как привязать программу к устройству. В данном примере будем привязывать программу к флешке. Смотрим пример:
    C/C++

    #include
    #include
    #include
    #include
    using namespace std;

    int main() {
    // Получаем тип носителя с которого запущена программа
    unsigned int drive_type = GetDriveType( NULL );

    char VolumeNameBuffer[100];
    char FileSystemNameBuffer[100];
    DWORD sz,fs;
    unsigned long drive_sn;
    GetVolumeInformationA(
    NULL,
    VolumeNameBuffer,
    100,
    &drive_sn,
    sz,
    fs,
    FileSystemNameBuffer,
    100
    );
    cout << "Volume serial number:t";
    if(drive_sn == 1018821877) //сравниваем серийный номер
    cout << "correct" << endl;
    else
    cout << "invalid" << endl;
    cout << "Drive type:t";
    if(drive_type == DRIVE_REMOVABLE)
    cout << "correct" << endl;
    else
    cout << "invalid" << endl;
    getch();
    }


    Delphi

    program Project1;

    {$APPTYPE CONSOLE}

    uses
    SysUtils,windows;

    var
    SerialNum,dtyp:DWORD;
    a,b:DWORD;
    Buffer,disk :Array[0..255]of char;
    begin
    dtyp:=GetDriveType(nil);
    if dtyp = DRIVE_REMOVABLE then
    writeln('Disk(type): Yes')
    else
    writeln('Disk(type): No');
    GetVolumeInformation(
    nil,
    Buffer,
    sizeof(Buffer),
    @SerialNum,
    a,
    b,
    nil,
    0);
    if SerialNum = 1018821877 then //сравниваем серийный номер
    writeln('SN: Yes')
    else
    writeln('SN: No');
    readln;
    end.


    Замечание: Может возникнуть вопрос, а как узнать серийник диска, чтобы знать с чем сравнивать? Очень просто, для этого пишем тестовую прогу, в которой пишем следующий код:
    C/C++

    ...
    GetVolumeInformationA(NULL, VolumeNameBuffer,100,
    &drive_sn,sz,fs,FileSystemNameBuffer,100);
    ...


    Delphi

    ...
    GetVolumeInformation(nil,Buffer,sizeof(Buffer),
    @SerialNum, a,b, nil, 0);
    writeln('S/N drive: ',SerialNum);
    readln;
    ...


    Рекомендуемые статьи для прочтения:
    Для тех кто в теме!
     
    varlok и Albeshka нравится это.
Статус темы:
Закрыта.