Create the AHCI branch for Aman's work
[reactos.git] / win32ss / user / user32 / misc / usrapihk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: win32ss/user/user32/misc/usrapihk.c
5 * PURPOSE: User32.dll User32 Api Hook interface and support functions
6 * PROGRAMMER:
7 *
8 *
9 *
10 * Information:
11 * http://www.reactos.org/wiki/RegisterUserApiHook
12 *
13 */
14 #include <user32.h>
15
16 #include <wine/debug.h>
17
18 WINE_DEFAULT_DEBUG_CHANNEL(user32);
19
20 BOOL WINAPI RealAdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
21 LRESULT WINAPI RealDefWindowProcA(HWND,UINT,WPARAM,LPARAM);
22 LRESULT WINAPI RealDefWindowProcW(HWND,UINT,WPARAM,LPARAM);
23 BOOL WINAPI RealDrawFrameControl(HDC,LPRECT,UINT,UINT);
24 BOOL WINAPI RealGetScrollInfo(HWND,INT,LPSCROLLINFO);
25 int WINAPI RealGetSystemMetrics(int);
26 BOOL WINAPI RealMDIRedrawFrame(HWND,DWORD);
27 INT WINAPI RealSetScrollInfo(HWND,int,LPCSCROLLINFO,BOOL);
28 BOOL WINAPI RealSystemParametersInfoA(UINT,UINT,PVOID,UINT);
29 BOOL WINAPI RealSystemParametersInfoW(UINT,UINT,PVOID,UINT);
30 DWORD WINAPI GetRealWindowOwner(HWND);
31 LRESULT WINAPI RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags);
32
33 /* GLOBALS *******************************************************************/
34
35 DWORD gcLoadUserApiHook = 0;
36 LONG gcCallUserApiHook = 0;
37 DWORD gfUserApiHook = 0;
38 HINSTANCE ghmodUserApiHook = NULL;
39 USERAPIHOOKPROC gpfnInitUserApi;
40 RTL_CRITICAL_SECTION gcsUserApiHook;
41 // API Hooked Message group bitmaps
42 BYTE grgbDwpLiteHookMsg[128];
43 BYTE grgbWndLiteHookMsg[128];
44 BYTE grgbDlgLiteHookMsg[128];
45
46 /* INTERNAL ******************************************************************/
47
48 /*
49 Pre and Post Message handler stub.
50 */
51 LRESULT
52 WINAPI
53 DefaultOWP(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR lResult, PDWORD pData)
54 {
55 return 0;
56 }
57
58 /*
59 Check for API Hooked Message Overrides. Using message bitmapping.. One bit
60 corresponds to one message number.
61 */
62 BOOL
63 FASTCALL
64 IsMsgOverride( UINT Msg, PUAHOWP puaowpOverride)
65 {
66 UINT nMsg = Msg / 8; // Group Indexed, (Msg 1024) / 8 = (0 -> 127) bytes Max
67
68 if ( puaowpOverride && nMsg < puaowpOverride->Size )
69 {
70 return (puaowpOverride->MsgBitArray[nMsg] & (1 << (Msg & WM_SETFOCUS)));
71 }
72 return FALSE;
73 }
74
75 VOID
76 FASTCALL
77 CopyMsgMask(PUAHOWP Dest, PUAHOWP Src, PVOID hkmsg, DWORD Size)
78 {
79 DWORD nSize;
80
81 if ( Src && Src->Size > 0 )
82 {
83 Dest->MsgBitArray = hkmsg;
84 nSize = Src->Size;
85 if ( Size < nSize) nSize = Size;
86 Dest->Size = nSize;
87 RtlCopyMemory(Dest->MsgBitArray, Src->MsgBitArray, nSize);
88 return;
89 }
90
91 Dest->MsgBitArray = NULL;
92 Dest->Size = 0;
93 return;
94 }
95
96
97 BOOL
98 FASTCALL
99 IsInsideUserApiHook(VOID)
100 {
101 if ( ghmodUserApiHook && gfUserApiHook ) return TRUE;
102 return FALSE;
103 }
104
105 BOOL
106 FASTCALL
107 BeginIfHookedUserApiHook(VOID)
108 {
109 InterlockedIncrement(&gcCallUserApiHook);
110 if (IsInsideUserApiHook()) return TRUE;
111
112 InterlockedDecrement(&gcCallUserApiHook);
113 return FALSE;
114 }
115
116 BOOL
117 FASTCALL
118 ForceResetUserApiHook(HINSTANCE hInstance)
119 {
120 if ( ghmodUserApiHook == hInstance &&
121 RtlIsThreadWithinLoaderCallout() )
122 {
123 ResetUserApiHook(&guah);
124 gpfnInitUserApi = NULL;
125 return TRUE;
126 }
127 return FALSE;
128 }
129
130 VOID
131 FASTCALL
132 ResetUserApiHook(PUSERAPIHOOK puah)
133 {
134 // Setup Structure.....
135 puah->size = sizeof(USERAPIHOOK);
136 puah->DefWindowProcA = RealDefWindowProcA;
137 puah->DefWindowProcW = RealDefWindowProcW;
138 puah->DefWndProcArray.MsgBitArray = NULL;
139 puah->DefWndProcArray.Size = 0;
140 puah->GetScrollInfo = (FARPROC)RealGetScrollInfo;
141 puah->SetScrollInfo = (FARPROC)RealSetScrollInfo;
142 puah->EnableScrollBar = (FARPROC)NtUserEnableScrollBar;
143 puah->AdjustWindowRectEx = (FARPROC)RealAdjustWindowRectEx;
144 puah->SetWindowRgn = NtUserSetWindowRgn;
145 puah->PreWndProc = DefaultOWP;
146 puah->PostWndProc = DefaultOWP;
147 puah->WndProcArray.MsgBitArray = NULL;
148 puah->WndProcArray.Size = 0;
149 puah->PreDefDlgProc = DefaultOWP;
150 puah->PostDefDlgProc = DefaultOWP;
151 puah->DlgProcArray.MsgBitArray = NULL;
152 puah->DlgProcArray.Size = 0;
153 puah->GetSystemMetrics = (FARPROC)RealGetSystemMetrics;
154 puah->SystemParametersInfoA = (FARPROC)RealSystemParametersInfoA;
155 puah->SystemParametersInfoW = (FARPROC)RealSystemParametersInfoW;
156 puah->ForceResetUserApiHook = (FARPROC)ForceResetUserApiHook;
157 puah->DrawFrameControl = (FARPROC)RealDrawFrameControl;
158 puah->DrawCaption = (FARPROC)RealUserDrawCaption;
159 puah->MDIRedrawFrame = (FARPROC)RealMDIRedrawFrame;
160 puah->GetRealWindowOwner = (FARPROC)GetRealWindowOwner;
161 }
162
163 BOOL
164 FASTCALL
165 EndUserApiHook(VOID)
166 {
167 HMODULE hModule;
168 USERAPIHOOKPROC pfn;
169 BOOL Ret = FALSE;
170
171 if ( !InterlockedDecrement(&gcCallUserApiHook) )
172 {
173 if ( !gcLoadUserApiHook )
174 {
175 RtlEnterCriticalSection(&gcsUserApiHook);
176
177 pfn = gpfnInitUserApi;
178 hModule = ghmodUserApiHook;
179 ghmodUserApiHook = NULL;
180 gpfnInitUserApi = NULL;
181
182 RtlLeaveCriticalSection(&gcsUserApiHook);
183
184 if ( pfn ) Ret = pfn(uahStop, 0);
185
186 if ( hModule ) Ret = FreeLibrary(hModule);
187 }
188 }
189 return Ret;
190 }
191
192 BOOL
193 WINAPI
194 ClearUserApiHook(HINSTANCE hInstance)
195 {
196 HMODULE hModule;
197 USERAPIHOOKPROC pfn = NULL, pfn1 = NULL;
198
199 RtlEnterCriticalSection(&gcsUserApiHook);
200 hModule = ghmodUserApiHook;
201 if ( ghmodUserApiHook == hInstance )
202 {
203 pfn1 = gpfnInitUserApi;
204 if ( --gcLoadUserApiHook == 0 )
205 {
206 gfUserApiHook = 0;
207 ResetUserApiHook(&guah);
208 if ( gcCallUserApiHook )
209 {
210 hInstance = NULL;
211 pfn1 = NULL;
212 pfn = gpfnInitUserApi;
213 gcLoadUserApiHook = 1;
214 }
215 else
216 {
217 hInstance = hModule;
218 ghmodUserApiHook = NULL;
219 gpfnInitUserApi = NULL;
220 }
221 }
222 }
223 RtlLeaveCriticalSection(&gcsUserApiHook);
224
225 if ( pfn )
226 {
227 pfn(uahShutdown, 0); // Shutdown.
228
229 RtlEnterCriticalSection(&gcsUserApiHook);
230 pfn1 = gpfnInitUserApi;
231
232 if ( --gcLoadUserApiHook == 0 )
233 {
234 if ( gcCallUserApiHook )
235 {
236 hInstance = NULL;
237 pfn1 = NULL;
238 }
239 else
240 {
241 hInstance = ghmodUserApiHook;
242 ghmodUserApiHook = NULL;
243 gpfnInitUserApi = NULL;
244 }
245 }
246 RtlLeaveCriticalSection(&gcsUserApiHook);
247 }
248
249 if ( pfn1 ) pfn1(uahStop, 0);
250
251 return hInstance != 0;
252 }
253
254 BOOL
255 WINAPI
256 InitUserApiHook(HINSTANCE hInstance, USERAPIHOOKPROC pfn)
257 {
258 USERAPIHOOK uah;
259
260 ResetUserApiHook(&uah);
261
262 RtlEnterCriticalSection(&gcsUserApiHook);
263
264 if (!pfn(uahLoadInit,&uah) || // Swap data, User32 to and Uxtheme from!
265 uah.ForceResetUserApiHook != (FARPROC)ForceResetUserApiHook ||
266 uah.size <= 0 )
267 {
268 RtlLeaveCriticalSection(&gcsUserApiHook);
269 return FALSE;
270 }
271
272 if ( ghmodUserApiHook )
273 {
274 if ( ghmodUserApiHook != hInstance )
275 {
276 RtlLeaveCriticalSection(&gcsUserApiHook);
277 pfn(uahStop, 0);
278 return FALSE;
279 }
280 gcLoadUserApiHook++;
281 }
282 else
283 {
284 ghmodUserApiHook = hInstance;
285 // Do not over write GetRealWindowOwner.
286 RtlCopyMemory(&guah, &uah, sizeof(USERAPIHOOK) - sizeof(LONG));
287 gpfnInitUserApi = pfn;
288 gcLoadUserApiHook = 1;
289 gfUserApiHook = 1;
290 // Copy Message Masks
291 CopyMsgMask(&guah.DefWndProcArray,
292 &uah.DefWndProcArray,
293 &grgbDwpLiteHookMsg,
294 sizeof(grgbDwpLiteHookMsg));
295
296 CopyMsgMask(&guah.WndProcArray,
297 &uah.WndProcArray,
298 &grgbWndLiteHookMsg,
299 sizeof(grgbWndLiteHookMsg));
300
301 CopyMsgMask(&guah.DlgProcArray,
302 &uah.DlgProcArray,
303 &grgbDlgLiteHookMsg,
304 sizeof(grgbDlgLiteHookMsg));
305 }
306 RtlLeaveCriticalSection(&gcsUserApiHook);
307 return TRUE;
308 }
309
310 BOOL
311 WINAPI
312 RealMDIRedrawFrame(HWND hWnd, DWORD flags)
313 {
314 return NtUserxMDIRedrawFrame(hWnd);
315 }
316
317 BOOL
318 WINAPI
319 MDIRedrawFrame(HWND hWnd, DWORD flags)
320 {
321 BOOL Hook, Ret = FALSE;
322
323 LoadUserApiHook();
324
325 Hook = BeginIfHookedUserApiHook();
326
327 /* Bypass SEH and go direct. */
328 if (!Hook) return RealMDIRedrawFrame(hWnd, flags);
329
330 _SEH2_TRY
331 {
332 Ret = guah.MDIRedrawFrame(hWnd, flags);
333 }
334 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
335 {
336 }
337 _SEH2_END;
338
339 EndUserApiHook();
340
341 return Ret;
342 }
343
344 USERAPIHOOK guah =
345 {
346 sizeof(USERAPIHOOK),
347 RealDefWindowProcA,
348 RealDefWindowProcW,
349 {NULL, 0},
350 (FARPROC)RealGetScrollInfo,
351 (FARPROC)RealSetScrollInfo,
352 (FARPROC)NtUserEnableScrollBar,
353 (FARPROC)RealAdjustWindowRectEx,
354 NtUserSetWindowRgn,
355 DefaultOWP,
356 DefaultOWP,
357 {NULL, 0},
358 DefaultOWP,
359 DefaultOWP,
360 {NULL, 0},
361 (FARPROC)RealGetSystemMetrics,
362 (FARPROC)RealSystemParametersInfoA,
363 (FARPROC)RealSystemParametersInfoW,
364 (FARPROC)ForceResetUserApiHook,
365 (FARPROC)RealDrawFrameControl,
366 (FARPROC)NtUserDrawCaption,
367 (FARPROC)RealMDIRedrawFrame,
368 (FARPROC)GetRealWindowOwner,
369 };
370
371 /* FUNCTIONS *****************************************************************/
372
373 /*
374 * @implemented
375 */
376 BOOL WINAPI RegisterUserApiHook(PUSERAPIHOOKINFO puah)
377 {
378 UNICODE_STRING m_dllname1;
379 UNICODE_STRING m_funname1;
380
381 if (puah->m_size == sizeof(USERAPIHOOKINFO))
382 {
383 WARN("RegisterUserApiHook: %S and %S",puah->m_dllname1, puah->m_funname1);
384 RtlInitUnicodeString(&m_dllname1, puah->m_dllname1);
385 RtlInitUnicodeString(&m_funname1, puah->m_funname1);
386 return NtUserRegisterUserApiHook( &m_dllname1, &m_funname1, 0, 0);
387 }
388 return FALSE;
389 }
390
391 /*
392 * @implemented
393 */
394 BOOL WINAPI UnregisterUserApiHook(VOID)
395 {
396 return NtUserUnregisterUserApiHook();
397 }