Interessanter Fehler, leider bekmm ich den nciht weg



  • Ich hab mir nen Hook zusammengebaut. Und nun stehe ich vor einem seltsamen Problem.
    Wenn ich die Funktionen aus der hook-dll in meinem Programm aufrufe, bekomme ich immer einen Fehler beim Speicherzugriff in Adresse ........
    Wenn ich aber direkt hinter den Aufruf ein "ShowMessage("");" setzte, funktioniert das.
    So funktioniert es:

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    	keys.KEY = 66;
    	RenewKBHook(keys);
    	ShowMessage("");
    }
    

    So bekomme ich eine Zugriffsverletzung:

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    	keys.KEY = 66;
    	RenewKBHook(keys);
    	ShowMessage("");
    }
    

    Im LowLevelKeyboardProc geht es auch wunderbar so:

    void __fastcall TForm1::KB_Hook(TMessage &msg)
    {
    	SetMSHook(Handle);
    	ShowMessage("");
    }
    

    So aber nicht:

    void __fastcall TForm1::KB_Hook(TMessage &msg)
    {
    	SetMSHook(Handle);
    }
    

    Der Quelltext der DLL ist folgender:

    //---------------------------------------------------------------------------
    #include <windows.h>
    #pragma hdrstop
    //---------------------------------------------------------------------------
    #define WM_KEYHOOK WM_USER+101
    typedef struct {
    	int KEY;
    	bool SHIFT;
    	bool CONTROL;
    	bool MENU;
    } CHECKKEY;
    
    bool alt = false,
         shift = false,
         ctrl = false;
    
    HHOOK ghKBHook;
    HINSTANCE ghKBInst;
    HWND MSG_TARGET;
    CHECKKEY usekey;
    //---------------------------------------------------------------------------
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
    {
    	ghKBInst = hinst;
    	return 1;
    }
    //---------------------------------------------------------------------------
    #define EXPORT extern "C" __declspec(dllexport)
    //---------------------------------------------------------------------------
    EXPORT DWORD CALLBACK llKBHook(int nCode, WPARAM wParam, LPARAM lParam)
    {
    	if((nCode < 0) || (nCode != HC_ACTION)){
    		return CallNextHookEx(ghKBHook, nCode, wParam, lParam);
    	}
    //	Skip if it's a repeat
    	if(lParam & 0x40000000)
    		return CallNextHookEx(ghKBHook, nCode, wParam, lParam);
    
    	PKBDLLHOOKSTRUCT p;
    	p = (PKBDLLHOOKSTRUCT) lParam;
    
    	if(wParam == WM_KEYDOWN){
    		if(p->vkCode == VK_SHIFT){       //Kann das hier überhaupt funktionieren? Oder wie kann ich angucken, ob noch Systemtasten gedrückt werden?
    			shift = true;
    		}
    		if(p->vkCode == VK_MENU){
    			alt = true;
    		}                       
    		if(p->vkCode == VK_CONTROL){
    			ctrl = true;
    		}
    
    		if(
    			   (p->vkCode == usekey.KEY)
    			&& (usekey.SHIFT == shift)
    			&& (usekey.CONTROL == ctrl)
    			&& (usekey.MENU == alt)
    			){
    			PostMessage(MSG_TARGET, WM_KEYHOOK, lParam, p->vkCode);
    			return 1;
    		}
    	}
    
    	if(wParam == WM_KEYUP){
    		if(p->vkCode == VK_SHIFT){
    			shift = false;
    		}
    		if(p->vkCode == VK_MENU){
    			alt = false;
    		}
    		if(p->vkCode == VK_CONTROL){
    			ctrl = false;
    		}
    	}
    	return CallNextHookEx(ghKBHook, nCode, wParam, lParam);
    }
    EXPORT void CALLBACK SetKBHook(HWND send_to_hwnd, CHECKKEY keys)
    {
    	usekey = keys;
    	MSG_TARGET = send_to_hwnd;
    	ghKBHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) llKBHook, ghKBInst, 0);
    }
    EXPORT void CALLBACK RemoveKBHook(void)
    {
    	UnhookWindowsHookEx(ghKBHook);
    }
    EXPORT void CALLBACK RenewKBHook(CHECKKEY NewKey)
    {
    	usekey = NewKey;
    }
    

    Im Programm wird das ganze so eingebunden:

    //header
    class TForm1 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
    //...
    private:	// Benutzer-Deklarationen
    //...
    	void __fastcall KB_Hook(TMessage &msg);
    	typedef void (setKBHook) (HWND, CHECKKEY); setKBHook *SetKBHook;        
    	typedef void (renewKBHook) (CHECKKEY); renewKBHook *RenewKBHook;
    	typedef void (removeKBHook) (void); removeKBHook *RemoveKBHook;
    
    public:		// Benutzer-Deklarationen
    	BEGIN_MESSAGE_MAP
    		MESSAGE_HANDLER(WM_KEYHOOK, TMessage, KB_Hook);
    		MESSAGE_HANDLER(WM_MOUSEHOOK, TMessage, MS_Hook);
    	END_MESSAGE_MAP(TForm);
    //...
    
    //cpp-file
    //...
    HINSTANCE kbhook_dll;
    //...
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    //DLLs laden + Fehlerüberprüfung
    //...
    	kbhook_dll = LoadLibrary("kbhook.dll");
    	SetKBHook = (setKBHook*) GetProcAddress((HMODULE)kbhook_dll, "SetKBHook");
    	RenewKBHook = (renewKBHook*) GetProcAddress((HMODULE)kbhook_dll, "RenewKBHook");
    	RemoveKBHook = (removeKBHook*) GetProcAddress((HMODULE)kbhook_dll, "RemoveKBHook");
    //...
    }
    void __fastcall TForm1::KB_Hook(TMessage &msg)
    {
    	SetMSHook(Handle);
    	ShowMessage("");
    }
    void __fastcall TForm1::BtChangeLookupKeyClick(TObject *Sender)
    {
    	keys.KEY = 66;
    	RenewKBHook(keys);
    	ShowMessage("");
    }
    

    Irgendwie ist dieses Phänomen sehr merkwürdig. Aber vllt weis ja einer eine Lösung?


Anmelden zum Antworten