Рейтинг@Mail.ru

WinAPI: Определение типа носителя и его серийного номера.


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

Нам понадобится всего 2 API — функции:

  • GetDriveType — определяет и возвращает тип носителя;
  • GetVolumeInformation — определяет информацию о носителе,  среди которой содержится серийный номер.

Рассмотрим описание этих функций для С++ и Delphi. Первой будет функция GetDriveType, она очень простая и использует всего один параметр — указатель на том. Например «c:\»,»a:\» и т.д. Функция возвращает одно из следующих значений:

DRIVE_UNKNOWN — 0 : диск неопределен/не существует

DRIVE_NO_ROOT_DIR — 1 : неверный путь/ путь не указывает на том

DRIVE_REMOVABLE2 : тип устройства определяется как съемный (дискета, флешка и т.д.)

DRIVE_FIXED3 : тип устройства — фиксированный диск (жесткий диск)

DRIVE_REMOTE 4 : тип устройства — удаленный(сетевой) диск

DRIVE_CDROM5 : это устройство CD-ROM

DRIVE_RAMDISK6 : виртуальный диск, созданный в оперативной памяти

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,    //путь к сетевому или локальному       // тому (пример: "\\MyServer\MyShare\" или "C:\".       LPTSTR lpVolumeNameBuffer, //буфер - в котором будет храниться                       // имя тома       DWORD nVolumeNameSize,     //размер буфера       LPDWORD lpVolumeSerialNumber, //серийный номер тома       LPDWORD lpMaximumComponentLength, //размер тома       LPDWORD lpFileSystemFlags, //тип файловой системы       LPTSTR lpFileSystemNameBuffer, //название файловой системы       DWORD nFileSystemNameSize //размер буфера под название ФС );
Delphi
function GetVolumeInformation(       lpRootPathName: PChar;    //путь к сетевому или локальному        //тому (пример: "\\MyServer\MyShare\" или "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('S\N: Yes')   else     writeln('S\N: 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; ...

Рекомендуемые статьи для прочтения:
WinAPI: Смена серийного номера тома.

Программирование, системное , ,

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1 звезда2 звезды3 звезды4 звезды5 звёзд (5 голосов, средний: 5,00 из 5)
Loading ... Loading ...

  1. Zero
    29 Январь 2009 в 23:52 | #1

    Очень нужная вещь эта привязка. Спасибо коффи

  2. 15 Февраль 2009 в 15:47 | #2

    Автор, за статью респект. В частности за реализацию на Делфи ;)

  3. Alexey
    23 Апрель 2009 в 13:43 | #3

    Не слишком поднодит для привязки. Поскольку этот серийник меняется при форматировании.
    Из описания GetVolumeInformation Function в MSDN :

    This function returns the volume serial number that the operating system assigns when a hard disk is formatted. To programmatically obtain the hard disk’s serial number that the manufacturer assigns, use the Windows Management Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber.

  4. C0ffe1n
    24 Апрель 2009 в 23:27 | #4

    Не понимаю Alexey, как вы так пришли к этому выводу… Может вы не понимаете определения привязки? … привязка представляет собой некоторую зависимость, при которой в данном случае будет запускаться/не запускаться программа. А от того что при форматировании сменился номер, фигово то тому кто отформатировал, потому что прога уже работать не будет(пока номер не сменить обратно) ;) … но соглашусь в одном что данный пример привязки очень прост, и достаточно быстро обходиться =)

  5. lizz
    25 Апрель 2009 в 17:04 | #5

    @C0ffe1n
    А что тут непонятного? «Поскольку этот серийник меняется при форматировании.» — по моему, всё очевидно.

  1. Пока что нет уведомлений.
*