Diese Webseite wendet sich an Windows-C-Programmierer. Das Beispiel wurde in Visual C++ 6.0 erstellt.
Wie immer bei mir ohne Laufzeitbibliothek.
Ein (menschlicher!) Assistent soll nun durch Tastendruck steuern, dass bestimmte Motive nicht klappen (bspw. unscharf oder einfach schwarz werden).
Dennoch ist man nicht chancenlos. Dazu gibt es Windows Hooks.
Als erstes wurde mittels Spy++ (beim Visual C++ dazu) untersucht,
welche Art Kindfenster dieses Programm zur Bildausgabe verwendet.
Das Programm verwendet ein Fenster der Klasse "Static" mit dem
entscheidenden Stilbit SS_IMAGE.
Dies ist ein Glücksfall, weil die Nachricht zum Setzen des Bildes
bekannt ist: STM_SETIMAGE.
Diese Nachricht abfangen und ändern ist das Ziel.
Es gibt verschiedene Methoden, um eine DLL in einen Wirtsprozess
einzuschleusen. Bei der Verwendung von globalen Windows-Hooks
(SetWindowHookEx())
kümmert sich Windows bereits selbst darum, und man hat die wenigste Arbeit.
Solche Hook-DLLs benötigen zwanghaft eine Variable, die über
alle Prozesse sichtbar ist; sie muss sich in einem sog.
shared-Datensegment befinden.
Die Attribute für das Segment namens .shared (Name beliebig)
werden mit der Linker-Befehlszeile in den Projekteinstellungen festgelegt:
/section:.shared,rws
Wichtig! Falsche Projekteinstellungen führen zum Windows-Crash!
SendMessage() oder
SendDlgItemMessage() verschickt),
wäre der Hooktyp WH_CALLWNDPROC naheliegend.
Er bewirkt jedoch viel zuviel Filteraufwand.
Wesentlich zielgerichteter ist es, das gewünschte Fenster als Unterklasse
zu erstellen, d.h. die Fensterprozedur anzuzapfen.
Dazu muss man nur das Erzeugen des Fensters abfangen.
Dies erledigt man mit CBT-Hooks (CBT = computer based training,
svw. Lernprogramm). Das heißt, der Hooktyp ist WH_CBT.
Jetzt muss die Anzapfung nur noch bei dem gewünschten Fenster erfolgen. Die notwendigen Vergleichswerte beschafft man sich mittels Spy++.
Für die Anzapfung der Tastatur wird noch ein prozess-lokaler Hook gesetzt.
lParam zu modifizieren.
Je nach zu ladendem Bild wird mittles LoadImage()
ein Bitmap geladen und der lParam-Parameter ersetzt.
Welche Datei geladen wird, bestimmt sich aus dem letzten Tastendruck,
welcher mit dem Tastatur-Hook (s.u.) erfasst wird.
Da aus der Windows-SDK-Dokumentation nicht hervorgeht, wer das Handle
löschen soll, bin ich davon ausgegangen, dass der Aufrufer von
SendMessage(...,STM_SETIMAGE,...)
ein gültiges Handle solange behalten muss, wie das Bild dargestellt werden soll.
Das heißt, der Aufrufer muss das Bitmap-Handle löschen.
Deshalb wird noch eine entsprechende globale Variable geführt
und das ursprüngliche lParam-Handle unbeachtet gelassen.
Eigentlich müsste man noch STM_GETIMAGE filtern und den
ursprünglichen lParam-Wert zurückgeben.
llib.exe („LoadLib“)
geschrieben, was eine DLL lädt (oder mehrere) und dann endlos wartet.
llib.exe kann nur gekillt werden, bspw. mit dem Task-Manager
oder killllib.exe.
Der Startup-Kode der DLL installiert den Hook; darafhin kriecht die DLL
in jeden laufenden Prozess.
Weil der Shutdown-Kode der DLL beim Killen von llib.exe
aufgerufen wird und dieser den Hook entfernt, zieht sich die DLL umgehend
aus den anderen Prozessen zurück.
Nur den Unterklassen-Kode müsste man von Hand aushängen (fehlt hier).
MessageBeep() bzw. Beep() eingebaut.
Um diese Meldungen zu sehen, sollte man das Programm DbgView
(gibt's kostenlos bei Micorosoft) benutzen.