Link to home
Start Free TrialLog in
Avatar of Frozt
Frozt

asked on

SubClassing Extern Program

Hello, how can i subclass a program like Microsft internet explorer to get its messages.
which steps i have to follow, if u have already a example for this, could you share it with me.

thank you for your time
Avatar of DaFox
DaFox

Hi Frozt.

Take a look at the functions GetWindowLong(), SetWindowLong to subclass an external application.
Be aware that you have to inject your code (DLL) into the context of this/these external app(s). Normally you  achieve this with a hook (SetWindowsHookEx())...
There are some good tutorials on the web.

Ask if you need more information.

Regards,
Markus
Because you can not access the memory space in another process, you can not Subclass, another apps windows. Also I have tried several different methods and memory access routines in several different "HOOK DLLs" to subclass another apps windows, but I got alot of access violations and never did subclass anything.
Avatar of Frozt

ASKER

Hi DaFox

i did a dll witch exports 2 procedures:
- SetGlobalHook
- UnSetGlobalHook

procedure SetGlobalHook;
begin
  if (hHook = 0) then
    hHook := SetWindowsHookEx(WH_CBT, @CBTProc, hInstance, 0);
end;

procedure UnSetGlobalHook;
begin
  if (hHook <> 0) then begin
    SetWindowLong(Handle, GWL_WNDPROC, OldProc);
    UnHookWindowsHookEx(MiHook);
  end;
end;

CBTProc is my callback funtion, there i get OldProc calling
OldProc := SetWindowLong(Handle, GWL_WNDPROC, Integer(@NewProc));
when i call UnSetGlobalHook, Handle is 0 and OldProc is also 0.
why is that ? :(, i cant restore OldProc
thank you


Hi Frozt!

That's because there's a copy of your dll in every process. But the variables (Handle, OldProc) are only initialized in the your application's process.

Try the following (IPC aka Inter Process Communication):

type
 THookRec = packed record
   hookHandle : DWord;
   oldProc: Pointer;
 end;

var
  map : dword;
  buf : ^THookRec;
  bIsDone: Boolean = false;

...

function TrayHookProc(nCode: Integer; wp: wParam; lp: lParam): LongInt; stdcall;
begin
  if (nCode >= HC_ACTION) and (not bIsDone) then
  begin
    bIsDone := true;
    SetWindowLong(Handle, GWL_WNDPROC, OldProc);
  end;
  Result := CallNextHookEx(buf^.Hook, nCode, wp, lp);
end;

procedure SetGlobalHook;
begin
  if (hHook = 0) then
  begin
    map := CreateFileMapping(DWord(-1), nil, PAGE_READWRITE, 0, SizeOf(THookRec), 'stift123');
    buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    buf^.hHook := SetWindowsHookEx(WH_CBT, @CBTProc, hInstance, 0);
  end;
end;

procedure UnSetGlobalHook;
begin
  if (buf^.hHook <> 0) then
  begin
    UnHookWindowsHookEx(buf^.hHook);
    buf^.hHook := 0;
    UnmapViewOfFile(buf);
    buf := nil;
  end;
end;

...

procedure DllEntry(dwReason: DWord);
begin
  Case dwReason of
    DLL_PROCESS_ATTACH:
    begin
      map := OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 'stift123');
      buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        CloseHandle(map);
        map := 0;
      end;
    end;
    DLL_PROCESS_DETACH:
    begin
      UnmapViewOfFile(buf);
      buf := nil;
    end;
  end;
end;

btw:
1. you don't have to use a system wide hook.
try:
hWnd := FindWindow('somewndclass', nil);
dwThreadId := GetWindowThreadProcessId(hWnd, nil);
buf^.hHook := SetWindowsHookEx(WH_CBT, @CBTProc, hInstance, dwThreadID);

because you just have to get into the context of your desired process!

2. What are you trying to do with 'Handle' in SetWindowLong()?
Try to call FindWindow to get the hWnd of your external window and take it into the buf.

Regards,
Markus
Avatar of Frozt

ASKER

Hi DaFox

i am trying to add an extra menu to Internet Expplorer and when i click in it do something.

i am using SetWindowsHookEx(WH_CBT, @CBTProc, hInstance, 0);

WH_CBT is to get when a window is created o destroyed so i can add the new menu.
so i have this:

function CBTProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  szClass: array[0..256] of Char;
begin
  if (nCode < 0) then begin
    Result := CallNextHookEx(hHook, nCode, wParam, lParam);
    Exit;
  end;
  if (nCode = HCBT_CREATEWND) then begin //Window Created
    hProc := wParam;
    FillChar(szClass, 256, 0);
    GetClassName(hProc, szClass, 256);
    if (szClass = 'IEFrame') then begin // it's IE
        hIE := hProc;
        OldProc := SetWindowLong(hIE, GWL_WNDPROC, Integer(@IEProc)); //try to subclass
    end;
  end else if (nCode = HCBT_DESTROYWND) then begin //window destroyed
    hProc := wParam;
    FillChar(szClass, 256, 0);
    GetClassName(hProc, szClass, 256);
    if (szClass = 'IEFrame') then begin
      hIE := hProc;
      SetWindowLong(hIE, GWL_WNDPROC, OldProc);
    end;  //try to set OldProc back
  end;
  Result := CallNextHookEx(hHook, nCode, wParam, lParam);
end;

but i guess i'm wrong :(, is ok to hook with WH_CBT ? :s
thank you for your time
Madshi has a greatsimple-to-use component for injecting a dll into a process. It will run on any windows Os (incl xp). You can find it at  http://help.madshi.net/madKernel.htm

Here's an example:

To inject a module (dll) into the destination process you can use the method "LoadModule". If you set "autoClose" to "true", the module is unloaded again as soon as the resulting IModule instance is freed. If you don't want that, please set "autoClose" to "false".

 function IProcess.LoadModule (fileName          : string;
                              autoClose         : boolean = true;
                              withoutReferences : boolean = false;
                              onlyAsDataFile    : boolean = false;
                              alteredSearchPath : boolean = false;
                              timeOut           : integer = 3000 ) : IModule;

// Example:
Process('explorer.exe').LoadModule('hookExpl.dll', false);  
 
Hi Frozt!

Yep, that should be okay.

If you're familiar with C take a look at this little sample: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=3087&lngWId=3

Regards,
Markus
Avatar of Frozt

ASKER

Hello DaFox

I looked that C++ example, and when i try to set back the OldProc, it show me that both variables are 0. so its the same problem i had before.
so i try with the Mapping thing, and i'm doing good (i think)
and when i try to set the oldproc, the window chashes when i click in it :s

how do i give points ?, im new to this forum
thank you
Hi Frozt!

> it show me that both variables are 0
Are you shure that you are using buf^.oldProc and buf^.hookHandle within the whole dll?

> so i try with the Mapping thing, and i'm doing good (i think)
Good! That's the beginning of your succes ;)

> and when i try to set the oldproc, the window chashes when i click in it :s
Hm, maybe oldProc is not initialized. try to use buf^.oldProc

>how do i give points ?
Click "accept answer" button next to the comment that helped you most. After that you have to give a grade. That's all...

Regards,
Markus
Avatar of Frozt

ASKER

Hi DaFox

yes i'm trying with the buf^.OldProc, then i set it back, and when i click on the window, it crashes :(
what could be wrong ?
if u want i can send you my dll source.
thanks
Yep, you can.
Unfortunately, I don't know how long it will take it until I can take a look at it... :/

Markus

PS: You can find my e-mail address in my profile.
ASKER CERTIFIED SOLUTION
Avatar of DaFox
DaFox

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Frozt

ASKER

Thank You Man