Разработка подпрограмм
В этой программе нам понадобятся две подпрограммы: процедура записи строки в файл и процедура получения серийного номера раздела жесткого диска. Разумеется, совсем необязательно выносить их в отдельные подпрограммы, можно выполнить все в одной программе в виде монолита. Однако чем сильнее раздроблена программа на процедуры и функции, тем легче ее читать и отлаживать. Поэтому настоятельно рекомендуется создать отдельные подпрограммы для выполнения этих функций. Код подпрограммы записи строки в файл приведен в листинге 4.1. Код подпрограммы определения серийного номера раздела жесткого диска приведен в листинге 4.2.
procedure WriteStringToFile(Filename, Str: String; Option : Integer); var fp : TextFile; Begin AssignFile(fp, Filename); // Связываем файл с дескриптором
Case Option Of FP_Append: Append(fp); Else Rewrite(fp); End;
Writeln(fp, Str); // Пишем строку в файл CloseFile(fp); // Закрываем файл, освобождаем дескриптор
end; Листинг 4.1 – Код подпрограммы записи строки в файл
Подпрограмма записи строки в файл получает три входных параметра: имя файла, в который производится запись, строка, которую нужно записать, и режим записи. Внутри самой подпрограммы используется константа FP_Append, объявленная в секции объявлений. В зависимости от значения переменной Option файл будет либо открыт на добавление, либо перезаписан. Все остальное в этой подпрограмме уже встречалось в предыдущих лабораторных работах.
function GetHardDiskSerial(const DriveLetter: Char): String; Var NotUsed: DWORD; VolumeFlags: DWORD; VolumeInfo: Array[0..MAX_PATH] Of Char; VolumeSerialNumber: DWORD; Begin GetVolumeInformation(PChar(DriveLetter + ':\'), nil, SizeOf(VolumeInfo), @VolumeSerialNumber, NotUsed, VolumeFlags, nil, 0); Result := Format('Метка = %s С/Н = %8.8X', [VolumeInfo, VolumeSerialNumber]) end; Листинг 4.2 – Код подпрограммы определения серийного номера раздела HDD
Подпрограмма определения серийного номера раздела жесткого диска в завуалированном виде использует системную API функцию GetVolumeInformation. Эта функция описана в системной библиотеке kernel32.dll и получает на входе множество параметров. Их описание занимает достаточно много места и выходит за рамки этого пособия, но вкратце можно сказать, что GetVolumeInformation получает несколько адресов переменных типа PChar, куда на выходе будут записаны данные о параметрах раздела жесткого диска. Вторая команда возвращает результат в удобном отформатированном для вывода на экран виде.
Разработка подпрограмм-обработчиков событий Поскольку на форме нашего приложения установлены четыре кнопки, нам понадобятся четыре обработчика событий нажатия на каждую из кнопок. Два обработчика вполне тривиальны и не нуждаются в особых комментариях. Это подпрограммы завершения работы приложения и очистки журнала. Коды этих подпрограмм приведены в листингах 4.3 и 4.4 соответственно.
procedure TfrmCopyProtect.btnQuitClick(Sender: TObject); Begin Close; end; Листинг 4.3 – Код подпрограммы-обработчика события «Выход»
procedure TfrmCopyProtect.btnClearLogClick(Sender: TObject); Begin memoLog.Clear; end; Листинг 4.4 – Код подпрограммы-обработчика события «Очистка журнала»
Теперь нам предстоит разработать оставшиеся две подпрограммы обработки событий снятия «снимка» текущей конфигурации системы и сверки конфигурации. Код подпрограммы-обработчика события снятия «снимка» конфигурации приведен в листинге 4.5. Код подпрограммы-обработчика события сверки конфигурации приведен в листинге 4.6.
procedure TfrmCopyProtect.btnSetConfigClick(Sender: TObject); Var lpVI : TOSVersionInfo; // Структура версии ОС CurrentDriveType : Integer; // Тип текущего накопителя DriveCSN : String; Begin
// Устанавливаем защиту путем опроса системы и сохранения конфигурации
memoLog.Lines.Clear; // Чистим журнал
//////////////////////////////////////////////////////////////////////// // ТИП ТЕКУЩЕГО ДИСКА ////////////////////////////////////////////////////////////////////////
CurrentDriveType := GetDriveType(Nil); // Получаем тип текущего дискового накопителя
memoLog.Lines.Add('ТИП ТЕКУЩЕГО НАКОПИТЕЛЯ:');
Case CurrentDriveType Of 0 : memoLog.Lines.Add('Тип текущего накопителя не определен'); 1 : memoLog.Lines.Add('Корневой директорий не существует'); DRIVE_REMOVABLE: memoLog.Lines.Add('Сьемный накопитель'); DRIVE_FIXED: memoLog.Lines.Add('Несъемный накопитель'); DRIVE_REMOTE: memoLog.Lines.Add('Сетевой диск'); DRIVE_CDROM: memoLog.Lines.Add('Привод CD/DVD'); DRIVE_RAMDISK: memoLog.Lines.Add('Виртуальный RAM-диск'); End;
memoLog.Lines.Add('');
WriteStringToFile(ConfigFile, IntToStr(CurrentDriveType), FP_Rewrite); // Получаем и сохраняем тип текущего драйвера в файле
//////////////////////////////////////////////////////////////////////// // ТЕКУЩАЯ ВЕРСИЯ ОС ////////////////////////////////////////////////////////////////////////
lpVI.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(lpVI); // Получаем текущую версию ОС
memoLog.Lines.Add('ВЕРСИЯ ОС');
Case lpVI.dwMajorVersion Of 3 : memoLog.Lines.Add('Windows NT 3.5'); 4 : memoLog.Lines.Add('Windows NT 4.0/9x'); 5 : memoLog.Lines.Add('Windows 2000/XP'); End; // Старшая часть версии ОС
memoLog.Lines.Add('Сборка - ' + IntToStr(lpVI.dwBuildNumber)); memoLog.Lines.Add(String(lpVI.szCSDVersion)); memoLog.Lines.Add('');
WriteStringToFile(ConfigFile, IntToStr(lpVI.dwMajorVersion), FP_Append); WriteStringToFile(ConfigFile, IntToStr(lpVI.dwMinorVersion), FP_Append); WriteStringToFile(ConfigFile, IntToStr(lpVI.dwBuildNumber), FP_Append); WriteStringToFile(ConfigFile, IntToStr(lpVI.dwPlatformId), FP_Append); WriteStringToFile(ConfigFile, String(lpVI.szCSDVersion), FP_Append); // Записываем информацию в файл
//////////////////////////////////////////////////////////////////////// // НОМЕР РАЗДЕЛА ЖЕСТКОГО ДИСКА ////////////////////////////////////////////////////////////////////////
memoLog.Lines.Add('СЕРИЙНЫЙ НОМЕР ТОМА');
DriveCSN := GetHardDiskSerial('C'); // Получаем информацию о диске С
memoLog.Lines.Add(DriveCSN);
WriteStringToFile(ConfigFile, DriveCSN, FP_Append); // Записываем информацию в файл end; Листинг 4.5 – Код подпрограммы-обработчика события снятия «снимка» конфигурации
Несмотря на значительный объем код, приведенный в листинге 4.5, очень прост и выполняется линейно без глубоких ветвлений и циклов. Логически он состоит из трех блоков: блока определения типа текущего диска (съемный, несъемный, CD-ROM, RAM-диск, сетевой и т.д.), блока определения типа и версии операционной системы и блока определения серийного номера раздела жесткого диска. Эти блоки, в общем-то, не зависят друг от друга, и некоторые из них могут вообще отсутствовать в программе. Однако, поскольку речь идет о конфигурации системы, чем большее количество параметров мы учтем, тем выше, в конечном счете, окажется вероятность определения законности производимого запуска программы. Все логические блоки имеют одинаковую структуру. Сначала производится обращение к системной API функции для получения информации о конфигурации. Затем полученные данные анализируются с помощью оператора case (только в том случае, если полученные данные закодированы, или имеют сложную структуру), выводятся на пользовательскую форму и сохраняются в файл.
procedure TfrmCopyProtect.btnCheckConfigClick(Sender: TObject); Var lpVI : TOSVersionInfo; // Структура версии ОС CurrentDriveType : Integer; // Тип текущего накопителя fp : TextFile; tempStr : String; isAnyError : Boolean; DriveCSN : String; Begin // Проверка конфигурации путем опроса текущей и сверки с сохраненной
AssignFile(fp, ConfigFile); Reset(fp); // Готовим файл конфигурации к загрузке
isAnyError := False; // Инициализируем флаг ошибки memoLog.Lines.Clear; // Чистим журнал
//////////////////////////////////////////////////////////////////////// // ТИП ТЕКУЩЕГО ДИСКА ////////////////////////////////////////////////////////////////////////
CurrentDriveType := GetDriveType(Nil); // Получаем тип текущего дискового накопителя
memoLog.Lines.Add('ТИП ТЕКУЩЕГО НАКОПИТЕЛЯ:');
Readln(fp, tempStr); // Загружаем сохраненное в файле значение
If tempStr = IntToStr(CurrentDriveType) Then memoLog.Lines.Add('OK') Else Begin memoLog.Lines.Add('ОШИБКА!'); isAnyError := True; End;
memoLog.Lines.Add('');
//////////////////////////////////////////////////////////////////////// // ТЕКУЩАЯ ВЕРСИЯ ОС ////////////////////////////////////////////////////////////////////////
lpVI.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(lpVI); // Получаем текущую версию ОС
memoLog.Lines.Add('ВЕРСИЯ ОС');
Readln(fp, tempStr); If tempStr = IntToStr(lpVI.dwMajorVersion) Then memoLog.Lines.Add('Семейство ОС - ОК') Else Begin memoLog.Lines.Add('Семейство ОС - ОШИБКА!'); isAnyError := True; End; // Проверка семейства ОС
Readln(fp, tempStr); If tempStr = IntToStr(lpVI.dwMinorVersion) Then memoLog.Lines.Add('Версия ОС - ОК') Else Begin memoLog.Lines.Add('Версия ОС - ОШИБКА!'); isAnyError := True; End; // Проверка версии ОС
Readln(fp, tempStr); If tempStr = IntToStr(lpVI.dwBuildNumber) Then memoLog.Lines.Add('Сборка - OK') Else Begin memoLog.Lines.Add('Сборка - ОШИБКА!'); isAnyError := True; End; // Проверка сборки ОС
Readln(fp, tempStr); If tempStr = IntToStr(lpVI.dwPlatformId) Then memoLog.Lines.Add('Платформа - ОК') Else Begin memoLog.Lines.Add('Платформа - ОШИБКА!'); isAnyError := True; End; // Проверка платформы
Readln(fp, tempStr); If tempStr = String(lpVI.szCSDVersion) Then memoLog.Lines.Add('Service Pack - OK') Else Begin memoLog.Lines.Add('Service Pack - ОШИБКА!'); isAnyError := True; End; // Проверка номера сервис пака
memoLog.Lines.Add('');
//////////////////////////////////////////////////////////////////////// // НОМЕР РАЗДЕЛА ЖЕСТКОГО ДИСКА ////////////////////////////////////////////////////////////////////////
DriveCSN := GetHardDiskSerial('C'); // Получаем информацию о текущем томе
Readln(fp, tempStr);
memoLog.Lines.Add('СЕРИЙНЫЙ НОМЕР ТОМА');
If tempStr = DriveCSN Then memoLog.Lines.Add('ОК') Else Begin memoLog.Lines.Add('ОШИБКА!'); isAnyError := True; End; // Проверка серийного номера тома
CloseFile(fp); // Закрываем файл, освобождаем дескриптор
If isAnyError Then Application.MessageBox('Параметры системы не соответствуют' + + ' сохраненным данным','Неудача') Else Application.MessageBox('Проверка прошла успешно','Успех');
end; Листинг 4.6 – Код подпрограммы-обработчика события сверки конфигурации со «снимком»
Этот листинг, по-видимому, не нуждается в подробных комментариях. Все производимые операции точно соответствуют описанным в листинге 4.6 за одним-единственным исключением. Вместо записи результатов в файл производится загрузка сохраненных данных из файла.
Общее задание
В данном примере все операции (и снятие конфигурации и проверка) реализованы в одной программе, тогда в действительности «снимок конфигурации» должна снимать программа-инсталлятор, а проверку производить сама защищаемая программа. Поэтому, прежде всего, нужно разнести эти функции по разным программам и обеспечить их сопряжение. Программа-инсталлятор должна записывать «снимок» системы в файл, а защищаемая программа должна иметь возможность загрузить его оттуда и проверить соответствие реальной и сохраненной конфигурации.
Популярное: Организация как механизм и форма жизни коллектива: Организация не сможет достичь поставленных целей без соответствующей внутренней... Почему двоичная система счисления так распространена?: Каждая цифра должна быть как-то представлена на физическом носителе... Как построить свою речь (словесное оформление):
При подготовке публичного выступления перед оратором возникает вопрос, как лучше словесно оформить свою... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (414)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |