source: trunk/src/user32/new/winproc.cpp@ 2290

Last change on this file since 2290 was 2290, checked in by cbratschi, 26 years ago

* empty log message *

File size: 9.3 KB
Line 
1/* $Id: winproc.cpp,v 1.1 2000-01-01 14:57:38 cbratschi Exp $ */
2/*
3 * Window procedure callbacks
4 *
5 * Copyright 1999 Sander van Leeuwen (OS/2 Port)
6 *
7 * Based on Wine Windows code (windows\winproc.c) 991114
8 *
9 *
10 * Copyright 1995 Martin von Loewis
11 * Copyright 1996 Alexandre Julliard
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16
17#include <os2win.h>
18#include <string.h>
19#include <win\winproc.h>
20#include <win\debugtools.h>
21#include <heapcode.h>
22#include "win32wbase.h"
23
24DECLARE_DEBUG_CHANNEL(relay)
25
26
27/* Simple jmp to call 32-bit procedure directly */
28#pragma pack(1)
29typedef struct
30{
31 BYTE jmp; /* jmp proc (relative jump) */
32 WNDPROC proc WINE_PACKED;
33} WINPROC_JUMP;
34#pragma pack()
35
36typedef struct tagWINDOWPROC
37{
38 WINPROC_JUMP jmp; /* Jump */
39 struct tagWINDOWPROC *next; /* Next window proc */
40 UINT magic; /* Magic number */
41 WINDOWPROCTYPE type; /* Function type */
42 WINDOWPROCUSER user; /* Function user */
43} WINDOWPROC;
44
45#define WINPROC_MAGIC ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
46
47#define WINPROC_THUNKPROC(pproc) \
48 (WNDPROC)((LONG)(pproc)->jmp.proc + (LONG)(&(pproc)->jmp.proc+1))
49
50/**********************************************************************
51 * WINPROC_GetPtr
52 *
53 * Return a pointer to the win proc.
54 */
55static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle )
56{
57 BYTE *ptr;
58 WINDOWPROC *proc;
59
60 if(ptr == NULL) {
61 return NULL;
62 }
63
64 ptr = (BYTE *)handle;
65 /* First check if it is the jmp address */
66// if (*ptr == 0xe9 /* jmp */) ptr -= (int)&((WINDOWPROC *)0)->jmp -
67// (int)&((WINDOWPROC *)0)->thunk;
68
69 /* Now we have a pointer to the WINDOWPROC struct */
70 if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
71 return (WINDOWPROC *)ptr;
72
73 return NULL;
74}
75
76
77/**********************************************************************
78 * WINPROC_AllocWinProc
79 *
80 * Allocate a new window procedure.
81 */
82static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC func, WINDOWPROCTYPE type,
83 WINDOWPROCUSER user )
84{
85 WINDOWPROC *proc, *oldproc;
86
87 /* Allocate a window procedure */
88
89 if (!(proc = (WINDOWPROC *)_cmalloc(sizeof(WINDOWPROC) ))) return 0;
90
91 /* Check if the function is already a win proc */
92
93 if ((oldproc = WINPROC_GetPtr( func )))
94 {
95 *proc = *oldproc;
96 }
97 else
98 {
99 switch(type)
100 {
101 case WIN_PROC_32A:
102 case WIN_PROC_32W:
103 proc->jmp.jmp = 0xe9;
104 /* Fixup relative jump */
105 proc->jmp.proc = (WNDPROC)((LONG)func - (LONG)(&proc->jmp.proc+1));
106 break;
107 default:
108 /* Should not happen */
109 break;
110 }
111 proc->magic = WINPROC_MAGIC;
112 proc->type = type;
113 proc->user = user;
114 }
115 proc->next = NULL;
116 return proc;
117}
118
119
120/**********************************************************************
121 * WINPROC_GetProc
122 *
123 * Get a window procedure pointer that can be passed to the Windows program.
124 */
125WNDPROC WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
126{
127 WINDOWPROC *lpProc = (WINDOWPROC *)proc;
128
129 if (!lpProc) return NULL;
130
131 /* We want a 32-bit address */
132 return (WNDPROC)&lpProc->jmp;
133}
134
135
136/**********************************************************************
137 * WINPROC_SetProc
138 *
139 * Set the window procedure for a window or class. There are
140 * three tree classes of winproc callbacks:
141 *
142 * 1) class -> wp - not subclassed
143 * class -> wp -> wp -> wp -> wp - SetClassLong()
144 * / /
145 * 2) window -' / - not subclassed
146 * window -> wp -> wp ' - SetWindowLong()
147 *
148 * 3) timer -> wp - SetTimer()
149 *
150 * Initially, winproc of the window points to the current winproc
151 * thunk of its class. Subclassing prepends a new thunk to the
152 * window winproc chain at the head of the list. Thus, window thunk
153 * list includes class thunks and the latter are preserved when the
154 * window is destroyed.
155 *
156 */
157BOOL WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC func,
158 WINDOWPROCTYPE type, WINDOWPROCUSER user )
159{
160 BOOL bRecycle = FALSE;
161 WINDOWPROC *proc, **ppPrev;
162
163 if(func == NULL) {
164 *(WINDOWPROC **)pFirst = 0;
165 return TRUE;
166 }
167
168 /* Check if function is already in the list */
169
170 ppPrev = (WINDOWPROC **)pFirst;
171 proc = WINPROC_GetPtr( func );
172 while (*ppPrev)
173 {
174 if (proc)
175 {
176 if (*ppPrev == proc)
177 {
178 if ((*ppPrev)->user != user)
179 {
180 /* terminal thunk is being restored */
181
182 WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
183 *(WINDOWPROC **)pFirst = *ppPrev;
184 return TRUE;
185 }
186 bRecycle = TRUE;
187 break;
188 }
189 }
190 else
191 {
192 if (((*ppPrev)->type == type) &&
193 (func == WINPROC_THUNKPROC(*ppPrev)))
194 {
195 bRecycle = TRUE;
196 break;
197 }
198 }
199
200 /* WPF_CLASS thunk terminates window thunk list */
201 if ((*ppPrev)->user != user) break;
202 ppPrev = &(*ppPrev)->next;
203 }
204
205 if (bRecycle)
206 {
207 /* Extract this thunk from the list */
208 proc = *ppPrev;
209 *ppPrev = proc->next;
210 }
211 else /* Allocate a new one */
212 {
213 if (proc) /* Was already a win proc */
214 {
215 type = proc->type;
216 func = WINPROC_THUNKPROC(proc);
217 }
218 proc = WINPROC_AllocWinProc( func, type, user );
219 if (!proc) return FALSE;
220 }
221
222 /* Add the win proc at the head of the list */
223
224 proc->next = *(WINDOWPROC **)pFirst;
225 *(WINDOWPROC **)pFirst = proc;
226 return TRUE;
227}
228
229
230/**********************************************************************
231 * WINPROC_FreeProc
232 *
233 * Free a list of win procs.
234 */
235void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
236{
237 while (proc)
238 {
239 WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
240 if (((WINDOWPROC *)proc)->user != user) break;
241 free( proc );
242 proc = next;
243 }
244}
245
246
247/**********************************************************************
248 * WINPROC_GetProcType
249 *
250 * Return the window procedure type.
251 */
252WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
253{
254 if (!proc ||
255 (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
256 return WIN_PROC_INVALID;
257 return ((WINDOWPROC *)proc)->type;
258}
259
260/**********************************************************************
261 * CallWindowProc32A (USER32.18)
262 *
263 * The CallWindowProc() function invokes the windows procedure _func_,
264 * with _hwnd_ as the target window, the message specified by _msg_, and
265 * the message parameters _wParam_ and _lParam_.
266 *
267 * Some kinds of argument conversion may be done, I'm not sure what.
268 *
269 * CallWindowProc() may be used for windows subclassing. Use
270 * SetWindowLong() to set a new windows procedure for windows of the
271 * subclass, and handle subclassed messages in the new windows
272 * procedure. The new windows procedure may then use CallWindowProc()
273 * with _func_ set to the parent class's windows procedure to dispatch
274 * the message to the superclass.
275 *
276 * RETURNS
277 *
278 * The return value is message dependent.
279 *
280 * CONFORMANCE
281 *
282 * ECMA-234, Win32
283 */
284LRESULT WINAPI CallWindowProcA(
285 WNDPROC func, /* window procedure */
286 HWND hwnd, /* target window */
287 UINT msg, /* message */
288 WPARAM wParam, /* message dependent parameter */
289 LPARAM lParam /* message dependent parameter */
290) {
291 WINDOWPROC *proc = WINPROC_GetPtr( func );
292
293 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
294 if(!window) {
295 dprintf(("CallWindowProcA, window %x not found", hwnd));
296 // return func( hwnd, msg, wParam, lParam );
297 return 0;
298 }
299
300 if (!proc) return func(hwnd, msg, wParam, lParam );
301
302#if testing
303 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
304 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
305#endif
306
307 switch(proc->type)
308 {
309 case WIN_PROC_32A:
310 return func(hwnd, msg, wParam, lParam );
311 case WIN_PROC_32W:
312 return WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam, lParam );
313 default:
314 WARN_(relay)("Invalid proc %p\n", proc );
315 return 0;
316 }
317}
318
319
320/**********************************************************************
321 * CallWindowProc32W (USER32.19)
322 */
323LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
324 WPARAM wParam, LPARAM lParam )
325{
326 WINDOWPROC *proc = WINPROC_GetPtr( func );
327
328 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
329 if(!window) {
330 dprintf(("CallWindowProcW, window %x not found", hwnd));
331 // return func( hwnd, msg, wParam, lParam );
332 return 0;
333 }
334
335 if (!proc) return func( hwnd, msg, wParam, lParam );
336
337#if testing
338 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
339 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
340#endif
341
342 switch(proc->type)
343 {
344 case WIN_PROC_32A:
345 return WINPROC_CallProc32WTo32A( func, hwnd, msg, wParam, lParam );
346 case WIN_PROC_32W:
347 return func(hwnd, msg, wParam, lParam );
348 default:
349 WARN_(relay)("Invalid proc %p\n", proc );
350 return 0;
351 }
352}
353
Note: See TracBrowser for help on using the repository browser.