
- •Введение
- •1. Лабораторная работа № 1
- •1.1. Цель работы
- •1.2. Теоретическое введение
- •1.2.1. Получение информации об операционной системе
- •1.2.2. Получение информации из реестра
- •1.2.3. Получение информации о системных каталогах Windows
- •1.2.4. Получение информации о диске
- •1.3. Создание приложения для получения характеристик компьютера и операционной системы
- •Контрольные вопросы
- •2. Лабораторная работа №2
- •2.1.Цель работы
- •2.2. Теоретическое введение
- •2.2.1. Процедуры и функции для работы с виртуальной памятью
- •2.3. Создание приложения, работающего с виртуальной памятью
- •2.4. Задание для самостоятельной работы
- •Контрольные вопросы
- •3. Лабораторная работа № 3
- •3.1. Цель работы
- •3.2. Пример использования механизма выделения виртуальной памяти для решения конкретных задач
- •3.3. Задания для самостоятельной работы
- •Контрольные вопросы
- •4. Лабораторная работа № 4
- •4.1. Цель работы
- •4. 2. Теоретическое введение
- •4.2.1 Создание или открытие объекта ядра «файла»
- •4.2.2 Создание объекта ядра «файл, проецируемый в память»
- •4.2.3 Проецирование файловых данных на адресное пространство процесса
- •4.2.4 Отмена проецирования на адресное пространство процесса объекта ядра «файл, проецируемый в память»
- •4.2.5 Закрытие объектов ядра «файл, проецируемый в память» и «файл»
- •4.3 Примеры программ, выполняющих проецирование в память
- •4.3.1 Пример 1
- •4.3.2 Пример 2
- •4.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •5. Лабораторная работа № 5
- •5.1.Цель работы
- •5.2. Теоретическое введение
- •5.2.1. Создание процесса
- •5.2.2. Запуск внешней программы функцией WinExec
- •5.2.3. Запуск внешней программы и открытие документа функцией ShellExecute
- •При успешном выполнении функция ShellExecute возвращает целое значение, большее 32. Значение меньшее или равное 32 указывает на ошибку. Значения эти те же, что и для функции WinExec.
- •5.2.4. Создание потока
- •5.2.5. Завершение процесса
- •5.2.6. Завершение потока
- •5.2.7. Изменение класса приоритета процесса
- •5.2.8. Получение информации о классе приоритета процесса
- •5.2.9. Изменение уровня приоритета потока
- •5.2.10. Получение информации о приоритете потока
- •5.3. Примеры программ для работы с процессами и потоками
- •5.3.1. Создание процесса с помощью функции CreateProcess.
- •5.3.2. Создание процесса с помощью функции WinExec.
- •5.3.3. Создание процесса с помощью функции ShellExecute.
- •5.3.4. Создание многопоточного приложения.
- •5.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •6. Лабораторная работа № 6
- •6.1. Цель работы
- •6.2. Теоретическое введение
- •6.2.1. Получение «мгновенного снимка» системы
- •6.2.2. Получение информации о процессах
- •6.2.3. Получение информации о потоках
- •6.2.4. Получение информации о модулях
- •6.2.5. Информация о кучах (heap)
- •6.2.6. Информация о виртуальной памяти.
- •6.2.7. Алгоритм работы функций ToolHelp
- •6.2.8. Как получить карту памяти любого процесса
- •6.3. Пример использования функций ToolHelp
- •6.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •7. Лабораторная работа № 7
- •7.1. Цель работы
- •7.2. Теоретическое введение
- •7.2.1. Критические секции
- •7.2.2. Синхронизация с использованием объектов ядра
- •7.2.3. Wait-функции
- •7.2.4. Синхронизация с использованием процессов и потоков
- •7.2.5. Объекты Mutex
- •7.2.6. Семафоры
- •7.2.7. События
- •7.3 Примеры работы с объектами синхронизации
- •7.3.1 Пример 1
- •7.3.1 Пример 2
- •7.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •8. Лабораторная работа № 8
- •8.1. Цель работы
- •8.2 Теоретическое введение
- •8.2.1 Создание dll
- •8.2.2 Неявная загрузка dll
- •8.2.3 Явная загрузка dll
- •8.2.4 Внедрение dll в адресное пространство другого процесса
- •8.3 Пример работы с dll
- •8.3.1 Создание dll, которая выполняет перехват нажатых клавиш
- •8.3.2 Разработка приложения, которое выполняет анализ и обработку нажатых клавиш.
- •8.4 Индивидуальные задания
- •Контрольные вопросы
- •9.2.2. Функции для работы с объектом «уведомление об изменении файловой системы»
- •9.3. Пример работы системы уведомления об изменениях в файловой системе
- •9.4. Задания для самостоятельной работы
- •Контрольные вопросы
- •Литература
- •214013 Г. Смоленск, Энергетический проезд, 1
8.2.2 Неявная загрузка dll
Рассмотрим неявную загрузку DLL на примере вызова процедуры HelloFromLib.
Последовательность действий:
Создадим приложение, экранная форма которого изображена на рисунке 8.1:
П
рограммный код модуля имеет следующий вид:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// неявная загрузка DLL
procedure HelloFromLib(k:Integer); external 'mess.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
HelloFromLib(StrToInt(Edit1.Text));
end;
end.
Примечание: Процедура HelloFromLib объявлена как внешняя.
8.2.3 Явная загрузка dll
Рассмотрим явную загрузку DLL на примере вызова процедуры HelloFromLib и функции fy.
Последовательность действий:
Создадим приложение, экранная форма которого изображена на рисунке 8.2.
П
рограммный код модуля имеет следующий вид:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
Edit2: TEdit;
Edit3: TEdit;
Button2: TButton;
Label2: TLabel;
Label3: TLabel;
Edit4: TEdit;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
// определение переменной – указателя на процедуру
HelloFromLibM:procedure (k:Integer);
// определение переменной – указателя на функцию
fyM:function(x:real;n:Integer):Real;
public
{ Public declarations }
end;
var
Form1: TForm1;
instance:LongWord;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
// явная загрузка DLL
instance:=LoadLibrary('D:\Lab_OS\DLL\mess.dll');
If instance<>0 then
Begin
// Получаем адрес требуемой функции
HelloFromLibM:=GetProcAddress(instance,'HelloFromLib');
// вызов функции из внешней DLL
HelloFromLibM(StrToInt(Edit1.text));
FreeLibrary(instance);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
Var y:Real;
begin
instance:=LoadLibrary('D:\Lab_OS\DLL\mess.dll');
If instance<>0 then
begin
fyM:=GetProcAddress(instance,'fy');
y:=fyM(StrToFloat(Edit2.text),StrToInt(Edit3.Text));
Edit4.Text:=FloatToStr(y);
FreeLibrary(instance);
end;
end;
end.
8.2.4 Внедрение dll в адресное пространство другого процесса
Одним из методов внедрения DLL в адресное пространство другого процесса является использование ловушек. Для создания ловушек используется функция
SetWindowsHookEx(idHook:Integer; lpfn: Pointer; hMod:DWORD; dwThreadId:DWORD):hHook;
где
idHook - тип ловушкиl
lpfn - адрес процедуры, которая обрабатывает ловушку
hMod - дескриптор приложения
dwThreadId - идентификатор потока.
Механизм, позволяющий внедрять DLL в адресное пространство другого процесса, работает следующим образом:
Процесс A устанавливает ловушку WH_GETMESSAGE и наблюдает за сообщениями, которые обрабатываются окнами в системе. Ловушка устанавливается вызовом SetWindowsHookEx:
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDll,0);
Аргумент WH_GETMESSAGE определяет тип ловушки, а параметр GetMsgProc — адрес функции (в адресном пространстве процесса), которую система должна вызывать всякий раз, когда окно собирается обработать сообщение. Параметр hinstDll идентифицирует DLL, содержащую функцию GetMsgProc. В Windows значение hinstDll для DLL фактически задаст адрес в виртуальной памяти, по которому DLL спроецирована на адресное пространство процесса. И, наконец, последний аргумент, 0, указывает поток, для которого предназначена ловушка. Поток может вызвать SetWindowsHookEx и передать ей идентификатор другого потока в системе. При передаче 0 системе сообщается, что ловушка ставится для всех существующих в ней GUI-потоков.
Перехват работает следующим образом::
Поток процесса B собирается направить сообщение какому-либо окну.
Система проверяет, не установлена ли для данного потока ловушка WH_GETMESSAGE.
Затем выясняет, спроецирована ли DLL, содержащая функцию GetMsgProc, на адресное пространство процесса B.
Если указанная DLL еще не спроецирована, система отображает ее на адресное пространство процесса B.
Вызывается GetMsgProc в адресном пространстве процесса B.
Причем, когда система внедряет или проецирует DLL, содержащую функцию фильтра ловушки, проецируется вся DLL, а не только эта функция. А значит, потокам, выполняемым в контексте процесса B, теперь доступны все функции такой DLL.
Для отключения DLL от адресного пространства процесса достаточно вызвать:
UnhookWindowsHookEx(HOOK: hHook):Boolean;