Подписаться на RSS рассылку
Главная » Статьи по Delphi » Диски » Привязка к железу

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

Автор: C0ffe1n

Tweet

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

Просмотров: 14532

Обсудить на форуме

0   Спам
(06.05.2012)
2. kilobyte88
Это не серийный номер физического диска(HDD), а серийный номер тома/раздела диска, который можно легко сменить, да он и сам может сменится при переустановке windows®, для привязки к железу он категорически не подходит так как это не надежно.

0   Спам
(18.11.2011)
1. Александр
Здравствуйте!
у меня есть программа ,вернее это скрипт (Бот).При установки просит активация через e-mail, и после установки привязывается к железу и работает только на одной машине.
Можно ли убрать эту активацию и привязку, т.е освободится от всего этого.

С Уважением,
Александр.


Имя *:
Email:


Код *:

Copyright © 2008 - 2018 Программирование на Delphi для начинающих и не только.

Полнота авторских прав на все материалы, опубликованные на сервере DelphiDevelop.ru принадлежит их авторам.

Перепечатка материалов разрешается с указанием авторства и гиперссылки на первоисточник информации.