WndProc override in injizierter DLL - interprozessuale Kommunikation



  • Liebe Community!

    Ich habe eine C# Applikation, die eine C++ DLL in einen anderen Prozess mit Fenster injiziert. Dabei werden beide WindowHandles (C#-App und Zielprozess) an die DLL übergeben.
    Um die Kommunikation zwischen der C# Applikation und der injizierten DLL sicherzustellen, möchte ich gerne selbst definierte WindowMessages verwenden.
    In der C# Applikation funktioniert das auch bereits, ich konnte hier relativ unkompliziert die WndProc-Methode überschreiben, um ankommende Nachrichten nach den selbst definierten Nachrichten zu durchsuchen.
    Auch das Senden von Messages der C++ DLL and die C# Applikation funktioniert.

    Ich finde jedoch keine Möglichkeit, die WndProc-Methode des Zielprozesses zu überschreiben. Die Recherchen sind inkonklusiv, wobei ich hier zugeben muss, dass ich C++ streng genommen nicht besonders gut kann und nicht wirklich immer 100% verstehe, was ich mache. Ich betone daher Nachsicht.

    Problem: ich kann nicht einfach in die DLL

    protected: virutal void WndProc(..) override { }
    

    schreiben, da ich außerhalb einer Form-Klasse bin.
    Eigentlich müsste ich auch alles haben, was ich brauche. Die DLL arbeitet im Adressbereich der Zielanwendung und ich habe ein Handle zum Fenster der Zielanwendung.

    Wie komme ich an die Form-Klasse der Zielanwendung, um deren WndProc-Methode zu überschreiben? Was wäre ein Lösungskonzept meines Problems?

    Liebe Grüße!



  • void2k11 schrieb:

    Ich betone daher Nachsicht.

    Was ist das?

    void2k11 schrieb:

    Wie komme ich an die Form-Klasse der Zielanwendung, um deren WndProc-Methode zu überschreiben?

    Was ist die Zielanwendung? Auch C# oder nativ?



  • "Ich betone daher Nachsicht." kann man sagen, wenn man davon ausgeht, Fehler gemacht zu haben bzw. mangelndes Verständnis einer Sache hat und das Urteil einer fachlich versierten Instanz fürchtet.

    Die Zielanwendung ist nativ.



  • void2k11 schrieb:

    Die Zielanwendung ist nativ.

    Und wie kommst du darauf, dass es in nativen Anwendungen sowas wie Forms Klassen gibt?



  • Und wie kommst du darauf, dass es in nativen Anwendungen sowas wie Forms Klassen gibt?

    Weil die Anwendung ein Fenster hat und mein Begriff von "Fenster" sehr stark mit Windows.Forms verbunden ist und ich mich außerhalb von C# praktisch nicht auskenne (ich muss mich also auf Halbwissen durch die Google-Suche berufen).

    Ich kann die Frage(n) auch gerne umformulieren:
    Wie kann ich die Nachrichten an das Fenster der Zielanwendung vor der Bearbeitung durch die Zielanwendung (WndProc?) nach meinen eigenen Nachrichten durchsuchen?
    Warum funktioniert GetMessage trotz eines validen(?) Handles nicht?

    Edit: Das Handle für GetMessage wurde durch die C# Applikation mittels Process.MainWindowHandle erstellt und übergeben.



  • Du könntest versuchen, dir mit GetWindowLong einen Zeiger auf die gesetzte window proc zu holen (GWL_WNDPROC), und mit SetWindowLong eine eigene zu setzen, die die vorherige Funktion aufruft.



  • void2k11 schrieb:

    "Ich betone daher Nachsicht." kann man sagen, wenn man davon ausgeht, Fehler gemacht zu haben bzw. mangelndes Verständnis einer Sache hat und das Urteil einer fachlich versierten Instanz fürchtet.

    Kenn ich auch nicht.
    Google auch nicht: Keine Ergebnisse für "Ich betone daher Nachsicht" gefunden

    ----

    Du könntest es auch mit SetWindowsHookEx versuchen. Und zwar mit einem WH_CALLWNDPROC bzw. WH_CALLWNDPROCRET Hook.

    Wobei die Variante von Mechanics vermutlich einfacher ist.
    Nur würde ich GetWindowLongPtr statt GetWindowLong verwenden 😉



  • Du könntest versuchen, dir mit GetWindowLong einen Zeiger auf die gesetzte window proc zu holen (GWL_WNDPROC), und mit SetWindowLong eine eigene zu setzen, die die vorherige Funktion aufruft.

    Also: Mit GetWindowLongPtr hole ich mir erstmal die originale WndProc-Funktion.
    Dann esetze ich mit SetWindowLongPtr die modifizierte WndProc-Funktion ein.
    In der modifizierten Methode durchsuche ich nach meinen eigenen Nachrichten und rufe dann wieder die originale WndProc Methode auf.

    HWND hWndMaster;
    HWND hWndChild;
    LONG OriginalWndProc;
    
    int SendMessageToMaster(int Message);
    int SendMessageToChild(int Message);
    void ShowInt(int value);
    
    LRESULT CALLBACK CustomWndProc(HWND hwnd, UINT Message, WPARAM wP, LPARAM lP) 
    {
    	MessageBox(0, "WndProc was called.", "", 0);
    	switch (Message)
    	{
    		case AM_MESSAGEDEFAULT:
    			MessageBox(0, "User defined Message received.", "", 0);
    			break;
    		default:
    			MessageBox(0, "Some Message received.", "", 0);
    			break;
    	}
    
    	return CallWindowProc((WNDPROC)OriginalWndProc, hwnd, Message, wP, lP);
    }
    
    DWORD WINAPI Main_Thread(LPVOID lpParameter)
    {
    	Sleep(1000);
    	MessageBox(0, "DLL loaded.", "", 0);
    
    	OriginalWndProc = GetWindowLongPtr(hWndChild, GWLP_WNDPROC);
    	if (OriginalWndProc == 0)
    		MessageBox(0, "Error in GetWindowLongPtr", "", 0);
    	int ErrorGet = GetLastError();
    	ShowInt(ErrorGet);
    
    	int retSet = SetWindowLongPtr(hWndChild, GWLP_WNDPROC, (LONG)CustomWndProc);
    	if (retSet == 0)
    		MessageBox(0, "Error in SetWindowLongPtr", "", 0);
    	int ErrorSet = GetLastError();
    	ShowInt(ErrorSet);
    
    	return S_OK;
    }
    
    void ShowInt(int value)
    {
    	std::stringstream ss;
    	ss << value;
    	std::string valueStr = ss.str();
    
    	MessageBox(0, valueStr.c_str(), "", 0);
    }
    

    Problem: Get und Set geben 0 zurück, sind also fehlgeschlagen. GetLastError ist hingegen 0, also ERROR_SUCCESS.



  • Rufst du das im richtigen Prozess auf? Das musst du im Zielprozess aufrufen.



  • Hm.
    Vermutlich muss man das A/W von GetWindowLongPtrA/W mit dem RegisterClassA/W Aufruf matchen...?



  • Mechanics schrieb:

    Rufst du das im richtigen Prozess auf? Das musst du im Zielprozess aufrufen.

    Vielen Dank, das war ein sehr guter Hinweis. Bin davon ausgegangen, aber ich lag völlig falsch. Mangel erkannt, Mangel abgestellt. Es funktioniert. Das Problem lag im Endeffekt völlig woanders, ohne deine/eure Hilfe wäre ich wohl nicht darauf gekommen, meine falschen Annahmen nocheinmal zu überprüfen!


Anmelden zum Antworten