Иногда в программах необходимо использовать возможность проверки типа носителя или его серийный номер. Причины могут быть разными от банального контроля устройств в системе до средств защит использующих привязку к железу. Сейчас я вам покажу как с помощью 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;
...
Рекомендуемые статьи для прочтения:
WinAPI: Смена серийного номера тома.
1 комментарий