![]() |
В программинге существует много деталей, которые отделяют любительскую поделку от профессионального софта. Одной из таких деталей является манифест приложения - XML-файл, который управляет тем, как ОС взаимодействует с программой. В Visual Studio и других IDE этот файл добавляется парой кликов мыши. Но как быть, если мы пишем на чистом ассемблере? В отличие от распространённого мнения, fasm предоставляет элегантные механизмы для встраивания манифестов. Более того, работа с ними на ассме даёт нам полный контроль над каждым байтом ресурсов. В этой статье мы разберём, что такое манифесты, зачем они нужны, и как правильно встраивать их в наши проекты.
1. Введение 2. Ресурс RT_MANIFEST 3. Информация о версии VERSIONINFO 4. Реализация на практике 5. Под занавес 1. Введение Манифест - это XML, который встраивается в исполняемый EXE/DLL в качестве ресурса. ОС читает этот файл при запуске программы, чтобы определить её поведение. Представьте манифест как паспорт вашей программы. В нём указано: 1. Кто вы (идентификатор сборки) 2. Что вам нужно (зависимости от библиотек элементов управления comctl32.dll) 3. Какие у вас права (требуется ли запуск от имени админа) 4. С какой версией Win вы совместимы (важно для корректной работы таких функций как GetVersionEx). При отсутствии манифеста ОС считает, что перед ней стандартная программа для XP, и применяет к ней устаревшие правила поведения. Именно из-за отсутствия правильного манифеста многие ASM-программы выглядят древними, и имеют проблемы с отображением интерфейса на современных Win10/11. 1.1. Зачем нужен манифест вFASM-проектах? Манифест критически важен по нескольким причинам: • Активация новых визуальных стилей Common Controls v6.0. Без манифеста кнопки, полосы прокрутки и другие элементы управления будут иметь вид из Win2k. Манифест же подключает современную либу comctl32.dll, даруя программе современный внешний вид (тени, прозрачность, округлые края, и т.п). • Правильное определение версии ОС. Начиная с Win8 функция Код:
GetVersionEx()• Запрос прав админа через UAC (User Account Control). Если коду нужно писать в системные каталоги или реестр, она должна запросить повышение прав. Манифест позволяет указать уровень привилегий: Код:
asInvokerКод:
requireAdministratorКод:
highestAvailable• Профессиональный вид. Встраивание манифеста с описанием программы, версии и другой информацией через ресурс VERSIONINFO, придаёт приложению ухоженный вид. 2. Тип ресурса "RT_MANIFEST" Для встраивания используется специальный ресурс RT_MANIFEST, константа которого равна 24 (см.инклуд фасма \equates\kernel32.inc). Для стандартного EXE используется ID=1. Существует два способа встроить XML манифеста: • Внедрение из внешнего файла (рекомендуется для больших XML) • Встраивание XML прямо в код (удобно для коротких манифестов) 2.1. Подключение внешнегоXML-файла Это самый чистый и поддерживаемый метод. Вы сохраняете манифест в отдельный файл (например, app.manifest), а затем в fasm указываете путь к этому файлу с помощью директивы Код:
fileXML: Код:
C-подобный: Код:
sectionДанный метод удобен, когда манифест короткий (например только для UAC, или только для визуальных стилей). XML просто вставляется как строка байт с помощью db. Пример для запроса прав админа (requireAdministrator) будет выглядеть так: C-подобный: Код:
sectionhttps://forum.antichat.xyz/attachmen...eea027d691.png 2.3. Альтернативный метод Хотя встраивание манифеста в ресурсы является предпочтительным и надёжным способом, существует ещё вариант. Если вы поместите файл с именем MySoft.exe.manifest в ту же папку, что и MySoft.exe, системный загрузчик образов подхватит его на автомате. Этот метод удобен на этапе отладки, но для финальной сборки использовать его не рекомендуется по сл.причинам: • При копировании программы можно забыть скопировать манифест. • Внешние файлы могут быть изменены/удалены антивирусами или юзером. • Это выглядит непрофессионально. 3. Добавление ресурса VERSIONINFO Хотя манифест - это важнейший ресурс, профессиональное приложение должно содержать и блок VERSIONINFO. Именно эти данные отображаются в свойствах файла, когда мы кликаем по нему правой кнопкой мыши. В fasm для его создания используется спец.структура, и директива Код:
versioninfoC-подобный: Код:
sectionКод:
ID=1Короткий ответ: Код:
ID=1Код:
RT_MANIFESTКод:
RT_VERSIONКод:
Type + IDКод:
1. Type: RT_VERSION(16), RT_MANIFEST(24), RT_DIALOG(5) и т.д.Код:
2. Name/ID: Уникальный идентификатор внутри этого типа.Код:
3. Language: LANG_ENGLISH, LANG_NEUTRAL и т.д.Код:
• Ветка RT_DIALOG -> ID 37 -> LangКод:
• Ветка RT_MANIFEST -> ID 01 -> LangКод:
• Ветка RT_VERSION -> ID 01 -> LangКод:
RT_MANIFEST#1Код:
RT_VERSION#1Секрет в том, как система ищет инфу о версии. Когда в свойствах файла мы выбираем "Подробно", под катом вызывается Код:
GetFileVersionInfo()А почему-же манифест работает с ID=1? Здесь похожая, но не такая строгая история. Win подхватывает манифест в нескольких случаях: 1. Встроенный, ищется по хард Код:
ID=12. Внешний (appname.exe.manifest). Если встроенного Код:
ID=13. Динамическая загрузка через Код:
FindResource() + LoadResource()Вот сводная таблица разных вариантов: Код:
Ресурс Тип ID Как работаетКод:
----------- --- -- -------------Код:
RT_MANIFEST 24 1 Загрузчик ищет строго ID=1 для встроенного манифеста.Код:
RT_VERSION 16 1 GetFileVersionInfo() ищет строго ID=1.Код:
RT_DIALOG 05 37 DialogBoxParam() использует ID=37, хотя будет работать и при ID=1.Ниже представлен код программы, которая запрашивает желаемую привилегию (как у текущего юзера, админ, или макс.возможную), и на основании выбора генерит готовый файл-манифеста, который можно будет подключить к своей программе. Помимо того, что код создаёт внешний XML-файл, он и сам в своей тушке имеет оба ресурса - и Код:
RT_VERSIONКод:
RT_MANIFESTКак результат получим такое окно. Чтобы обозначить разницу, здесь я сделал 2 скрина - слева с манифестом, а справа без. Как видим стиль кнопок приобрёл уже другой вид: с голубой подсветкой, края округлённые, а если в окне были-бы и другие элементы управления (полосы прокрутки, списки комбо/лист-бокс, и прочее), то изменились-бы и они на более современные. В общем профит от манифестов на лицо. Просмотреть содержимое манифеста (и даже подправить пару строк) можно в крутой тулзе "CFF-Explorer" как показано на скрине ниже. Ну и конечно специально заточенная для этих нужд утилита "Resource Hacker" позволяет создавать манифесты из своих шаблонов - вписываем в строку "Name" имя своей прожки, и всё пучком. Одним словом, здесь есть из чего выбирать: https://forum.antichat.xyz/attachmen...197f12bd34.png А по коду, после того-как получили дескриптор открытого файла (здесь я использовал функцию _lopen(), которая под катом вызывает CreateFile() с дефолтными настройками безопасности), можно в любой момент сбрасывать в него фрагменты данных, и они будут дописываться в конец по текущему указателю. Этот указатель хранится в файловом объекте ядра, и при каждой записи увеличивается на указанное при вызове https://forum.antichat.xyz/attachmen...130c3363f0.png Код:
_lwrite()Код:
CloseHandle()Код: Код:
0: kd> dt _file_objectМанифесты в FASM это не магия и не проблема. Освоив технику вы перестаёте быть "тем парнем, который пишет ассм под DOS", и становитесь проф.разработчиком под Windows, способным создавать современные приложения с правильным поведением и внешним видом. Используйте директиву Код:
resdataКод:
RT_MANIFESTКод:
ID=1Код:
VERSIONINFOСсылки по теме MSDN - Описание всех элементов манифеста: Манифесты приложения - Win32 apps MSDN - Включение визуальных стилей: Включение визуальных стилей - Win32 apps Зачем приложению манифест: Зачем Win32-приложению манифест? |
| Время: 06:18 |