Динамически подключаемые библиотеки 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Динамически подключаемые библиотеки



Лабораторная работа № 3

 

Динамически подключаемые библиотеки

Цель работы: получение практических навыков программирования с применением Win 32/64 API и создания динамических библиотек.

 

Общие сведения

Динамически подключаемая библиотека (DLL, Dynamic Link Library) - программный модуль, который может быть загружен в виртуальную память процесса как статически (неявно), во время создания исполняемого модуля процесса, так и динамически (явно), во время исполнения процесса операционной системой. Разработанный в виде DLL программный модуль, хранится на диске в виде файла, с расширением dll, и может содержать как подпрограммы, так и данные. Для загрузки DLL в память используется подход отображения файлов в память.

Применение DLL предоставляет ряд преимуществ:

1. Расширение функциональности приложения. DLL можно загружать в адресное пространство процесса на этапе выполнения, что позволит программе, определив, какие действия от нее требуются, подгружать нужный код.

2. Более простое управление проектом. Использование DLL упрощает отладку, тестирование и сопровождение проекта.

3. Экономия памяти. Если одну и ту же DLL используют несколько приложений, то в оперативной памяти хранится только один ее экземпляр, доступный этим приложениям.

4. Разделение ресурсов. DLL могут содержать такие ресурсы, как строки, растровые изображения, шаблоны диалоговых окон. Этими ресурсами может воспользоваться любое приложение.

5. Возможность использования разных языков программирования.

Механизм DLL -библиотек является неотъемлемой частью операционной системы Windows. В процессе компоновки исполняемого модуля с использованием внешних подпрограмм в него помещаются не сами подпрограммы, а только их названия вместе с названиями DLL -библиотек в которых они включены.

Исполняемый код в DLL не предполагает автономного использования. Динамически подключаемые библиотеки предназначены, главным образом, для разработки функционально-замкнутых библиотек функций, которые могут использоваться разными приложениями. Содержимое каждого DLL –файла загружается приложением и проецируется на адресное пространство вызывающего процесса, т. е. в этом случае все приложения разделяют один и тот же экземпляр исполняемого кода DLL, загруженный в физическую память. Это достигается либо за счет неявного связывания при загрузке, либо за счет явного связывания в период выполнения.

Важно понимать, что процесс, загрузивший DLL, получает собственную копию глобальных данных, используемых этой библиотекой. Это защищает DLL от ошибок приложений, а процессы, использующие DLL, от взаимного влияния друг на друга.

Особый формат модулей DLL предполагает наличие в них разделов
импорта и экспорта. Раздел экспорта указывает те идентификаторы
объектов (функций, классов, переменных), доступ к которым разрешен
для клиентов.

В DLL содержатся все функции Win 32/64 API. Например, DLL:
Kernel32.dll (управление памятью, процессами и потоками), User32.dll (поддержка пользовательского интерфейса, в том числе функции, связанные с созданием окон и передачей сообщений) и GDI32.dll (графика и вывод текста), AdvAPI32.dll (защита объектов, работа с реестром и регистрация событий), ComDlg32.dll (диалоговые окна, например, FileOpen и FileSave), ComCtl32.dll (стандартные элементы управления).

Как правило, если язык программирования поддерживает разработку Windows-приложений, то он имеет средства для разработки и использования DLL -библиотек. Язык ассемблера не является исключением. Общие принцип DDL -библиотек для всех языков одинаковы, так как эти библиотеки являются универсальным средством, не зависящим от конкретного языка. Разрабатывая модуль необходимо учитывать общие требования к таким библиотекам.

 

Format PE GUI 6.0 DLL

Entry DllEntryPoint

include 'win32a.inc'

Endp

 

Proc ShowMessage hWnd

local Buffer:DWORD

   lea eax,[Buffer]

   invoke MessageBox, [hWnd], [Buffer], NULL, MB_OK

   ret

Endp

 

Format PE GUI 6.0 DLL

Entry DllEntryPoint

include 'win32a.inc'

DllStart db 'Загружена',0

DllStop db 'Выгружена',0

Endp

 

Proc ShowMessage hWnd

local Buffer:DWORD

   lea eax,[Buffer]

   invoke MessageBox, [hWnd], [Buffer], NULL, MB_OK

   ret

Endp

 

Вызов функций из DLL

Существует два способа загрузки DLL:

а) неявная;

б) явная;

Рассмотрим неявную загрузку DLL. Для построения приложения, рассчитанного на неявную загрузку DLL, необходимы ссылки на импортируемые идентификаторы. Компоновщик (линкер, редактор связей) формирует загрузочный EXE – модуль. В этом модуле компоновщик помещает также раздел импорта, где перечисляются имена всех необходимых DLL -модулей. Для каждой DLL в разделе импорта указывается, на какие имена функций и переменных встречаются ссылки в коде исполняемого файла. Эти сведения будет использовать загрузчик операционной системы. После запуска EXE -модуля загрузчик операционной системы выполняет следующие операции: 1. Создает виртуальное адресное пространство для нового процесса и проецирует на него исполняемый модуль;

2. Анализирует раздел импорта, определяя все необходимые DLL -модули и тоже проецирует их на адресное пространство процесса.

DLL может импортировать функции и переменные из другой DLL. А значит, у нее может быть собственный раздел импорта, для которого необходимо повторить те же действия. В результате на инициализацию процесса может уйти довольно длительное время. После отображения EXE -модуля и всех DLL-модулей на адресное пространство процесса его первичный поток готов к выполнению, и приложение начинает работу.

Недостатками неявной загрузки являются обязательная загрузка библиотеки, даже если обращение к ее функциям не будет происходить, и, соответственно, обязательное требование к наличию библиотеки при компоновке.

Явная загрузка DLL устраняет отмеченные выше недостатки за счет некоторого усложнения кода. Программисту приходится самому заботиться о загрузке DLL и подключении экспортируемых функций. Зато явная загрузка позволяет подгружать DLL по мере необходимости и дает возможность программе обрабатывать ситуации, возникающие при отсутствии DLL.

В случае явной загрузки процесс работы с DLL происходит в три этапа:

1. Загрузка DLL с помощью функции LoadLibrary (или ее расширенного аналога LoadLibraryEx). В случае успешной загрузки функция возвращает дескриптор hLib типа HMODULE, что позволяет в дальнейшем обращаться к этой DLL.

2. Вызовы функции GetProcAddress для получения указателей на требуемые функции или другие объекты. В качестве первого параметра функция GetProcAddress получает дескриптор hLib, в качестве второго параметра –адрес строки с именем импортируемой функции. Далее полученный указатель используется клиентом. Например, если это указатель на функцию, то осуществляется вызов нужной функции.

3. Когда загруженная динамическая библиотека больше не нужна, рекомендуется ее освободить, вызвав функцию FreeLibrary. Освобождение библиотеки не означает, что операционная система немедленно удалит ее из памяти. Задержка выгрузки предусмотрена на тотслучай, когда эта же DLL через некоторое время вновь понадобится какому-то процессу. Но если возникнут проблемы с оперативной памятью, Windows в первую очередь удаляет из памяти освобожденные библиотеки.

Пример текста DLL:

Format PE GUI 6.0 DLL

Entry DllEntryPoint

include 'C:\Users\work\Desktop\fasmw17121\INCLUDE\win32a.inc'

 

Format PE GUI 6.0

Entry start

 

include 'C:\Users\work\Desktop\fasmw17121\INCLUDE\win32a.inc'

 

Format PE GUI 6.0

Entry start

 

include 'C:\Users\work\Desktop\fasmw17121\INCLUDE\win32a.inc'

 

Примеры Win 32/64 API -функций получения системной информации

 

Некоторые Win 32/64 API -функции получения системной информации: GetComputerName, GetSystemMetrics, GetWindowsDirectoty, GetKeyboardTy ре, GetTempPath, Set Со m р uterName, GetSysColor, GetUserName, SetSysColors, CecSystemDirectory, GetVersion, SystemParametersInfo, GetSystemlnfo, GetVersioriEx, GetUserName.

Функция GetComputerName используется для получения текущего имени компьютера. Связанная с ней SetСomputerName используется для присвоения имени компьютеру.

 

BOOL GetComputerName (

DWORD GetTempPath(

DWORD nBufferLength,           // Размер буфера в символах

  LPTSTR IpBuffer         // Указатель на буфер пути к каталогу временных файлов.

);

Функция GetVersionEx возвращает информацию о версии операционной системы. Она объявляется как

 

BOOL GetVersionEx (

LPOSVERSIONINFO IpVersionlnformation. // Указатель на структуру

        //с информацией о версии.

 );

где IpVersionlnformation - указатель на структуру OSVERSIONINFO, которая определена следующим образом:

typedef struct _OSVERSIONINFO (

DWORD dwOSVersionlnfoSise;

DWORD dwMajorVersion;

DWORD dwMinorVersion;

DWORD dwBuildNumber;

DWORD dwPlatformId;

TCHAR szCSDVersion[ 128 ];

) OSVERSIONINFO;

В документации об этой структуре  говорится следующее:

DwOSVersionlnfoSize

Задает размер структуры OSVERSIONINFO в байтах. Для структур это является общим требованием. Так как DWORD - четырехбайтовое беззнаковое типа long и поскольку Delphi и VB преобразуют строку из 128 символов в массив символов ANSI из 128 байт, общий размер структуры составляет. 4x5+ 128 = 148 байт. Это значение возвращает функция Len для VB и SizeOf для Delphi.

DwMajorVersion

Указывает номер основной версии операционной системы. Например, для Windows NT версии 3.51 номер основной версии - 3. Для Windows NT 4.0 и Windows 9х номер основной версии - 4.

DwMinorVersion

Указывает дополнительный номер версии операционной системы. Например, для Windows NT версии 3.51 дополнительный номер версии - 51. Для Windows NT 4.0 и Windows 95 дополнительный номер версии - 0. Для Windows 98 дополнительный номер версии - 10.

DwBuildNumber

Указывает номер сборки операционной системы для Windows NT. Для Windows 9х два младших байта содержат номер сборки операционной системы, а два старших байта - номер основной версии и дополнительный номер версии.

dwPiatformId

Идентифицирует платформу операционной системы, может иметь одно из следующих значений:

 

VER_PLATFORM_WIN32s (= 0).                Win32s, работающая на Windows

VER_PLATFORM_WIN32_WINDOWS (= 1).    Win32, работающая на Windows 95 или

                                                                        Windows 98.

 VER_PLATFORM_WIN32_NT (= 2).            Win32, работающая на Windows NT

SzCSDVersion

В Windows NT содержит строку завершающеюся нулевым символом, например «Service Pack3», которая указывает самую последнюю версию установленного в системе служебного пакета программ (service pack). Строка будет пустой, если служебный пакет не установлен. В Windows 95 включает строку с завершающим нулевым символом, в которой может быть произвольная дополнительная информация об операционной системе.

Функция GetSystemMetrics получает информацию о метриках (системе единиц измерения) объектов операционной системы.

Int GetSystemMetrics(

int nlndex                               // Системная метрика или установки конфигурации.

);

Параметр nIndex принимает значение одной из 84 возможных констант. Функция возвращает запрошенные единицы измерения (в общем случае в пикселях или в безразмерных единицах).

Чтобы дать общее представление о типе возвращаемой информации, здесь приведены образцы некоторых констант для этой функции. Единицы измерения высоты и ширины приведены в пикселях:

SM _ CMOUSEBUTTOMS = 43        // Delphi    ' Количество клавиш мыши.

Const SM_CMOUSEBUTTOMS = 43  // VB                   

SM_MOUSEWHEELPRESENT = 75                           ' Истина (True), если мышь имеет

                                          ' колесо прокрутки.

                           ' (Только Win NT 4 или Win 98.)

SM _ SWAPBUTTON = 23                                         ' Истина (True), если клавиши мыши

' можно поменять местами (мышь                                              ' для левши).

SM _ CXBORDER = 5                                               ' Ширина и высота рамки окна.

SM _ CYBORDER = 6                                                         

SM _ CXSCREEN = 0                                                  ' Ширина и высота экрана.

SM _ CYSCREEN = 1

SM _ CXFULLSCREEN = 16                                          ' Ширина и высота области

                                ' приложения в полноэкранном    

SM _ CYFULLSCREEN = 17                                      'режиме.

SM _ CXHTHUMB = 10                                              'Ширина прямоугольного курсора

                                   'в горизонтальной полосе                                          'прокрутки.

SM _ CXICONS PACING = 38                                      'Размеры ячейки сетки для

SM _ CYICONS РАС ING = З9                                   'значка в режиме просмотра с     'крупными значками.

SM _ CYCAPTION = 4                                                 '       Высота стандартной области                  'заголовка.

 

Системные параметры

Функция SystemParamterslnfo - это мощная функция, предназначенная для получения или установки всех системных параметров. Также она может в процессе установки параметра обновлять пользовательские профили. Ниже приведена ее декларация:

BOOL SystemParametersInfo (

UINT uiAction,                               //  Запрашиваемый или устанавливаемый

//   системный  параметр.

UIN Т uiParam,                             // Зависит от принятого системного

// параметра.

PVOID pvParam,                            // Зависит от принятого системного параметра.

UINT fWinIni                     // Флаг обновления пользовательского профиля.
};

 

Эта функция может принимать, по меньшей мере, 90 различных значений uiAction. Ниже приведены некоторые константы uiAction:

SPI_GETACCESSTIMEOUT - используется для определения данных о временных интервалах, относящихся к специальным возможностям Windows;

SPI_GETANIMATION – используется для определения данных об анимации, используемой при сворачивании и восстановлении окон;

SPI_GETBEEP - признак разрешения звуковых сигналов;

SPI_GETBORDER – параметру присваивается коэффициент, управляющий толщиной рамки для изменения размеров окна;

SPI_GETDEFAULTINPUTLANG – параметру присваивается 32-х разрядный дескриптор раскладки клавиатуры по умолчанию;

SPI_GETDRAGFULLWINDOWS – характеристики перемещения окна мышью;

SPI_GETFASTTASKSWITCH – признак, определяющий быстрое переключение задач;

SPI_GETFILTERKEYS - используется для определения данных о специальных возможностях, относящихся к работе с клавиатурой;           

SPI_GETFONTSMOOTHING      - режимы сглаживания шрифтов;

SPI_GETGRIDGRANULARITY – гранулярность сетки рабочего стола;

SPI_GETICONMETRICS - используется для определения информации о характеристиках иконок.

Системные цвета

Функции GetSysColor и SetSysColors используются для получения и установки цветов различных элементов системы, таких как кнопки, строки заголовков и т.д. Цветовой палитрой также может управлять пользователь с помощью апплета Display (Экран) на панели Control Panel (Панель управления).

Декларация GetSysColor:

DWORD GetSysColor (

int nIndex                                   // Элемент экрана.

);

  nIndex может принимать значение одной из множества символьных констант, например

# define COLOR _ ACTIVECAPTION   3

Возвращаемое значение - это цвет в формате RGB. В частности, каждый цвет занимает один байт в возвращаемом значении типа unsigned long: красный цвет - младший байт, зеленый - следующий байт, далее - синий цвет. Самый старший байт равен нулю. Байты цветов представлены в переменной тина long в обратном порядке, поскольку при записи переменной в память байты располагаются от младших к старшим.

 

 

Объявление функции SetsysColors:

BOOL WINAPI SetSysColors (

int cElements,                                           // Количество изменяемых

             // элементов.

CONST INT *lpaElements,                      // Адрес массива элементов.
CONST COLORREF *lpaRgbValues            // Адрес массива значений RGB.

 

Здесь cElements определяет количество системных элементов, цвет которых требуется изменить; IpaElements - указатель на целочисленный массив VC++, который содержит индексы изменяемых элементов; IpaRgbvalues ссылается на целочисленный массив VC++ новых значений цвета в формате RGB.

Таблица 1.

Вариант Название API-функции
1 ActivateKeyboardLayout, GetCurrencyFormat, GetLastError, OemToChar                       
2 CharToOem, GetCursor, GetLocaleInfo, OemToCharBuff,
3 AnsiToOemBuff, GetCursorPos, GetNumberFormat, SetCaretPos,          
4 ClipCursor, GetDoubleClickTime, GetOEMCP, SetCursor
5 CreateCaret, GetEnvironmentStrings, GetQueueStatus, SetCursorPos
6 DestroyCaret, GetEnvironmentVariable, GetSystemDefaultLangID, SetDoubleClickTime 
7 EnumSystemCodePages, GetInputState, GetLastError, SetKeyboardState
8 ExitWindowsEx, GetKBCodePage, GetSystemDefaultLCID, SetCaretBlinkTime               
9 GetACP, GetKeyboardLayout, GetSystemPowerStatus, SetComputerName
10 GetAsyncKeyState, GetKeyboardLayoutList, GetTickCount, SetLocaleInfo
11 GetCaretBlinkTime, GetKeyboardLayoutName, GetLastError, SetSystemCursor
12 GetCaretPos, GetKeyboardState, GetUserDefaultLangID, SetSystemPowerState
13 GetClipCursor, GetKeyboardType, GetUserDefaultLCID, ShowCursor
14 GetCommandLine, GetKeyNameText, MessageBeep, SwapMouseButton
15 GetCPInfo, GetKeyState, GetLastError, UnloadKeyboardLayout

 

Контрольные вопросы

1. Что такое DLL?

2. Зачем нужен раздел экспорта?

3. Какие преимущества использования DLL?

4. Как защищаются данные DLL от ошибок приложений?

5. Какие способы загрузки DLL Вы знаете?

6. Как осуществляется неявная загрузка DLL?

7. Как выполняется загрузка exe-файла, использующего DLL при неяв-

ном связывании?

8. Каковы недостатки неявной загрузки?

9. Чем отличается явная загрузка от неявной?

10. Каково назначение функции LoadLibrary?

11. Зачем используется функция GetProcAdress?

12. Перечислите этапы работы с DLL при явной загрузке.

13. Что такое отложенная загрузка DLL?

14. Зачем используется отложенная загрузка?

15. Как организуется отложенная загрузка?

16. Зачем нужна функция входа-выхода DLL?

17. В каких случаях вызывается DllEntryPoint?

18. Какие параметры у функции входа-выхода?

19. Какие причины вызова DllEntryPoint Вы знаете?

20. Как узнать, каким способом загружается DLL?

Лабораторная работа № 3

 

Динамически подключаемые библиотеки



Поделиться:


Последнее изменение этой страницы: 2021-07-18; просмотров: 267; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.19.29.89 (0.084 с.)