ae4505272bb48dd1d9ec295cec5ebf1df4fc09a6
[openafs.git] / src / WINNT / afsapplib / subclass.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include <windows.h>
16 #include <WINNT/subclass.h>
17 #include <winnt/osi_malloc.h>
18
19
20 /*
21  * PROTOTYPES _________________________________________________________________
22  *
23  */
24
25 LONG CALLBACK Subclass_WndProc (HWND hTarget, UINT msg, WPARAM wp, LPARAM lp);
26
27
28 /*
29  * MISCELLANEOUS ______________________________________________________________
30  *
31  */
32
33 #ifndef REALLOC
34 #define REALLOC(_a,_c,_r,_i) SubclassReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
35 BOOL SubclassReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
36 {
37    LPVOID pNew;
38    size_t cNew;
39
40    if (cReq <= *pcTarget)
41       return TRUE;
42
43    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
44       return FALSE;
45
46    if ((pNew = (LPVOID)GlobalAlloc (GMEM_FIXED, cbElement * cNew)) == NULL)
47       return FALSE;
48    memset (pNew, 0x00, cbElement * cNew);
49
50    if (*pcTarget != 0)
51       {
52       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
53       GlobalFree ((HGLOBAL)*ppTarget);
54       }
55
56    *ppTarget = pNew;
57    *pcTarget = cNew;
58    return TRUE;
59 }
60 #endif
61
62
63 /*
64  * VARIABLES __________________________________________________________________
65  *
66  */
67
68 typedef struct
69    {
70    HWND hTarget;        // window being subclassed
71    PVOID procOrig;      // original pre-SubclassProc proc
72
73    struct
74       {
75       PVOID wndProc;
76       size_t nReq;
77       } *aHooks;
78
79    size_t nHooks;       // number of entries in aHooks
80    size_t nHooksActive; // number of hooks in use
81    } SubclassWindow;
82
83 SubclassWindow *aTargets = NULL;
84 size_t nTargets = 0;
85
86 #define cREALLOC_SUBCLASS_TARGETS  8
87 #define cREALLOC_SUBCLASS_HOOKS    4
88
89
90 /*
91  * ROUTINES ___________________________________________________________________
92  *
93  */
94
95 BOOL Subclass_AddHook (HWND hTarget, PVOID wndProc)
96 {
97    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
98       {
99       if (aTargets[ iTarget ].hTarget == hTarget)
100          break;
101       }
102    if (iTarget >= nTargets)
103       {
104       for (iTarget = 0; iTarget < nTargets; ++iTarget)
105          {
106          if (aTargets[ iTarget ].hTarget == NULL)
107             break;
108          }
109       }
110    if (iTarget >= nTargets)
111       {
112       if (!REALLOC (aTargets, nTargets, 1+iTarget, cREALLOC_SUBCLASS_TARGETS))
113          return FALSE;
114       }
115
116    aTargets[ iTarget ].hTarget = hTarget;
117
118
119    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
120       {
121       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
122          break;
123       }
124    if (iHook >= aTargets[ iTarget ].nHooks)
125       {
126       for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
127          {
128          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == NULL)
129             break;
130          }
131       }
132    if (iHook >= aTargets[ iTarget ].nHooks)
133       {
134       if (!REALLOC (aTargets[ iTarget ].aHooks, aTargets[ iTarget ].nHooks, 1+iHook, cREALLOC_SUBCLASS_HOOKS))
135          return FALSE;
136       }
137
138    aTargets[ iTarget ].aHooks[ iHook ].wndProc = wndProc;
139    aTargets[ iTarget ].aHooks[ iHook ].nReq ++;
140    aTargets[ iTarget ].nHooksActive ++;
141
142    if (aTargets[ iTarget ].nHooksActive == 1)
143       {
144       aTargets[ iTarget ].procOrig = (PVOID)GetWindowLong (hTarget, GWL_WNDPROC);
145       SetWindowLong (hTarget, GWL_WNDPROC, (LONG)Subclass_WndProc);
146       }
147
148    return TRUE;
149 }
150
151
152 void Subclass_RemoveHook (HWND hTarget, PVOID wndProc)
153 {
154    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
155       {
156       if (aTargets[ iTarget ].hTarget == hTarget)
157          break;
158       }
159    if (iTarget < nTargets)
160       {
161       for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
162          {
163          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
164             break;
165          }
166       if (iHook < aTargets[ iTarget ].nHooks)
167          {
168          aTargets[ iTarget ].aHooks[ iHook ].nReq --;
169          if (aTargets[ iTarget ].aHooks[ iHook ].nReq == 0)
170             {
171             memset (&aTargets[ iTarget ].aHooks[ iHook ], 0x00, sizeof(aTargets[ iTarget ].aHooks[ iHook ]));
172             }
173          }
174
175       aTargets[ iTarget ].nHooksActive --;
176       if (aTargets[ iTarget ].nHooksActive == 0)
177          {
178          SetWindowLong (aTargets[ iTarget ].hTarget, GWL_WNDPROC, (LONG)aTargets[ iTarget ].procOrig);
179          memset (&aTargets[ iTarget ], 0x00, sizeof(aTargets[ iTarget ]));
180          }
181       }
182 }
183
184
185 PVOID Subclass_FindNextHook (HWND hTarget, PVOID wndProc)
186 {
187    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
188       {
189       if (aTargets[ iTarget ].hTarget == hTarget)
190          break;
191       }
192    if (iTarget >= nTargets)
193       return NULL;
194
195    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
196       {
197       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
198          break;
199       }
200    if (iHook >= aTargets[ iTarget ].nHooks)
201       return aTargets[ iTarget ].procOrig;
202
203    for (++iHook; iHook < aTargets[iTarget].nHooks; ++iHook)
204       {
205       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
206          return aTargets[ iTarget ].aHooks[ iHook ].wndProc;
207       }
208
209    return aTargets[ iTarget ].procOrig;
210 }
211
212
213 LONG CALLBACK Subclass_WndProc (HWND hTarget, UINT msg, WPARAM wp, LPARAM lp)
214 {
215    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
216       {
217       if (aTargets[ iTarget ].hTarget == hTarget)
218          break;
219       }
220    if (iTarget >= nTargets)
221       return DefWindowProc (hTarget, msg, wp, lp);
222
223    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
224       {
225       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
226          break;
227       }
228
229    if (iHook >= aTargets[iTarget].nHooks)
230       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].procOrig, hTarget, msg, wp, lp);
231    else
232       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].aHooks[ iHook ].wndProc, hTarget, msg, wp, lp);
233 }
234