Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > Получение скриншота DirectX через внедренную dll


Автор: denkil92 7.4.2012, 22:05
Здравствуйте!
 Необходимо реализовать снятие скриншота в DirectX приложениях (играх).
 Поискав информацию в сети, пришёл к выводу, что для этого мне надо внедрять dll в приложение и перехватывать функцию D3DEndScene.
 Нашёл несколько примеров, но не удалось ни один из них заставить работать.

 С внедрерением проблем нет. DLL внедряется, DllMain выполняется. А вот сделать хук D3DEndScene не выходит.
 Важно, чтобы я мог внедрить эту DLL уже непосредственно в работающую программу, а не при запуске.
 Может кто-то помочь в решении данной проблемы?

 Текущий код DLL:
Код

#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

#pragma once

typedef HRESULT (WINAPI *CreateDevice_t)(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, 
                     DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, 
                     IDirect3DDevice9** ppReturnedDeviceInterface);
typedef HRESULT (WINAPI *EndScene_t)(IDirect3DDevice9* surface);


 CreateDevice_t D3DCreateDevice_orig;
 EndScene_t D3DEndScene_orig;

 HRESULT WINAPI D3DCreateDevice_hook(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, 
                     DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, 
                     IDirect3DDevice9** ppReturnedDeviceInterface);
 HRESULT WINAPI D3DEndScene_hook(IDirect3DDevice9* device);

 PDWORD IDirect3D9_vtable = NULL;

#define CREATEDEVICE_VTI 16
#define ENDSCENE_VTI 42

 HRESULT WINAPI HookCreateDevice();
 DWORD WINAPI VTablePatchThread(LPVOID threadParam);


 BOOL APIENTRY DllMain( HMODULE hModule,
                        DWORD  ul_reason_for_call,
                        LPVOID lpReserved
                      )
{
     HMODULE d3dmodule;
     PBYTE funcAddress;
     switch (ul_reason_for_call)
     {
     case DLL_PROCESS_ATTACH:
         MessageBoxA(NULL, "DLL Injected", "DLL Injected", MB_ICONEXCLAMATION);
         if (HookCreateDevice() == D3D_OK)
         {
             return TRUE;
         } else {
             return FALSE;
         }

         break;
     case DLL_THREAD_ATTACH:
         MessageBoxA(NULL, "DLL_THREAD_ATTACH", "DLL", MB_ICONEXCLAMATION);
         break;
     case DLL_THREAD_DETACH:
         MessageBoxA(NULL, "DLL_THREAD_DETACH", "DLL", MB_ICONEXCLAMATION);
         break;
     case DLL_PROCESS_DETACH:
         MessageBoxA(NULL, "DLL_PROCESS_DETACH", "DLL", MB_ICONEXCLAMATION);
         break;
     }
     return TRUE;
}

 HRESULT WINAPI HookCreateDevice()
{
     IDirect3D9* device = Direct3DCreate9(D3D_SDK_VERSION);
     if (!device)
     {
         return D3DERR_INVALIDCALL;
     }
     IDirect3D9_vtable = (DWORD*)*(DWORD*)device;
     device->Release();

     DWORD protectFlag;
     if (VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), PAGE_READWRITE, &protectFlag))
     {
         *(DWORD*)&D3DCreateDevice_orig = IDirect3D9_vtable[CREATEDEVICE_VTI];
         *(DWORD*)&IDirect3D9_vtable[CREATEDEVICE_VTI] = (DWORD)D3DCreateDevice_hook;

         if (!VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), protectFlag, &protectFlag))
         {
             return D3DERR_INVALIDCALL;
         }
     } else {
         return D3DERR_INVALIDCALL;
     }
     return D3D_OK;
}

 HRESULT WINAPI D3DCreateDevice_hook(IDirect3D9* Direct3D_Object, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, 
                     DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, 
                     IDirect3DDevice9** ppReturnedDeviceInterface)
{
     HRESULT result = D3DCreateDevice_orig(Direct3D_Object, Adapter, DeviceType, hFocusWindow, BehaviorFlags | D3DCREATE_MULTITHREADED, pPresentationParameters, ppReturnedDeviceInterface);

     DWORD protectFlag;
     if (VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), PAGE_READWRITE, &protectFlag))
     {
         *(DWORD*)&IDirect3D9_vtable[CREATEDEVICE_VTI] = (DWORD)D3DCreateDevice_orig;

         if (!VirtualProtect(&IDirect3D9_vtable[CREATEDEVICE_VTI], sizeof(DWORD), protectFlag, &protectFlag))
         {
             return D3DERR_INVALIDCALL;
         }
     } else {
         return D3DERR_INVALIDCALL;
     }

     if (result == D3D_OK)
     {
         IDirect3D9_vtable = (DWORD*)*(DWORD*)*ppReturnedDeviceInterface;
         *(PDWORD)&D3DEndScene_orig = (DWORD)IDirect3D9_vtable[ENDSCENE_VTI];

         if (!CreateThread(NULL, 0, VTablePatchThread, NULL, NULL, NULL))
         {
             return D3DERR_INVALIDCALL;
         }
     }

     return result;
}

 DWORD WINAPI VTablePatchThread(LPVOID threadParam)
{
     while (true)
     {
         Sleep(100);

         *(DWORD*)&IDirect3D9_vtable[ENDSCENE_VTI] = (DWORD)D3DEndScene_hook;
     }
}


 HRESULT WINAPI D3DEndScene_hook(IDirect3DDevice9* device)
{
     MessageBoxA(NULL, "Endscene", "4", MB_ICONEXCLAMATION);
     HRESULT result = NULL;

     return result;
}

Автор: Dem_max 8.4.2012, 17:04
зачем тебе самому изобретать велосипед ??? есть же куча программ которые могут делать скриншоты из игр.

Автор: denkil92 8.4.2012, 18:46
Потому что мне нужна программа, которая сможет делать скриншоты и в дальнейшем их обрабатывать. И это должно работать быстро и стабильно, так что как-то пыаться юзать фрапс и его подобные не вариант.

Автор: Dem_max 11.4.2012, 14:30
насколько быстро должно быть, быстрее фрапс ??? 
Читерить хочешь ? Так сразу скажу некоторые игры имеют защиту от читерства.

Автор: denkil92 11.4.2012, 20:21
Не надо быстрее, надо на уровне. Нет, это не для чита

Автор: Dem_max 12.4.2012, 11:58
Объясни задачу что хочешь сделать, пиши в личку.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)