Autor Beitrag
Tobi482
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: So 16.07.06 11:17 
Hi Leute,

ihr kennt doch sicherlich alle die Windows Messages die mit SendMessage(hwnd, msg, wparam, lparam) verschickt werden. Die beste IPC Methode ist ja, so denke ich doch, das Windows-Message-System. Ich habe eine eigene Art TSO(Teamspeak-Overlay) geschrieben, dass noch etwas mehr macht als das Original.

Für die, die TSO nicht kennen:

Teamspeak ist ein Programm das für Voice-Chat verwendet wird. Es gibt eine Chatroom Hierarchie und Admins und Channel-Admins wie in einem richtigen Chat. Das besondere an diesem Voice-Chat ist, dass er durch seine starken Voiceencoder den Datenstrom so klein hält, dass es die Latenzzeiten von Computerspielen recht gering hält und damit eine gutes "lagfrei" gameplay bietet. Oftmals sind aber soviele Leute in den Channels, dass man diese meiste an der Stimme nicht mehr indentifizieren kann. Da man nicht immer das Spiel minimieren kann und nachzugucken wer da gerade mit einem spricht wurde TSO entwickelt. Dieses Programm klinkt sich in den Frame-Render-Prozess des Spiels ein und zeichnet bevor die Frame aus dem Backbuffer auf den Schirm kommt noch schnell ein Fenster mit den Usernamen der Leute die gerade im Teamspeak sprechen. Man sieht also immer im Spiel wer gerade spricht.

Mein TSO zeigt noch etwas mehr an als nur die User die da gerade sprechen und diese Informatinen müssen irgendwie übergeben werden (IPC).

Der Kern von TSO ist eine DLL die per Injection dem Gameprozess hinzugefügt wird.

Ich muss also mit dieser DLL kommunizieren. Ein intervallgesteurte Shared-Memory abgfrage ist sehr CPU-lastig,d aher möchte ich ein Siganl über Sendmessage an den Spielprozess schicken. Meine DLL soll diese Nachricht abfangen bevor sie an das eigentliche Spiel weitergeleitet wird.

Ich denke mal das Stichwort dafür sind "Hooks".

Jedes mal jedoch wenn ich einen WH_GETMESSAGE in einer DLL startete, hookt der sämtliche Prozesse.

Ich möchte jedoch nur die Windows-MEssages hooken die das Spiel bekommt.

Hier ein Ausschnitt aus der Hook-DLL

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
var
     phook      : integer;

function HookProc(nCode:Integer; wparam:WPARAM; lparam:LPARAM):HRESULT;stdcall;
begin
     result := CallNextHookEx(phook, nCode, wparam, lparam);

     //if bla bla bla
end;
//------------------------------------------------------------------------------
procedure InstallHook;
begin
     phook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, HInstance, 0);
end;
//------------------------------------------------------------------------------
//Entrypoint der DLL
procedure DLLMain(reason:Integer);
begin
     //Wenn DLL eingeladen wird
     if reason = DLL_PROCESS_ATTACH then
     begin
          //InstallHook;
          Showmessage('hook installiert');
     end;

     //Wenn DLL ausgeladen wird
     if reason = DLL_PROCESS_DETACH then
     begin
          //UnhookWindowsHookEX(hook);
          Showmessage('hook entfernt');
     end;
end;
//------------------------------------------------------------------------------
begin
     DllProc := @DllMain;
     DllMain(DLL_PROCESS_ATTACH);
end.


Sobald diese DLL eingeladen wird bekomme ich aus Zeile 23 eine Messagebox von jedem laufenden Prozess. Obwohl ich diese DLL nur in einen Prozess eingeplanzt habe.

Frage:

Wie Hooke ich nur einen Prozess?
Ist WH_GETMESSAGE der richtige Hook um SendMessage(a,b,c,d) abzufangen?

Mit freundlichen Grüßen
Tobi
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: So 16.07.06 11:29 
Also ein Hook ist in diesem Fall IMHO absolut unötig! Es gibt auch andere Möglichkeiten als ein Hook oder Polling.
Meine Idee wäre ein Event (kein Ereignis im Delphi-OOP Sinn, sondern ein Windows Kernel-Objekt - Suche im MSDN CREATEEVENT). In deiner Dll erstellst du einen Thread der per WaitForSingleObject auf dieses Event wartet. Dadurch wird diesem Thread keine Rechenzeit zugeteilt solange das Event nicht ausgelöst wird. Wird nun der Inhalt deines Shared-Memory geändert, so löst du das Event aus, der Thread wird aufgeweckt, du liest den Inhalt des Shared-Memory aus, (verarbeitest ihn) und schickst den Thread wieder per WaitForSingleObject schlafen und wartest aufs nächste Mal...

Gruß, Motzi

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Tobi482 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: So 16.07.06 12:17 
Hi,

Ok das ging schnell^^

hast meine große Frage sofort erschlagen :-P
Prima Danke, ja klingt logisch ...
Habe das ganze nun eventgesteuert gebaut.

Noch mal ein ganz MGEA GROßES DANKESCHÖN :-D
Dein Tipp spart mir ne Menge Code.

Mit freundlichen Grüßen
Tobi