На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> Подмена данных о GPU с помощью MS Detours 3.0 , Не получается перехватить и подменить IEnumWbemClassObject::CreateInstanceEnum
    Цитата Qraizer @
    Цитата Mr.Newbie‎ @
    Calling Conventions - совпадают.
    Это не имеет значения. this может передаваться в регистре.

    Если это проблема оптимизации, её можно прекратить.
    Как-то делал так:
    ExpandedWrap disabled
      // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      #pragma warning (push)
      #pragma warning (disable:4700)
      #pragma optimize ("", off)
      // ..........................................................................
      BOOL WINAPI ... (...)
      {
       ...
      }
      // ..........................................................................
      #pragma optimize ("", on)
      #pragma warning (pop)


    Добавлено
    Цитата Mr.Newbie‎ @
    Пришел к такому решению, оно наполовину рабочее...

    Значение "this" тоже проверь. Это просто указатель на объект.
    Например:
    pObject->SomeRoutine(...); -> pObject это и есть "this".
      Цитата Qraizer @
      Цитата Mr.Newbie‎ @
      Calling Conventions - совпадают.

      Это не имеет значения. this может передаваться в регистре.

      Не надо чересчур обобщать, т.к. в данном случае речь идет о COM-интерфейсе WinAPI, поэтому параметр this передается не как-то особо\вычурно, а "на общих основаниях" в соответствии с конвенцией WINAPI (точнее говоря, safecall, что в данном случае не имеет значения, т.к. сам прототип функции соответствует этой конвенции).
        COM-интерфейс может по-разному быть реализован в соответствие с safecall, без оного или ещё каким причинам. Маршалинг никто не отменял. Это во-первых. А во-вторых, не вижу препятствий к тому, чтобы указатель на функцию заменить обратно на указатель на метод, как было в первом посту.
          Цитата ЫукпШ @
          Доказательство как бы намекает, что суслик может быть не один

          :yes:
          Второй суслик наверняка прячется в вольном обращении с 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 реализована верно, и соотв-но великий и всемогущий маршалинг (в данном случае) "тихо курит в сторонке" :)
            До следующего креативного обновления? Ну ок.
              Цитата
              Это же out-параметр COM-интерфейса, который должен подчиняться установленным правилам, а именно BSTR в pVal должна выделяться\очищаться системными функциями SysAllocString\SysFreeString (и т.п.).


              Через SysAllocString\SysFreeString делал, толку ноль.

              Цитата
              С чего им "пахнуть", если судя по #2 и #3 ты изменяешь pVal до вызова оригинальной функции Get, а не после нее. Это же out-параметр этой функции, соотв-но несмотря на переданное ей значение (судя по "списочку в консоли" туда всегда передается пустая строка), она всегда его переписывает своим значением.


              Я думал вызов происходит не до и не после, а во время и вместо оригинальной Get подсовывается моя ф-я с измененным значением out-параметра. :scratch:

              Так мне что искать еще сусликов или не ?)
                Цитата Qraizer @
                До следующего креативного обновления? Ну ок.

                Ты что предлагаешь?
                Цитата Qraizer @
                указатель на функцию заменить обратно на указатель на метод, как было в первом посту.

                Развей дальше эту идею. Или ты не знаешь, что указатель на метод (member function) - это в общем случае не просто указатель на функцию (о чём регулярно вопят в разделе "чистого С++"), и что внутреннее представление этих указателей является implementation specific и соотв-но может быть разным в разных компиляторах? Ты уверен, что во всех компиляторах указатель на виртуальный метод (какими являются все методы COM-интерфейса) должен быть именно указателем на саму функцию, а к примеру, не комбинацией указателя на vtable и смещения на указатель соответствующего метода в этой таблице?
                Мы же получаем этот указатель не для "внутреннего использования", а чтобы передать его в DetourAttach, которая принимает только обычные указатели и ес-но "ругается" на указатели на методы. А тайпкастить указатель на метод к void* - это либо верх наивности\глупости, либо "тайное" знание того, что в данном конкретном случае это прокатит и не приведет к AV или другим ошибкам. Спрашивается, чем это тайное знание лучше документированного (или полу-документированного) знания о том, что первым параметром в методы COM-интерфейса передается указатель на сам интерфейсный объект? Если можно реализовать COM-интерфейс с помощью абстрактного класса со стандартной конвенцией вызова в любом С++ компиляторе, то это означает, что параметр this должен передаваться также "стандартно" наравне с другими параметрами, а не как-то особо (через какой-то особый регистр - иначе это должно было было быть как-то особо документировано в WinAPI).

                Добавлено
                Цитата Mr.Newbie‎ @
                Я думал вызов происходит не до и не после, а во время и вместо оригинальной Get подсовывается моя ф-я с измененным значением out-параметра

                :wacko: Сам понял, что сказал?
                Да, вместо оригинальной Get "подсовывается" твоя. Но ты же конце своей Get вызываешь оригинальную True_Get, которая изменят значение pVal, затирая все твои "художества". Соотв-но твоя Get возвращает наружу то, что выдала в pVal True_Get. Нужно либо вызывать True_Get по условию if ... else, либо изменять pVal не до, а после вызова True_Get.

                Цитата Mr.Newbie‎ @
                Через SysAllocString\SysFreeString делал, толку ноль.

                Может ты это до первого this-суслика делал? Покажи реальный код
                Сообщение отредактировано: leo -
                  Цитата
                  Развей дальше эту идею. Или ты не знаешь, что указатель на метод (member function) - это в общем случае не просто указатель на функцию (о чём регулярно вопят в разделе "чистого С++"), и что внутреннее представление этих указателей является implementation specific и соотв-но может быть разным в разных компиляторах? Ты уверен, что во всех компиляторах указатель на виртуальный метод (какими являются все методы COM-интерфейса) должен быть именно указателем на саму функцию, а к примеру, не комбинацией указателя на vtable и смещения на указатель соответствующего метода в этой таблице?
                  Мы же получаем этот указатель не для "внутреннего использования", а чтобы передать его в DetourAttach, которая принимает только обычные указатели и ес-но "ругается" на указатели на методы. А тайпкастить указатель на метод к void* - это либо верх наивности\глупости, либо "тайное" знание того, что в данном конкретном случае это прокатит и не приведет к AV или другим ошибкам. Спрашивается, чем это тайное знание лучше документированного (или полу-документированного) знания о том, что первым параметром в методы COM-интерфейса передается указатель на сам интерфейсный объект? Если можно реализовать COM-интерфейс с помощью абстрактного класса со стандартной конвенцией вызова в любом С++ компиляторе, то это означает, что параметр this должен передаваться также "стандартно" наравне с другими параметрами, а не как-то особо (через какой-то особый регистр - иначе это должно было было быть как-то особо документировано в WinAPI).


                  user posted image

                  Цитата
                  Нужно либо вызывать True_Get по условию if ... else, либо изменять pVal не до, а после вызова True_Get.

                  После вызова True_Get ?! Это как ?! :blink:

                  Цитата
                  Автор же привел в #15 "наполовину рабочее решение" (без манипуляций с pVal), которое работает без ошибок.

                  Не совсем.. если убрать DisableThreadLibraryCalls и влепить ApplyHooks напрямую без CreateThread, то через какое-то время dxdiag валится, при этом в консоле видно как перед этим он сотню раз раз обращается к Get.

                  Добавлено
                  И еще один странный момент, вывел в консоль &fn_real ф-и HookFunction и заметил как кое где проскакивают пустые значения. Такое возможно? и может ли это быть причиной вылета с ошибкой ?
                  Сообщение отредактировано: Mr.Newbie‎ -
                    leo, давай ты не будешь мне читать лекции по Плюсам, ок? Если ты не понял, я именно поэтому и встрял в эту высокоэлитную беседу. Вместо демонстрации собственных навыков логического мышления, в наличии которых нет ничего плохого, когда они к месту, я первый пост читал.
                      Цитата Mr.Newbie‎ @
                      После вызова True_Get ?! Это как ?! :blink:

                      Ты прикидываешься или издеваешься? :angry:
                      ExpandedWrap disabled
                        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.
                        Цитата Qraizer @
                        leo, давай ты не будешь мне читать лекции по Плюсам, ок?

                        1) И не думал этого делать. В Плюсах я "не в зуб ногой", о чем уже сотню раз говорил. Поэтому в ваши "чистые С++" дела принципиально не лезу.
                        2) В данном случае речь идет не о Плюсах, а о низкоуровневом перехвате функций с помощью DetoursAttach. Чем тут могут помочь ("высокоуровневые" implementation specific) указатели на методы, я искренне не понимаю. Если ты знаешь - поделись.
                        3) Какое отношение к Плюсам имеет способ передачи указателя this в технологии COM, я тоже не понимаю. COM это универсальная технология, которую можно использовать в разных ЯП. Если я вижу\знаю как передается this при вызове метода COM-интерфейса в своем "родном" дельфи\паскале, то почему он должен или может передаваться иначе в MSVC (managed code ЯП не в счет)? Да, маршаллинг никто не отменял, но для системных WinAPI интерфейсов этот маршаллинг (если он используется) должен быть зашит в самих системных dll, которые представляют эти интерфейсы. Т.е. dll должна представлять пользователям стандартный ABI интерфейс вызова методов, а то, куда она его дальше транслирует и как-то маршаллит, это уже её личное\приватное дело. Или я не прав?
                          Цитата leo @
                          Поэтому в ваши "чистые С++" дела принципиально не лезу.

                          Вступай в нашу банду, leo.
                          - Ловля сусликов с любой шкуркой.
                          - Самые брутальные дискуссии, плавно переходящие "в зуб ногой".
                          - Широкие возможности влезать в "чиста С++".
                          и множество других бонусов и удовольствий, не доступных в Дельфи !
                          Сообщение отредактировано: ЫукпШ -
                            Цитата

                            Ты прикидываешься или издеваешься? :angry:


                            Мозг отказал :crazy:

                            Цитата

                            В #2 у тебя было правильно - хук\перехват устанавливался только один раз при DLL_PROCESS_ATTACH, но из-за ошибок с this и pVal ничего не работало. Затем, начиная с #3 ты зачем-то убрал условие DLL_PROCESS_ATTACH, и соотв-но твой код перехвата стал срабатывать множество раз при создании (а в #3 и при завершении) потоков приложения. Поэтому тебе пришлось добавить DisableThreadLibraryCalls, чтобы запретить повторные срабатывания кроме первого.


                            Если ставлю DLL_PROCESS_ATTACH, то отрабатывает один раз и все. :wall:
                              Цитата Mr.Newbie‎ @
                              Если ставлю DLL_PROCESS_ATTACH, то отрабатывает один раз и все

                              Это может означать то, что приложение грузит dll динамически и выгружает ее после использования. Поэтому и твой однократный хук перестает работать, и "кое где проскакивают пустые значения" fn_real, если ты пытаешься ставить перехват в момент, когда dll не загружена.
                              Выход из этой ситуации - обеспечить загрузку этой dll самому. Можно либо создать ссылку на соответствующий интерфейсный объект и хранить ее в глоб.\стат. переменной до выгрузки dll, либо просто вызвать LoadLibrary. То и другое лучше делать в отдельном потоке ApplyHooks, т.к. грузить либы в DllMain не рекомендуется. Кстати, в этом же потоке можно организовать периодическую проверку загрузки dll и установки хука по таймеру на случай, если он по какой-то (очередной непонятной) причине слетит.
                                Цитата leo @
                                т.к. грузить либы в DllMain не рекомендуется

                                В DllMain вообще ничего делать не рекомендуется, кроме получения статуса загрузки/выгрузки и выделения/освобождения динамической локальной памяти
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0546 ]   [ 17 queries used ]   [ Generated: 28.03.24, 23:11 GMT ]