Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование для Windows NT

© Александр Фролов, Григорий Фролов
Том 27, часть 2, М.: Диалог-МИФИ, 1996, 272 стр.

[Назад] [Содеожание] [Дальше]

Как работает DLL-библиотека

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

В процессе инициализации после загрузки 16-разрядной DLL-библиотеки в память Windows версии 3.1 вызывает функцию LibEntry, которая должна быть определена в каждой DLL-библиотеке. Задачей функции LibEntry является инициализация локальной области памяти, если она определена для DLL-библиотеки.

Функция LibEntry должна быть дальней функцией, составленной на языке ассемблера, так как она получает параметры через регистры процессора. Мы подробно описали функцию LibEntry и ее параметры в 13 томе “Библиотеки системного программиста”. Заметим, что использование языка ассемблера затрудняет создание мультиплатформных приложенй, поэтому в мультиплатформной операционной системе Microsoft Windows NT используется другой способ инициализации.

Создавая 16-разрядную DLL-библиотеку, вам не надо определять функцию LibEntry самостоятельно, так как при создании файла DLL-библиотеки редактор связей, входящий в систему разработки, включит уже имеющийся в стандартной библиотеке модуль. Этот стандартный модуль выполняет всю необходимую работу по инициализации локальной области памяти DLL-библиотеки (с помощью функции LocalInit) и затем вызывает функцию LibMain.

Функция LibMain должна присутствовать в каждой 16-разрядной DLL-библиотеке. Эту функцию надо определить самостоятельно, причем вы можете воспользоваться языком программирования С.

По своему назначению функция LibMain напоминает функцию WinMain обычного приложения Windows. Функция WinMain получает управление при запуске приложения, а функция LibMain - при первой загрузке DLL-библиотеки в память. Так же как и функция WinMain, функция LibMain имеет параметры, которые можно использовать для инициализации библиотеки.

Прототип функции LibMain и ее параметры были описаны в 13 томе “Библиотеки системного программиста”.

Другая функция, которая присутствует в каждой 16-разрядной DLL-библиотеке, это функция WEP.

В среде Microsoft Windows версии 3.1 DLL-библиотека в любой момент времени может быть выгружена из памяти. В этом случае Windows перед выгрузкой вызывает функцию WEPXE. Эта функция, как и функция LibMain, вызывается только один раз. Она может быть использована для уничтожения структур данных и освобождения блоков памяти, заказанных при инициализации DLL-библиотеки.

Вам не обязательно самостоятельно определять функцию WEP. Так же как и функция LibEntry, функция WEP добавляется в 16-разрядную DLL-библиотеку транслятором.

Что же касается 32-разрядных DLL-библиотек операционной системы Microsoft Windows NT, то их инициализация и выгрузка из памяти происходит иначе.

Инициализация DLL-библиотеки в среде Microsoft Windows NT

В 32-разрядных DLL-библиотеках операционной системы Microsoft Windows NT вместо функций LibMain и WEP используется одна функция DLLEntryPoint, которая выполняет все необходимые задачи по инициализации библиотеки и при необходимости освобождает заказанные ранее ресурсы (имя функции инициализации может быть любым).

Функции LibMain и WEP вызываются только один раз при загрузке библиотеки в память и при ее выгрузке. В отличие от них, функция DLLEntryPoint вызывается всякий раз, когда выполняется инициализация процесса или задачи, обращающихся к функциям библиотеки, а также при явной загрузке и выгрузке библиотеки функциями LoadLibrary XE "LoadLibrary" и FreeLibrary XE "FreeLibrary" .

Ниже мы привели прототип функции DLLEntryPoint:


BOOL WINAPI DllEntryPoint(
  HINSTANCE hinstDLL,  // идентификатор модуля DLL-библиотеки 
  DWORD     fdwReason, // код причины вызова функции 
  LPVOID    lpvReserved); // зарезервировано 

Через параметр hinstDLL функции DLLEntryPoint передается идентификатор модуля DLL-библиотеки, который можно использовать при обращении к ресурсам, расположенным в файле этой библиотеки.

Что же касается параметра fdwReason, то он зависит от причины, по которой произошел вызов функции DLLEntryPoint. Этот параметр может принимать следующие значения:

 Значение

 Описание

 DLL_PROCESS_ATTACH

 Библиотека отображается в адресное пространство процесса в результате запуска процесса или вызова функции LoadLibrary

 DLL_THREAD_ATTACH

 Текущий процесс создал новую задачу, после чего система вызывает функции DLLEntryPoint всех DLL-библиотек, подключенных к процессу

 DLL_THREAD_DETACH

 Этот код причины передается функции DLLEntryPoint, когда задача завершает свою работу нормальным (не аварийным) способом

 DLL_PROCESS_DETACH

 Отображение DLL‑библиотеки в адресное пространство отменяется в результате нормального завершения процесса или вызова функции FreeLibrary

Параметр lpvReserved зарезервирован. В SDK, тем не менее, сказано, что значение параметра lpvReserved равно NULL во всех случаях, кроме двух следующих:

·       когда параметр fdwReason равен DLL_PROCESS_ATTACH и используется статическая загрузка DLL-библиотеки;

·       когда параметр fdwReason равен DLL_PROCESS_DETACH и функция DLLEntryPoint вызвана в результате завершения процесса, а не вызова функции FreeLibrary

В процессе инициализации функция DLLEntryPoint может отменить загрузку DLL-библиотеки. Если код причины вызова равен DLL_PROCESS_ATTACH, функция DLLEntryPoint отменяет загрузку библиотеки, возвращая значение FALSE. Если же инициализация выполнена успешно, функция должна возвратить значение TRUE.

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

Приведем пример функции инициализации DLL-библиотеки:


BOOL WINAPI DLLEntryPoint(
  HMODULE hModule,    // идентификатор модуля
  DWORD   fdwReason,  // причина вызова функции DLLEntryPoint
  LPVOID  lpvReserved)// зарезервировано
{
  switch(fdwReason)
  {
    // Подключение нового процесса
    case DLL_PROCESS_ATTACH:
    {
      // Обработка подключения процесса
      . . .
      break;
    }

    // Подключение новой задачи
    case DLL_THREAD_ATTACH:
    {
      // Обработка подключения новой задачи
      . . .
      break;
    }

    // Отключение процесса
    case DLL_PROCESS_DETACH:
    {
       // Обработка отключения процесса
       . . .
       break;
    }

    // Отключение задачи
    case DLL_THREAD_DETACH:
    {
      // Обработка отключения задачи
      . . .
      break;
    }
  }
  return TRUE;
}

Экспортирование функций и глобальных переменных

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

Кроме функций LibMain и WEP в 16-разрядных DLL-библиотеках операционной системы Microsoft Windows версии 3.1 и функции DLLEntryPoint в 32-разрядных библиотеках операционных систем Microsoft Windows NT и Microsoft Windows 95 могут быть определены экспортируемые и неэкспортируемые функции.

Экспортируемые функции доступны для вызова приложениям Windows. Неэкспортируемые являются локальными для DLL-библиотеки, они доступны только для функций библиотеки.

При необходимости вы можете экспортировать из 32-разрядных DLL-библиотек не только функции, но и глобальные переменные.

Самый простой способ сделать функцию экспортируемой - перечислить все экспортируемые функции в файле определения модуля при помощи оператора EXPORTSXE:


EXPORTS
  ИмяТочкиВхода [=ВнутрИмя] [@Номер] [NONAME] [CONSTANT]
    . . .

Здесь ИмяТочкиВхода задает имя, под которым экспортируемая из DLL-библиотеки функция будет доступна для вызова.

Внутри DLL-библиотеки эта функция может иметь другое имя. В этом случае необходимо указать ее внутреннее имя ВнутрИмя.

С помощью параметра @Номер вы можете задать порядковый номер экспортируемой функции.

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

Заметим, что ссылка на экспортируемую функцию может выполняться двумя различными способами - по имени функции и по ее порядковому номеру. Если функция вызывается по имени, ее порядковый номер не имеет значения. Однако вызов функции по порядковому номеру выполняется быстрее, поэтому использование порядковых номеров предпочтительнее.

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

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

Флаг CONSTANT позволяет экспортировать из DLL-библиотеки не только функции, но и данные. При этом параметр ИмяТочкиВхода задает имя экспортируемой глобальной переменной, определенной в DLL-библиотеке.

Приведем пример экспортирования функций и глобальных переменных из DLL-библиотеки:


EXPORTS
  DrawBitmap=MyDraw  @4
  ShowAll     
  HideAll
  MyPoolPtr   @5 CONSTANT
  GetMyPool   @8 NONAME
  FreeMyPool  @9 NONAME

В приведенном выше примере в разделе EXPORTS перечислены имена нескольких экспортируемых функций DrawBitmap, ShowAll, HideAll, GetMyPool, FreeMyPool и глобальной переменной MyPoolPtr.

Функция MyDraw, определенная в DLL-библиотеке, экспортируется под именем DrawBitmap. Она также доступна под номером 4.

Функции ShowAll и HideAll экспортируются под своими “настоящими” именами, с которыми они определены в DLL-библиотеке. Для них не заданы порядковые номера.

Функции GetMyPool и FreeMyPool экспортируются с флагом NONAME, поэтому к ним можно обращаться только по их порядковым номерам, которые равны, соответственно, 8 и 9.

Имя MyPoolPtr экспортируется с флагом CONSTANT, поэтому оно является именем глобальной переменной, определенной в DLL-библиотеке, и доступной для приложений, загружающих эту библиотеку.

Импортирование функций

Когда вы используете статическую компоновку, то включаете в файл проекта приложения соответствующий lib-файл, содержащий нужную вам библиотеку объектных модулей. Такая библиотека содержит исполняемый код модулей, который на этапе статической компоновки включается в exe-файл загрузочного модуля.

Если используется динамическая компоновка, в загрузочный exe-файл приложения записывается не исполнимый код функций, а ссылка на соответствующую DLL-библиотеку и функцию внутри нее. Как мы уже говорили, эта ссылка может быть организована с использованием либо имени функции, либо ее порядкового номера в DLL-библиотеке.

Откуда при компоновке приложения редактор связей узнает имя DLL-библиотеки, имя или порядковый номер экспортируемой функции? Для динамической компоновки функции из DLL-библиотеки можно использовать различные способы.

Библиотека импорта

Для того чтобы редактор связей мог создать ссылку, в файл проекта приложения вы должны включить так называемую библиотеку импорта (import library). Эта библиотека создается автоматически системой разработки Microsoft Visual C++.

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

Динамический импорт функций во время выполнения приложения

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

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

Однако приложение может в любой момент времени загрузить любую DLL-библиотеку, вызвав специально предназначенную для этого функцию программного интерфейса Windows с именем LoadLibrary. Приведем ее прототип:


HINSTANCE WINAPI LoadLibrary(LPCSTR lpszLibFileName);

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

·       каталог, из которого запущено приложение;

·       текущий каталог;

·       32-разрядный системный каталог Microsoft Windows NT;

·       16-разрядный системный каталог;

·       каталог в котором находится операционная система Windows NT;

·       каталоги, перечисленные в переменной описания среды PATH

Если файл DLL-библиотеки найден, функция LoadLibrary возвращает идентификатор модуля библиотеки. В противном случае возвращается значение NULL. При этом код ошибки можно получить при помощи функции GetLastError.

Функция LoadLibrary может быть вызвана разными приложениями для одной и той же DLL-библиотеки несколько раз. В этом случае в среде операционной системы Microsoft Windows версии 3.1 загрузка DLL-библиотеки выполняется только один раз. Последующие вызовы функции LoadLibrary приводят только к увеличению счетчика использования DLL-библиотеки. Что же касается Microsoft Windows NT, то при многократном вызове функции LoadLibrary различными процессами функция инициализации DLL-библиотеки получает несколько раз управление с кодом причины вызова, равным значению DLL_PROCESS_ATTACH.

В качестве примера приведем фрагмент исходного текста приложения, загружающего DLL-библиотеку из файла DLLDEMO.DLL:


typedef HWND (WINAPI *MYDLLPROC)(LPSTR);
MYDLLPROC    GetAppWindow;
HANDLE       hDLL;

hDLL = LoadLibrary("DLLDEMO.DLL");
if(hDLL != NULL)
{
  GetAppWindow = (MYDLLPROC)GetProcAddress(hDLL, 
    "FindApplicationWindow");
  if(GetAppWindow != NULL)
  {
    if(GetAppWindow(szWindowTitle) != NULL)
      MessageBox(NULL, "Application window was found",
        szAppTitle, MB_OK | MB_ICONINFORMATION);
    else
      MessageBox(NULL, "Application window was not found",
        szAppTitle, MB_OK | MB_ICONINFORMATION);
  }
  FreeLibrary(hDLL);
}

Здесь вначале с помощью функции LoadLibrary выполняется попытка загрузки DLL-библиотеки DLLDEMO.DLL. В случае успеха приложение получает адрес точки входа для функции с именем FindApplicationWindow, для чего используется функция GetProcAddress XE "GetProcAddress" . Этой функцией мы займемся немного позже.

Если точка входа получена, функция вызывается через указатель GetAppWindow.

После использования DLL-библиотека освобождается при помощи функции FreeLibrary, прототип который показан ниже:


void WINAPI FreeLibrary(HINSTANCE hLibrary);

В качестве параметра этой функции следует передать идентификатор освобождаемой библиотеки.

При освобождении DLL-библиотеки ее счетчик использования уменьшается. Если этот счетчик становится равным нулю (что происходит, когда все приложения, работавшие с библиотекой, освободили ее или завершили свою работу), DLL-библиотека выгружается из памяти.

Каждый раз при освобождении DLL-библиотеки вызывается функция DLLEntryPoint с параметрами DLL_PROCESS_DETACH или DLL_THREAD_DETACH, выполняющая все необходимые завершающие действия.

Теперь о функции GetProcAddress.

Для того чтобы вызвать функцию из библиотеки, зная ее идентификатор, необходимо получить значение дальнего указателя на эту функцию, вызвав функцию GetProcAddress:


FARPROC WINAPI GetProcAddress(HINSTANCE hLibrary, 
  LPCSTR lpszProcName);

Через параметр hLibrary вы должны передать функции идентификатор DLL-библиотеки, полученный ранее от функции LoadLibrary.

Параметр lpszProcName является дальним указателем на строку, содержащую имя функции или ее порядковый номер, преобразованный макрокомандой MAKEINTRESOURCE.

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


FARPROC lpMsg;
FARPROC lpTellMe;
lpMsg = GetProcAddress(hLib, "Msg");
lpTellMe = GetProcAddress(hLib, MAKEINTRESOURCE(8));

Перед тем как передать управление функции по полученному адресу, следует убедиться в том, что этот адрес не равен NULL:


if(lpMsg != (FARPROC)NULL)
{
  (*lpMsg)((LPSTR)"My message");
}

Для того чтобы включить механизм проверки типов передаваемых параметров, вы можете определить свой тип - указатель на функцию, и затем использовать его для преобразования типа адреса, полученного от функции GetProcAddress:


typedef int (PASCAL *LPGETZ)(int x, int y);
LPGETZ lpGetZ;
lpGetZ = (LPGETZ)GetProcAddress(hLib, "GetZ");

А что произойдет, если приложение при помощи функции LoadLibrary попытается загрузить DLL-библиотеку, которой нет на диске?

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

Для того чтобы отключить режим вывода диалоговой панели с сообщением о невозможности загрузки DLL-библиотеки, вы можете использовать функцию SetErrorMode, передав ей в качестве параметра значение SEM_FAILCRITICALERRORS:


UINT nPrevErrorMode;
nPrevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
hDLL = LoadLibrary("DLLDEMO.DLL");
if(hDLL != NULL)
{
  // Работа с DLL-библиотекой
  . . .
}
SetErrorMode(nPrevErrorMode);

Приведем прототип функции SetErrorMode:


UINT WINAPI SetErrorMode(UINT fuErrorMode);

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

 Значение

 Описание

 SEM_FAILCRITICALERRORS

 Операционная система Microsoft Windows NT не выводит на экран сообщения обработчика критических ошибок, возвращая приложению соответствующий код ошибки

 SEM_NOGPFAULTERRORBOX

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

 SEM_NOOPENFILEERRORBOX

 Если Microsoft Windows NT не может открыть файл, на экран не выводится диалоговая панель с сообщением об ошибке

Функция SetErrorMode возвращает предыдущий режим обработки ошибки.

Файл определения модуля для DLL-библиотеки

Файл определения модуля для DLL-библиотекиотличается от соответствующего файла обычного приложения Windows. В качестве примера приведем образец такого файла:


LIBRARY     DLLNAME
DESCRIPTION 'DLL-библиотека DLLNAME'
EXPORTS
DrawBitmap=MyDraw  @4
  ShowAll     
  HideAll
  MyPoolPtr   @5 CONSTANT
  GetMyPool   @8 NONAME
  FreeMyPool  @9 NONAME

В файле определения модуля DLL-библиотеки вместо оператора NAME должен находиться оператор LIBRARYXE , определяющий имя модуля DLL-библиотеки, под которым она будет известна Windows. Однако формат строк файла описания модуля зависит от используемой системы разработки. Например, если вы создаете DLL-библиотеку при помощи Microsoft Visual C++ версии 4.0, оператор LIBRARY можно не указывать.

Анализ DLL-библиотек при помощи программы dumpbin.exe

В комплекте системы разработки Microsoft Visual C++ входит программа dumpbin.exe, предназначенная для запуска из командной строки. С помощью этой утилиты вы сможете проанализировать содержимое любого загрузочного файла в формате COFF, в том числе DLL-библиотеки, определив имена экспортируемых функций, их порядковые номера, имена DLL-библиотек и номера функций, импортируемых из этих библиотек и т. д. Можно даже дизассемблировать секции кода с использованием таблицы символов, если такая имеется в файле.

Выберем для исследования DLL-библиотеку comdlg32.dll, в которой находятся функции для работы со стандартными диалоговыми панелями.

Вначале запустим программу dumpbin.exe, передав ей в качестве параметра имя DLL-библиотеки:


c:\msdev\bin>dumpbin comdg32.dll > lst.txt

Перед запуском программы dumpbin.exe мы скопировали файл comdg32.dll в каталог c:\msdev\bin.

Программа запишет в файл lst.txt информацию о типе файла (DLL-библиотека) и перечислит названия секций и их размер, как это показано ниже:


Microsoft (R) COFF Binary File Dumper Version 3.10.6038
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file comdlg32.dll
File Type: DLL
     Summary
        4000 .data
        1000 .edata
        2000 .rdata
        2000 .reloc
        9000 .rsrc
       17000 .text

Ниже мы перечислили названия некоторых стандартных секций (полное описание вы найдете в документации, которая поставляется в составе использованного вами средства разработки приложений для Microsoft Windows NT):

 Название

 Описание

 .data

 Секция инициализированных данных

 .text

 Секция кода

 .rdata

 Данные, которые можно только читать во время выполнения

 .edata

 Таблица экспортируемых имен

 .reloc

 Таблица перемещений

 .rsrc

 Ресурсы

 .bss

 Секция неинициализированных данных

 .xdata

 Таблица обработки исключений

 .CRT

 Данные библиотеки C, которые можно только читать во время выполнения

 .debug

 Отладочная информация

 .tls

 Локальная память задач

Для просмотра более подробной информации о секции следует воспользоваться параметром /SECTION:


c:\msdev\bin>dumpbin comdg32.dll /SECTION:.data > lst.txt

Результат выполнения этой команды показан ниже:


Microsoft (R) COFF Binary File Dumper Version 3.10.6038
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file comdlg32.dll
File Type: DLL
SECTION HEADER #3
   .data name
    35E4 virtual size
   1A000 virtual address
     E00 size of raw data
   18C00 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C8000040 flags
         Initialized Data
         Not Paged
         (no align specified)
         Read Write
     Summary
        4000 .data

Аналогичная информация о секции .text приведена ниже:


Microsoft (R) COFF Binary File Dumper Version 3.10.6038
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file comdlg32.dll
File Type: DLL
SECTION HEADER #1
   .text name
   16FF9 virtual size
    1000 virtual address
   17000 size of raw data
     400 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
68000020 flags
         Code
         Not Paged
         (no align specified)
         Execute Read
     Summary
       17000 .text

Для просмотра списка имен экспортируемых функций и глобальных переменных запустите программу dumpbin.exe с параметром /EXPORTS:


c:\msdev\bin>dumpbin comdg32.dll /EXPORTS > lst.txt

Список появится в следующем виде:


Microsoft (R) COFF Binary File Dumper Version 3.10.6038
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file comdlg32.dll
File Type: DLL
    Section contains the following Exports for comdlg32.dll
                   0 characteristics
            30D0D8ED time date stamp Fri Dec 15 05:09:49 1995
                0.00 version
                   1 ordinal base
                  23 number of functions
                  23 number of names

            ordinal hint   name

                  1    0   ChooseColorA  (00012442)
                  2    1   ChooseColorW  (0001164F)
                  3    2   ChooseFontA  (00009235)
                  4    3   ChooseFontW  (00014028)
                  5    4   CommDlgExtendedError  (0000F92A)
                  6    5   FindTextA  (0001373A)
                  7    6   FindTextW  (0001372A)
                  8    7   GetFileTitleA  (0000FB57)
                  9    8   GetFileTitleW  (0000FAF1)
                 10    9   GetOpenFileNameA  (00004952)
                 11    A   GetOpenFileNameW  (0000F9EE)
                 12    B   GetSaveFileNameA  (0000493B)
                 13    C   GetSaveFileNameW  (0000FA37)
                 14    D   LoadAlterBitmap  (0000A450)
                 15    E   PageSetupDlgA  (00014277)
                 16    F   PageSetupDlgW  (00014373)
                 17   10   PrintDlgA  (0000738E)
                 18   11   PrintDlgW  (00014238)
                 19   12   ReplaceTextA  (0001375A)
                 20   13   ReplaceTextW  (0001374A)
                 21   14   WantArrows  (000122D5)
                 22   15   dwLBSubclass  (000018F7)
                 23   16   dwOKSubclass  (000018C4)
     Summary
        4000 .data
        1000 .edata
        2000 .rdata
        2000 .reloc
        9000 .rsrc
       17000 .text

Наряду с именами функций здесь отображаются порядковые номера функций и их адреса (в скобках).

Указав параметр /DISASM, вы можете дизассемблировать секцию кода, однако полученный в результате листинг может оказаться слишком большим и трудным для анализа. Вот фрагмент такого листинга:


Microsoft (R) COFF Binary File Dumper Version 3.10.6038
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file comdlg32.dll
File Type: DLL
  77DF1000: 83 3D EC C4 E0 77  cmp   dword ptr ds:[77E0C4ECh],0
            00
  77DF1007: 56                 push  esi
  77DF1008: 75 2D              jne   77DF1037
  77DF100A: 83 3D 8C C7 E0 77  cmp   dword ptr ds:[77E0C78Ch],0
            00
  77DF1011: 8B 74 24 08        mov   esi,dword ptr [esp+8]
  77DF1015: 0F 84 93 97 00 00  je    77DFA7AE
  77DF101B: 83 FE 01           cmp   esi,1
  77DF101E: 1B C0              sbb   eax,eax
  77DF1020: 24 FE              and   al,0FEh
  77DF1022: 05 02 7F 00 00     add   eax,7F02h
  77DF1027: 50                 push  eax
  77DF1028: 6A 00              push  0

В заключение этого раздела приведем список параметров программы dumpbin.exe.

 Параметр

 Описание

 /ALL

 Просмотр всей доступной информации, исключая листинг дизассемблирования

 /ARCHIVEMEMBERS

 Просмотр минимальной информации об объектах библиотеки

 /DISASM

 Дизассемблирование секции кода

 /EXPORTS

 Просмотр экспортируемых имен

 /FPO

 Просмотр записи FPO (Frame Pointer Optimization)

 /HEADERS

 Просмотр заголовка файла и заголовков каждой секции, либо заголовка каждого объекта, расположенного в библиотеке

 /IMPORTS

 Просмотр импортированных имен

 /LINENUMBERS

 Просмотр номеров строк формата COFF

 /LINKERMEMBER

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

 /OUT:ИмяФайла

 Запись выходной информации не на стандартное устройство вывода (консоль), а в файл с именем ИмяФайла

 /RAWDATA

 Просмотр дампа каждой секции

 /RELOCATIONS

 Просмотр таблицы перемещений

 /SECTION:Секция

 Просмотр информации только о секции, имеющей имя Секция

 /SUMMARY

 Просмотр минимальной информации о секциях

 /SYMBOLS

 Просмотр таблицы символов формата COFF


[Назад] [Содеожание] [Дальше]