В программинге существует много деталей, которые отделяют любительскую поделку от профессионального софта. Одной из таких деталей является манифест приложения - XML-файл, который управляет тем, как ОС взаимодействует с программой. В Visual Studio и других IDE этот файл добавляется парой кликов мыши. Но как быть, если мы пишем на чистом ассемблере? В отличие от распространённого мнения, fasm предоставляет элегантные механизмы для встраивания манифестов. Более того, работа с ними на ассме даёт нам полный контроль над каждым байтом ресурсов. В этой статье мы разберём, что такое манифесты, зачем они нужны, и как правильно встраивать их в наши проекты.
1. Введение
Манифест - это XML, который встраивается в исполняемый EXE/DLL в качестве ресурса. ОС читает этот файл при запуске программы, чтобы определить её поведение. Представьте манифест как паспорт вашей программы. В нём указано:
При отсутствии манифеста ОС считает, что перед ней стандартная программа для XP, и применяет к ней устаревшие правила поведения. Именно из-за отсутствия правильного манифеста многие ASM-программы выглядят древними, и имеют проблемы с отображением интерфейса на современных Win10/11.
1.1. Зачем нужен манифест в FASM-проектах?
Манифест критически важен по нескольким причинам:
2. Тип ресурса "RT_MANIFEST"
Для встраивания используется специальный ресурс RT_MANIFEST, константа которого равна 24 (см.инклуд фасма \equates\kernel32.inc). Для стандартного EXE используется ID=1. Существует два способа встроить XML манифеста:
2.1. Подключение внешнего XML-файла
Это самый чистый и поддерживаемый метод. Вы сохраняете манифест в отдельный файл (например, app.manifest), а затем в fasm указываете путь к этому файлу с помощью директивы
Код для подключения этого файла:
2.2. Встраивание XML непосредственно в код
Данный метод удобен, когда манифест короткий (например только для UAC, или только для визуальных стилей). XML просто вставляется как строка байт с помощью db. Пример для запроса прав админа (requireAdministrator) будет выглядеть так:
После сборки и запуска программы с таким манифестом, Win будет показывать диалог UAC, запрашивая разрешение на выполнение с правами админа. Определить, что манифест исправно подключён к программе можно по наличию "щита" на иконке исполняемого файла, как это показано ниже (слева xml, справа exe).
2.3. Альтернативный метод
Хотя встраивание манифеста в ресурсы является предпочтительным и надёжным способом, существует ещё вариант. Если вы поместите файл с именем MySoft.exe.manifest в ту же папку, что и MySoft.exe, системный загрузчик образов подхватит его на автомате. Этот метод удобен на этапе отладки, но для финальной сборки использовать его не рекомендуется по сл.причинам:
3. Добавление ресурса VERSIONINFO
Хотя манифест - это важнейший ресурс, профессиональное приложение должно содержать и блок VERSIONINFO. Именно эти данные отображаются в свойствах файла, когда мы кликаем по нему правой кнопкой мыши. В fasm для его создания используется спец.структура, и директива
Обратите внимание, что оба ресурса и манифест и версия имеют одинаковый идентификатор
Короткий ответ:
Обычно код создаёт в секции .rsrc три разные ветки:
Для загрузчика образов
Секрет в том, как система ищет инфу о версии. Когда в свойствах файла мы выбираем "Подробно", под катом вызывается
А почему-же манифест работает с ID=1?
Здесь похожая, но не такая строгая история. Win подхватывает манифест в нескольких случаях:
Вот сводная таблица разных вариантов:
4. Реализация на практике
Ниже представлен код программы, которая запрашивает желаемую привилегию (как у текущего юзера, админ, или макс.возможную), и на основании выбора генерит готовый файл-манифеста, который можно будет подключить к своей программе. Помимо того, что код создаёт внешний XML-файл, он и сам в своей тушке имеет оба ресурса - и
Как результат получим такое окно. Чтобы обозначить разницу, здесь я сделал 2 скрина - слева с манифестом, а справа без. Как видим стиль кнопок приобрёл уже другой вид: с голубой подсветкой, края округлённые, а если в окне были-бы и другие элементы управления (полосы прокрутки, списки комбо/лист-бокс, и прочее), то изменились-бы и они на более современные. В общем профит от манифестов на лицо.
Просмотреть содержимое манифеста (и даже подправить пару строк) можно в крутой тулзе "CFF-Explorer" как показано на скрине ниже. Ну и конечно специально заточенная для этих нужд утилита "Resource Hacker" позволяет создавать манифесты из своих шаблонов - вписываем в строку "Name" имя своей прожки, и всё пучком. Одним словом, здесь есть из чего выбирать:
А по коду, после того-как получили дескриптор открытого файла (здесь я использовал функцию _lopen(), которая под катом вызывает CreateFile() с дефолтными настройками безопасности), можно в любой момент сбрасывать в него фрагменты данных, и они будут дописываться в конец по текущему указателю. Этот указатель хранится в файловом объекте ядра, и при каждой записи увеличивается на указанное при вызове
5. Заключение
Манифесты в FASM это не магия и не проблема. Освоив технику вы перестаёте быть "тем парнем, который пишет ассм под DOS", и становитесь проф.разработчиком под Windows, способным создавать современные приложения с правильным поведением и внешним видом. Используйте директиву
Ссылки по теме
MSDN - Описание всех элементов манифеста:
Манифесты приложения - Win32 apps
MSDN - Включение визуальных стилей:
Включение визуальных стилей - Win32 apps
Зачем приложению манифест:
Зачем Win32-приложению манифест?
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() перестала возвращать реальную версию системы, если приложение не имеет совместимого манифеста. Без него программа всегда будет думать, что работает на Win8, даже если запущена на последней Win11.
• Запрос прав админа через 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 указываете путь к этому файлу с помощью директивы
file. Вот структура файла app.manifest (минимальный пример):
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<!-- 1. ИДЕНТИФИКАТОР ВАШЕЙ ПРОГРАММЫ (обязательный) -->
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="amd64"
name="MyApp" <---------------- имя ВАШЕГО файла (без .exe)
type="win32" />
<!-- 2. ОПИСАНИЕ ЗАВИСИМОСТЕЙ (опционально, но часто нужно) -->
<dependency>
<dependentAssembly>
<!-- Common Controls 6.0 для современного визуального оформления -->
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*" />
</dependentAssembly>
</dependency>
<!-- 3. ЗАПРОС ПРАВ (ваша основная задача) -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
Код для подключения этого файла:
C-подобный:
section '.rsrc' resource data readable
;// Определяем каталог для манифестов
directory RT_MANIFEST, manifests
;// Определяем сам ресурс: ID=1, язык нейтральный, данные из блока 'resmanifest'
resource manifests, 1, LANG_NEUTRAL, resmanifest
;// Подключаем внешний файл!
resdata resmanifest
file 'app.manifest'
endres
2.2. Встраивание XML непосредственно в код
Данный метод удобен, когда манифест короткий (например только для UAC, или только для визуальных стилей). XML просто вставляется как строка байт с помощью db. Пример для запроса прав админа (requireAdministrator) будет выглядеть так:
C-подобный:
section '.rsrc' resource data readable
directory RT_MANIFEST, manifests
resource manifests, 1, LANG_NEUTRAL, resmanifest
;// XML-строка прямо в коде
resdata resmanifest
db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">'
db ' <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="MyAdminApp" type="win32"/>'
db ' <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">'
db ' <security>'
db ' <requestedPrivileges>'
db ' <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>'
db ' </requestedPrivileges>'
db ' </security>'
db ' </trustInfo>'
db '</assembly>'
endres
После сборки и запуска программы с таким манифестом, Win будет показывать диалог UAC, запрашивая разрешение на выполнение с правами админа. Определить, что манифест исправно подключён к программе можно по наличию "щита" на иконке исполняемого файла, как это показано ниже (слева xml, справа exe).
2.3. Альтернативный метод
Хотя встраивание манифеста в ресурсы является предпочтительным и надёжным способом, существует ещё вариант. Если вы поместите файл с именем MySoft.exe.manifest в ту же папку, что и MySoft.exe, системный загрузчик образов подхватит его на автомате. Этот метод удобен на этапе отладки, но для финальной сборки использовать его не рекомендуется по сл.причинам:
• При копировании программы можно забыть скопировать манифест.
• Внешние файлы могут быть изменены/удалены антивирусами или юзером.
• Это выглядит непрофессионально.
3. Добавление ресурса VERSIONINFO
Хотя манифест - это важнейший ресурс, профессиональное приложение должно содержать и блок VERSIONINFO. Именно эти данные отображаются в свойствах файла, когда мы кликаем по нему правой кнопкой мыши. В fasm для его создания используется спец.структура, и директива
versioninfo.
C-подобный:
section '.rsrc' resource data readable
;// Определяем каталоги: RT_VERSION и RT_MANIFEST
directory RT_VERSION, versions,\
RT_MANIFEST, manifests
;// Описываем ресурс версии: ID=1, язык нейтральный, данные из блока 'version'
resource versions, 1, LANG_NEUTRAL, version
;// Блок VERSIONINFO
versioninfo version, VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN, LANG_ENGLISH + SUBLANG_DEFAULT, 0, \
'FileDescription', 'Краткое описание приложения', \
'LegalCopyright', '(C)2024, Codeby.net', \
'FileVersion', '1.1.0.0', \
'ProductVersion', '1.0.0.0', \
'OriginalFilename', 'MyApp.exe'
;// Описываем ресурс манифеста
resource manifests, 1, LANG_NEUTRAL, resmanifest
resdata resmanifest
file 'app.manifest'
endres
Обратите внимание, что оба ресурса и манифест и версия имеют одинаковый идентификатор
ID=1. Это принципиально важно, т.к. при других значениях загрузчик посчитает блок невалидным и проигнорирует его. Но как могут быть одинаковые ID у двух ресурсов, ведь по логике вещей это не допустимо?Короткий ответ:
ID=1 в разных типах ресурсов RT_MANIFEST и RT_VERSION - это разные пространства имён. Они не конфликтуют, потому что идентифицируются не только по ID, а именно парой Type + ID. В секции .rsrc ресурсы организованы в трёхуровневую иерархию:1. Type: RT_VERSION(16), RT_MANIFEST(24), RT_DIALOG(5) и т.д.2. Name/ID: Уникальный идентификатор внутри этого типа.3. Language: LANG_ENGLISH, LANG_NEUTRAL и т.д.Обычно код создаёт в секции .rsrc три разные ветки:
• Ветка RT_DIALOG -> ID 37 -> Lang• Ветка RT_MANIFEST -> ID 01 -> Lang• Ветка RT_VERSION -> ID 01 -> LangДля загрузчика образов
RT_MANIFEST#1 и RT_VERSION#1 - это совершенно разные объекты, как файлы C:\Windows\System32\kernel32.dll и D:\MyProject\kernel32.dll. Путь к ним разный, поэтому они живут мирно. Так почему-же версия не отображается, если ID не 1?Секрет в том, как система ищет инфу о версии. Когда в свойствах файла мы выбираем "Подробно", под катом вызывается
GetFileVersionInfo() с таким алго: -"Найти в секции ресурсов тип RT_VERSION(16) с идентификатором VS_VERSION_INFO(1)". Если мы ставим ID=1, Win находит ресурс и версия отображается. Если-же задать ID=2 (42, 1000), api ищет ID=1, не находит его и молча решает «Версии нет». Никакой ошибки не будет, просто поля версии в свойствах файла останутся пустыми.А почему-же манифест работает с ID=1?
Здесь похожая, но не такая строгая история. Win подхватывает манифест в нескольких случаях:
1. Встроенный, ищется по хард
ID=1.2. Внешний (appname.exe.manifest). Если встроенного
ID=1 нет, загрузчик ищет манифест рядом с EXE.3. Динамическая загрузка через
FindResource() + LoadResource(). Если мы врукопашную ищем манифест, то сработает любой ID, однако при старте процесса загрузчик этого не делает.Вот сводная таблица разных вариантов:
Ресурс Тип ID Как работает----------- --- -- -------------RT_MANIFEST 24 1 Загрузчик ищет строго ID=1 для встроенного манифеста.RT_VERSION 16 1 GetFileVersionInfo() ищет строго ID=1.RT_DIALOG 05 37 DialogBoxParam() использует ID=37, хотя будет работать и при ID=1.4. Реализация на практике
Ниже представлен код программы, которая запрашивает желаемую привилегию (как у текущего юзера, админ, или макс.возможную), и на основании выбора генерит готовый файл-манифеста, который можно будет подключить к своей программе. Помимо того, что код создаёт внешний XML-файл, он и сам в своей тушке имеет оба ресурса - и
RT_VERSION и RT_MANIFEST для отображения визуальных стилей Win10/11.
C-подобный:
format pe64 gui 6.0
include 'win64ax.inc'
include 'encoding\win1251.inc'
entry start
ID_Invok = 101
ID_Admin = 102
ID_High = 103
ID_Logo = 104
;//-----------------
section '.text' code readable executable
start: push rbp
invoke InitCommonControls
invoke GetModuleHandle,0
mov [hModule],eax
invoke DialogBoxParam,rax,37,0,DialogProc,0
invoke ExitProcess,0
proc DialogProc uses rsi rdi rbx, hWnd,Msg,wParam,lParam
mov [hWnd], rcx
mov [wParam],r8
cmp edx,WM_INITDIALOG
je @initialize
cmp edx,WM_COMMAND
je @command
cmp edx,WM_CLOSE
je @close
xor rax,rax
jmp @fin
@initialize:
;//---- Вставляем в окно логотип в формате *.bmp ----------
invoke LoadImage,[hModule],55,IMAGE_BITMAP,0,0,0
mov [hBitmap],eax
invoke GetDlgItem,[hWnd],ID_Logo
invoke SendMessage,eax,STM_SETIMAGE,IMAGE_BITMAP,[hBitmap]
;//---- Выберем и взведём чек-бокс по умолчанию -----------
invoke CheckRadioButton,[hWnd],ID_Invok,ID_High,ID_Invok
jmp @next
@command:
cmp [wParam],BN_CLICKED shl 16 + IDCANCEL
je @close
cmp [wParam],BN_CLICKED shl 16 + IDOK
jne @next
;//---- Если нажата пимпа "Создать" -----------------------
;//********************************************************
invoke _lcreat,<'NewManifest.xml',0>,0
mov [hFile],eax
invoke _lwrite,eax,xmlHdr,admin-xmlHdr
invoke IsDlgButtonChecked,[hWnd],ID_Invok ;// тест радио-буттонов
cmp eax,BST_CHECKED
jne @admin
invoke _lwrite,[hFile],user,31 ;// длина строка = 31
jmp @f
@admin: invoke IsDlgButtonChecked,[hWnd],ID_Admin
cmp eax,BST_CHECKED
jne @hight
invoke _lwrite,[hFile],admin,42
jmp @f
@hight: invoke _lwrite,[hFile],hight,38
@@: invoke _lwrite,[hFile],endHdr,endBss-endHdr
invoke _lclose,[hFile]
invoke MessageBox,0,<'Файл NewManifest.xml успешно создан!',0>,\
<'Генератор манифестов',0>,0
jmp @next
;//**********************************
@close: invoke EndDialog,[hWnd],0
@next: mov rax,1
@fin: ret
endp
;//--------------------
section '.idata' import data readable writeable
library kernel32,'kernel32.dll',\
comctl32,'comctl32.dll',user32,'user32.dll'
include 'api\kernel32.inc'
include 'api\comctl32.inc'
include 'api\user32.inc'
;//--------------------
section '.rsrc' resource data readable
directory RT_DIALOG, dialogs,\
RT_VERSION, version,\
RT_BITMAP, bitmaps,\
RT_MANIFEST,manifest
resource dialogs,\
37,LANG_ENGLISH+SUBLANG_DEFAULT,form
resource version,\
1,LANG_NEUTRAL,vInfo
resource bitmaps,\
55,LANG_NEUTRAL,logo
resource manifest,\
1,LANG_NEUTRAL,manifest_data
dialog form, 'Генератор манифеста PE32/64',0,0,177,104,WS_CAPTION + WS_SYSMENU + WS_POPUP + DS_CENTER,,,'Verdana',8
dialogitem 'BUTTON',' Права ',-1,10,10,090,060, WS_VISIBLE + BS_GROUPBOX
dialogitem 'BUTTON','Текущие', ID_Invok, 20,023,60,13,WS_VISIBLE + BS_AUTORADIOBUTTON + WS_TABSTOP + WS_GROUP
dialogitem 'BUTTON','Администратор',ID_Admin, 20,037,70,13,WS_VISIBLE + BS_AUTORADIOBUTTON
dialogitem 'BUTTON','Максимальные', ID_High, 20,051,70,13,WS_VISIBLE + BS_AUTORADIOBUTTON
dialogitem 'STATIC','Лого',ID_Logo, 115,013,0,0, WS_VISIBLE + SS_BITMAP
dialogitem 'BUTTON','Создать',IDOK, 010,080,90,14,WS_VISIBLE + WS_TABSTOP + BS_DEFPUSHBUTTON
dialogitem 'BUTTON','Выход',IDCANCEL,115,080,52,14,WS_VISIBLE + WS_TABSTOP + BS_PUSHBUTTON
enddialog
versioninfo vInfo,\
VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN,\
LANG_ENGLISH + SUBLANG_DEFAULT, 0,\ ;//<-------- Lang/CodePage
'LegalCopyright' , 'Copyright (c) 2020-2026. Marylin',\
'ProductName' , 'Manifest utility',\
'ProductVersion' , '6.1.7601',\
'FileDescription' , 'Генератор манифестов fasm',\
'FileVersion' , '1.0.0',\
'OriginalFilename', 'ManifestUtil.exe'
resdata manifest_data
file 'Manifest.xml' ;//<-------- Подключаем внешний манифест!
endres
;//-----------------
section '.data' data readable writeable
hFile dd 0
hBitmap dd 0
hModule dd 0
;//----- Данные для записи в файл --------------
xmlHdr db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',13,10
db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">',13,10
db '<assemblyIdentity version="1.0.0.0" processorArchitecture="amd64" name="AppName" type="win32" />',13,10
db ' <dependency>',13,10
db ' <dependentAssembly>',13,10
db ' <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />',13,10
db ' </dependentAssembly>',13,10
db ' </dependency>',13,10
db ' <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">',13,10
db ' <security>',13,10
db ' <requestedPrivileges>',13,10
db '<requestedExecutionLevel level="'
admin db 'requireAdministrator" uiAccess="false"/>',13,10 ;// длина строки = 42 байта
hight db 'highestAvailable" uiAccess="false"/>',13,10
user db 'asInvoker" uiAccess="false"/>',13,10
endHdr db ' </requestedPrivileges>',13,10
db ' </security>',13,10
db ' </trustInfo>',13,10
db '</assembly>',13,10
endBss:
bitmap logo,'logo.bmp'
Как результат получим такое окно. Чтобы обозначить разницу, здесь я сделал 2 скрина - слева с манифестом, а справа без. Как видим стиль кнопок приобрёл уже другой вид: с голубой подсветкой, края округлённые, а если в окне были-бы и другие элементы управления (полосы прокрутки, списки комбо/лист-бокс, и прочее), то изменились-бы и они на более современные. В общем профит от манифестов на лицо.
Просмотреть содержимое манифеста (и даже подправить пару строк) можно в крутой тулзе "CFF-Explorer" как показано на скрине ниже. Ну и конечно специально заточенная для этих нужд утилита "Resource Hacker" позволяет создавать манифесты из своих шаблонов - вписываем в строку "Name" имя своей прожки, и всё пучком. Одним словом, здесь есть из чего выбирать:
А по коду, после того-как получили дескриптор открытого файла (здесь я использовал функцию _lopen(), которая под катом вызывает CreateFile() с дефолтными настройками безопасности), можно в любой момент сбрасывать в него фрагменты данных, и они будут дописываться в конец по текущему указателю. Этот указатель хранится в файловом объекте ядра, и при каждой записи увеличивается на указанное при вызове
_lwrite() кол-во байт. Он будет всегда смотреть в конец файла, пока мы не закроем дескриптор по CloseHandle(). Вот внутренняя структура любого файла в отладчике WinDbg, где по смещению(0x68) лежит позиция указателя в файле:
Код:
0: kd> dt _file_object
nt!_FILE_OBJECT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 DeviceObject : Ptr64 _DEVICE_OBJECT
+0x010 Vpb : Ptr64 _VPB <------- Volume Param Block (инфа о разделе диска)
+0x018 FsContext : Ptr64 Void
+0x020 FsContext2 : Ptr64 Void
+0x028 SectionObjectPointer : Ptr64 _SECTION_OBJECT_POINTERS
+0x030 PrivateCacheMap : Ptr64 Void
+0x038 FinalStatus : Int4B
+0x040 RelatedFileObject : Ptr64 _FILE_OBJECT
+0x048 LockOperation : UChar
+0x049 DeletePending : UChar
+0x04a ReadAccess : UChar ----+
+0x04b WriteAccess : UChar |
+0x04c DeleteAccess : UChar |
+0x04d SharedRead : UChar +---> Атрибуты доступа
+0x04e SharedWrite : UChar |
+0x04f SharedDelete : UChar |
+0x050 Flags : Uint4B ---+
+0x058 FileName : _UNICODE_STRING
+0x068 CurrentByteOffset : _LARGE_INTEGER <------ Текущее смещение в файле!
+0x070 Waiters : Uint4B
+0x074 Busy : Uint4B
+0x078 LastLock : Ptr64 Void
+0x080 Lock : _KEVENT
+0x098 Event : _KEVENT
+0x0b0 CompletionContext : Ptr64 _IO_COMPLETION_CONTEXT
+0x0b8 IrpListLock : Uint8B
+0x0c0 IrpList : _LIST_ENTRY
+0x0d0 FileObjectExtension : Ptr64 Void
0: kd>
5. Заключение
Манифесты в FASM это не магия и не проблема. Освоив технику вы перестаёте быть "тем парнем, который пишет ассм под DOS", и становитесь проф.разработчиком под Windows, способным создавать современные приложения с правильным поведением и внешним видом. Используйте директиву
resdata для встраивания XML, не забывайте про RT_MANIFEST и ID=1, добавляйте VERSIONINFO для информации о файле, и ваши программы будут выглядеть так, как будто они написаны на самом современном компиляторе. В мире FASM нет границ: если вы можете описать это в коде - ассемблер это соберёт.Ссылки по теме
MSDN - Описание всех элементов манифеста:
Манифесты приложения - Win32 apps
MSDN - Включение визуальных стилей:
Включение визуальных стилей - Win32 apps
Зачем приложению манифест:
Зачем Win32-приложению манифест?