Hook

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
chi
Beiträge: 90
Registriert: 17.05.2007 09:30
Wohnort: Austria

Hook

Beitrag von chi »

hi leute,

ich würde gern die buttons in der titelleiste (minimieren, maximieren, schließen) von externen programmen
abfangen um zb. ne messagebox mit "ja/nein programm schließen" zwischen zu schalten...

mit pb internen programmen hab ichs schon geschafft:

Code: Alles auswählen

Global Callback.l

Procedure Callback(WindowID, Message, wParam, lParam)
  Select Message
    Case #WM_SYSCOMMAND
      Select wParam
        Case #SC_CLOSE
          Callback = 1
          ProcedureReturn 0
        Case #SC_MAXIMIZE
          Callback = 2
          ProcedureReturn 0
        Case #SC_MINIMIZE
          Callback = 3
          ProcedureReturn 0
      EndSelect
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

OpenWindow(0, 0, 0, 320, 240, " test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
TextGadget(1, 10, 10, 150, 14, "")
SetWindowCallback(@Callback(), 0)

Repeat
  
  Event = WaitWindowEvent()
  
  If Callback
    Select Callback
        
      Case 1
        SetGadgetText(1, "Close Button")
        quit = MessageRequester("Info", "Quit program?", #PB_MessageRequester_YesNo)
        If quit = #PB_MessageRequester_Yes
          exit = 1
        Else
          Callback = 0
        EndIf
        
      Case 2
        SetGadgetText(1, "Maximize Button")
        
      Case 3
        SetGadgetText(1, "Minimize Button")
        
      Default
        Callback = 0
        
    EndSelect
  EndIf
  
Until exit
End
... nur wie schauts zb. mit calc.exe aus? soweit ich mitbekommen hab brauch ich ne separate dll um externe events zu hooken. hab in den foren leider (für mich) nichts nützliches gefunden...
hat jemand von euch schon mal ähnliches versucht und kann mir ev. unter die arme greifen?

danke schonmal, chi
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Oh, das is easy. Window Hook ist kein Problem.
Als erstes brauchst du DLL-Injection. Das bedeutet, du injizierst eine von dir geschriebene DLL in den Prozess, dessen Fenster du hooken möchtest. Das machst du, damit dein Code in dem Prozess läuft und somit alles uneingeschränkt machen kann/darf.

Hier gibts ein gratis Code zum DLL injecten von mir.

Ist deine DLL erstmal injiziert, muss sie nur das Fenster finden und hooken. Das Fenster zu finden sollte nicht das Problem sein, deshalb überspringe ich das einfach mal. Falls das nicht klar ist, kannst ja nochmal danach fragen.

Dann hookst du das Fenster. Ist super einfach. Du brauchst als erstes eine WindowProc in deiner DLL.
Die sieht z.b. so aus:

Code: Alles auswählen

Procedure.l WindowHook(hWnd.l,uMsg.l,wParam.l,lParam.l)

  Select uMsg

    Case #WM_MOVE,#WM_SIZE
      If GotClipRect = 2
        AdjustClipRect()
      EndIf

  EndSelect

  ProcedureReturn CallWindowProc_(OrigWndProc,hWnd,uMsg,wParam,lParam)

EndProcedure
Das ist ein Codeschnipsel aus meinem sagenumwobenen inoffiziellen 2.30 Patch für Sacred Underworld, den ich hoffentlich irgendwann mal vollenden werde. :mrgreen:

Diese Prozedur soll nun immer wenn ein Event das Fenster erreicht aufgerufen werden. Das erreichst du indem du eine nette WinAPI-Funktion aufrufst: SetWindowLong
Folgender Code veranschaulicht das:

Code: Alles auswählen

Procedure InstallWindowHook()
  
  OrigWndProc = GetWindowLong_(SacredHWnd,#GWL_WNDPROC)
  SetWindowLong_(SacredHWnd,#GWL_WNDPROC,@WindowHook())
  
EndProcedure
Den Rückgabewert von GetWindowLong musst du, wie du siehst sichern, der ist extrem wichtig, ansonsten schrottest du die Eventverarbeitung des Programms. Das ist die Adresse der originalen WindowProc. Die musst du aufrufen, nachdem deine WindowProc durchgearbeitet wurde. Den Rückgabewert der originalen WindowProc muss deine WindowProc auch zurückgeben, wichtig!
Aber siehst du ja alles im Code.

Natürlich kannst du Messages auch "verschlucken" oder ändern und dann weiterleiten.
Zuletzt geändert von Thorium am 08.10.2008 19:20, insgesamt 1-mal geändert.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
chi
Beiträge: 90
Registriert: 17.05.2007 09:30
Wohnort: Austria

Beitrag von chi »

danke thorium für deine schnelle antwort...

meine befürchtung ist aber leider wahr geworden -> ich versteh nur bahnhof!
WindowHook und InstallWindowHook kann ich ja noch nachvollziehen. aber dein code zum injecten is dann doch noch etwas zu hoch für mich.
habe eigentlich gehofft, daß es genau so einfach wie mit pb-internen fenster geht. dem ist aber anscheinend nicht so :oops:

falls du (oder jemand anderer) zeit und lust hast mir das ganze etwas genauer zu erklären, wäre ich dir sehr dankbar!

lg, chi
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

chi hat geschrieben: aber dein code zum injecten is dann doch noch etwas zu hoch für mich.
habe eigentlich gehofft, daß es genau so einfach wie mit pb-internen fenster geht. dem ist aber anscheinend nicht so :oops:
Der Unterschied zu einem PB-internen Fenster ist ja recht gering. Die WindowProc (WindowHook) ist ja die der Window Callback von PB.

Mein Code für die DLL-Injection ist etwas komlizierter, weil er CreateRemoteThread nicht verwendet.

Hier ist ein etwas einfacherer aus dem englischen Forum.

Ich kann dir auch später mal erklären wie das genau funktioniert hab aber grad jetzt leider keine Zeit.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
hardfalcon
Beiträge: 3447
Registriert: 29.08.2004 20:46

Beitrag von hardfalcon »

Funktioniert DLL-Injection eigentlich auch noch unter Vista, oder funkt da die UAC dazwischen?
Antworten