[Q]: Как Win32-EXE переносятся в OS/2? Что такое Odin, Open32, INNOWIN? [A]: Andrew Belov (2:5020/181.2) Попытаемся вспомнить несколько технологий: 1. IBM Open32 (в прошлом DAPIE или DAX) В эпоху NT v 3.5 задачу совместимости с Win32 начали решать с помощью Developer API Extensions (DAX). Было решено продолжить опыт проектов WLO и MIRRORS (библиотеки для миграции из Win16 в PM) и рассчитывать на инициативу разработчиков конкретных приложений. Ближе к XR_W017 внутри PMMERGE.DLL выросла стопка функций, дополняющих PM API некоторыми Win32-понятиями (Caret'ы и т.п.), и появились PMWINX/PMDDEML - сборники Win32-API. Ресурсы GUI при таком подходе должны были приводиться к PM'мному формату (поэтому внешний вид и поведение перенесенного софта слабо отличались от PM'ного), хранение настроек поощрялось в стандартных *.INI. Сам софт целиком пересобирался OS/2-компиляторами, при этом все API, не охваченные Open32, например, WINMM, оставались на совести программиста. LX-EXE Open32 OS/2 +---------------+ +--------------+ | Вызовы W32 API| -> [PMWINX.DLL, PMDDEML.DLL] -> | ... | +---------------+ | PMMERGE.DLL | |Вызовы OS/2 API| ------------------------------> | | +---------------+ | DOSCALL1.DLL | | PM-ресурсы | | ... | +---------------+ +--------------+ По этой технологии перенесены все SmartSuite после 1996 г. и мифический MGI PhotoSuite. Оверхед - 1M памяти для PMWINX. 2. Довески - REGISTRY.DLL и WGSS4?.DLL В конце 1997 г. IBM слегка дополнил мерлиновский PMWINX.DLL и выпустил два "довеска", архитектурно независимых от Open32. REGISTRY.DLL - воспроизводит Win32'шные API Reg*, позволяя любой OS/2'шной программе работать с древовидным "реестром" (физически он находится в \OS2\SYSTEM\*.DAT) и не прибегать к "родным" Prf*. Изначально реестр был центральной концепцией в OS/2 for PowerPC (configuration namespace), но на i386 он оказался полезным для портирования из Win32. WGSS4?.DLL - были придуманы для собственных нужд портирования Netscape 4.xx (первые альфы 4.03/4.04 еще использовали PMWINX.DLL). Они содержат только ограниченное подмножество функций Gpi*, оверхед - сотни килобайт. LX-EXE OS/2 +-----------------+ +--------------+ | Вызовы GDI32, | --------> WGSS46.DLL -------> | PMMERGE.DLL | | ADVAPI32 | --------> REGISTRY.DLL -------> | DOSCALL1.DLL | +-----------------+ +--------------+ | Вызовы OS/2 API | ------------------------------> | | +-----------------+ | *.DLL | | PM-ресурсы | | | +-----------------+ +--------------+ 3. Win32-OS/2 В 1997 г. несколько энтузиастов развили идею Open32: заметив, что формат EXE и DLL в Win32 (Portable Executable - PE) не успел далеко уйти от OS/2 (Linear eXecutable - LX), они выпустили конвертор - PE2LX.EXE. Win32-программа превращалась в OS/2-программу, импортировавшую библиотеки под теми же именами, но в OS/2'шном формате. Ресурсы по возможности/необходимости приводились конвертором к формату PM. Соответственно, были написаны LX-аналоги USER32.DLL, KERNEL32.DLL и прочей системщины, составившие рантайм Win32-OS/2. Отсутствующие в PMWINX.DLL интерфейсы были доделаны вручную - появились WINMM, TAPI32, DDRAW, ... Некоторые "несистемные" DLL, например, COMCTL32.DLL, предлагалось конвертировать из ближайшего дистрибутива WinNT. Все PE-библиотеки из комплекта устанавливаемого Win32-софта также подлежали конвертации. LX-EXE (полученный из PE) LX-DLL (полученная из PE) +--------------+ +--------------------+ |Вызовы несист.| ----> |Выз. сист. Win32-DLL| | Win32-DLL | +----------||--------+ OS/2 | Вызовы сист. | +------\/----------+ Open32 +-----+ | Win32-DLL | --------> | Вызовы OS/2-DLL | -->[PMWINX]--> |*.DLL| +--------------+ +------------------+ -------------> +-----+ | PM-ресурсы + | Рантайм Win32-OS/2 |Win32-ресурсы | (KERNEL32, USER32, GDI32...) +--------------+ Благодаря конвертору требование перекомпиляции исчезло - первым примером работы Win32-OS/2 стал Quake II-OS/2, сделанный из Win32-бинарников. Оверхед - больший в сравнении с перекомпиляцией под Open32 (1.5-4M), но главное - принципиальная невозможность конвертации многих (например, сжатых) PE-EXE и отсутствие перспектив из-за прекращения развития Open32 API. 4. Project Odin Для оживления Win32-OS/2 пришлось наращивать уровни абстракции. USER32.DLL и COMCTL32.DLL были перестроены на исходниках проекта WINE - элементы GUI отныне отрисовываются "с нуля", и сходство с PM'ом было восстановлено только путем ручной имитации PM'ного оформления. Примером нового подхода был RealPlayer/Win32 из комплекта eComStation v 1.00. PE2LX.EXE был официально заменен WIN32K.SYS и PE.EXE. Преобразование PE -> LX происходит "на лету" внутри KERNEL32.DLL. Впоследствии команда выпустила новый PE2LX (XX2LX.EXE), который вместо полноценной конвертации порождал суррогат (грубо говоря, результатом был упрощенный LX-загрузчик с прикрепленным в "хвосте" слегка переваренным имиджем исходного PE-файла). Вопрос "какие DLL вызываются и надо ли их перегонять в LX?" быстро отошел на второй план. По мере того, как проект переезжал на рельсы WINE, за Open32 остался только минимум API. В 2001 г. Innotek GmbH получил от IBM исходники WGSS46.DLL и части PMWINX.DLL, объединив их в closed-source модуль WGSS50.DLL. В результате проект Odin ныне упирается только в фундаментальные ограничения OS/2 и PM. PE-EXE: Odin-рантайм: OS/2: +---------+ +-+--------++--------++ +----------+ |Win32-код|\-> PE.EXE/WIN32K.SYS -> |K| USER32 || WGSS50 | -> | PMMERGE | +---------+ \ |E| GDI32 ++========++ | PMGPI | \ +-PE-DLL:-+ |R| WINMM | | MDM | LX (из PE): > |Win32-код| <----> |N| DDRAW | | DIVE | +---------+ / +---------+ |E| ADVAPI32 | -> | REGISTRY | |OS/2-stub| ----------------------> |L| WSOCK32 | | SO32DLL | +---------+/ |3| NTDLL ++========++ | DOSCALL1 | |модиф.код| <---------------------> |2| ... || ODINCRT | -> | ... | +---------+ +-+--------++---------+ +----------+ Оверхед при такой схеме заметно вырос (4-10M + перерасход памяти на 10-20% по сравнению с NT), Помимо этого, многообразие "прослоек" сильно сказалось на быстродействии и стабильности. 5. Odin Custom-Build (INNOWIN.DLL, OPODIN32.DLL, VPCWIN32.DLL, ...) Поскольку PE.EXE отменил необходимость наличия отдельных USER32.DLL/GDI32.DLL и т.д., появилась возможность собирать требуемые модули в одну общую DLL и загружать с ней как OS/2'шные (перекомпилированные) приложения, так и исходные Win32'шные. При этом новому билду можно назначить собственную ветку в Registry, которую не затронут эксперименты юзера с "общим" Odin'ом. Первый пример - Opera/2 v 5.12 (1999-2002) - тщательно проработанный порт браузера в OS/2, собранный VisualAge C++ в родной LX-EXE и использующий Odin наравне с некоторыми нативными API. Имея внутри Odin'овскую KERNEL32.DLL, порт может подгружать Win32-плагины в неизменном виде. OPERA*.EXE (LX) OPODIN32.DLL OS/2 +--------------+ +--------++--------+ +-----------------+ | | ------------> | USER32 ||OPWGSS50| -> | | | | | GDI32 |+========+ | | |Портированная | PE-DLL | ... || OPCRT | | | | часть | +-----------+ | ... ++======+-+ | Системные | | | | Win32- | | KERNEL32 + | -> | *.DLL | | | | плагины |<->| PE-загрузчик | | | | | +-----------+ +----------------+ | | +--------------+ | | | OS/2-код | --------------------------------------> | | +--------------+ +-----------------+ "Новый" XX2LX.EXE нашел применение в Innotek Virtual PC for OS/2 (2001-2002), где исходники собирались уже Visual C++ v 6.0, а результирующий PE-EXE переводился под OS/2 с помощью конвертора. Этот же проект привнес в KERNEL32 роутер запросов к драйверам - для портирования софта, где часть операций выполнялась в привилегированном режиме через драйвер (драйвер, естественно, переписывался с нуля). VPC.EXE (PE->LX) VPCWIN.DLL OS/2 +--------------+ +--------++--------+ +-----------------+ | OS/2-stub | ------------> | USER32 ||VPCWGSS | -> | | +--------------+ | GDI32 |+========+ | Системные | | Модифицир. | +----------+ |KERNEL32|| VPCCRT | -> | | | | | R0-helper| | ... ++=======++ | *.DLL | | Win32-код | |VPCAPP.SYS|<--| роутер IOCtl'ов | | | +--------------+ +----------+ +-----------------+ +-----------------+ В последующих проектах (2004 г.) Innotek окончательно спрямил XX2LX.EXE до формулы "PE.EXE + Win32-модуль в одном бинарнике". В Java и OpenOffice соответствующие *.EXE состоят из типового LX-загрузчика, следом за которым идет полная копия исходного Win32-EXE и указатель на его начало. Заодно был введен единый closed-source рантайм INNOWIN.DLL, поглотивший WGSS и ODINCRT (рантайм VisualAge), а вся специфика конкретных портов при необходимости выносилась в мелкие "объединительные" модули. SOFFICE.EXE, JAVA.EXE OS/2 +---------------------+ Запрос путей к DLL через Registry +--------------+ | Универсальный |-----------------------------------> | | | OS/2-stub |-+ | | +---------------------+ | Объединительный модуль | | | | | +----------------------+ | | | | +->| OOWIN.DLL, J2WIN.DLL | | Системные | | Немодифицированный | +----------||----------+ | *.DLL | | Win32-код | || | | | | +----------\/----------+ | | | |<-->| INNOWIN.DLL | ----> | | | | +----------------------+ | | +---------------------+ Innotek Win32 Runtime +--------------+ Параллельно были изобретены врапперы для плагинов к Netscape (Java, Acrobat Reader и Flash 7). Они базируются на общем прототипе под названием NPOdin и обращаются через INNOWIN-рантайм к Win32-плагину для Netscape, который в свою очередь может взаимодействовать с любыми PE-DLL из Win32-мира: LX : PE Flash 6/Flash 7: : +------------+-------------------------+--------------+ | NPSWF2.DLL | FLASHWIN.DLL | NPSWF32.DLL | +------------+-------------------------+--------------+ : Innotek Kit for Java: : +------------+-----------+-------------+--------------+ | NPJ2.DLL | J2WIN.DLL | INNOWIN.DLL | NPOJI610.DLL | -> Sun JRE/Win32 +------------+-----------+-------------+--------------+ : Yuri Dario выпустил комплект для самостоятельного изготовления врапперов к Win32-плагинам - NpWrap. Врапперы работают с обычным Odin (не с INNOWIN), по архитектуре NpWrap аналогичен NPOdin, но объединительные модули здесь не требуются.