Remote IDirect3DDevice

Started by
6 comments, last by IkeKiller 22 years, 1 month ago
Im stuck i need to be able to get a IDirect3DDevice of another window, i have played about with a few diffrent ways of achieving this but keep hitting dead ends, any help or even a suggestion would be greatly appreciated. I dont have access to the other windows source, the aim is to sortof plug into the Direct3DDevice and render aditional information in the same window, without affecting the origonal.
Advertisement
Eeek, that is not a trivial task!

Problem #1: what you term "another window" is likely to be another "process". With a single CPU, only *one* process runs at a time (the thread scheduler switches between them automatically). Any app you write is in a *different* process.

Problem #2: if you want to render on top of someone elses scene, you need to do it between their BeginScene()/EndScene() calls, and before their Present() call.

Problem #3: you need knowledge of the states they set: imagine all of the other apps scene is rendered with ONE:ONE blending and that state is set *once* when the program starts up, to "plug in" something which renders opaque on top with ONE:ZERO blending - will mean you need to change the state - you''ll need to be able to save and restore all of their state before drawing!


Solutions ?:

Firstly this has nothing to do with their device window - there''s *no* way (IMO) of safely hooking their D3D calls from a *different process* using their UI as an entry.

So it''ll involve some sort of API overloading - which hints very strongly at techniques like "DLL injection". The most common way any apps which can "hook in" to the D3D API work is to rename the D3D8.DLL, and write a replacement DLL with the same entry points which forwards (or intercepts) calls onto the ''real'' DLL.

Since you''ll need to be called before the end of the other apps'' scene you''ll probably want to reimplement the EndScene() method with a call to your extra rendering code, like:

HRESULT IDirect3DDevice8::EndScene(){  // add new output to original scene  doMyExtraRendering();  return m_genuineD3DDevice->EndScene();} 



Because the app you''re hooking into is likely to be relying on certain states being set (render states, the current vertex buffer, the current texture etc etc etc) you''ll also need to keep track of any Set*() calls to the API so you know what to restore after your render has finished.


Sounds complicated ? - it is in places! - some apps have successfully done this hooking of D3D using that technique over the years - learning how they work, and perhaps talking to their authors could be of use:

- "DLL Detective" by Adam Moravanszky
http://n.ethz.ch/student/adammo/DLLDetective/

- "GRAZ" by Herb Marselas of Ensemble Studios
http://www.ensemblestudios.com/openjournal4/story/nine.shtml

- "IPEAK GPT" by Intel DRG
http://developer.intel.com/ [can''t find exact link]
[Incidentally IPEAK GPT was written by Herb Marselas before he moved to Ensemble].


Of all of those DLL Detective is probably of most interest since the source code is available etc

--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

yeah, DLL inhection would work. you force your DLL to load into another program and hack a call to your code between the BeginScene and EndScene function.

I have added a DLL to a program a few times, the hardest part if finding the call to EndScene. once you find it you can change the CALL address to a stub you added to the end of the program, which calls your DLL and then runs the origonal code you replaced. you also need to add a function to the start of the program to load your DLL and get the address of your custom function

Too badt his is the only way, but is the most fun you will ever have with a computer

check out this site: http://win32asm.cjb.net/ aswell as look for tutorials on crack sites :p

This is a basic overview of the changes you need:

-Existing code
-EndScene
-Existing code

Chnage that to

-Existing code
-Jump to my code
-Existing code

(at the end of the program, where there is free space)
-My code (call DLL)
-End Scele
-Return


because you hooked the EndScene fuinction, you get the address of the d3dDevice, which you can use to reder things!
I just thought of something! what S1CA said about hooking the DLL, that wouldn''t work because I think COM objects use virtual functions. Once you get the interface for the d3ddevice, you could just hook the virtual function!!

Here is the code for an EndScene call

//DirectDrawClass::lpd3dDevice->EndScene();	mov	eax, DWORD PTR ?lpd3dDevice@DirectDrawClass@@2PAUIDirect3DDevice7@@A ; DirectDrawClass::lpd3dDevice	push	eax	mov	ecx, DWORD PTR [eax]	call	DWORD PTR [ecx+24] 


EAX is the pointer to the d3ddevice, and [ecx+24] is where the the address to the endscene function is stored. Just make a C++ version that hooks EndScene like S1CA said, and copy the address to [ecx+24] once you get the d3ddevice interface. maybe after the interface is created
Alternatively replace the DLL completely in the same way GRAZ, IPEAK GPT and DLL Detective do.

It solves a lot of worries about matching the calling conventions, making sure the Vtable works etc

You simply (umm...) implement the Direct3DCreate8() DLL export to pass back your overloaded version of the COM - it should even be possible to forward anything you don''t want to handle to the original DLL with no extra work.



--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

So if i were for instance create my own d3d8.dll with the exact same exports as the origonal d3d8.dll and place this dll in the applications directory i could then intercept all d3d calls and then in my overloaded dll forward them to the real d3d8.dll?
Yep, check the links I posted - particularly DLLDetective

--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Thanks so much, you have been an amazing help, damn you deserve a medal

This topic is closed to new replies.

Advertisement