Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.218.168.16] |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Если это проблема оптимизации, её можно прекратить. Как-то делал так: // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #pragma warning (push) #pragma warning (disable:4700) #pragma optimize ("", off) // .......................................................................... BOOL WINAPI ... (...) { ... } // .......................................................................... #pragma optimize ("", on) #pragma warning (pop) Добавлено Значение "this" тоже проверь. Это просто указатель на объект. Например: pObject->SomeRoutine(...); -> pObject это и есть "this". |
Сообщ.
#17
,
|
|
|
Не надо чересчур обобщать, т.к. в данном случае речь идет о COM-интерфейсе WinAPI, поэтому параметр this передается не как-то особо\вычурно, а "на общих основаниях" в соответствии с конвенцией WINAPI (точнее говоря, safecall, что в данном случае не имеет значения, т.к. сам прототип функции соответствует этой конвенции). |
Сообщ.
#18
,
|
|
|
COM-интерфейс может по-разному быть реализован в соответствие с safecall, без оного или ещё каким причинам. Маршалинг никто не отменял. Это во-первых. А во-вторых, не вижу препятствий к тому, чтобы указатель на функцию заменить обратно на указатель на метод, как было в первом посту.
|
Сообщ.
#19
,
|
|
|
Второй суслик наверняка прячется в вольном обращении с V_BSTR(pVal) = L"NO_DATA"; Это же out-параметр COM-интерфейса, который должен подчиняться установленным правилам, а именно BSTR в pVal должна выделяться\очищаться системными функциями SysAllocString\SysFreeString (и т.п.). Если же ты просто присваиваешь значению pVal->bstrVal указатель на "неизвестно что", то впоследствии где-то возникает ошибка при попытке очистки этой строки через SysFreeString или VariantClear. PS: Поэтому и "наполовину рабочее" решение #15 не выдает ошибки, т.к. ты не изменяешь своим топорным методом pVal->bstrVal Цитата Mr.Newbie @ Пример кода того как пытался поменять значения у строковых переменных. Причем если после изменения вывести в консоль pVal, то оно будет изменено на "NO_DATA", а в dxdiag.exe изменениями и не пахнет. С чего им "пахнуть", если судя по #2 и #3 ты изменяешь pVal до вызова оригинальной функции Get, а не после нее. Это же out-параметр этой функции, соотв-но несмотря на переданное ей значение (судя по "списочку в консоли" туда всегда передается пустая строка), она всегда его переписывает своим значением. Добавлено Qraizer Ты опять обобщаешь и пытаешься найти суслика там, где его действительно нет Автор же привел в #15 "наполовину рабочее решение" (без манипуляций с pVal), которое работает без ошибок. Значит конвенция вызова на уровне ABI реализована верно, и соотв-но великий и всемогущий маршалинг (в данном случае) "тихо курит в сторонке" |
Сообщ.
#20
,
|
|
|
До следующего креативного обновления? Ну ок.
|
Сообщ.
#21
,
|
|
|
Цитата Это же out-параметр COM-интерфейса, который должен подчиняться установленным правилам, а именно BSTR в pVal должна выделяться\очищаться системными функциями SysAllocString\SysFreeString (и т.п.). Через SysAllocString\SysFreeString делал, толку ноль. Цитата С чего им "пахнуть", если судя по #2 и #3 ты изменяешь pVal до вызова оригинальной функции Get, а не после нее. Это же out-параметр этой функции, соотв-но несмотря на переданное ей значение (судя по "списочку в консоли" туда всегда передается пустая строка), она всегда его переписывает своим значением. Я думал вызов происходит не до и не после, а во время и вместо оригинальной Get подсовывается моя ф-я с измененным значением out-параметра. Так мне что искать еще сусликов или не ?) |
Сообщ.
#22
,
|
|
|
Цитата Qraizer @ До следующего креативного обновления? Ну ок. Ты что предлагаешь? Цитата Qraizer @ указатель на функцию заменить обратно на указатель на метод, как было в первом посту. Развей дальше эту идею. Или ты не знаешь, что указатель на метод (member function) - это в общем случае не просто указатель на функцию (о чём регулярно вопят в разделе "чистого С++"), и что внутреннее представление этих указателей является implementation specific и соотв-но может быть разным в разных компиляторах? Ты уверен, что во всех компиляторах указатель на виртуальный метод (какими являются все методы COM-интерфейса) должен быть именно указателем на саму функцию, а к примеру, не комбинацией указателя на vtable и смещения на указатель соответствующего метода в этой таблице? Мы же получаем этот указатель не для "внутреннего использования", а чтобы передать его в DetourAttach, которая принимает только обычные указатели и ес-но "ругается" на указатели на методы. А тайпкастить указатель на метод к void* - это либо верх наивности\глупости, либо "тайное" знание того, что в данном конкретном случае это прокатит и не приведет к AV или другим ошибкам. Спрашивается, чем это тайное знание лучше документированного (или полу-документированного) знания о том, что первым параметром в методы COM-интерфейса передается указатель на сам интерфейсный объект? Если можно реализовать COM-интерфейс с помощью абстрактного класса со стандартной конвенцией вызова в любом С++ компиляторе, то это означает, что параметр this должен передаваться также "стандартно" наравне с другими параметрами, а не как-то особо (через какой-то особый регистр - иначе это должно было было быть как-то особо документировано в WinAPI). Добавлено Цитата Mr.Newbie @ Я думал вызов происходит не до и не после, а во время и вместо оригинальной Get подсовывается моя ф-я с измененным значением out-параметра Сам понял, что сказал? Да, вместо оригинальной Get "подсовывается" твоя. Но ты же конце своей Get вызываешь оригинальную True_Get, которая изменят значение pVal, затирая все твои "художества". Соотв-но твоя Get возвращает наружу то, что выдала в pVal True_Get. Нужно либо вызывать True_Get по условию if ... else, либо изменять pVal не до, а после вызова True_Get. Цитата Mr.Newbie @ Через SysAllocString\SysFreeString делал, толку ноль. Может ты это до первого this-суслика делал? Покажи реальный код |
Сообщ.
#23
,
|
|
|
Цитата Развей дальше эту идею. Или ты не знаешь, что указатель на метод (member function) - это в общем случае не просто указатель на функцию (о чём регулярно вопят в разделе "чистого С++"), и что внутреннее представление этих указателей является implementation specific и соотв-но может быть разным в разных компиляторах? Ты уверен, что во всех компиляторах указатель на виртуальный метод (какими являются все методы COM-интерфейса) должен быть именно указателем на саму функцию, а к примеру, не комбинацией указателя на vtable и смещения на указатель соответствующего метода в этой таблице? Мы же получаем этот указатель не для "внутреннего использования", а чтобы передать его в DetourAttach, которая принимает только обычные указатели и ес-но "ругается" на указатели на методы. А тайпкастить указатель на метод к void* - это либо верх наивности\глупости, либо "тайное" знание того, что в данном конкретном случае это прокатит и не приведет к AV или другим ошибкам. Спрашивается, чем это тайное знание лучше документированного (или полу-документированного) знания о том, что первым параметром в методы COM-интерфейса передается указатель на сам интерфейсный объект? Если можно реализовать COM-интерфейс с помощью абстрактного класса со стандартной конвенцией вызова в любом С++ компиляторе, то это означает, что параметр this должен передаваться также "стандартно" наравне с другими параметрами, а не как-то особо (через какой-то особый регистр - иначе это должно было было быть как-то особо документировано в WinAPI). Цитата Нужно либо вызывать True_Get по условию if ... else, либо изменять pVal не до, а после вызова True_Get. После вызова True_Get ?! Это как ?! Цитата Автор же привел в #15 "наполовину рабочее решение" (без манипуляций с pVal), которое работает без ошибок. Не совсем.. если убрать DisableThreadLibraryCalls и влепить ApplyHooks напрямую без CreateThread, то через какое-то время dxdiag валится, при этом в консоле видно как перед этим он сотню раз раз обращается к Get. Добавлено И еще один странный момент, вывел в консоль &fn_real ф-и HookFunction и заметил как кое где проскакивают пустые значения. Такое возможно? и может ли это быть причиной вылета с ошибкой ? |
Сообщ.
#24
,
|
|
|
leo, давай ты не будешь мне читать лекции по Плюсам, ок? Если ты не понял, я именно поэтому и встрял в эту высокоэлитную беседу. Вместо демонстрации собственных навыков логического мышления, в наличии которых нет ничего плохого, когда они к месту, я первый пост читал.
|
Сообщ.
#25
,
|
|
|
Цитата Mr.Newbie @ После вызова True_Get ?! Это как ?! Ты прикидываешься или издеваешься? HRESULT res = True_Get(...); if (...) { //проверка res, wszName и pVal ... //если нужно, меняем pVal и\или res } return res; Цитата Mr.Newbie @ Не совсем.. если убрать DisableThreadLibraryCalls и влепить ApplyHooks напрямую без CreateThread, то через какое-то время dxdiag валится Потому, что у тебя суслик на суслике сидит и сусликом погоняет. В #2 у тебя было правильно - хук\перехват устанавливался только один раз при DLL_PROCESS_ATTACH, но из-за ошибок с this и pVal ничего не работало. Затем, начиная с #3 ты зачем-то убрал условие DLL_PROCESS_ATTACH, и соотв-но твой код перехвата стал срабатывать множество раз при создании (а в #3 и при завершении) потоков приложения. Поэтому тебе пришлось добавить DisableThreadLibraryCalls, чтобы запретить повторные срабатывания кроме первого. Резюме: нужно исправить свои собственные баги (с неучетом this, с неправильной установкой pVal и т.п.) и вернуться к стандартной схеме установки хука\перехвата функции с помощью Detours (с учетом многопоточности приложения). Как правильно устанавливать этот перехват - это отдельный вопрос, который наверняка можно найти в документации и\или примерах использования Detours. |
Сообщ.
#26
,
|
|
|
Цитата Qraizer @ leo, давай ты не будешь мне читать лекции по Плюсам, ок? 1) И не думал этого делать. В Плюсах я "не в зуб ногой", о чем уже сотню раз говорил. Поэтому в ваши "чистые С++" дела принципиально не лезу. 2) В данном случае речь идет не о Плюсах, а о низкоуровневом перехвате функций с помощью DetoursAttach. Чем тут могут помочь ("высокоуровневые" implementation specific) указатели на методы, я искренне не понимаю. Если ты знаешь - поделись. 3) Какое отношение к Плюсам имеет способ передачи указателя this в технологии COM, я тоже не понимаю. COM это универсальная технология, которую можно использовать в разных ЯП. Если я вижу\знаю как передается this при вызове метода COM-интерфейса в своем "родном" дельфи\паскале, то почему он должен или может передаваться иначе в MSVC (managed code ЯП не в счет)? Да, маршаллинг никто не отменял, но для системных WinAPI интерфейсов этот маршаллинг (если он используется) должен быть зашит в самих системных dll, которые представляют эти интерфейсы. Т.е. dll должна представлять пользователям стандартный ABI интерфейс вызова методов, а то, куда она его дальше транслирует и как-то маршаллит, это уже её личное\приватное дело. Или я не прав? |
Сообщ.
#27
,
|
|
|
Цитата leo @ Поэтому в ваши "чистые С++" дела принципиально не лезу. Вступай в нашу банду, leo. - Ловля сусликов с любой шкуркой. - Самые брутальные дискуссии, плавно переходящие "в зуб ногой". - Широкие возможности влезать в "чиста С++". и множество других бонусов и удовольствий, не доступных в Дельфи ! |
Сообщ.
#28
,
|
|
|
Цитата Ты прикидываешься или издеваешься? Мозг отказал Цитата В #2 у тебя было правильно - хук\перехват устанавливался только один раз при DLL_PROCESS_ATTACH, но из-за ошибок с this и pVal ничего не работало. Затем, начиная с #3 ты зачем-то убрал условие DLL_PROCESS_ATTACH, и соотв-но твой код перехвата стал срабатывать множество раз при создании (а в #3 и при завершении) потоков приложения. Поэтому тебе пришлось добавить DisableThreadLibraryCalls, чтобы запретить повторные срабатывания кроме первого. Если ставлю DLL_PROCESS_ATTACH, то отрабатывает один раз и все. |
Сообщ.
#29
,
|
|
|
Цитата Mr.Newbie @ Если ставлю DLL_PROCESS_ATTACH, то отрабатывает один раз и все Это может означать то, что приложение грузит dll динамически и выгружает ее после использования. Поэтому и твой однократный хук перестает работать, и "кое где проскакивают пустые значения" fn_real, если ты пытаешься ставить перехват в момент, когда dll не загружена. Выход из этой ситуации - обеспечить загрузку этой dll самому. Можно либо создать ссылку на соответствующий интерфейсный объект и хранить ее в глоб.\стат. переменной до выгрузки dll, либо просто вызвать LoadLibrary. То и другое лучше делать в отдельном потоке ApplyHooks, т.к. грузить либы в DllMain не рекомендуется. Кстати, в этом же потоке можно организовать периодическую проверку загрузки dll и установки хука по таймеру на случай, если он по какой-то (очередной непонятной) причине слетит. |
Сообщ.
#30
,
|
|
|
Цитата leo @ т.к. грузить либы в DllMain не рекомендуется В DllMain вообще ничего делать не рекомендуется, кроме получения статуса загрузки/выгрузки и выделения/освобождения динамической локальной памяти |