Edocecrous
asked on
DirectX screen capture
If someone knows,
how to access a thread's (program's) (secondary) surfaces from another thread (program).
I think the DirectX surface capturing is a well kept secret. /at least i could not find ANY info on the topic/
I need just the idea, i can implement it...
THX,
Edocecrous
how to access a thread's (program's) (secondary) surfaces from another thread (program).
I think the DirectX surface capturing is a well kept secret. /at least i could not find ANY info on the topic/
I need just the idea, i can implement it...
THX,
Edocecrous
ASKER
Did you used the GDI-compatible surface and GDI to make copy of it, or you could get the lpDDsurface pointer, and accessed the memory?
(Because i need to access the secondary surfaces, and GDI has no access to that.)
ps.:I'm reversing a screen-grabber's dll right now, but it moves slowly, so any idea welcomed.
Edocecrous
(Because i need to access the secondary surfaces, and GDI has no access to that.)
ps.:I'm reversing a screen-grabber's dll right now, but it moves slowly, so any idea welcomed.
Edocecrous
I didn't attempt to gain access to the secondary surface, I used the GDI to create a device context for the "Display", which allowed me to basicaly take what you see on the monitor and use it wherever i wanted. I tried it with a couple directX games and it worked. But you want to get access to the secondary surface, and I do as well. But I have yet to find anyone that can help me there.
Here is the address of the code example I used to make my
screen cap program. It is VB code so if you don't have vb
then this won't help much.
http://www.vbcode.com/asp/code.asp?lstCategory=Graphics
Here is the address of the code example I used to make my
screen cap program. It is VB code so if you don't have vb
then this won't help much.
http://www.vbcode.com/asp/code.asp?lstCategory=Graphics
ASKER
Right now i'm working on a model, how to get to those surfaces. First, i created a program which creates the surfaces.
-than i made code to enumerate those surfaces,
-i'll try if it works from different thread,
-if it does, i'll try it from different process.
As far as i could get into the details with the directX capturer program i'm dissecting, first if finds where the ddraw.dll is mapped in the current process's address space.
Than it gets the address of the DirectDrawCreate() function in it. THan it gets the currentprocessID. Than it tries to enumerate the surfaces by poking around in memory...
So it's basically not hard stuff, but i'll have to work on it...
I think these DX-grabber programs use a techinc called "code infusion", where you copy your code into the address space of the program you want the surfaces from.
Code infusion should raise no problems, but to write code that can call API or DirectX functions inside a different context will be interesting...
So i'll get back to it....
(I'm also working on 'low level' version, writing a VxD which can poke around in the other process....)
-than i made code to enumerate those surfaces,
-i'll try if it works from different thread,
-if it does, i'll try it from different process.
As far as i could get into the details with the directX capturer program i'm dissecting, first if finds where the ddraw.dll is mapped in the current process's address space.
Than it gets the address of the DirectDrawCreate() function in it. THan it gets the currentprocessID. Than it tries to enumerate the surfaces by poking around in memory...
So it's basically not hard stuff, but i'll have to work on it...
I think these DX-grabber programs use a techinc called "code infusion", where you copy your code into the address space of the program you want the surfaces from.
Code infusion should raise no problems, but to write code that can call API or DirectX functions inside a different context will be interesting...
So i'll get back to it....
(I'm also working on 'low level' version, writing a VxD which can poke around in the other process....)
Hmm, interesting... That is something I should look into
as well. What I have been trying to do for a while now is to get a small graphic to display at all times on the screen. Even over a directX application. So maby I could
instead of writing to the primary display memory area,
I could write my image data in the secondary memory area set by directX itself to reduce screen flicker. Well that
is only if it isn't locked in some way. Time to do more
research, hopefully I can figure this out as this has been
haunting me for some time now. hehe
Good luck to you
Time to go learn! :)
as well. What I have been trying to do for a while now is to get a small graphic to display at all times on the screen. Even over a directX application. So maby I could
instead of writing to the primary display memory area,
I could write my image data in the secondary memory area set by directX itself to reduce screen flicker. Well that
is only if it isn't locked in some way. Time to do more
research, hopefully I can figure this out as this has been
haunting me for some time now. hehe
Good luck to you
Time to go learn! :)
ASKER
In DirectX, to display something over the screen, they use overlay surfaces, maybe that's waht you need. /DVD players use that technic/
Also, if the flipping chain is locked, DirectX can't use it, so there should be plenty of time to catch it.
What i want to do is to get access to the offsecreen surfaces of games, and learn how they do the animation, and how thaey build up the levels, etc...
Without using Ring-0, there are functions like CreateRemoteThreadEx, and WriteProcessMemory, etc. to access other processes. Also, i did a test, and in 2 different DirectX processes, the directdraw interface was mapped to the same (shared memory) region. The shared region is: 0x80000000 to 0xBFFFFFFF).
Edocecrous
Also, if the flipping chain is locked, DirectX can't use it, so there should be plenty of time to catch it.
What i want to do is to get access to the offsecreen surfaces of games, and learn how they do the animation, and how thaey build up the levels, etc...
Without using Ring-0, there are functions like CreateRemoteThreadEx, and WriteProcessMemory, etc. to access other processes. Also, i did a test, and in 2 different DirectX processes, the directdraw interface was mapped to the same (shared memory) region. The shared region is: 0x80000000 to 0xBFFFFFFF).
Edocecrous
Did you ever figure this one out? Know that you probably havent checked this for a while, but it's a unlocked q, so I'm hoping you'll check the email ;)
ASKER
Hi there!
Yes, i checked my mail. I have 5 mail accounts to check, but i checked this one. hehe.
So, I did figure out, but not all. what i realy want to do, is to get inside the game diablo, and check out the animation, and background arrangement of the sprites, because i'll write a similar one, and it's a good oportunity to learn.
I wrote the program to inject code inside diablo's process, it's working. Also, it's running in a separate thread, so after that, the hooking is released.
The only problem so far is the COM object of directx.
When a thread creates a surface object, it gets back an interface pointer. When the program is already running, where the hell the DDRAW object keeps the interface list, and how to get there....
My only problem is, i'm maximalistic. I want a code wich works with any running process.
Otherwise, i could start up diablo in a process at suspended state, modify the ddraw dll loaded in the process, or modify the Import Address Table ot the diablo.exe, so when it calls ddraw.create etc, it uns through my code, which logs it.
As soon as i have the pointer, beeing in the same process, i can access all the surfaces... ...i tried that part, it works.
So far i spent $150 on books to get the info i need, but couldn't find it.
I guess i just have to play with the code... right now i have no time to do it, but i'm determined to solve the problem the mentioned way if it's not working out othervise.
Edocecrous
Yes, i checked my mail. I have 5 mail accounts to check, but i checked this one. hehe.
So, I did figure out, but not all. what i realy want to do, is to get inside the game diablo, and check out the animation, and background arrangement of the sprites, because i'll write a similar one, and it's a good oportunity to learn.
I wrote the program to inject code inside diablo's process, it's working. Also, it's running in a separate thread, so after that, the hooking is released.
The only problem so far is the COM object of directx.
When a thread creates a surface object, it gets back an interface pointer. When the program is already running, where the hell the DDRAW object keeps the interface list, and how to get there....
My only problem is, i'm maximalistic. I want a code wich works with any running process.
Otherwise, i could start up diablo in a process at suspended state, modify the ddraw dll loaded in the process, or modify the Import Address Table ot the diablo.exe, so when it calls ddraw.create etc, it uns through my code, which logs it.
As soon as i have the pointer, beeing in the same process, i can access all the surfaces... ...i tried that part, it works.
So far i spent $150 on books to get the info i need, but couldn't find it.
I guess i just have to play with the code... right now i have no time to do it, but i'm determined to solve the problem the mentioned way if it's not working out othervise.
Edocecrous
I'm trying to do the exact same thing myself, with ultima online though, not diablo (directdraw).
could you tell me which api calls your hooking? I was thinking about getting handles from the directdrawcreate function or something like that, though that's quick thinking and I haven't really done any research on it yet.
could you tell me which api calls your hooking? I was thinking about getting handles from the directdrawcreate function or something like that, though that's quick thinking and I haven't really done any research on it yet.
ASKER
You know, it's a pain in the b*tt to log in to EE each time i need to answer. Please just send a letter to edocecrous@angelfire.com OK? or my ICQ:27494791
First of all, it has been an idea so far.
I have a running thread inside Diablo's process, so i can do whatever i want in the Diablo address space.
But i did not hook any functions yet, i didn't do the IAT patching yet. I would start with ddcreate, however.
Right now i have a different approach, and i suggest to you, to do the same thing, so we can help each-other, and share;-)
Here it comes:
-What is the problem: We have no idea how to get the interface of the surface created by another thread.
-What we know: If we have the interface address, we CAN access the interface from a different thread than the creator thread of the surface.
The IAT patching will be our (at least main) last trick, which must work. BUT, first i like to try some other tricky way to get the interface pointers.
To do that: I created a program, which has 2 threads, and and 1 thread creates a surface. The other thread tries to get it...
This way the situation is the same as we would be inside a program with our spy-thread, and trying to get the interface. But, we have the advantage of KNOWING the interface pointer, and all the creation parameters, so we can actualy check, if we are successful or not.
I would try to create many surfaces, and then compare the interface's addresses, maybe they follow each other? Or something like that.
Edocecrous
ps.:If this approach fails, we have to do the IAT patching. I have a book which explains it. (not the IAT patching, but how to patch directx)
I just simply not want to do it before i'm not sure that's the only way. Also, i never tried to start another program in suspended state, so i need to look into that either...
So drop me an email....
pps.:I'm doing my finals this month, that's why i can't check out things right now.
First of all, it has been an idea so far.
I have a running thread inside Diablo's process, so i can do whatever i want in the Diablo address space.
But i did not hook any functions yet, i didn't do the IAT patching yet. I would start with ddcreate, however.
Right now i have a different approach, and i suggest to you, to do the same thing, so we can help each-other, and share;-)
Here it comes:
-What is the problem: We have no idea how to get the interface of the surface created by another thread.
-What we know: If we have the interface address, we CAN access the interface from a different thread than the creator thread of the surface.
The IAT patching will be our (at least main) last trick, which must work. BUT, first i like to try some other tricky way to get the interface pointers.
To do that: I created a program, which has 2 threads, and and 1 thread creates a surface. The other thread tries to get it...
This way the situation is the same as we would be inside a program with our spy-thread, and trying to get the interface. But, we have the advantage of KNOWING the interface pointer, and all the creation parameters, so we can actualy check, if we are successful or not.
I would try to create many surfaces, and then compare the interface's addresses, maybe they follow each other? Or something like that.
Edocecrous
ps.:If this approach fails, we have to do the IAT patching. I have a book which explains it. (not the IAT patching, but how to patch directx)
I just simply not want to do it before i'm not sure that's the only way. Also, i never tried to start another program in suspended state, so i need to look into that either...
So drop me an email....
pps.:I'm doing my finals this month, that's why i can't check out things right now.
Hey Edocecrous,
I analyzed a directx program wrote by myself and found sth. really interesting.Here's what i got.
Whenever we call DirectDrawCreate in a process,we'll get the same IDirectDraw object and it points to a undocumented structure.The 2nd DWORD value points to another structure and the value of that structure at offset 44 is the pointer toward primary surface.
Ooh!
Sorry for my poor english.I think I should speak in "code" instead.
the following is sample code.hope it can works on ur PC.
BTW,the code can also get the back surfaces,but i can't express clearly how to get it :(
**Delphi code ONLY**
unit test1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DirectDraw, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
lb: TListBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FDirectDraw:IDirectDraw;
FPSurface,FBSurface:IDirec tDrawSurfa ce;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender : TObject);
var
DC:HDC;
SurfaceDesc:TDDSURFACEDESC ;
DDSCaps:TDDSCAPS;
a,b,c:dword;
begin
if DirectDrawCreate(nil,FDire ctDraw,nil )=DD_OK then
if FDirectDraw.SetCooperative Level(Appl ication.Ha ndle,
DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
or DDSCL_ALLOWREBOOT)=DD_OK then
if FDirectDraw.SetDisplayMode (640,480,8 )=DD_OK then
begin
FillChar(SurfaceDesc,SizeO f(SurfaceD esc),0);
SurfaceDesc.dwSize:=Sizeof (SurfaceDe sc);
SurfaceDesc.dwFlags:=DDSD_ CAPS or DDSD_BACKBUFFERCOUNT;
SurfaceDesc.ddsCaps.dwCaps :=DDSCAPS_ PRIMARYSUR FACE or DDSCAPS_FLIP
or DDSCAPS_COMPLEX;
SurfaceDesc.dwBackBufferCo unt:=1;
if FDirectDraw.CreateSurface( SurfaceDes c,FPSurfac e,nil)=DD_ OK then
begin
ddsCaps.dwCaps:=DDSCAPS_BA CKBUFFER;
if FPSurface.GetAttachedSurfa ce(DDSCaps ,FBSurface )=DD_OK then
begin
if FPSurface.GetDC(DC)=DD_OK then
begin
FPSurface.ReleaseDC(DC);
end;
if FBSurface.GetDC(DC)=DD_OK then
begin
FBSurface.ReleaseDC(DC);
end;
Timer1.Enabled:=true;
a:=dword(pointer(@FDirectD raw)^);
b:=dword(pointer(@FPSurfac e)^);
c:=dword(pointer(@FbSurfac e)^);
lb.Items.Add('iDirectDraw: '+inttohex (a,8));
lb.Items.Add('FPSurface:'+ inttohex(b ,8));
lb.Items.Add('FbSurface:'+ inttohex(c ,8));
lb.Items.Add('');
Exit;
end;
end;
end;
MessageBox(Handle,PChar('E rror!'),PC har('Error !'),MB_OK) ;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
hr:HRESULT;
begin
while true do
begin
hr:=FPSurface.Flip(nil,0);
case hr of
DD_OK: exit;
else
exit;
end;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if FDirectDraw<>nil then
begin
FDirectDraw.FlipToGDISurfa ce;
FDirectDraw.SetCooperative Level(Appl ication.Ha ndle,DDSCL _NORMAL);
if FBSurface<>nil then FBSurface:=nil;
if FPSurface<>nil then FPSurface:=nil;
FDirectDraw:=nil;
end;
end;
procedure x;
var
DC:HDC;
a,b,c:dword;
pp:pointer;
FD:IDirectDraw;
sur:array [0..5] of dword;
i,j:integer;
// bm:tbitmap;
begin
if DirectDrawCreate(nil,FD,ni l)=DD_OK then
begin
pp:=@fd;
a:=dword(pointer(dword(pp^ )+8)^); //IDirectDraw
sur[0]:=dword(pointer(dwor d(pointer( a+4)^)+44) ^); //point to PrimarySurface structure
b:=sur[0];
for i:=1 to 5 do
begin //point to backSurface structure
b:=dword(pointer(dword(poi nter(dword (pointer(b +4)^)+12)^ )+12)^);
if b<=0 then break;
if dword(pointer(b+12)^)<dwor d(pointer( sur[i-1]+1 2)^) then break;
sur[i]:=b;
end;
for j:=0 to i-1 do //form the primary surface to the last back surface
//j:=0; //only process the parimary surface
begin
pp:=pointer(sur[j]);
////////////1
asm //getdc
lea edx,dc
push edx
mov eax,pp
push eax
mov eax,[eax]
call [eax+$44]
mov c,eax
end;
if c<>DD_OK then exit;
SetBKColor(dc,RGB(0,0,255) );
{ bm:=tbitmap.Create;
bm.Width:=GetDeviceCaps(dc ,HORZRES);
bm.Height:=GetDeviceCaps(d c,VERTRES) ;
}//Need Lock??
SetTextColor(DC,RGB(255,25 5,0));
TextOut(dc,0,0,PChar('XYZA B'),5);
{ bitblt(bm.Canvas.Handle,0, 0,bm.Width ,bm.Height ,dc,0,0,SR CCOPY);
bm.SaveToFile('C:\WINDOWS\ Desktop\1. bmp'); //save a screenshot
bm.Free;}
asm //releasedc
@@a:
lea edx,dc
push edx
mov eax,pp
push eax
mov eax,[eax]
call [eax+$68]
cmp eax,0
jz @@a
end;
end;
fd:=nil;
end;
end;
procedure TForm1.Button2Click(Sender : TObject);
begin
x;
end;
end.
I analyzed a directx program wrote by myself and found sth. really interesting.Here's what i got.
Whenever we call DirectDrawCreate in a process,we'll get the same IDirectDraw object and it points to a undocumented structure.The 2nd DWORD value points to another structure and the value of that structure at offset 44 is the pointer toward primary surface.
Ooh!
Sorry for my poor english.I think I should speak in "code" instead.
the following is sample code.hope it can works on ur PC.
BTW,the code can also get the back surfaces,but i can't express clearly how to get it :(
**Delphi code ONLY**
unit test1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DirectDraw, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
lb: TListBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FDirectDraw:IDirectDraw;
FPSurface,FBSurface:IDirec
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender
var
DC:HDC;
SurfaceDesc:TDDSURFACEDESC
DDSCaps:TDDSCAPS;
a,b,c:dword;
begin
if DirectDrawCreate(nil,FDire
if FDirectDraw.SetCooperative
DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
or DDSCL_ALLOWREBOOT)=DD_OK then
if FDirectDraw.SetDisplayMode
begin
FillChar(SurfaceDesc,SizeO
SurfaceDesc.dwSize:=Sizeof
SurfaceDesc.dwFlags:=DDSD_
SurfaceDesc.ddsCaps.dwCaps
or DDSCAPS_COMPLEX;
SurfaceDesc.dwBackBufferCo
if FDirectDraw.CreateSurface(
begin
ddsCaps.dwCaps:=DDSCAPS_BA
if FPSurface.GetAttachedSurfa
begin
if FPSurface.GetDC(DC)=DD_OK then
begin
FPSurface.ReleaseDC(DC);
end;
if FBSurface.GetDC(DC)=DD_OK then
begin
FBSurface.ReleaseDC(DC);
end;
Timer1.Enabled:=true;
a:=dword(pointer(@FDirectD
b:=dword(pointer(@FPSurfac
c:=dword(pointer(@FbSurfac
lb.Items.Add('iDirectDraw:
lb.Items.Add('FPSurface:'+
lb.Items.Add('FbSurface:'+
lb.Items.Add('');
Exit;
end;
end;
end;
MessageBox(Handle,PChar('E
end;
procedure TForm1.Timer1Timer(Sender:
var
hr:HRESULT;
begin
while true do
begin
hr:=FPSurface.Flip(nil,0);
case hr of
DD_OK: exit;
else
exit;
end;
end;
end;
procedure TForm1.FormDestroy(Sender:
begin
if FDirectDraw<>nil then
begin
FDirectDraw.FlipToGDISurfa
FDirectDraw.SetCooperative
if FBSurface<>nil then FBSurface:=nil;
if FPSurface<>nil then FPSurface:=nil;
FDirectDraw:=nil;
end;
end;
procedure x;
var
DC:HDC;
a,b,c:dword;
pp:pointer;
FD:IDirectDraw;
sur:array [0..5] of dword;
i,j:integer;
// bm:tbitmap;
begin
if DirectDrawCreate(nil,FD,ni
begin
pp:=@fd;
a:=dword(pointer(dword(pp^
sur[0]:=dword(pointer(dwor
b:=sur[0];
for i:=1 to 5 do
begin //point to backSurface structure
b:=dword(pointer(dword(poi
if b<=0 then break;
if dword(pointer(b+12)^)<dwor
sur[i]:=b;
end;
for j:=0 to i-1 do //form the primary surface to the last back surface
//j:=0; //only process the parimary surface
begin
pp:=pointer(sur[j]);
////////////1
asm //getdc
lea edx,dc
push edx
mov eax,pp
push eax
mov eax,[eax]
call [eax+$44]
mov c,eax
end;
if c<>DD_OK then exit;
SetBKColor(dc,RGB(0,0,255)
{ bm:=tbitmap.Create;
bm.Width:=GetDeviceCaps(dc
bm.Height:=GetDeviceCaps(d
}//Need Lock??
SetTextColor(DC,RGB(255,25
TextOut(dc,0,0,PChar('XYZA
{ bitblt(bm.Canvas.Handle,0,
bm.SaveToFile('C:\WINDOWS\
bm.Free;}
asm //releasedc
@@a:
lea edx,dc
push edx
mov eax,pp
push eax
mov eax,[eax]
call [eax+$68]
cmp eax,0
jz @@a
end;
end;
fd:=nil;
end;
end;
procedure TForm1.Button2Click(Sender
begin
x;
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi!
I'm sorry for not posting anything for a while, but i had school.
I was about to post the same thing myself, because i found out exactly the same thing, myself... :-)
I have delphi, but i don't like pascal.
I hope that Microsoft will not read this article, because if they will, they will change this goodie, and it will be not available in future directx versions.
I read through your code, and i did nearly exatly the same thing!
(about a week ago, but i had no time to post it)
The delphi code looks lengthy, compared to the C++ one i wrote.
But it works on the same principle.
Also, i went into diablo, and find out something:
They used only Lock() and Unlock(), and they wrote their own rendering code. Thus, there is no double-buffering (back surface) no Blitting to copy strites, nothing.
They render directly to the screen, using repz movsd...
That was disappointing, since that time DirectX 3 was out, whith nice features, like BltFast() etc...
I'm happy you found the solution, and even more, because you found it without (too much) help!
Also, please do not make a news from our findings, since i'm sure Micro$oft will change it if it gets out!
They did it for smaller things...
If someone needs it, can find it on this post.
You know, what's funny, i did all the things:
Inserting a thread into the Process,
Doing Global Hooking,
Loading/freezing the app to do IAT patch,
etc,,,
1.And it turns out, this tweak works cross-process, without doing any illegal stuff... :-)
2.I find out, Diablo has no offscreen surfaces, and use no Blitting...
Edocecrous (Csaba L. Bacskay)
ps.:If you, or anyone else has questions about this post, please write an email to:edocecrous@angelfire.co m
pps.:If you want to write a DirectX screen grabber program, HyperSnap DX is out there, and it does Glide and regular screens too.
I'm working on a program, which can display all active DirectDraw interfaces and surfaces, and save them to file, like Primary, back buffer, offscreen, overlay.
When it's finished and out there, you can ask questions. Not before.
I'm sorry for not posting anything for a while, but i had school.
I was about to post the same thing myself, because i found out exactly the same thing, myself... :-)
I have delphi, but i don't like pascal.
I hope that Microsoft will not read this article, because if they will, they will change this goodie, and it will be not available in future directx versions.
I read through your code, and i did nearly exatly the same thing!
(about a week ago, but i had no time to post it)
The delphi code looks lengthy, compared to the C++ one i wrote.
But it works on the same principle.
Also, i went into diablo, and find out something:
They used only Lock() and Unlock(), and they wrote their own rendering code. Thus, there is no double-buffering (back surface) no Blitting to copy strites, nothing.
They render directly to the screen, using repz movsd...
That was disappointing, since that time DirectX 3 was out, whith nice features, like BltFast() etc...
I'm happy you found the solution, and even more, because you found it without (too much) help!
Also, please do not make a news from our findings, since i'm sure Micro$oft will change it if it gets out!
They did it for smaller things...
If someone needs it, can find it on this post.
You know, what's funny, i did all the things:
Inserting a thread into the Process,
Doing Global Hooking,
Loading/freezing the app to do IAT patch,
etc,,,
1.And it turns out, this tweak works cross-process, without doing any illegal stuff... :-)
2.I find out, Diablo has no offscreen surfaces, and use no Blitting...
Edocecrous (Csaba L. Bacskay)
ps.:If you, or anyone else has questions about this post, please write an email to:edocecrous@angelfire.co
pps.:If you want to write a DirectX screen grabber program, HyperSnap DX is out there, and it does Glide and regular screens too.
I'm working on a program, which can display all active DirectDraw interfaces and surfaces, and save them to file, like Primary, back buffer, offscreen, overlay.
When it's finished and out there, you can ask questions. Not before.
ASKER
Just because i figured it out myself i will not deny the points from the correct answer. Way to go tTUi!
ASKER
!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!! !!!!!!!!!! !!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!! !!!!!!!!!! !!!!!!!!
!! !!
!! Since i've got lot's of email about this stuff, !!
!! please know this: I WILL NOT SEND YOU CODE. !!
!! So please don't send an email asking for it. !!
!! I DO HELP YOU FIND THE ANSWER, but you have to !!
!! work on/for it. !!
!! ps.:Looking for talented people. !!
!! !!
!! WWW.MYNERGY.COM !!
!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!! !!!!!!!!!! !!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!! !!!!!!!!!! !!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! Since i've got lot's of email about this stuff, !!
!! please know this: I WILL NOT SEND YOU CODE. !!
!! So please don't send an email asking for it. !!
!! I DO HELP YOU FIND THE ANSWER, but you have to !!
!! work on/for it. !!
!! ps.:Looking for talented people. !!
!! !!
!! WWW.MYNERGY.COM !!
!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!
I had this same dilema you are having, I could not find anything about directX screen capture either, so I just started trying everything. The thought I had was that all I had to do was make a copy of the primary display surface and save it as a .bmp file. So I eventualy found that using the windows GDI allowed me to gain access to the windows handle(hWnd) of the primary display surface. I would start looking into that, I am sure there are better ways but this methode has worked for me.
I hope this helps you get on the right track. :)