# Справочник по плагину API — DE Decompiler

> Общий интерфейс обратного вызова для пользовательских нативных плагинов.

Canonical HTML: <https://www.de-decompiler.com/plugins_sdk_rus.htm>

## справочник по плагинам API

Общий интерфейс обратного вызова для пользовательских нативных плагинов.

DE Decompiler использует общий ABI плагинов VB Decompiler. Имена экспортируемых функций сохраняют префикс VBDecompilerPlugin. Общие идентификаторы компиляторов и исторические имена команд VB/FRX относятся к API и не определяют поддерживаемые продуктом входные форматы. Для каждой операции проверяйте данные, доступные в текущем проекте DE Decompiler.

Данная документация описывает интерфейс плагина, общий для VB Decompiler и DE Decompiler. Система плагинов позволяет анализировать, изменять или расширять декомпилированный код и внутренние структуры приложения с помощью общей библиотеки (DLL).

1. Обзор архитектуры

Система плагинов работает на основе модели обратных вызовов:

- Хост-декомпилятор загружает ваш DLL-плагин.

- Он вызывает ваши экспортируемые функции для получения имени плагина и информации об авторе.

- Вызывается VBDecompilerPluginLoad, передавая указатель на его внутренний **Движок обратных вызовов (Callback Engine)**.

- Ваш плагин взаимодействует с хостом, вызывая функции этого Движка с использованием конкретных идентификаторов действий (vlType ).

2. Экспортируемые функции

Ваша DLL должна экспортировать следующие stdcall функции:

VBDecompilerPluginName

Вызывается хостом для получения отображаемого имени вашего плагина.

void __stdcall VBDecompilerPluginName(
HWND VBDecompilerHWND, // Дескриптор главного окна
HWND RichTextBoxHWND,  // Дескриптор окна редактора кода
char* Buffer,          // Целевой буфер (100 байт, ANSI)
int Reserved           // Зарезервировано
);

*Пример использования:* Скопируйте стандартную ASCII-строку (максимум 100 символов) с именем вашего плагина в Buffer.

VBDecompilerPluginAuthor

Вызывается для получения контактной информации автора.

void __stdcall VBDecompilerPluginAuthor(
HWND VBDecompilerHWND,
HWND RichTextBoxHWND,
char* Buffer,          // Целевой буфер (ANSI)
int Reserved
);

*Пример использования:* Скопируйте строку вида "Author Name, email@domain.com" в Buffer.

VBDecompilerPluginLoad

Основная точка входа, где выполняется логика вашего плагина.

void __stdcall VBDecompilerPluginLoad(
HWND VBDecompilerHWND,
HWND RichTextBoxHWND,
char* Buffer,          // Зарезервировано/Буфер
void* PluginEngine     // <--- Указатель на функцию обратного вызова
);

*Пример использования:* Сохраните PluginEngine указатель. Вы будете использовать его для вызова команд GetValue / SetValue (см. раздел «Движок обратного вызова» ниже).

3. Движок обратного вызова

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

**Сигнатура функции:**

typedef wchar_t* (__stdcall *TVBDPluginEngine)(
int vlType,       // Идентификатор команды (действие)
int vlNumber,     // Первичный индекс (идентификатор формы/модуля)
int vlFnNumber,   // Вторичный индекс (идентификатор функции)
char* vlNewValue  // Значение для установки (строка ANSI) или NULL для команд получения
);

**Примечание:** Движок принимает строки ANSI (char*) для входных данных, но возвращает строки Unicode (wchar_t*) для результатов.

4. Справочник по командам (vlType)

Следующие константы используются в качестве vlType аргумента для выполнения конкретных действий.

Глобальные команды проекта

Операции, связанные с файлом проекта или глобальными настройками. vlNumber и vlFnNumber обычно соответствуют 0.

| ID | Константа | Описание |
| --- | --- | --- |
| 1 | GetVBProject | Получить полный текст декомпилированного файла проекта. |
| 2 | SetVBProject | Заменить содержимое файла проекта. |
| 3 | GetFileName | Получить полный путь к анализируемому файлу. |
| 4 | IsNativeCompilation | Возвращает "1", если целевой файл скомпилирован в нативный код, и "0" для P-Code. |
| 5 | ClearAllBuffers | Очищает внутренние структуры декомпилятора. Используйте этот метод, если ваш плагин реализует полную пользовательскую декомпиляцию для нового языка. |
| 6 | GetCompiler | Возвращает тип компилятора: 1=VB, 2=.NET, 3=Delphi, 4=Неизвестно. |
| 7 | IsPacked | Возвращает "1", если файл упакован/сжат, и "0" в противном случае. |
| 56 | GetVBDecompilerPath | Возвращает путь к исполняемому файлу DE Decompiler. |
| 100 | UpdateAll | Применяет изменения и обновляет графический интерфейс (GUI). **Обязательно** после установки значений, чтобы пользователь увидел изменения. |
| 64 | GetProductName | Необязательная загруженная идентичность хоста, независимая от анализируемого компилятора; см. SDK 26.6 ниже. |

Элементы управления интерфейсом

Управление элементами интерфейса DE Decompiler.

| ID | Константа | Описание |
| --- | --- | --- |
| 8 | SetStackCheckBoxValue | Установить **«Парсить парам. из стека» (Parse stack parameters)** состояние флажка. "1" = отмечен, "0" = не отмечен. |
| 9 | SetAnalyzerCheckBoxValue | Установить **«Анализ и оптимизация кода» (Procedure analyzer and optimizer)** состояние флажка. "1" = отмечен, "0" = не отмечен. |
| 50 | GetActiveText | Получить текст, отображаемый в активном окне кода. |
| 51 | SetActiveText | Установить текст в активном окне кода. |
| 52 | GetActiveDisasmText | Получить сырой текст дизассемблирования окна дизассемблера. |
| 53 | SetActiveDisasmText | Установить сырой текст дизассемблирования в окно дизассемблера. |
| 54 | SetActiveTextLine | Прокрутить или перейти к указанному номеру строки (передаётся как строка в vlNewValue). |
| 55 | GetActiveModuleCoordinats | Получить идентификаторы активного представления. Перед использованием проверьте возвращаемое значение. |
| 58 | SetStatusBarText | Отобразить пользовательское сообщение в строке состояния приложения. |

Формы

Операции с восстановленными формами. vlNumber: индекс формы (на основе 0).

| ID | Константа | Описание |
| --- | --- | --- |
| 10 | GetVBFormName | Получить имя формы. |
| 11 | SetVBFormName | Переименовать форму. |
| 12 | GetVBForm | Получить декомпилированные свойства формы. |
| 13 | SetVBForm | Установить свойства формы. |
| 14 | GetVBFormCount | Возвращает общее количество форм в проекте. |

Модули

Операции со стандартными модулями (.bas) или модулями классов (.cls). vlNumber: Индекс модуля (на основе 0).

| ID | Константа | Описание |
| --- | --- | --- |
| 30 | GetModuleName | Получить имя модуля. |
| 31 | SetModuleName | Переименовать модуль. |
| 32 | GetModule | Получить заголовок с декомпилированными объявлениями модуля. |
| 33 | SetModule | Установить заголовок с декомпилированными объявлениями модуля. |
| 34 | GetModuleStringReferences | Получить список ссылок на строки, используемые в данном модуле. |
| 35 | SetModuleStringReferences | Установить ссылки на строки. |
| 36 | GetModuleCount | Возвращает общее количество модулей. |

Процедуры / Функции

Операции с конкретными функциями внутри модуля.

vlNumber: Индекс модуля.

vlFnNumber: Индекс функции (на основе 0) в пределах данного модуля.

| ID | Константа | Описание |
| --- | --- | --- |
| 20 | GetSubMain | Получить код точки входа (Sub Main). (Аргументы индекса игнорируются). |
| 21 | SetSubMain | Установить код точки входа. |
| 40 | GetModuleFunctionName | Получить имя конкретной функции. |
| 41 | SetModuleFunctionName | Переименовать функцию. |
| 42 | GetModuleFunctionAddress | Получить виртуальный адрес (VA) функции в памяти. |
| 43 | SetModuleFunctionAddress | Установить адрес функции. |
| 44 | GetModuleFunction | Получить декомпилированный код функции. |
| 45 | SetModuleFunction | Установить код функции. |
| 46 | GetModuleFunctionStrRef | Получить строковые ссылки, специфичные для данной функции. |
| 47 | SetModuleFunctionStrRef | Установить строковые ссылки для данной функции. |
| 48 | GetModuleFunctionCount | Возвращает количество функций в указанном модуле. |
| 57 | GetModuleFunctionCode | Получить код функции в режиме «Быстрая декомпиляция» (если данная функция в данный момент не обрабатывается). |
| 70 | GetModuleFunctionDisasm | Получить дизассемблирование (ASM) функции. |
| 71 | SetModuleFunctionDisasm | Установить дизассемблирование функции. |

Ресурсы (FRX)

Доступ к ресурсам в бинарном формате (иконки/изображения). vlNumber: Индекс иконки.

| ID | Константа | Описание |
| --- | --- | --- |
| 60 | GetFrxIconCount | Количество зарегистрированных оригинальных изображений (индексы с нуля), включая нативные растровые листы ImageList. |
| 61 | GetFrxIconOffset | Устаревший скорректированный офсет: фактический офсет изображения минус 8. Перед чтением прибавьте 8. |
| 62 | GetFrxIconSize | Устаревший скорректированный размер: фактическое количество байт изображения плюс 8. Перед чтением вычтите 8. |
| 63 | GetFrxImageListInfo | Необязательные метаданные IL1 для зарегистрированного нативного цветного растрового изображения DFM ImageList; см. ниже SDK 26.6. |

5. Нативные изображения и необязательные команды SDK 26.6

Эта общая ревизия SDK реализована через **VB Decompiler 26.6** и **DE Decompiler 26.6**. Команды 63 и 64 являются необязательными, только для чтения геттерами. Подпись обратного вызова, экспортируемые символы и существующие номера команд не изменены. Вызывайте обратный вызов в основном потоке хост-приложения.

Зарегистрированные изображения: команды 60–62

Индексы изображений отсчитываются с нуля. `GetFrxIconCount` возвращает количество зарегистрированных оригинальных изображений, а не количество логических иконок внутри ImageLists. Читайте их исходные байты из исполняемого файла или DLL, возвращаемой `GetFileName` (команда 3).

Для изображения с фактическим офсетом в файле `P` и фактивным количеством байт `N`, команда 61 возвращает `P - 8` , а команда 62 возвращает `N + 8`. Прибавьте 8 к возвращённому офсету и вычтите 8 из возвращённого размера:

```
Offset := GetInteger(GetFrxIconOffset, ImageIndex);
Size := GetInteger(GetFrxIconSize, ImageIndex);
FileStream.Position := Offset + 8;
ImageStream.CopyFrom(FileStream, Size - 8);
```

Проверьте индекс, скорректированный диапазон и сигнатуру полезной нагрузки перед чтением. Эти унаследованные корректировки не подразумевают наличия физического заголовка FRX в исполняемом файле Delphi. Полученная полезная нагрузка начинается с её сигнатуры BMP, PNG, JPEG, GIF, ICO или CUR; префиксы свойства DFM и заголовки контейнера ImageList исключены.

DE Decompiler регистрирует изображения во время декодирования двоичных значений формы DFM. Независимо закодированные изображения коллекции имеют отдельные записи. Оригинальное цветное растровое изображение и необязательная маска нативного ImageList остаются обычными записями растровых изображений, поэтому существующие плагины могут продолжать отображать или экспортировать полные листы.

63 — GetFrxImageListInfo

Передайте существующий индекс изображения в `vlNumber`; передайте ноль для `vlFnNumber` и нулевой указатель ввода. Для распознанного нативного цветного растрового изображения DFM ImageList текущий ответ:

```
IL1;<Count>;<Width>;<Height>;<Flags>;<MaskOffset>;<MaskSize>
```

| Поле | Значение |
| --- | --- |
| `Count` | Количество логических изображений, исключая резервную ёмкость. |
| `Width` , `Height` | Размеры ячейки в пикселях. |
| `Flags` | Исходные флаги ImageList. Бит 0 указывает на наличие маски; формат цвета `$20` указывает `ILC_COLOR32` . |
| `MaskOffset` | Фактическое смещение файла сигнатуры растрового изображения маски. Не добавляйте 8. |
| `MaskSize` | Фактное количество байт маски. Не вычитайте 8. |

Числовые поля представлены в десятичном формате и разделены точками с запятой. Оба поля маски равны нулю, если маска отсутствует. Цветные данные по-прежнему используют команды 61–62 и их унаследованную корректировку. Команда 63 возвращает только метаданные: она не изменяет индексы, не растеризует ячейки и не дублирует данные изображений в хосте.

Текущая `IL1` реализация распознаёт нативную версию потока `$0101` с растровыми листами BMP. Обычное изображение, неподдерживаемый поток или более старшая версия хоста могут вернуть пустую строку; недействительные индексы возвращают `Error`. Рассматривайте пустые ответы, ошибки, некорректные данные и ответы с неизвестной версией как неподдерживаемые и сохраняйте обработку целого изображения везде, где доступна исходная запись изображения.

Для индекса ячейки `K`, используйте логические координаты верхнего левого угла:

```
Columns := ColorBitmap.Width div CellWidth;
X := (K mod Columns) * CellWidth;
Y := (K div Columns) * CellHeight;
```

Требовать `0 <= K < Count`. Проверить геометрию и диапазоны файлов, а также учесть DIB-сканлайны с нижним началом. Применить соответствующую однобитовую маску или предварительно умноженный альфа-канал. В более старых 32-битовых списках может встречаться полностью нулевой альфа-канал; в этом случае маска остаётся резервным вариантом.

Предоставленный `shared/PluginSDK.pas` и `shared/modFrxImageList.pas` реализует геттеры, парсер и читатель ImageList, используемые обновлённым просмотрщиком. В приведённом ниже фрагменте предполагается, что `FileStream` открыт для анализируемого файла:

```
InfoText := GetString(GetFrxImageListInfo, ImageIndex);
if ParseFrxImageListInfo(InfoText, Info) then begin
  ColorOffset := GetInteger(GetFrxIconOffset, ImageIndex) + 8;
  ColorSize := GetInteger(GetFrxIconSize, ImageIndex) - 8;
  Images := TFrxImageList.Create(FileStream, ColorOffset, ColorSize, Info);
  try
    Icon := Images.Icon(0);
    try
      Icon.SaveToFile('Image_0.ico');
    finally
      Icon.Free;
    end;
  finally
    Images.Free;
  end;
end;
```

Читатель проверяет диапазоны и геометрию и использует общие элементы управления Windows для декодирования нативного списка. Перебрать каждый распознанный список один раз. Подавить его отдельную запись маски, сравнив фактическое смещение маски с каждым скорректированным смещением изображения плюс 8. Экспортируемые ячейки ICO-файлов являются производными изображениями со списка масок/альфа-канала; автономные изображения сохраняют свои исходные полезную нагрузку.

64 — GetProductName

Передайте нули для обоих индексов и нулевой указатель ввода. Результатом будет `VB Decompiler` или `DE Decompiler`, полученный из идентификатора загруженного хоста независимо от компилятора анализируемого файла.

Скопируйте каждую возвращаемую UTF-16-строку немедленно: указатель принадлежит хосту и остаётся действительным только до следующего обратного вызова. Предоставленный `DecompilerProductName` помощник проверяет ответ и переходит к `VB Decompiler` на более старых хостах. Сохраните исторические экспорты SDK, пути реестра и ключи локализации без изменений.

Совместимость и загрузки

- Существующие плагины продолжают использовать команды 60–62 без изменений.

- Обновлённый просмотрщик сохраняет поведение целого изображения на более старых хостах.

- Распознанные нативные DFM-списки используют команду 63 для индивидуальных предварительных просмотров ячеек и экспорта ICO; независимо закодированные изображения коллекций остаются обычными записями.

- VB5/6 и графика .NET сохраняют свои существующие пути извлечения.

- Эти новые геттеры не изменяют исходный файл, восстановленный код, формы или текущий выбор.

[Скачать общий SDK](https://www.de-decompiler.com/files/vb_decompiler_plugins_sdk.zip), включая ссылку на необязательную команду и вспомогательные средства Delphi. [Ознакомьтесь с предоставленными дополнениями SDK 26.6](https://www.de-decompiler.com/files/SDK_ADDITIONS_26_6.md). См. [FRX Image Viewer](https://www.de-decompiler.com/help/ru/plugins.htm#frx-image-viewer) для описания сценария работы пользователя.

[Скачайте общий плагин SDK](https://www.de-decompiler.com/files/vb_decompiler_plugins_sdk.zip) чтобы начать создание пользовательского расширения.

### SDK 26.6: открытые элементы, отметки и полные адреса

DE Decompiler 26.6 поддерживает следующие дополнительные команды через существующий callback PluginEngine. Вызывайте API в главном потоке приложения. Копируйте возвращённую строку UTF-16 до следующего callback; входные строки сохраняют существующий формат ANSI с завершающим нулём.

| ID | Константа | Аргументы и результат |
| --- | --- | --- |
| 65 | `GetDisplayedTreeItem` | Без аргументов. Возвращает TREE1;kind;module;function;form для открытого содержимого независимо от выделения в дереве; при отсутствии актуального элемента — пустую строку. |
| 66 | `GetModuleFunctionMark` | Индексы модуля и функции. Возвращает 0 или 1 либо пустую строку, если функции нет в текущем дереве. |
| 67 | `SetModuleFunctionMark` | Индексы модуля и функции; на входе 0 или 1. Возвращает 1 при успехе либо пустую строку, если функции нет в текущем дереве. |
| 68 | `FindModuleFunctionByVA` | На входе шестнадцатеричный адрес; в аргументе модуля — номер совпадения с нуля. Возвращает module,function для точного совпадения либо пустую строку, когда совпадений больше нет. |
| 69 | `GetModuleFunctionVA` | Индексы модуля и функции. Возвращает полный беззнаковый виртуальный адрес десятичной строкой с учётом PE ImageBase для x64. |

В TREE1 возможны виды function, module, unit, form, usercontrol, otherform, submain, root и other. Неиспользуемые индексы равны -1; юнит Delphi не представляется индексом модуля. Команда 55 по-прежнему возвращает координаты последней активной процедуры и может сохранять их при показе формы.

Отметки функций соответствуют действию клавиши Space. Чтение или установка отметки не открывает и не декомпилирует функцию, не меняет выделение и позицию курсора. Перестроение дерева может удалить отметки; эти команды не добавляют их сохранение в VDD.

Адрес на входе всегда шестнадцатеричный, даже если содержит только цифры; допустимы префиксы 0x и $. Поиск выполняется по точному адресу и позволяет перебрать функции с общим адресом. Для x64 принимаются полный VA и адрес модели совместимости. Команда 42 сохраняет прежний знаковый 32-битный результат. Это адреса нативного кода, а не токены метаданных.

Старые хосты возвращают пустую строку для неизвестных команд. Неверные индексы или входные данные, отклонённый вызов вне главного потока и запрещённая запись возвращают Error. Если полный адрес x64 недоступен, также возвращается Error. Явно обрабатывайте пустую строку и Error, сохраняя прежний резервный способ работы.

```
Current := GetString(GetDisplayedTreeItem);
Coords := FindFunctionByVA('0x89CB90');
State := GetString(GetModuleFunctionMark, 4, 51);
Reply := SetStringResult(SetModuleFunctionMark, '1', 4, 51);
FullVA := GetString(GetModuleFunctionVA, 4, 51);
```
