Осваиваю работу с dll , по вот этому полезному материалу: Как подключить к своей программе DLL -библиотеку Проблема вот какая: Есть несколько методов и все они находятся в dll . Как можно вызвать интересующий нас метод? Может к GetProcAddress прибавить смещение какое-то? Спасибо.
Отслеживать
371 1 1 золотой знак 5 5 серебряных знаков 13 13 бронзовых знаков
задан 29 авг 2013 в 16:52
2,586 8 8 золотых знаков 50 50 серебряных знаков 104 104 бронзовых знака
Каких ещё методов? Пример — в студию!
29 авг 2013 в 17:51
Интересующий метод можно вызвать получив указатель на него по его имени (передав его в GetProcAddress), затем полученный указатель преобразовав к необходимому типу функции, и затем произведя вызов функции передав ей необходимые параметры. В статье которую вы указали все написано ведь)))
29 авг 2013 в 18:01
29 авг 2013 в 18:20
progzdeveloper, а можно простой пример? Просто имя функции в dll и имя указателя на нее в исполняемом файле должны совпадать?
Динамически загружаемые библиотеки (DLL)
29 авг 2013 в 19:21
29 авг 2013 в 22:27
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
При создании проекта в компиляторе укажите библиотека DLL. (в visual studio создать->проект->win32(или консоль) -> далее -> библиотека dll + пустой проект) далее вставить код
#include #include extern «C» __declspec(dllexport) void dll_function(int arg); extern «C» __declspec(dllexport) void dll_function(int arg) < std::cout LPCSTR func_name = «dll_function»; // название загружаемой функции FARPROC adresse_la_func = GetProcAddress(le_module, func_name); if(adresse_la_func!=0) < std::cout FreeLibrary(le_module); std::cout
Отслеживать
ответ дан 30 авг 2013 в 11:17
6,333 7 7 золотых знаков 47 47 серебряных знаков 92 92 бронзовых знака
C подключением и вызовом функций из dll разобрался, хотя что вот это GetModuleFileName(NULL, (LPTSTR)mod_name, size__); в вашем примере(извлекает путь к исполняемому файлу текущего процесса), что она сделает? Сейчас вопрос возник с листингом DUMPBIN. Содержание листинга не совсем понтно?
30 авг 2013 в 11:31
1)Это ничего, можно убрать. 2) Зачем вам этот листинг? Вы функцию получили? Вот и все что необходимо знать. Остальное уже не относится к вопросу.
30 авг 2013 в 12:59
Но а все же, если знаете. Или просто новый вопрос задать?
30 авг 2013 в 18:36
Продолжил разбираться и наткнулся на программу DUMPBIN, которая:
The Microsoft COFF Binary File Dumper (DUMPBIN.EXE) displays information about Common Object File Format (COFF) binary files. You can use DUMPBIN to examine COFF object files, standard libraries of COFF objects, executable files, and dynamic-link libraries (DLLs). Это отсюда: http://msdn.microsoft.com/en-us/library/c1h23y6c.aspx

Итак, я захотел посмотреть таблицу импорта библиотеки которую сам же и собрал. Вот что я увидел:
Где тут таблица импорта? Кроме имени функции, содержащейся в dll ничего не смог разобрать. Сколько переменных и какого типа она принимает, что возвращает функция, если вообще что-то возвращает? На эти вопросы можно по этой картинке ответить? Что такое Summary, что за цифры?
Разработка приложений с помощью WinAPI. Урок 12 DLL. Функции
Цифры 0 00011005-это смещение в памяти по которому будет расположен указатель на функцию, по которому вызывается функция? Что за характеристики и 00000000? И прочие цифры типа 1 ordinal base что означают? Что за порядок? Расшифруйте кто может)
Источник: ru.stackoverflow.com
Статья DLL библиотеки – инструкция к метле
Ещё во-времена старушки дос стало очевидно, что некоторые программные модули лучше хранить не внутри исполняемого файла, а вынести их наружу и подгружать по мере необходимости. В то время такие «прицепы» называли оверлеями и с точки зрения экономии 1М-байтного адресного пространства это было разумно – одну большую программу кромсали на мелкие части, и эти части отрабатывали в памяти по очереди. Подобная техника докатилась и до наших дней, только теперь это динамически подгружаемые DLL.
По сути, нет смысла копать данную тему в очередной раз – всё давно расписано, поэтому добавим экшена и сделаем ставку на нестандартное их применение. Как показывает практика, фишка с защитой программ на основе статически прилинкованных DLL пользуется спросом среди коммерческого софта, значит пора сорвать с неё вуаль и познакомиться по-ближе.
—————————————
«Dynamic Link Library» или DLL – это часть исполняемого РЕ-файла в виде внешнего модуля. Он оформлен как ларчик с N-нным количеством уникальных для наших программ функций, которых нет в составе системных Win32-API. Программный экзо-скелет динамических библиотек идентичен исполняемым файлам экзе, однако есть и некоторые нюансы:
1. Наличие секции-экспорта в коде, которой могут похвастаться исключительно библиотеки. Приложение может вызывать (импортировать) только те функции из DLL, которые оглашены в её секции-экспорта «.edata» . Однако бывают и внутренние функции, которые DLL не экспортирует во-внешний мир, используя только внутри своей тушки для производственных нужд – к их числу можно отнести, например функцию точки-входа в библиотеку DllEntryPoint() . По сути, в данной статье мы сделаем акцент только на этой процедуре инициализации.
2. Второе отличие DLL от EXE – это не способность ими исполнять свой код самостоятельно, поскольку каждый участок кода обёрнут в отдельную функцию. Все эти функции тупо ждут своего часа, пока их услуги не станут восстребованы экзе-файлу и он не затребует их явно. Исключение здесь составляет только упомянутая точка-входа, с которой без нашего ведома активно общается загрузчик LDR, на протяжении всего времени работы приложения.
Система предоставляет нам два способа подключения DLL к своим проектам – статический и динамический . В первом случае мы подключаем библиотеку и указываем импортируемые из неё функции на этапе компиляции РЕ-файла, и эти функции сразу загружаются в наше адресное пространство, вместе с приложением. Во-втором (динамическом) случае, можно загрузить функцию из DLL в произвольный момент времени, сыграв аккордом LoadLibrary() , GetProcAddress() и FreeLibrary() .
Скомпоновать библиотеку довольно просто – пишем обычный ЕХЕ, только в шапке указываем директиву «format PE DLL» . В результате, из выхлопной трубы fasm’a получим файл в формате *.dll. Однако при программировании пользовательских библиотек нужно учитывать ряд их особенностей, в частности релокацию образа в памяти.
Чтобы DLL не загрузилась поверх исполняемого приложения (конфликт базовых адресов), её ImageBase обязательно должна быть перемещаемой – достаточно добавить секцию .reloc в коде, об остальном компилятор позаботится сам. В этой секции будут собраны т.н. фиксапы (fixups) – адреса, к которым загрузчик должен будет внести поправки. Фиксапы применяются исключительно к инструкциям, которые обращаются по абсолютным адресам в памяти. Если адрес относительный (в пределах 127 байт), то он не требует модификации:
Такие отладчики как OllyDbg подчёркивают адреса, которые требуют коррекции после перемещения образа в памяти – на рис.выше их всего 4, и непосредственно опкод инструкции не учитывается (здесь pushcall, хотя могут быть и условныебезусловные переходы). Размер самих фиксапов равен 12-бит (выделены красным), а это 2^12=4096 или одна страница виртуальной памяти. Соответственно фиксап не может адресовать блок памяти свыше 4 Кбайт. Другими словами, каждая страница (блок) имеет свой набор фиксов.
Точка входа в DLL-библиотеку
Теперь о насущном..
Подобно исполняемым экзе-приложениям, библиотеки тоже имеют свою точку входа – в доках MSDN эта функция известна как DllEntryPoint() (или DllMain в терминологии си). Здесь и кроется всё самое интересное, чему мы посвятим весь последующий разговор.
Любое обращение EXE-модуля к функциям из DLL происходит через системного посредника LdrLoadDLL() . В системном ансамбле, эта кошерная функция из Ntdll.dll играет огромную роль. Она не только загружает библиотеки в пространство юзера на этапе проецирования образа в память, но и обслуживает функции динамического вызова процедур типа LoadLibrary() , GetModuleHandle() и прочии, от которых мы ожидаем получить дескрипторы модулей. Вот её прототип:
LdrLoadDll( PathToFile ;// путь (опционально); Flags ;// флаги (опционально); ModuleFileName ;// имя библиотеки; ModuleHandle ) ;// возвращаемый дескриптор.
Диалог этого загрузчика с вызываемой библиотекой происходит по схеме «запрос-ответ». Любая библиотека должна иметь упомянутую функцию взаимодействия с загрузчиком DllEntryPoint() , от которой в регистре EAX лоадер ждёт или TRUE (библиотека способна обработать запрос), или FALSE (что-то пошло не так). Не соблюдение этих правил приводит к краху приложения.
LdrLoadDLL() может извещать библиотеку о четырёх событиях, которые происходят во-внешнем (по отношению к библиотеке) мире. Эта информация передаётся точке-входа в DLL в параметре fdwReason . Кроме события, загрузчик сразу передаёт либе её базу в памяти, и способ подключения к исполняемому файлу. Прототип описывается так:
BOOL DllEntryPoint ( hinstDLL ;// виртуальная база данной библиотеки в памяти; fdwReason ;// причина вызова; lpvReserved ); ;// способ подключения: статический(0), или динамический(1). ;// ..(статический = явно, динамический = не явно) ;// Возможные значения «fdwReason» ;//——————————- • DLL_PROCESS_DETACH (0) – FreeLibrary() или DLL отключается от процесса, • DLL_PROCESS_ATTACH (1) – первое подключении DLL к процессу, при его запуске, • DLL_THREAD_ATTACH (2) — процесс создаёт новый поток, • DLL_THREAD_DETACH (3) — процесс завершает поток.
Из всей этой братии, нам интересен лишь аргумент DLL_PROCESS_ATTACH = 1 , благодаря которому статически присобачив библиотеку к нашему процессу, мы можем например, предварительно расшифровать основной код программы, обнаружить отладчик в фоне и т.д. Дело в том, что загрузчик проецирует DLL в пространство процесса задолго до точки-входа в программу, с которой начинают анализ все отладчики, а значит Оля пропустит этот этап между ног. Здесь уместно вспомнить про функции TLS-Callback , ..но поскольку загрузчик парсит импорт из библиотек вторым (а TLS аж десятым), то выигрыш тут на лицо.
DLL – промышленная реализация
Чтобы сформировать образ, приведём код типичной библиотеки. Пока она будет выводить на экран только сообщения об удачном подсоединению к родительскому процессу, а после его закрытия – покажет ещё одну мессагу, что мол родительский процесс отработал и отправляется на покой. Когда приложение вызывает библиотеку, в её стеке оказывается фрейм из трёх (не считая адреса-возврата) аргументов функции DllEntryPoint() , которые загрузчик кладёт туда на всеобщее обозрение – так это выглядит в отладчике:
Соответственно, мы можем снимать эти аргументы прямо со-стека, и сразу проверять их – код ниже придерживается именно такой политики:
Теперь у нас есть либа, и нужно написать родительское приложение, которое будет статически привязывать к себе эту библиотеку. Во-первых, обратим внимание на имя новоиспечённой DLL – здесь, в секции-экспорта я определил его как «about.dll», это важно! Теперь просто импортируем эту библиотеку по имени, и вызываем из неё функцию примерно так:
format pe console include ‘win32ax.inc’ entry start ;//—— .data frmt db ‘%s’,0 ;//—— .code start: cinvoke Hello ;// зовём функцию из about.dll . cinvoke scanf,frmt,frmt+2 ;// ждём клаву.. cinvoke exit,0 ;// Game Over! ;//—— section ‘.idata’ import data readable library msv,’msvcrt.dll’, about,’about.dll’ ;// указать точное имя DLL! import msv, scanf,’scanf’,exit,’exit’ import about, Hello,’Hello’
Тёмная сторона луны
Пробежавшись по макушкам кода библиотек, посмотрим на них из другой проекции..
Алгоритм работы загрузчика образов LDR плохо освещён в документации и это не удивительно – весь ядерный код мастдая, коммерческая тайна (будь она не ладна). Как это принято у Microsoft, она советует нам ознакомиться с третьей поправкой, восьмого исправления, четвёртой редакции от 32 февраля где сказано, что «..в военное время не только прямой угол может достигть 100 градусов, но и функция инициализации DllEntryPoint() может использоваться не по назначению». Самое главное: кто, где и когда объявляет это положение неизвестно, а значит мы вольны назначать его сами.
Мощь (и беспомощность) точки-входа в библиотеку в том, что некоторая часть театра действий происходит под управлением системных механизмов, отследить которые из прикладного уровня довольно сложно. В документации на РЕ-файл можно найти формат каталога секций «Data-Directories» . В этом дире рассчитавшись на первый-второй выстроены в ряд все секции, которые обходит загрузчик образов LdrLoadDll() при инициализации приложения. Причём последовательность секций строго регламентируется. Вот как выглядит эта структура в представлении редактора PE-Explorer:
Таким образом, импорт анализируется загрузчиком на самом начальном этапе, и большинство служебных структур прикладного уровня в этот момент даже не инициализированы ещё до конца – в частности, это относится к структуре PEB , не говоря уже о дочерней к ней структуре ТЕВ. Например, если мы внутри DllEntryPoint() захотим из РЕВ получить флаг-отладки нашего приложения «BeingDebugger» , то потерпим фиаско (проверено на практике). На скамейку запасных сразу отправляется и функция IsDebuggerPresent() , которая читает этот-же флаг из РЕВ. Значит нужно спускаться на уровень ниже, а для защитных механизмов это только гуд.
Если развивать мысль дальше, то наша библиотека не единственная у приложения. Кроме неё, в память каждого процесса система загружает и свои либы Ntdll.dll (собственно в ней и живёт загрузчик LDR), а так-же библиотеку kernel32.dll. С очерёдностью загрузки в память системных библиотек можно ознакомится в отладчике WinDbg, озадачив его командой !peb – поле InMemoryOrderModuleList как-раз отрапортует нам об этом:
Здесь видно, что первым десантируется в память мой исполняемый файл «DLL_attach.exe», следом за ним системные библиотеки, и только потом моя пользовательская либа «about.dll». Повторюсь, что система выстраивает структуру РЕВ только когда окончательно покончит с окружением процесса, скидывая в неё результаты проделанной работы. А лог на рисунке выше, WinDbg парсит уже из рабочего процесса, поэтому РЕВ как-бы готова к употреблению.
DllEntryPoint() на страже приложения
Теперь будем мыслить так.. Если точка-входа в библиотеку с аргументом DLL_PROCESS_ATTACH отрабатывает на низком уровне, значит на её основе можно соорудить защитный механизм. Система вызывает DllEntryPoint() с аргументом ATTACH сразу после того-как DLL спроецирована на адресное пространство процесса – такая ситуация возможна всего один раз, и на протяжении всего «сеанса» больше не повторяется! В следующий раз, когда тред вызовет LoadLibrary() для уже спроецированной на память DLL, система просто увеличит счётчик обращения к ней и всё.
В предоставленном на суд примере, статически (явно) прилинкованная библиотека внутри DllEntryPoint() будет искать отладчик, и если обнаружит таковой, то вернёт ошибку. Как упоминалось выше, флаги-отладки из структуры РЕВ для этих целей уже не подходят, поэтому придётся искать обходные пути.
Одним из вариантов обнаружения факта отладки является проверка своего статуса в системе. Дело в том, что в дефолте, запущенный на исполнение процесс не имеет привилегии SeDebugPrivilege, зато ею обладает отладчик. Когда он загружает нас в своё тело, то автоматом передаёт и свою привилегию, чекнув которую мы можем определить этот факт. Есть куча способов узнать привилегию своего процесса, и мы воспользуемся самым простым – попытаемся открыть системный процесс csrss.exe.
CSRSS.EXE – это часть пользовательской подсистемы Win32, и при обычных обстоятельствах он не доступен прикладным задачам. Однако привилегия Debug снимает этот запрет, и мы можем открыть его функцией OpenProcess() со-всеми вытекающими последствиями. CSRSS (clientserver run-time subsystem) отвечает за консоль, работу с потоками Thread, и за 16-битную среду MS-DOS (на х64 её кастрировали). Это процесс пользовательского режима, который перехватывает обращения к ядру и решает простые вопросы на уровне прикладных задач.
Проблема в том, что функции OpenProcess() требуется идентификатор PID открываемого процесса, т.е. нам нужно будет просканировать всю память и найти нужный процесс по его имени – тривиальная задача по обнаружению отладчика превращается в ад. В сети можно встретить разные варианты перечисления процессов – это CreateToolhelp32Snapshot() , обход в цикле через Process32FirstNext() , EnumProcess() и тяжеловес NtQuerySystemInformation() .
Однако получить PID именно процесса CSRSS.EXE можно специально предназначенной для этого функцией из Ntdll.dll под названием CsrGetProcessId() – у неё нет аргументов и в EAX она сразу возвращает столь необходимый нам PID. С использованием этой функции, проверка на отладчик укладывается в пару строк ассемблерного кода. Мы поместим её внутрь DllEntryPoint() и будем проверять запрос на DLL_PROCESS_ATTACH .
В общем случае, программа будет следовать такому алго..
Мы пишем приложение, которое запрашивает пароль. Если юзер введёт валидный пасс, то управление примет зашифрованная функция, которую расшифрует декриптор из внешней библиотеки, с непримечальным именем «about.dll». Алгоритм декриптора – самый примитивный ксор 1-байтныйм ключом, однако тут есть подвох! Пароль на валидность мы вообще не будем проверять, а декриптор сняв с него хэш-сумму сразу расшифрует ей критический блок в основном приложении. Теперь уже взломщик не сможет просто обратить условие проверки, и ему придётся осуществлять только брут, перебором всех возможных ключей.
Если юзер подсунет левый пароль и его хэш не совпадёт с тем, которым мы зашифровали блок, то рано или поздно процессор нарвётся на исключение , поскольку пойдёт пахать зашифрованный код. Чтобы защитить честь его мундира, для таких случаев мы устанавливаем SEH-обработчик, который и будет отлавливать эти исключения. То-есть, если SEH примет управление, значит пасс невалидный и мы подкорректировав значение регистра EIP в контексте, выводим мессагу Wrong и на выход..
Основная проблема тут – правильно зашифровать критический блок кода в основном приложении. Я уже приводил пример шифрования в hex-редакторе HIEW, поэтому повторяться не буду. Если возникнут вопросы, их всегда можно задать в комментах этой темы. Ключ – это сумма всех символов любой строки. Например, в данном случае я использовал пароль «codeby.net» и получил его 1-байтную хэш сумму = 0xEB . Для этого можно воспользоваться услугами редактора HxD и виндовым калькулятором:
После того-как получим хэш валидного пассворда, можно приступать к шифрованию всего блока этим ключом. Если на запрос юзер введёт валидный пасс, то функция декриптора в библиотеке рассчитает его хэш на автомате, и опять проксорит этим-же клюсом – в результате получим расшифрованный блок, и процессор не споткнётся уже об него. Ниже приведён готовый к употреблению код, который остаётся только скомпилировать, и в основном приложении зашифровать указанный блок:
Код основного приложения:
Теперь код библиотеки, которую обязательно нужно назвать «about.dll».
Для разминки мозгов, в скрепке предлагаю построенный на этом алгоритме крэкми. Здесь нужен брутом найти пароль, и чтобы он не занимал много времени, длина ключа такая-же 1-байт. Без проблем можно было увеличить его разрядность хоть до 4-х байт, однако сути это не меняет.. просто дольше нужно будет подбирать. Всех с наступающим 0х07E4 .
Источник: codeby.net
Библиотеки динамической линковки DLL
Библиотеки динамической линковки DLL, структура и использование DLL (англ. Dynamic-link library — динамически подключаемая библиотека) — понятие операционных систем Microsoft Windows и IBM OS/2; динамическая библиотека, позволяющая многократное применение различными программными приложениями. K DLL относятся также элементы управления ActiveX и драйверы.
В мире UNIX аналогичные функции выполняют т. н. shared objects («разделяемые объекты»). Понятие DLL Чем же отличаются Dynamic Link Library (DLL) от обычных приложений? Для понимания этого требуется уточнить понятия задачи (task), экземпляра (копии) приложения (instance) и модуля (module).
При запуске нескольких экземпляров одного приложения, Windows загружает в оперативную память только одну копию кода и ресурсов — модуль приложения, создавая несколько отдельных сегментов данных, стека и очереди сообщений (см. рис. 3), каждый набор которых представляет из себя задачу, в понимании Windows. Копия приложения представляет из себя контекст, в котором выполняется модуль приложения. Задача 1 Задача 2 Копия 1 приложения Копия 2 приложения Данные Данные Стек Стек
Рекомендуемые материалы
Вариант 11 — ЛР №10 — Программирование с использованием библиотеки Qt
Объектно-ориентированное программирование (ООП)
Вариант 24 — ЛР №9 — Программирование с использованием библиотеки Qt
Объектно-ориентированное программирование (ООП)
Вариант 1 — ЛР №9 — Программирование с использованием библиотеки Qt
Объектно-ориентированное программирование (ООП)
Отчет по лабораторной работе №9 «Программирование с использованием библиотеки Qt» (вариант №1)
Объектно-ориентированное программирование (ООП)
Отчет по лабораторной работе №9 «Программирование с использованием библиотеки Qt» (вариант №1)
Объектно-ориентированное программирование (ООП)
Вариант 5 — ЛР №8 — Программирование с использованием динамической памяти
Информатика
Очередь сообщений Очередь сообщений Модуль приложения Код Ресурсы Рис.3 : Копии приложения и модуль приложения DLL — библиотека также является модулем. Она находится в памяти в единственном экземпляре и содержит сегмент кода и ресурсы, а также сегмент данных (см. рис. 4).
DLL-библиотека Код Ресурсы Данные Рис.4 : Структура DLL в памяти DLL — библиотека, в отличие от приложения не имеет ни стека, ни очереди сообщений. Функции, помещенные в DLL, выполняются в контексте вызвавшего приложения, пользуясь его стеком. Но эти же функции используют сегмент данных, принадлежащий библиотеке, а не копии приложения.
В силу такой организации DLL, экономия памяти достигается за счет того, что все запущенные приложения используют один модуль DLL, не включая те или иные стандартные функции в состав своих модулей. Часто, в виде DLL создаются отдельные наборы функций, объединенные по тем или иным логическим признакам, аналогично тому, как концептуально происходит планирование модулей ( в смысле unit ) в Pascal.
Отличие заключается в том, что функции из модулей Pascal компонуются статически — на этапе линковки, а функции из DLL компонуются динамически, то есть в run-time. 3.3. Структура DLL-библиотеки DLL-библиотека состоит из нескольких специфических функций и произвольного набора функций, выполняющих ту работу, для которой разрабатывалась данная библиотека.
Как мы уже говорили, DLL-библиотека может иметь (а может и не иметь) сегмент данных и ресурсы. В заголовке загрузочного модуля DLL-библиотеки описаны экспортируемые точки входа, соответствующие всем или некоторым определенным в ней функциям. Приложения могут вызывать только те функции DLL-библиотеки, которые экспортируются ей.
Функция LibEntry До тех пор, пока ни одно из приложений не затребовало функцию из DLL-библиотеки, сама библиотека находится в файле на диске. В оперативной памяти ее нет. Однако как только приложение затребует функцию из DLL-библиотеки или загрузит библиотеку в память явным образом, начнется процесс инициализации библиотеки.
Этот процесс выполняется только один раз, так как в памяти может находиться только одна копия DLL-библиотеки. В процессе инициализации после загрузки библиотеки в память Windows вызывает функцию LibEntry , которая должна быть определена в каждой DLL-библиотеке. Можно считать, что функция LibEntry является точкой входа библиотеки, получающей управление при загрузке библиотеки в память.
Задачей функции LibEntry является инициализация локальной области памяти, если она определена для DLL-библиотеки. Функция LibEntry должна быть дальней функцией, составленной на языке ассемблера, так как она получает параметры через регистры процессора. Перечислим и опишем параметры, передаваемые функции LibEntry при загрузке DLL-библиотеки в память.
Вам не надо определять функцию LibEntry самостоятельно, так как при создании файла DLL-библиотеки редактор связей, входящий в систему разработки, включит уже имеющийся в стандартной библиотеке модуль. Этот стандартный модуль выполняет всю необходимую работу по инициализации локальной области памяти DLL-библиотеки (с помощью функции LocalInit) и затем вызывает функцию LibMain, которая будет описана в следующем разделе.
Иногда для DLL-библиотеки может потребоваться нестандартная инициализация. Только в этом случае вам придется разработать функцию LibEntry самостоятельно. За основу вы можете взять файл libentry.asm из SDK, который содержит исходный текст упомянутой выше функции. Функция LibMain Функция LibMain должна присутствовать в каждой стандартной DLL-библиотеке.
Эту функцию вам надо определить самостоятельно, причем вы можете воспользоваться языком программирования С. По своему назначению функция LibMain напоминает функцию WinMain обычного приложения Windows. Функция WinMain получает управление при запуске приложения, а функция LibMain — при загрузке DLL-библиотеки в память.
Так же как и функция WinMain, функция LibMain имеет параметры, которые можно использовать для инициализации библиотеки. Если инициализация DLL-библиотеки выполнена успешно, функция LibMain должна возвратить ненулевое значение. Если в процессе инициализации произошла ошибка, следует возвратить нуль. В этом случае функция LibEntry также возвратит нуль.
Это приведет к тому, что Windows выгрузит библиотеку из памяти. Разрабатывая процедуру инициализации DLL-библиотеки, учтите, что функция LibMain вызывается только один раз, во время загрузки библиотеки в память. Не следует думать, что для каждого приложения, использующего одну и ту же DLL-библиотеку, будет вызвана функция LibMain.
При попытке повторной загрузки уже загруженной ранее DLL-библиотеки будет увеличено содержимое счетчика использования библиотеки, но и только. Если для каждого приложения в локальной области данных DLL-библиотеки необходимо выделять отдельные структуры данных, вам придется разработать собственную процедуру регистрации приложения.
Например, можно создать специальную функцию регистрации LibRegister, которая возвращает приложению указатель на выделенную для него в локальной области структуру данных. Вызывая функции из DLL-библиотеки, приложение передает им в качестве, например, первого параметра, этот указатель.
Перед завершением работы приложение должно вызвать созданную вами функцию, освобождающую выделенную структуру данных. Она может называться, например, LibUnregister. Если функция LibMain заказывает блоки памяти из глобальной области данных, следует использовать флаг GMEM_SHARE. Такие блоки памяти будут принадлежать создавшей их DLL-библиотеке.
Освобождение заказанных глобальных блоков памяти можно выполнить в функции WEP, получающей управление при выгрузке DLL-библиотеки из памяти. В лекции «Защита от ошибок в сетях» также много полезной информации. Функция WEP DLL-библиотека в любой момент времени может быть выгружена из памяти.
В этом случае Windows перед выгрузкой вызывает функцию WEP . Эта функция, как и функция LibMain, вызывается только один раз. Она может быть использована для уничтожения структур данных и освобождения блоков памяти, заказанных при инициализации DLL-библиотеки. Приведем прототип функции WEP (при использовании системы разработки Borland Turbo C++ for Windows): int FAR PASCAL WEP(int bSystemExit); Параметр bSystemExit может принимать значения WEP_FREE_DLL и WEP_SYSTEM_EXIT . Этот параметр указывает причину выгрузки DLL-библиотеки из памяти. В первом случае выгрузка выполняется потому, что либо функциями библиотеки не пользуется ни одно приложение, либо одно из приложений выдало запрос на выгрузку. Если же параметр имеет значение WEP_SYSTEM_EXIT, выгрузка библиотеки происходит из-за завершения работы операционной системы Windows. Функция WEP должна всегда возвращать значение 1.
Поделитесь ссылкой:
Рекомендуемые лекции
- Доходная часть бюджета
- Защита от ошибок в сетях
- Типы, размер в байтах, экстремальные значения
- Эхокардиографические измерения
- 1. Основные понятия автоматизации управления
Свежие статьи
![]()
Обзор программы Экранная Студия. Как записать видео с экрана
![]()
Как и где студенту составить резюме?
![]()
Правила оформления презентации для студентов в 2023 году
![]()
С Новым 2023 годом!
![]()
Как студенту выбрать ноутбук и принтер?
Источник: studizba.com