Условия:
1) Загружаемый бинарный файл был скомпилирован как DLL (при использовании gcc / ld это означает использование опции --shared
; если вы используете --shared
, результирующий файл будет dll и не будет работать, см. Ниже)
2) IMAGE_FILE_DLL
устанавливается в заголовке PE-файла загружаемого двоичного файла. Если он установлен, файл является dll, и компоновщик Windows будет вызывать для вас функцию DllMain()
, когда связывает этот файл с вашей программой (не имеет значения, как он связан - LoadLibrary()
во время выполнения или -llibraryname
при компиляции время). Для этого файл также должен удовлетворять (1). Но с этим флагом загружаемый двоичный файл не будет работать. Если IMAGE_FILE_DLL
не задано, DllMain()
не будет вызываться при загрузке файла в вашу программу.
Компиляция dll с помощью --shared
и последующее ручное удаление IMAGE_FILE_DLL
из его заголовка (т. Е. С помощью шестнадцатеричного редактора) не будет работать - при его запуске будет выполняться только DllMain()
, и fdwReason
будет неопределенный номер (0x28ffd4
на моей машине).
Обновление
Все файлы DLL и EXE в Windows являются PE-файлами, разница в том, как они связаны и какие флаги установлены в их заголовках. Вот почему я пишу file being loaded
, а не dll being loaded
.
В последнем абзаце также описывается сценарий, в котором вы компилируете файл как dll, а затем превращаете его в exe, связываясь с его заголовком. Это не работает.
Именование не имеет к этому никакого отношения (вы можете выбрать любое имя, и, немного поработав pexports
+ dlltool
, вы можете создать библиотеку импорта для файла .exe и связать ее как -lexenamewithoutextension
уточнить:
- , если вы скомпилируете его без
--shared
:
IMAGE_FILE_DLL
не будет установлен в нем, он будет работать, но DllMain () НЕ будет вызываться, когда вы связываете его.
- , если вы скомпилируете его с
--shared
:
IMAGE_FILE_DLL
будет установлен в нем, он НЕ будет работать, но DllMain () будет вызываться при его привязке.
- если вы скомпилируете его без
--shared
, то включите флаг IMAGE_FILE_DLL
в нем вручную:
- он больше не будет работать, и при его связывании DllMain () не будет вызываться.
- если вы скомпилируете его с помощью
--shared
, а затем вручную отключите флаг IMAGE_FILE_DLL
:
- он будет запущен, но DllMain () будет выполняться вместо main (), и DllMain () НЕ будет вызываться при его связывании.