4.1 Достаточный минимум Путем некоторых исследований, мной было установлено, что для простой подгрузки своих native-функций нет надобности возить за собой весь grimoire: достаточно минимального комплекта: bin\<ваша библиотека>.dll bin\japi.dll bin\ongameload.dll bin\exehack.exe startwar3.bat lua5.1.dll findpath.lua ongameload.lua war3.lua Его прилагаю к сей статье. 4.2 Код базовой библиотеки для Delphi Благодаря AiwaDoter, теперь доступен код базовой библиотеки для добавления native функций для Delphi. Вот он: unit jAPIDLL; { library by AiwaDoter } {$DEFINE DYNAMIC} { закомментируйте эту директиву, чтобы реализовать статический импорт если он нужен } interface {$IFDEF DYNAMIC} { Объявления процедур для динамического импорта } procedure jStartAPI; {$ELSE} { Объявления процедур для статического импорта } {$ENDIF} implementation {$IFDEF DYNAMIC} uses Windows; { библиотека Windows } type { создание нестандартных типов и процедур библиотеки jAPI } jString = longint; jInt = longint; jReal = longint; AddNative = procedure(routine: Pointer; name: PChar; prototype: PChar); cdecl; StrMap = function(const str: PChar): jString; cdecl; StrGet = function(strid: jString): PChar; cdecl; var { Логический номер модуля DLL } LibInstance : HMODULE; jAddNative: AddNative; jStrMap: StrMap; jStrGet: StrGet; { функция нативы которую хотим внедрить в процес } function test: jString; stdcall; begin Result:= jStrMap('ZOMG TEH FUNC! - DELPHI'); end; procedure jStartAPI; begin if(LibInstance = 0)then begin { если DLL еще не загружена, попытаемся загрузить } LibInstance := LoadLibrary('japi.dll'); { Если LoadLibrary возвращает 0, произошла ошибка } if(LibInstance = 0)then begin MessageBox(0, 'Could not locate jAPI', 'Error', MB_ICONEXCLAMATION or MB_OK); exit; end; { DLL загружена, теперь попытаемся найти функции } jAddNative:= AddNative(GetProcAddress(LibInstance, 'jAddNative')); if(Not Assigned(jAddNative))then { Если GetProcAddress возвращает Nil, возникли проблемы } MessageBox(0, 'Could not find jAddNative', 'Error', MB_ICONEXCLAMATION or MB_OK); jStrMap:= StrMap(GetProcAddress(LibInstance, 'jStrMap')); if(Not Assigned(jStrMap))then MessageBox(0, 'Could not find jStrMap', 'Error', MB_ICONEXCLAMATION or MB_OK); jStrGet:= StrGet(GetProcAddress(LibInstance, 'jStrGet')); if(Not Assigned(jStrGet))then MessageBox(0, 'Could not find jStrGet', 'Error', MB_ICONEXCLAMATION or MB_OK); end; { здесь передаем адрес функции "test" задаем имя нативы и ее параметры } jAddNative(@test, 'test', '()S'); end; initialization LibInstance := 0; jAddNative:=Nil; jStrMap:=Nil; jStrGet:=Nil; finalization { Если DLL была загружена, ее обязательно нужно выгрузить } if(LibInstance<>0)then begin FreeLibrary(LibInstance); LibInstance:= 0; end; end. {$ELSE} end. {$ENDIF} 4.3 Избавление от придирок антивирусов Используя небольшую хитрость, можно добиться отказа от использования exehack.exe, что положительно повлияет на весь комплект: именно этот файл антивирусы чаще всего считают вредным. Также использование этой хитрости позволяет запускать варкрафт с добавленными native функциями в linux (естественно, из-под wine). Итак, порядок действий: 1. Скачать PEditor http://www.softpedia.com/get/Programming/File-Editors/PEditor.shtml 2. Скопировать папку bin/ нашей сборки в PEditor/bin 3. Скопировать lua5.1.dll в PEditor/ 4. Сделать резервную копию war3.exe 5. PEditor -> открыть war3.exe -> directory -> imports, щелчок правой кнопкой add import: dll name = bin/ongameload.dll, func name = DllMain 6. Нажать +, нажать OK, выйти из PEditor Дело сделано! Теперь можно заменить оригинальный war3.exe в папке игры (не забудьте сделать резервную копию!) и наслаждаться. Этот метод позволяет исключить из списка возимых за собой файлов exehack.exe, startwar3.bat, findpath.lua и war3.lua. Важно! При выполнении пункта 5, PEditor может выдать ошибку плана "Сan't find the "DllMain" function in the dll". Тогда вам нужно открыть ongameload.dll в любом просмотрщике ресурсов (рекомендую CFF Explorer — кстати в нем можно и импорт прописывать, даже удобнее: на PEditor антивирусы все еще могут ругнуться), найти таблицу экспорта и в ней посмотреть, имя какой функции содержит что-то, намекающее на загрузку (в моем случае это было _Z16LoadLibraryAWrapPKc@4) — её и использовать в этом шаге.
|