Есть несколько подходов к этой проблеме. Большинство из них неприглядны, и это полностью зависит от того, какой тип графического API вы хотите использовать, и какие функции использует целевое приложение.
Большинство приложений DirectX, GDI + и OpenGL имеют двойную или тройную буферизацию, поэтому все они вызывают:
void SwapBuffers(HDC hdc)
в какой-то момент. Они также генерируют сообщения WM_PAINT в своей очереди сообщений всякий раз, когда должно быть нарисовано окно. Это дает вам два варианта.
Вы можете установить глобальный хук или локальный хук поток в целевой процесс и захватывать сообщения WM_PAINT. Это позволяет вам копировать содержимое из контекста устройства непосредственно перед тем, как происходит рисование. Процесс может быть найден путем перечисления всех процессов в системе и поиска известного имени окна или известного дескриптора модуля.
Вы можете внедрить код в локальную копию целевого процесса SwapBuffers. В Linux это было бы легко сделать через переменную окружения LD_PRELOAD или явно вызвав ld-linux.so.2, но в Windows не существует эквивалента. К счастью, есть платформа от Microsoft Research, которая может сделать это для вас Detours . Вы можете найти это здесь: ссылка .
Демосценовая группа Farbrausch создала инструмент демо-захвата под названием kkapture, который использует библиотеку Detours. Однако их инструмент предназначен для приложений, которые не требуют ввода пользователя, поэтому они в основном запускают демонстрации с фиксированной частотой кадров, подключаясь ко всем возможным функциям времени, таким как timeGetTime (), GetTickCount () и QueryPerformanceCounter (). Это полностью рад. Презентация, написанная ryg (я думаю?) О внутренностях kkapture, может быть найдена здесь . Я думаю, что это вас интересует.
Для получения дополнительной информации о хуках Windows см. здесь и здесь .
EDIT:
Эта идея заинтриговала меня, поэтому я использовал Detours, чтобы подключиться к приложениям OpenGL и связываться с графикой. Вот Quake 2 с добавленным зеленым туманом:
Еще немного информации о том, как работает Detours, поскольку я использовал его из первых рук:
Обходы работают на двух уровнях. Фактическое перехватывание работает только в том же пространстве процесса, что и целевой процесс. Таким образом, в Detours есть функция для внедрения DLL в процесс и принудительного запуска его DLLMain, а также функции, которые должны использоваться в этой DLL. Когда DLLMain запущен, DLL должна вызвать DetourAttach (), чтобы указать функции для перехвата, а также функцию «обход», которая является кодом, который вы хотите переопределить.
Так что это в основном работает так:
- У вас есть приложение запуска, единственной задачей которого является вызов DetourCreateProcessWithDll (). Он работает так же, как CreateProcessW, только с несколькими дополнительными параметрами. Это внедряет DLL в процесс и вызывает ее DllMain ().
- Вы реализуете DLL, которая вызывает функции Detour и настраивает функции батута. Это означает вызов DetourTransactionBegin (), DetourUpdateThread (), DetourAttach (), за которым следует DetourTransactionEnd ().
- Используйте модуль запуска для внедрения DLL, которую вы внедрили в процесс.
Хотя есть несколько предостережений. Когда DllMain запущен, библиотеки, которые импортируются позже с помощью LoadLibrary (), еще не видны. Таким образом, вы не можете обязательно все настроить во время события вложения DLL. Обходной путь - отслеживать все функции, которые были переопределены до сих пор, и пытаться инициализировать другие функции внутри этих функций, которые вы уже можете вызвать. Таким образом, вы обнаружите новые функции, как только LoadLibrary отобразит их в область памяти процесса. Я не совсем уверен, насколько хорошо это будет работать для wglGetProcAddress, хотя. (Возможно, у кого-то еще есть идеи по этому поводу?)
Некоторые вызовы LoadLibrary () кажутся неудачными. Я тестировал с Quake 2, и DirectSound и waveOut API по какой-то причине не смогли инициализироваться. Я все еще расследую это.