Bonjour,

Voici le tuto que je tente de réaliser sur Code::Blocks : http://tcharles.developpez.com/simul/#hooks.

Malheureusement, je rencontre un soucis majeur pour ce tutoriel : au moment d'utiliser la fonction "GetProcAddress", l'adresse retournée reste à 0. Du coup, à l'appel de "InitHooks(fenetrePrincipale);", un "segmentation fault" a tout stoppé.
Je devine donc que la fonction n'a pas réussi à trouver l'adresse de la procédure, mais je ne sais pas comment corriger le problème.

Voici le code de la DLL Hook :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <windows.h>
 
#define DLL_EXPORT __declspec(dllexport)
 
// Définition de la structure de la zone mémoire partagée
typedef struct _TDonnees {
     HHOOK MouseHookHandle; // Handle du hook de la souris
     HHOOK KeybdHookHandle; // Handle du hook du clavier
     HWND hDestWindow; // Handle de la fenêtre à laquelle le hook du clavier doit les données
     // Mettez ici toutes les données que vous voulez partager
} TDonnees;
 
// Déclaration des variables globales de la DLL
HANDLE MemPartagee; // Handle de la zone de mémoire partagée
TDonnees * VueDonnees; // Pointeur vers la zone de mémoire
HINSTANCE HInst; // Handle d'intance de la DLL
 
// Déclaration des fonctions de la DLL
EXTERN_C CALLBACK void DLL_EXPORT InitHook(HWND hDest);
EXTERN_C CALLBACK void DLL_EXPORT EndHook();
LRESULT CALLBACK DLL_EXPORT MouseProc(int nCode,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK DLL_EXPORT KeybdProc(int nCode,WPARAM wParam,LPARAM lParam);
 
// fonction d'initialisation de la DLL
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) {
    HInst = hinst;
    switch (reason) {
        case DLL_PROCESS_ATTACH : // à la création de l'instance de la DLL
            // Attachement d'une zone de mémoire partagée (notez le cast)
            MemPartagee = CreateFileMapping((HANDLE)0xFFFFFFFF, // On map un espace mémoire
                            NULL, // Pas d'informations de sécurité
                            PAGE_READWRITE, // Partage en lecture/écriture
                            0, // Taille de la zone réservée sur 64 bits (32 bits de poid fort)
                            sizeof(TDonnees), // 32 bits de poids faible
                            "Tutoriel Hooks par gRRosminet"); // Nom de la zone réservée
 
            // Création d'une vue pour pouvoir accéder à la zone de mémoire partagée (notez le cast)
            VueDonnees = (TDonnees *)(MapViewOfFile((HANDLE)MemPartagee, // Zone sur laquelle créer la vue
                            FILE_MAP_WRITE, // Mode d'accès en lecture/écriture
                            0, 0, // Offset de début de la vue sur 64 bits
                            0)); // Taille de la vue (0 = tout)
            break;
 
        case DLL_PROCESS_DETACH : // au détachement de la DLL
            // Destruction de la vue sur la zone de mémoire partagée
            UnmapViewOfFile((LPVOID)VueDonnees);
            // Détachement de la zone de mémoire partagée
            CloseHandle(MemPartagee);
            break;
 
        default :
            // DLL_THREAD_ATTACH, DLL_THREAD_DETACH
            break;
    }
    return 1;
}
 
void DLL_EXPORT InitHook(HWND hDest) {// _export est spécifique à BCB
    // Installation du hook sur la souris
    VueDonnees->MouseHookHandle = SetWindowsHookEx(WH_MOUSE, // Créer un hook sur la souris
                                    (HOOKPROC)MouseProc, // Utiliser la fonction MouseProc
                                    HInst, // Dans la DLL d'instance HInst
                                    0); // Pour tous les threads
 
    // Installation du hook pour le clavier
    VueDonnees->KeybdHookHandle = SetWindowsHookEx(WH_KEYBOARD, // Créer un hook sur le clavier
                                    (HOOKPROC)KeybdProc, // Utiliser la fonction KeybdProc
                                    HInst, // Dans la DLL d'instance HInst
                                    0); // Pour tous les threads
 
 
    // Partage de la fenêtre destinatrice des données du clavier
    VueDonnees->hDestWindow = hDest;
}
 
void DLL_EXPORT EndHook() {
    // Supression des hooks
    UnhookWindowsHookEx(VueDonnees->MouseHookHandle);
    UnhookWindowsHookEx(VueDonnees->KeybdHookHandle);
}
 
LRESULT CALLBACK DLL_EXPORT MouseProc(int nCode,WPARAM wParam,LPARAM lParam) {
    // On joue un son à chaque fois que l'utilisateur enfonce le bouton gauche
    if (wParam == WM_LBUTTONDOWN)
        MessageBeep(MB_ICONEXCLAMATION);
 
    return CallNextHookEx(VueDonnees->MouseHookHandle,nCode,wParam,lParam);
}
 
#define WMAP_KEYBDHOOKMSG WM_APP + 1
 
LRESULT CALLBACK DLL_EXPORT KeybdProc(int nCode,WPARAM wParam,LPARAM lParam) {
    // On envoie un message WMAP_KEYBDHOOKMSG à chaque fois que
    // l'utilisateur presse la touche ENTREE
    if (wParam == VK_RETURN)
        PostMessage(VueDonnees->hDestWindow, WMAP_KEYBDHOOKMSG, 0, 0);
 
    return CallNextHookEx(VueDonnees->KeybdHookHandle,nCode,wParam,lParam);
}
où EXTERN_C = extern "C"
et CALLBACK = __stdcall

Et pour la WINAPI, voici le code (je n'ai pas fait de header) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
 
#include <windows.h>
#include <stdio.h>
 
#define ID_CHECKBOX_1       113
#define WMAP_KEYBDHOOKMSG WM_APP + 1
 
HINSTANCE instance;
typedef void (*TInitFunc) (HWND);
typedef void (*TEndFunc) ();
 
bool bHook;
int nbEntree;
 
TInitFunc InitHooks; // fonction d'initialisation des hooks
TEndFunc EndHooks; // fonction de suppression des hooks
HINSTANCE hinstDLL; // instance de la DLL
 
/*  Declare Windows procedure  */
LRESULT CALLBACK procedureFenetrePrincipale (HWND, UINT, WPARAM, LPARAM);
VOID RemplieFenetrePrincipale(HWND fenetrePrincipale);
VOID NotificationControle(HWND fenetrePrincipale,UINT message, WPARAM wParam, LPARAM lParam);
VOID ActionCheckBox(int index,HWND hCtl,HWND fenetrePrincipale);
void dessineTexte (HWND fenetreCiblee, char *chaine, int left, int top);
 
int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance, LPSTR lignesDeCommande, int modeDAffichage) {
 
    HWND fenetrePrincipale;     /* This is the handle for our window */
    MSG messages;               /* Here messages to the application are saved */
    WNDCLASS classeFenetre;    /* Data structure for the windowclass */
 
    /* The Window structure */
    classeFenetre.style = 0;                             /* None */
    classeFenetre.lpfnWndProc = procedureFenetrePrincipale;     /* This function is called by windows */
    classeFenetre.cbClsExtra = 0;                      /* No extra bytes after the window class */
    classeFenetre.cbWndExtra = 0;                      /* No extra bytes after the window class */
    classeFenetre.hInstance = NULL;
    classeFenetre.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    classeFenetre.hCursor = LoadCursor (NULL, IDC_ARROW);
    classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
    classeFenetre.lpszMenuName = NULL;                 /* No menu */
    classeFenetre.lpszClassName = "classeF";
 
    /* Register the window class, and if it fails quit the program */
    if (!RegisterClass(&classeFenetre)) return FALSE;
 
    /* The class is registered, let's create the program*/
    fenetrePrincipale = CreateWindow(
        "classeF",
        "Première fenêtre en winAPI !",
        WS_OVERLAPPEDWINDOW, /*Style qui permet d'avoir une fenêtre tout ce qu'il y a de plus normale : barre de titre, menu système (réduire, maximiser, fermer), bordure etc...*/
        CW_USEDEFAULT, // Permet à l'OS de déterminer dynamiquement la position de la fenêtre
        CW_USEDEFAULT, //Idem
        450,
        320,
        NULL, // Pas de fenêtre parent, puisque c'est la principale
        NULL, //Aucun menu ne lui est associé
        cetteInstance,
        NULL); // Aucun paramètre à lui envoyer en plus
 
    if (!fenetrePrincipale) return FALSE;
 
    /* Make the window visible on the screen */
    ShowWindow(fenetrePrincipale, modeDAffichage);
    UpdateWindow(fenetrePrincipale);
 
    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage(&messages, NULL, 0, 0)) {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }
 
    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}
 
 
/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK procedureFenetrePrincipale(HWND fenetrePrincipale, UINT message, WPARAM wParam, LPARAM lParam) {
 
    char texte[] = "Pressions de ENTREE : 0";
 
    switch (message) {
        case WM_CREATE:
            RemplieFenetrePrincipale(fenetrePrincipale);
            return 0;
        case WM_PAINT:
            sprintf(texte, "Pressions de ENTREE : %d",nbEntree);
            dessineTexte(fenetrePrincipale, texte, 20, 80);
            return 0;
 
        case WM_COMMAND:
            NotificationControle(fenetrePrincipale,message,wParam,lParam);
            return 0;
 
        case WM_DESTROY:
            if (bHook) EndHooks();
            PostQuitMessage(0);
            return 0;
 
        default:
            return DefWindowProc(fenetrePrincipale, message, wParam, lParam);
    }
}
 
VOID RemplieFenetrePrincipale(HWND fenetrePrincipale) {
 
    HWND hGroup = CreateWindow(
        "BUTTON",
        "La check box",
        WS_CHILD|WS_VISIBLE|BS_GROUPBOX,
        10,10,
        200,50,
        fenetrePrincipale,
        NULL,
        instance,
        NULL);
    {
        HWND hControle;
        // une check box automatique deux états
        hControle=CreateWindow(
            "BUTTON",
            "Hook (ON/OFF)",
            WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
            10+10,10+20,
            180,20,
            fenetrePrincipale,
            (HMENU)ID_CHECKBOX_1,
            instance,
            NULL);
    }
 
    bHook = false;
    hinstDLL = LoadLibrary("hook.dll");
    if (!hinstDLL) // Erreur lors du chargement de la librairie ?
        MessageBox(fenetrePrincipale,"Impossible de charger la librairie.","gloups",MB_OK);
    else {
        // On récupère les adresses des fonctions
        InitHooks = (TInitFunc)GetProcAddress(hinstDLL, "InitHook");
        EndHooks = (TEndFunc)GetProcAddress(hinstDLL, "EndHook");
    }
 
}
 
VOID NotificationControle(HWND fenetrePrincipale,UINT message, WPARAM wParam, LPARAM lParam) {
    UINT iId=LOWORD(wParam);
    HWND hCtl=(HWND)lParam;
 
    switch(iId) {
        case ID_CHECKBOX_1:
            ActionCheckBox(iId-ID_CHECKBOX_1,hCtl,fenetrePrincipale);
            break;
    }
}
 
VOID ActionCheckBox(int index,HWND hCtl,HWND fenetrePrincipale) {
    // test si la check box est cochée, non cochée ou inderterminée.
    LRESULT lRes=SendMessage(hCtl,BM_GETCHECK,0,0);
    CHAR lpMessage[128];
 
    sprintf(lpMessage,"La check box n°%d est maintenant %s",index,
        (lRes==BST_CHECKED)?"cochée":
        (lRes==BST_UNCHECKED)?"décochée":"inderterminée");
 
    MessageBox(fenetrePrincipale,lpMessage,"Vous avez modifié une check box",
        MB_ICONINFORMATION|MB_OK);
 
    if (hinstDLL) { // Vérifie que la librairie est chargée, sinon, inutile de continuer
        if (lRes==BST_CHECKED) { // Activer les hooks
            nbEntree = 0; // On réinitialise le compteur
            InitHooks(fenetrePrincipale); // On initialise les hooks
        } else { // Désactiver les hooks
            EndHooks(); // On supprime les hooks
        }
    }
 
}
 
void dessineTexte(HWND fenetreCiblee, char *chaine, int left, int top) {
    //Déclarations préalables
    PAINTSTRUCT ps;
    HDC dc;
 
    //Récupération de la surface de dessin dans dc
    dc = BeginPaint(fenetreCiblee, &ps);
 
    //Permet au texte d'avoir un fond transparent
    SetBkMode(dc, TRANSPARENT);
    //Applique la couleur de texte au dc
    SetTextColor(dc, 0x00000000);
 
    //Affichage du texte
    TextOut(dc, left, top, chaine, strlen(chaine));
    //TextOut(dc, 40, 50, "Toto", 4);
 
    //Libération de la surface et du dc
    EndPaint(fenetreCiblee, &ps);
 
    return;
}
Merci d'avance pour votre aide