| 
 
				Bers, продолжим здесь. baratorch Wrote:Berserker Wrote:На мой взгляд, указанная тобой, Бара, проверка, неэффективна. Мало ли из какого кода какого модуля вызывается запись патча? Из ЕРМ? Из сгенерированного в оперативной памяти обработчика? Из модуля, который использует функционал другого?Берс, я хочу чтобы у тебя там все работало с патчером.
 Patcher := Core.GlobalPatcher.CreateInstance(pchar(GetUniquePatchName(BinPatchSource)));
 Я создавал по экземпляру патчера для каждого файла-заплатки под уникальным именем и тут же пробовал через этот объект вносить изменения в цикле:
 Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);
 В итоге ошибки и, как следствие, вылеты.
 Но что ты предлагаешь, убрать эту проверку совсем?
 Мне это сделать не сложно. Я задавал вопросы, чтобы понять, можно ли решить твою проблему не трогая патчер, но ситуацию ты не прояснил.
 
 Я пока не представляю себе случая когда модулю нужно создать патчер_инстанс, но не писать патч, а модулю не создававшему использовать чужой патчер_инстанс чтобы создавать патч; и чтобы требуемую задачу нелзя было полностью решить с помощью того что есть сейчас.
 Покажи мне конкретный пример (из твоих слов о цикле и заплатках мне ничего не понятно).
 
 Если убрать эту проверку, то (как мне кажется) теряется вообще смысл в классе PatcherInstance. И как тогда отслеживать авторов патчей в логе и дампе (одна из важнейших фич патчера), если автором патча может быть кто угодно, вместо обозначенного?
 
 
 
 Quote:Patcher := Core.GlobalPatcher.CreateInstance(pchar(GetUniquePatchName(BinPatchSource)));Вот я написанное понимаю так, что и инстанция и патч через эту инстанцию создаются в одном куске кода, т.е. без вариантов в одном модуле (pe-файле... dll/exe).Я создавал по экземпляру патчера для каждого файла-заплатки под уникальным именем и тут же пробовал через этот объект вносить изменения в цикле:
 Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);
 Поэтому та проверка (на идейном плане), считаю, не может быть помехой (разве что в ее реализации косяки).
 
 вот код из ХД:
 
 
 
Code:
 void LoadBinPatch(char* file_name){
 DWORD fr;
 _dword_ patches_count = 0;
 _dword_ patch_size = 0;
 _byte_ patch_data[2048];
 _ptr_ address = 0;
 HANDLE hFile = INVALID_HANDLE_VALUE;
 hFile = CreateFile(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 if (hFile != INVALID_HANDLE_VALUE)
 {
 PatcherInstance* _PIbin = _P->CreateInstance(Base::GetShortFileName(file_name));
 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
 if (ReadFile(hFile, (LPVOID)&patches_count, 4, &fr,  NULL))
 for (int i = 0; i < patches_count; i++)
 if (ReadFile(hFile, (LPVOID)&address, 4, &fr,  NULL))
 if (ReadFile(hFile, (LPVOID)&patch_size, 4, &fr,  NULL))
 {
 if (patch_size > 2048) BREAKPOINT;
 if (ReadFile(hFile, (LPVOID)&patch_data, patch_size, &fr,  NULL))
 {
 _PIbin->Write(address, (_ptr_)patch_data, patch_size);
 }
 
 }
 CloseHandle(hFile);
 }
 }
 
 ...
 
 void LoadBinPatches(char* dir)
 {
 WIN32_FIND_DATA file_find_data;
 HANDLE h_search;
 BOOL finished = FALSE;
 
 Base::dir_set(dir);
 h_search = FindFirstFile("*.bin", &file_find_data);
 if (h_search == INVALID_HANDLE_VALUE)
 {
 Base::dir_restore();
 return;
 }
 
 while (!finished)
 {
 //////////////////////////////////////
 LoadBinPatch(file_find_data.cFileName);
 //////////////////////////////////////
 
 if (!FindNextFile(h_search, &file_find_data))
 if (GetLastError() == ERROR_NO_MORE_FILES)
 finished = TRUE;
 else
 {
 FindClose(h_search);
 Base::dir_restore();
 return;
 }
 }
 
 FindClose(h_search);
 Base::dir_restore();
 }
 в цикле вызывается создание инстанций для каждой заплатки и запись патча этой заплатки через созданную инстанцию.
 по-моему то же самое. все работает.
 
 ...
 
Я понял в чем дело.
 
Нужно заменить
 
Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, CODE_PATCH);
 
на
 
Patcher.Write(cardinal(Patch.Addr), cardinal(@Patch.Bytes), Patch.NumBytes, DATA_PATCH);
 
Это не очевидно, но я объясню почему.
 
Я понимаю что, практически все сочиняемые пачти подразумевают содержание кода. Однако CODE_PATCH в Методе Write 
означает не то что 'мы пишем код',  а то что данные по адресу @Patch.Bytes будут восприниматься как код.
 
Возмем пример из ченджлога к патчеру 2.5. 
Допустим мы хотим поставить патч 0x639C40: call 0x447799. 
В бин-файле это будет записано в прямом виде:    0x639C40, 5,  E8  54 DB E0 FF 
после считывания в Patch.Bytes будет E8 54 DB E0 FF 
но ведь @Patch.Bytes не равен 0x639C40!!! 
а значит если мы подразумеваем что по адресу  @Patch.Bytes код, а не данные, то E8 54 DB E0 FF будет вызывать не 0x447799, а функцию заданную адресом относительным к @Patch.Bytes. 
Ну вот представь, что мы процессору передали на выполнение адрес @Patch.Bytes: будет вызвана функция не 0x447799, а совершенно левая.
 
***
 
Еще раз повторю вопрос: что выдает лог патчера?
 
создаем рядом с patcher_x86.dll - patcher_x86.ini c записью Logging = 1 
и после установки всех патчей вызываем Patcher::SaveLog(char* file_name).
 
если в логе отсутствуют записи  
ERROR!   Can not create ... at ... (...): Wrong Patcher Instance! 
то проверка на верный модуль ни при чем, а дело в CODE_PATCH
 
жду ответа.
			 |