Windows для профессионалов

       

Описатель экземпляра процесса


Любому EXE- или DLL-модулю, загружаемому в адресное пространство процесса, присваивается уникальный описатель экземпляра. Описатель экземпляра Вашего EXE-файла передается как первый параметр функции (w)WinMain - hinstExe. Это значение обычно требуется при вызовах функций, загружающих те или иные ресурсы. Например, чтобы загрузить из образа ЕХЕ-файла такой ресурс, как значок, надо вызвать:

HICON LoadIcon( HINSTANCE hinst, PCTSTR pszIcori);

Первый параметр в LoadIcon указывает, в каком файле (EXE или DLL) содержится интересующий Вас ресурс. Многие приложения сохраняют параметр hinstExe функции (w)WinMain в глобальной переменной, благодаря чему он доступен из любой части кода ЕХЕ-файла.

В документации Platform SDK утверждается, что некоторые Windows-функции требуют параметр типа HMODULE. Пример — функция GetModuleFileName.

DWORD GetModuleFileName( HMODULE hinstModule, PTSTR pszPath, DWORD cchPath);

NOTE:
Как оказалось, HMODULE и HINSTANCE — это идно и то же. Встретив в документации указание передать какой-то функции HMODULE, смело передавайте HINSTANCE, и наоборот. Они существуют в таком виде лишь потому, что в l6 разрядпой Windows идентифицировали совершенно разные вещи.

Истинное значение параметра hinstExe функции (w)WinMain - базовый адрес в памяти, определяющий ту область в адресном пространстве процесса, куда был загружен образ данного ЕХЕ-файла. Например, если система открывает исполняемый файл и загружает его содержимое по адресу 0x00400000, то hinstExe функции (w)Win Main получает значение 0x00400000.

Базовый адрес, но которому загружается приложение, определяется компоновщи ком. Разные компоновщики выбирают и разные (no умолчанию) базовые адреса. Компоновщик Visual С++ использует по умолчанию базовый адрес 0x00400000 — самый нижний в Windows 98, начиная с которого в ней допускается загрузка образа исполняемого файла. Указав параметр /BASE: адрес (в случае компоновщика от Microsoft), можно изменить базовый адрес, по которому будет загружаться приложение.


При попытке загрузить исполняемый файл в Windows 98 по базовому адресу ниже 0x00400000 загрузчик переместит его на другой адрес. Это увеличит время загрузки приложения, но оно по крайней мере будет выполнено. Если Вы разрабатываете программы и для Windows 98, и для Windows 2000, сделайте так, чтобы приложение загружалось по базовому адресу не ниже 0x00400000. Функция GetModuleHandle.

HMODULE GetModuleHandle( PCTSTR pszModule);

возвращает описатель/базовый адрес, указывающий, куда именно (в адресном пространстве процесса) загружается EXE- или DLL-файл. При вызове этой функции имя нужного EXE- или DLL-файла передается как строка с нулевым символом в конце. Если система находит указанный файл, GetModuleHandle возвращает базовый адрес, по которому располагается образ данного файла. Если же файл системой не найден, функция возвращает NULL. Кроме того, можно вызвать эту функцию, передав ей NULL вместо параметра pszModule, — тогда Вы узнаете базовый адрес EXE-файла. Именно это и делает стартовый код из библиотеки С/С++ при вызове (w)WinMain из Вашей программы.

Есть еще две важные вещи, касающиеся GetModuleHandle. Во-первых, она прове ряет адресное пространство только того процесса, который ее вызвал. Если этот про цесс не использует никаких функций, связанных со стандартными диалоговыми ок нами, то, вызвав GetModuleHandle и передав ей аргумент "ComDlg32", Вы получите NULL - пусть даже модуль ComDlg32.dll и загружен в адресное пространство какого нибудь другого процесса. Во-вторых, вызов этой функции и передача ей NULL дает в результате базовый адрес ЕХЕ-фяйла в адресном пространстве процесса. Так что, вызывая функцию в виде GetModuleHandle(NULL) - даже из кода в DLL, — Вы получаете базовый адрес EXE-, а не DLL-файла.


Содержание раздела