Revert, thx Thomas, wasnt sure.
[reactos.git] / reactos / subsys / win32k / ntuser / callback.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/wndproc.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Thomas Weidenmueller (w3seek@users.sourceforge.net)
27 * REVISION HISTORY:
28 * 06-06-2001 CSH Created
29 * NOTES: Please use the Callback Memory Management functions for
30 * callbacks to make sure, the memory is freed on thread
31 * termination!
32 */
33
34 /* INCLUDES ******************************************************************/
35
36 #include <w32k.h>
37
38 #define NDEBUG
39 #include <debug.h>
40
41 /* CALLBACK MEMORY MANAGEMENT ************************************************/
42
43 typedef struct _INT_CALLBACK_HEADER
44 {
45 /* list entry in the W32THREAD structure */
46 LIST_ENTRY ListEntry;
47 }
48 INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER;
49
50 PVOID FASTCALL
51 IntCbAllocateMemory(ULONG Size)
52 {
53 PINT_CALLBACK_HEADER Mem;
54 PW32THREAD W32Thread;
55
56 if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER),
57 TAG_CALLBACK)))
58 {
59 return NULL;
60 }
61
62 W32Thread = PsGetWin32Thread();
63 ASSERT(W32Thread);
64
65 /* insert the callback memory into the thread's callback list */
66
67 InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry);
68
69 return (Mem + 1);
70 }
71
72 VOID FASTCALL
73 IntCbFreeMemory(PVOID Data)
74 {
75 PINT_CALLBACK_HEADER Mem;
76 PW32THREAD W32Thread;
77
78 ASSERT(Data);
79
80 Mem = ((PINT_CALLBACK_HEADER)Data - 1);
81
82 W32Thread = PsGetWin32Thread();
83 ASSERT(W32Thread);
84
85 /* remove the memory block from the thread's callback list */
86 RemoveEntryList(&Mem->ListEntry);
87
88 /* free memory */
89 ExFreePool(Mem);
90 }
91
92 VOID FASTCALL
93 IntCleanupThreadCallbacks(PW32THREAD W32Thread)
94 {
95 PLIST_ENTRY CurrentEntry;
96 PINT_CALLBACK_HEADER Mem;
97
98 while (!IsListEmpty(&W32Thread->W32CallbackListHead))
99 {
100 CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead);
101 Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER,
102 ListEntry);
103
104 /* free memory */
105 ExFreePool(Mem);
106 }
107 }
108
109 /* FUNCTIONS *****************************************************************/
110
111 VOID STDCALL
112 co_IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback,
113 HWND hWnd,
114 UINT Msg,
115 ULONG_PTR CompletionCallbackContext,
116 LRESULT Result)
117 {
118 SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments;
119 NTSTATUS Status;
120
121 Arguments.Callback = CompletionCallback;
122 Arguments.Wnd = hWnd;
123 Arguments.Msg = Msg;
124 Arguments.Context = CompletionCallbackContext;
125 Arguments.Result = Result;
126
127 UserLeaveCo();
128
129 Status = NtW32Call(USER32_CALLBACK_SENDASYNCPROC,
130 &Arguments,
131 sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS),
132 NULL,
133 NULL);
134
135 UserEnterCo();
136
137 if (!NT_SUCCESS(Status))
138 {
139 return;
140 }
141 return;
142 }
143
144 LRESULT STDCALL
145 co_IntCallWindowProc(WNDPROC Proc,
146 BOOLEAN IsAnsiProc,
147 HWND Wnd,
148 UINT Message,
149 WPARAM wParam,
150 LPARAM lParam,
151 INT lParamBufferSize)
152 {
153 WINDOWPROC_CALLBACK_ARGUMENTS StackArguments;
154 PWINDOWPROC_CALLBACK_ARGUMENTS Arguments;
155 NTSTATUS Status;
156 PVOID ResultPointer;
157 ULONG ResultLength;
158 ULONG ArgumentLength;
159 LRESULT Result;
160
161 if (0 < lParamBufferSize)
162 {
163 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize;
164 Arguments = IntCbAllocateMemory(ArgumentLength);
165 if (NULL == Arguments)
166 {
167 DPRINT1("Unable to allocate buffer for window proc callback\n");
168 return -1;
169 }
170 RtlMoveMemory((PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
171 (PVOID) lParam, lParamBufferSize);
172 }
173 else
174 {
175 Arguments = &StackArguments;
176 ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS);
177 }
178 Arguments->Proc = Proc;
179 Arguments->IsAnsiProc = IsAnsiProc;
180 Arguments->Wnd = Wnd;
181 Arguments->Msg = Message;
182 Arguments->wParam = wParam;
183 Arguments->lParam = lParam;
184 Arguments->lParamBufferSize = lParamBufferSize;
185 ResultPointer = Arguments;
186 ResultLength = ArgumentLength;
187
188 UserLeaveCo();
189
190 Status = NtW32Call(USER32_CALLBACK_WINDOWPROC,
191 Arguments,
192 ArgumentLength,
193 &ResultPointer,
194 &ResultLength);
195
196 UserEnterCo();
197
198 if (!NT_SUCCESS(Status))
199 {
200 if (0 < lParamBufferSize)
201 {
202 IntCbFreeMemory(Arguments);
203 }
204 return -1;
205 }
206 Result = Arguments->Result;
207
208 if (0 < lParamBufferSize)
209 {
210 RtlMoveMemory((PVOID) lParam,
211 (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)),
212 lParamBufferSize);
213 IntCbFreeMemory(Arguments);
214 }
215
216 return Result;
217 }
218
219 HMENU STDCALL
220 co_IntLoadSysMenuTemplate()
221 {
222 LRESULT Result;
223 NTSTATUS Status;
224 PVOID ResultPointer;
225 ULONG ResultLength;
226
227 ResultPointer = &Result;
228 ResultLength = sizeof(LRESULT);
229
230 UserLeaveCo();
231
232 Status = NtW32Call(USER32_CALLBACK_LOADSYSMENUTEMPLATE,
233 NULL,
234 0,
235 &ResultPointer,
236 &ResultLength);
237
238 UserEnterCo();
239
240 if (!NT_SUCCESS(Status))
241 {
242 return(0);
243 }
244 return (HMENU)Result;
245 }
246
247 BOOL STDCALL
248 co_IntLoadDefaultCursors(VOID)
249 {
250 LRESULT Result;
251 NTSTATUS Status;
252 PVOID ResultPointer;
253 ULONG ResultLength;
254 BOOL DefaultCursor = TRUE;
255
256 ResultPointer = &Result;
257 ResultLength = sizeof(LRESULT);
258
259 UserLeaveCo();
260
261 Status = NtW32Call(USER32_CALLBACK_LOADDEFAULTCURSORS,
262 &DefaultCursor,
263 sizeof(BOOL),
264 &ResultPointer,
265 &ResultLength);
266
267 UserEnterCo();
268
269 if (!NT_SUCCESS(Status))
270 {
271 return FALSE;
272 }
273 return TRUE;
274 }
275
276 LRESULT STDCALL
277 co_IntCallHookProc(INT HookId,
278 INT Code,
279 WPARAM wParam,
280 LPARAM lParam,
281 HOOKPROC Proc,
282 BOOLEAN Ansi,
283 PUNICODE_STRING ModuleName)
284 {
285 ULONG ArgumentLength;
286 PVOID Argument;
287 LRESULT Result;
288 NTSTATUS Status;
289 PVOID ResultPointer;
290 ULONG ResultLength;
291 PHOOKPROC_CALLBACK_ARGUMENTS Common;
292 CBT_CREATEWNDW *CbtCreateWnd =NULL;
293 PCHAR Extra;
294 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra ;
295 PUNICODE_STRING WindowName = NULL;
296 PUNICODE_STRING ClassName = NULL;
297
298 ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS) - sizeof(WCHAR)
299 + ModuleName->Length;
300 switch(HookId)
301 {
302 case WH_CBT:
303 switch(Code)
304 {
305 case HCBT_CREATEWND:
306 CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
307 ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
308 WindowName = (PUNICODE_STRING) (CbtCreateWnd->lpcs->lpszName);
309 ArgumentLength += WindowName->Length + sizeof(WCHAR);
310 ClassName = (PUNICODE_STRING) (CbtCreateWnd->lpcs->lpszClass);
311 if (! IS_ATOM(ClassName->Buffer))
312 {
313 ArgumentLength += ClassName->Length + sizeof(WCHAR);
314 }
315 break;
316 default:
317 DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
318 return 0;
319 }
320 break;
321 case WH_KEYBOARD_LL:
322 ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
323 break;
324 case WH_MOUSE_LL:
325 ArgumentLength += sizeof(MSLLHOOKSTRUCT);
326 break;
327 default:
328 DPRINT1("Trying to call unsupported window hook %d\n", HookId);
329 return 0;
330 }
331
332 Argument = IntCbAllocateMemory(ArgumentLength);
333 if (NULL == Argument)
334 {
335 DPRINT1("HookProc callback failed: out of memory\n");
336 return 0;
337 }
338 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
339 Common->HookId = HookId;
340 Common->Code = Code;
341 Common->wParam = wParam;
342 Common->lParam = lParam;
343 Common->Proc = Proc;
344 Common->Ansi = Ansi;
345 Common->ModuleNameLength = ModuleName->Length;
346 memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
347 Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
348
349 switch(HookId)
350 {
351 case WH_CBT:
352 switch(Code)
353 {
354 case HCBT_CREATEWND:
355 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
356 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
357 CbtCreatewndExtra->Cs = *(CbtCreateWnd->lpcs);
358 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
359 Extra = (PCHAR) (CbtCreatewndExtra + 1);
360 RtlCopyMemory(Extra, WindowName->Buffer, WindowName->Length);
361 CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
362 CbtCreatewndExtra->Cs.lpszClass = ClassName->Buffer;
363 Extra += WindowName->Length;
364 *((WCHAR *) Extra) = L'\0';
365 Extra += sizeof(WCHAR);
366 if (! IS_ATOM(ClassName->Buffer))
367 {
368 RtlCopyMemory(Extra, ClassName->Buffer, ClassName->Length);
369 CbtCreatewndExtra->Cs.lpszClass =
370 (LPCWSTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
371 Extra += ClassName->Length;
372 *((WCHAR *) Extra) = L'\0';
373 }
374 break;
375 }
376 break;
377 case WH_KEYBOARD_LL:
378 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(KBDLLHOOKSTRUCT));
379 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
380 break;
381 case WH_MOUSE_LL:
382 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSLLHOOKSTRUCT));
383 Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
384 break;
385 }
386
387 ResultPointer = &Result;
388 ResultLength = sizeof(LRESULT);
389
390 UserLeaveCo();
391
392 Status = NtW32Call(USER32_CALLBACK_HOOKPROC,
393 Argument,
394 ArgumentLength,
395 &ResultPointer,
396 &ResultLength);
397
398 UserEnterCo();
399
400 IntCbFreeMemory(Argument);
401
402 if (!NT_SUCCESS(Status))
403 {
404 return 0;
405 }
406
407 return Result;
408 }
409
410 /* EOF */