Implemented PolylineTo.
[wine/multimedia.git] / windows / winproc.c
blobcffb4be23af4393c357c78eb6603d83646010fc0
1 /*
2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include "windows.h"
9 #include "callback.h"
10 #include "heap.h"
11 #include "selectors.h"
12 #include "struct32.h"
13 #include "win.h"
14 #include "winproc.h"
15 #include "debug.h"
16 #include "spy.h"
17 #include "commctrl.h"
19 /* Window procedure 16-to-32-bit thunk,
20 * see BuildSpec16Files() in tools/build.c */
22 typedef struct
24 BYTE popl_eax; /* popl %eax (return address) */
25 BYTE pushl_func; /* pushl $proc */
26 WNDPROC32 proc WINE_PACKED;
27 BYTE pushl_eax; /* pushl %eax */
28 WORD pushw_bp WINE_PACKED; /* pushw %bp */
29 BYTE pushl_thunk; /* pushl $thunkfrom16 */
30 void (*thunk32)() WINE_PACKED;
31 BYTE lcall; /* lcall cs:relay */
32 void (*relay)() WINE_PACKED; /* WINPROC_CallProc16To32A/W() */
33 WORD cs WINE_PACKED;
34 } WINPROC_THUNK_FROM16;
36 /* Window procedure 32-to-16-bit thunk,
37 * see BuildSpec32Files() in tools/build.c */
39 typedef struct
41 BYTE popl_eax; /* popl %eax (return address) */
42 BYTE pushl_func; /* pushl $proc */
43 WNDPROC16 proc WINE_PACKED;
44 BYTE pushl_eax; /* pushl %eax */
45 BYTE jmp; /* jmp relay (relative jump)*/
46 void (*relay)() WINE_PACKED; /* WINPROC_CallProc32ATo16() */
47 } WINPROC_THUNK_FROM32;
49 /* Simple jmp to call 32-bit procedure directly */
50 typedef struct
52 BYTE jmp; /* jmp proc (relative jump) */
53 WNDPROC32 proc WINE_PACKED;
54 } WINPROC_JUMP;
56 typedef union
58 WINPROC_THUNK_FROM16 t_from16;
59 WINPROC_THUNK_FROM32 t_from32;
60 } WINPROC_THUNK;
62 typedef struct tagWINDOWPROC
64 WINPROC_THUNK thunk; /* Thunk */
65 WINPROC_JUMP jmp; /* Jump */
66 struct tagWINDOWPROC *next; /* Next window proc */
67 UINT32 magic; /* Magic number */
68 WINDOWPROCTYPE type; /* Function type */
69 WINDOWPROCUSER user; /* Function user */
70 } WINDOWPROC;
72 #define WINPROC_MAGIC ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
74 #define WINPROC_THUNKPROC(pproc) \
75 (((pproc)->type == WIN_PROC_16) ? \
76 (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
77 (WNDPROC16)((pproc)->thunk.t_from16.proc))
79 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
80 UINT32 msg, WPARAM32 wParam,
81 LPARAM lParam );
82 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
83 UINT32 msg, WPARAM32 wParam,
84 LPARAM lParam );
85 static LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
86 WPARAM16 wParam, LPARAM lParam,
87 WNDPROC32 func );
88 static LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
89 WPARAM16 wParam, LPARAM lParam,
90 WNDPROC32 func );
92 static HANDLE32 WinProcHeap;
95 /**********************************************************************
96 * WINPROC_Init
98 BOOL32 WINPROC_Init(void)
100 WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR | HEAP_WINE_CODESEG, 0, 0 );
101 if (!WinProcHeap)
103 WARN(relay, "Unable to create winproc heap\n" );
104 return FALSE;
106 return TRUE;
110 /**********************************************************************
111 * WINPROC_CallWndProc32
113 * Call a 32-bit WndProc.
115 static LRESULT WINPROC_CallWndProc32( WNDPROC32 proc, HWND32 hwnd, UINT32 msg,
116 WPARAM32 wParam, LPARAM lParam )
118 TRACE(relay, "(wndproc=%p,hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
119 proc, hwnd, SPY_GetMsgName(msg), wParam, lParam );
120 return proc( hwnd, msg, wParam, lParam );
124 /**********************************************************************
125 * WINPROC_GetPtr
127 * Return a pointer to the win proc.
129 static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
131 BYTE *ptr;
132 WINDOWPROC *proc;
134 /* Check for a linear pointer */
136 if (HEAP_IsInsideHeap( WinProcHeap, 0, (LPVOID)handle ))
138 ptr = (BYTE *)handle;
139 /* First check if it is the jmp address */
140 if (*ptr == 0xe9 /* jmp */) ptr -= (int)&((WINDOWPROC *)0)->jmp -
141 (int)&((WINDOWPROC *)0)->thunk;
142 /* Now it must be the thunk address */
143 if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
144 /* Now we have a pointer to the WINDOWPROC struct */
145 if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
146 return (WINDOWPROC *)ptr;
149 /* Check for a segmented pointer */
151 if (!IsBadReadPtr16((SEGPTR)handle,sizeof(WINDOWPROC)-sizeof(proc->thunk)))
153 ptr = (BYTE *)PTR_SEG_TO_LIN(handle);
154 if (!HEAP_IsInsideHeap( WinProcHeap, 0, ptr )) return NULL;
155 /* It must be the thunk address */
156 if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
157 /* Now we have a pointer to the WINDOWPROC struct */
158 if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
159 return (WINDOWPROC *)ptr;
162 return NULL;
166 /**********************************************************************
167 * WINPROC_AllocWinProc
169 * Allocate a new window procedure.
171 static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type,
172 WINDOWPROCUSER user )
174 WINDOWPROC *proc, *oldproc;
176 /* Allocate a window procedure */
178 if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
180 /* Check if the function is already a win proc */
182 if ((oldproc = WINPROC_GetPtr( func )))
184 *proc = *oldproc;
186 else
188 switch(type)
190 case WIN_PROC_16:
191 proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */
192 proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */
193 proc->thunk.t_from32.proc = func;
194 proc->thunk.t_from32.pushl_eax = 0x50; /* pushl %eax */
195 proc->thunk.t_from32.jmp = 0xe9; /* jmp relay*/
196 proc->thunk.t_from32.relay = /* relative jump */
197 (void(*)())((DWORD)WINPROC_CallProc32ATo16 -
198 (DWORD)(&proc->thunk.t_from32.relay + 1));
199 break;
200 case WIN_PROC_32A:
201 case WIN_PROC_32W:
202 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
203 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
204 proc->thunk.t_from16.proc = (FARPROC32)func;
205 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
206 proc->thunk.t_from16.pushw_bp = 0x5566; /* pushw %bp */
207 proc->thunk.t_from16.pushl_thunk = 0x68; /* pushl $thunkfrom16 */
208 proc->thunk.t_from16.thunk32 = (type == WIN_PROC_32A) ?
209 (void(*)())WINPROC_CallProc16To32A :
210 (void(*)())WINPROC_CallProc16To32W;
211 proc->thunk.t_from16.lcall = 0x9a; /* lcall cs:relay */
212 proc->thunk.t_from16.relay = Callbacks->CallFrom16WndProc;
213 GET_CS(proc->thunk.t_from16.cs);
214 proc->jmp.jmp = 0xe9;
215 /* Fixup relative jump */
216 proc->jmp.proc = (WNDPROC32)((DWORD)func -
217 (DWORD)(&proc->jmp.proc + 1));
218 break;
219 default:
220 /* Should not happen */
221 break;
223 proc->magic = WINPROC_MAGIC;
224 proc->type = type;
225 proc->user = user;
227 proc->next = NULL;
228 TRACE(win, "(%08x,%d): returning %08x\n",
229 (UINT32)func, type, (UINT32)proc );
230 return proc;
234 /**********************************************************************
235 * WINPROC_GetProc
237 * Get a window procedure pointer that can be passed to the Windows program.
239 WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
241 if (!proc) return NULL;
242 if (type == WIN_PROC_16) /* We want a 16:16 address */
244 if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
245 return ((WINDOWPROC *)proc)->thunk.t_from32.proc;
246 else
247 return (WNDPROC16)HEAP_GetSegptr( WinProcHeap, 0,
248 &((WINDOWPROC *)proc)->thunk );
250 else /* We want a 32-bit address */
252 if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
253 return (WNDPROC16)&((WINDOWPROC *)proc)->thunk;
254 else if (type != ((WINDOWPROC *)proc)->type)
255 /* Have to return the jmp address if types don't match */
256 return (WNDPROC16)&((WINDOWPROC *)proc)->jmp;
257 else
258 /* Some Win16 programs want to get back the proc they set */
259 return (WNDPROC16)((WINDOWPROC *)proc)->thunk.t_from16.proc;
264 /**********************************************************************
265 * WINPROC_SetProc
267 * Set the window procedure for a window or class. There are
268 * three tree classes of winproc callbacks:
270 * 1) class -> wp - not subclassed
271 * class -> wp -> wp -> wp -> wp - SetClassLong()
272 * / /
273 * 2) window -' / - not subclassed
274 * window -> wp -> wp ' - SetWindowLong()
276 * 3) timer -> wp - SetTimer()
278 * Initially, winproc of the window points to the current winproc
279 * thunk of its class. Subclassing prepends a new thunk to the
280 * window winproc chain at the head of the list. Thus, window thunk
281 * list includes class thunks and the latter are preserved when the
282 * window is destroyed.
285 BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
286 WINDOWPROCTYPE type, WINDOWPROCUSER user )
288 BOOL32 bRecycle = FALSE;
289 WINDOWPROC *proc, **ppPrev;
291 /* Check if function is already in the list */
293 ppPrev = (WINDOWPROC **)pFirst;
294 proc = WINPROC_GetPtr( func );
295 while (*ppPrev)
297 if (proc)
299 if (*ppPrev == proc)
301 if ((*ppPrev)->user != user)
303 /* terminal thunk is being restored */
305 WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
306 *(WINDOWPROC **)pFirst = *ppPrev;
307 return TRUE;
309 bRecycle = TRUE;
310 break;
313 else
315 if (((*ppPrev)->type == type) &&
316 (func == WINPROC_THUNKPROC(*ppPrev)))
318 bRecycle = TRUE;
319 break;
323 /* WPF_CLASS thunk terminates window thunk list */
324 if ((*ppPrev)->user != user) break;
325 ppPrev = &(*ppPrev)->next;
328 if (bRecycle)
330 /* Extract this thunk from the list */
331 proc = *ppPrev;
332 *ppPrev = proc->next;
334 else /* Allocate a new one */
336 if (proc) /* Was already a win proc */
338 type = proc->type;
339 func = WINPROC_THUNKPROC(proc);
341 proc = WINPROC_AllocWinProc( func, type, user );
342 if (!proc) return FALSE;
345 /* Add the win proc at the head of the list */
347 TRACE(win, "(%08x,%08x,%d): res=%08x\n",
348 (UINT32)*pFirst, (UINT32)func, type, (UINT32)proc );
349 proc->next = *(WINDOWPROC **)pFirst;
350 *(WINDOWPROC **)pFirst = proc;
351 return TRUE;
355 /**********************************************************************
356 * WINPROC_FreeProc
358 * Free a list of win procs.
360 void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
362 while (proc)
364 WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
365 if (((WINDOWPROC *)proc)->user != user) break;
366 TRACE(win, "freeing %08x\n", (UINT32)proc);
367 HeapFree( WinProcHeap, 0, proc );
368 proc = next;
373 /**********************************************************************
374 * WINPROC_GetProcType
376 * Return the window procedure type.
378 WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
380 if (!proc ||
381 (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
382 return WIN_PROC_INVALID;
383 return ((WINDOWPROC *)proc)->type;
385 /**********************************************************************
386 * WINPROC_TestCBForStr
388 * Return TRUE if the lparam is a string
390 BOOL32 WINPROC_TestCBForStr ( HWND32 hwnd )
391 { WND * wnd = WIN_FindWndPtr(hwnd);
392 return ( !(LOWORD(wnd->dwStyle) & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) ||
393 (LOWORD(wnd->dwStyle) & CBS_HASSTRINGS) );
395 /**********************************************************************
396 * WINPROC_TestLBForStr
398 * Return TRUE if the lparam is a string
400 BOOL32 WINPROC_TestLBForStr ( HWND32 hwnd )
401 { WND * wnd = WIN_FindWndPtr(hwnd);
402 return ( !(LOWORD(wnd->dwStyle) & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) ||
403 (LOWORD(wnd->dwStyle) & LBS_HASSTRINGS) );
405 /**********************************************************************
406 * WINPROC_MapMsg32ATo32W
408 * Map a message from Ansi to Unicode.
409 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
411 * FIXME:
412 * WM_CHAR, WM_CHARTOITEM, WM_DEADCHAR, WM_MENUCHAR, WM_SYSCHAR, WM_SYSDEADCHAR
414 * FIXME:
415 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
416 * the first four bytes are the handle of the icon
417 * when the WM_SETTEXT message has been used to set the icon
419 INT32 WINPROC_MapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
421 switch(msg)
423 case WM_GETTEXT:
425 LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
426 wParam * sizeof(WCHAR) + sizeof(LPARAM) );
427 if (!ptr) return -1;
428 *ptr++ = *plparam; /* Store previous lParam */
429 *plparam = (LPARAM)ptr;
431 return 1;
433 case WM_SETTEXT:
434 case CB_DIR32:
435 case CB_FINDSTRING32:
436 case CB_FINDSTRINGEXACT32:
437 case CB_SELECTSTRING32:
438 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
439 return (*plparam ? 1 : -1);
441 case WM_NCCREATE:
442 case WM_CREATE:
444 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
445 sizeof(*cs) );
446 if (!cs) return -1;
447 *cs = *(CREATESTRUCT32W *)*plparam;
448 if (HIWORD(cs->lpszName))
449 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
450 (LPCSTR)cs->lpszName );
451 if (HIWORD(cs->lpszClass))
452 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
453 (LPCSTR)cs->lpszClass );
454 *plparam = (LPARAM)cs;
456 return 1;
457 case WM_MDICREATE:
459 MDICREATESTRUCT32W *cs =
460 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
461 if (!cs) return -1;
462 *cs = *(MDICREATESTRUCT32W *)*plparam;
463 if (HIWORD(cs->szClass))
464 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
465 (LPCSTR)cs->szClass );
466 if (HIWORD(cs->szTitle))
467 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
468 (LPCSTR)cs->szTitle );
469 *plparam = (LPARAM)cs;
471 return 1;
473 /* Listbox */
474 case LB_ADDSTRING32:
475 case LB_INSERTSTRING32:
476 if ( WINPROC_TestLBForStr( hwnd ))
477 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
478 return (*plparam ? 1 : -1);
480 case LB_GETTEXT32: /* fixme: fixed sized buffer */
481 { if ( WINPROC_TestLBForStr( hwnd ))
482 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
483 if (!ptr) return -1;
484 *ptr++ = *plparam; /* Store previous lParam */
485 *plparam = (LPARAM)ptr;
488 return 1;
490 /* Combobox */
491 case CB_ADDSTRING32:
492 case CB_INSERTSTRING32:
493 if ( WINPROC_TestCBForStr( hwnd ))
494 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
495 return (*plparam ? 1 : -1);
497 case CB_GETLBTEXT32: /* fixme: fixed sized buffer */
498 { if ( WINPROC_TestCBForStr( hwnd ))
499 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
500 if (!ptr) return -1;
501 *ptr++ = *plparam; /* Store previous lParam */
502 *plparam = (LPARAM)ptr;
505 return 1;
507 /* Multiline edit */
508 case EM_GETLINE32:
509 { WORD len = (WORD)*plparam;
510 LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
511 if (!ptr) return -1;
512 *ptr++ = *plparam; /* Store previous lParam */
513 (WORD)*ptr = len; /* Store the lenght */
514 *plparam = (LPARAM)ptr;
516 return 1;
518 case WM_ASKCBFORMATNAME:
519 case WM_DEVMODECHANGE:
520 case WM_PAINTCLIPBOARD:
521 case WM_SIZECLIPBOARD:
522 case WM_WININICHANGE:
523 case EM_REPLACESEL32:
524 case EM_SETPASSWORDCHAR32:
525 case LB_ADDFILE32:
526 case LB_DIR32:
527 case LB_FINDSTRING32:
528 case LB_SELECTSTRING32:
529 FIXME(msg, "message %s (0x%x) needs translation\n", SPY_GetMsgName(msg), msg );
530 return -1;
531 default: /* No translation needed */
532 return 0;
537 /**********************************************************************
538 * WINPROC_UnmapMsg32ATo32W
540 * Unmap a message that was mapped from Ansi to Unicode.
542 void WINPROC_UnmapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
544 switch(msg)
546 case WM_GETTEXT:
548 LPARAM *ptr = (LPARAM *)lParam - 1;
549 lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)lParam, wParam );
550 HeapFree( SystemHeap, 0, ptr );
552 break;
554 case WM_NCCREATE:
555 case WM_CREATE:
557 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
558 if (HIWORD(cs->lpszName))
559 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
560 if (HIWORD(cs->lpszClass))
561 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
562 HeapFree( SystemHeap, 0, cs );
564 break;
566 case WM_MDICREATE:
568 MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
569 if (HIWORD(cs->szTitle))
570 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
571 if (HIWORD(cs->szClass))
572 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
573 HeapFree( SystemHeap, 0, cs );
575 break;
577 case WM_SETTEXT:
578 case CB_DIR32:
579 case CB_FINDSTRING32:
580 case CB_FINDSTRINGEXACT32:
581 case CB_SELECTSTRING32:
582 HeapFree( SystemHeap, 0, (void *)lParam );
583 break;
585 /* Listbox */
586 case LB_ADDSTRING32:
587 case LB_INSERTSTRING32:
588 if ( WINPROC_TestLBForStr( hwnd ))
589 HeapFree( SystemHeap, 0, (void *)lParam );
590 break;
592 case LB_GETTEXT32:
593 { if ( WINPROC_TestLBForStr( hwnd ))
594 { LPARAM *ptr = (LPARAM *)lParam - 1;
595 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
596 HeapFree( SystemHeap, 0, ptr );
599 break;
601 /* Combobox */
602 case CB_ADDSTRING32:
603 case CB_INSERTSTRING32:
604 if ( WINPROC_TestCBForStr( hwnd ))
605 HeapFree( SystemHeap, 0, (void *)lParam );
606 break;
608 case CB_GETLBTEXT32:
609 { if ( WINPROC_TestCBForStr( hwnd ))
610 { LPARAM *ptr = (LPARAM *)lParam - 1;
611 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
612 HeapFree( SystemHeap, 0, ptr );
615 break;
617 /* Multiline edit */
618 case EM_GETLINE32:
619 { LPARAM *ptr = (LPARAM *)lParam - 1; /* get the old lParam */
620 WORD len = *(WORD *)ptr;
621 lstrcpynWtoA( ((LPSTR)*ptr)+2, ((LPWSTR)(lParam + 1))+1, len );
622 HeapFree( SystemHeap, 0, ptr );
624 break;
629 /**********************************************************************
630 * WINPROC_MapMsg32WTo32A
632 * Map a message from Unicode to Ansi.
633 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
635 INT32 WINPROC_MapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
636 { switch(msg)
638 case WM_GETTEXT:
640 LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
641 wParam + sizeof(LPARAM) );
642 if (!ptr) return -1;
643 *ptr++ = *plparam; /* Store previous lParam */
644 *plparam = (LPARAM)ptr;
646 return 1;
648 case WM_SETTEXT:
649 case CB_DIR32:
650 case CB_FINDSTRING32:
651 case CB_FINDSTRINGEXACT32:
652 case CB_SELECTSTRING32:
653 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
654 return (*plparam ? 1 : -1);
656 case WM_NCCREATE:
657 case WM_CREATE:
659 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
660 sizeof(*cs) );
661 if (!cs) return -1;
662 *cs = *(CREATESTRUCT32A *)*plparam;
663 if (HIWORD(cs->lpszName))
664 cs->lpszName = HEAP_strdupWtoA( SystemHeap, 0,
665 (LPCWSTR)cs->lpszName );
666 if (HIWORD(cs->lpszClass))
667 cs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
668 (LPCWSTR)cs->lpszClass);
669 *plparam = (LPARAM)cs;
671 return 1;
672 case WM_MDICREATE:
674 MDICREATESTRUCT32A *cs =
675 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
676 if (!cs) return -1;
677 *cs = *(MDICREATESTRUCT32A *)*plparam;
678 if (HIWORD(cs->szTitle))
679 cs->szTitle = HEAP_strdupWtoA( SystemHeap, 0,
680 (LPCWSTR)cs->szTitle );
681 if (HIWORD(cs->szClass))
682 cs->szClass = HEAP_strdupWtoA( SystemHeap, 0,
683 (LPCWSTR)cs->szClass );
684 *plparam = (LPARAM)cs;
686 return 1;
688 /* Listbox */
689 case LB_ADDSTRING32:
690 case LB_INSERTSTRING32:
691 if ( WINPROC_TestLBForStr( hwnd ))
692 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
693 return (*plparam ? 1 : -1);
695 case LB_GETTEXT32: /* fixme: fixed sized buffer */
696 { if ( WINPROC_TestLBForStr( hwnd ))
697 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
698 if (!ptr) return -1;
699 *ptr++ = *plparam; /* Store previous lParam */
700 *plparam = (LPARAM)ptr;
703 return 1;
705 /* Combobox */
706 case CB_ADDSTRING32:
707 case CB_INSERTSTRING32:
708 if ( WINPROC_TestCBForStr( hwnd ))
709 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
710 return (*plparam ? 1 : -1);
712 case CB_GETLBTEXT32: /* fixme: fixed sized buffer */
713 { if ( WINPROC_TestCBForStr( hwnd ))
714 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
715 if (!ptr) return -1;
716 *ptr++ = *plparam; /* Store previous lParam */
717 *plparam = (LPARAM)ptr;
720 return 1;
722 /* Multiline edit */
723 case EM_GETLINE32:
724 { WORD len = (WORD)*plparam;
725 LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
726 if (!ptr) return -1;
727 *ptr++ = *plparam; /* Store previous lParam */
728 (WORD)*ptr = len; /* Store the lenght */
729 *plparam = (LPARAM)ptr;
731 return 1;
733 case WM_ASKCBFORMATNAME:
734 case WM_DEVMODECHANGE:
735 case WM_PAINTCLIPBOARD:
736 case WM_SIZECLIPBOARD:
737 case WM_WININICHANGE:
738 case EM_REPLACESEL32:
739 case EM_SETPASSWORDCHAR32:
740 case LB_ADDFILE32:
741 case LB_DIR32:
742 case LB_FINDSTRING32:
743 case LB_SELECTSTRING32:
744 FIXME(msg, "message %04x needs translation\n",msg );
745 return -1;
746 default: /* No translation needed */
747 return 0;
752 /**********************************************************************
753 * WINPROC_UnmapMsg32WTo32A
755 * Unmap a message that was mapped from Unicode to Ansi.
757 void WINPROC_UnmapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
759 switch(msg)
761 case WM_GETTEXT:
763 LPARAM *ptr = (LPARAM *)lParam - 1;
764 lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)lParam, wParam );
765 HeapFree( SystemHeap, 0, ptr );
767 break;
769 case WM_SETTEXT:
770 case CB_DIR32:
771 case CB_FINDSTRING32:
772 case CB_FINDSTRINGEXACT32:
773 case CB_SELECTSTRING32:
774 HeapFree( SystemHeap, 0, (void *)lParam );
775 break;
777 case WM_NCCREATE:
778 case WM_CREATE:
780 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
781 if (HIWORD(cs->lpszName))
782 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
783 if (HIWORD(cs->lpszClass))
784 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
785 HeapFree( SystemHeap, 0, cs );
787 break;
789 case WM_MDICREATE:
791 MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
792 if (HIWORD(cs->szTitle))
793 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
794 if (HIWORD(cs->szClass))
795 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
796 HeapFree( SystemHeap, 0, cs );
798 break;
800 /* Listbox */
801 case LB_ADDSTRING32:
802 case LB_INSERTSTRING32:
803 if ( WINPROC_TestLBForStr( hwnd ))
804 HeapFree( SystemHeap, 0, (void *)lParam );
805 break;
807 case LB_GETTEXT32:
808 { if ( WINPROC_TestLBForStr( hwnd ))
809 { LPARAM *ptr = (LPARAM *)lParam - 1;
810 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
811 HeapFree( SystemHeap, 0, ptr );
814 break;
816 /* Combobox */
817 case CB_ADDSTRING32:
818 case CB_INSERTSTRING32:
819 if ( WINPROC_TestCBForStr( hwnd ))
820 HeapFree( SystemHeap, 0, (void *)lParam );
821 break;
823 case CB_GETLBTEXT32:
824 { if ( WINPROC_TestCBForStr( hwnd ))
825 { LPARAM *ptr = (LPARAM *)lParam - 1;
826 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
827 HeapFree( SystemHeap, 0, ptr );
830 break;
832 /* Multiline edit */
833 case EM_GETLINE32:
834 { LPARAM *ptr = (LPARAM *)lParam - 1; /* get the old lParam */
835 WORD len = *(WORD *)ptr;
836 lstrcpynAtoW( ((LPWSTR)*ptr)+1, ((LPSTR)(lParam + 1))+2, len );
837 HeapFree( SystemHeap, 0, ptr );
839 break;
844 /**********************************************************************
845 * WINPROC_MapMsg16To32A
847 * Map a message from 16- to 32-bit Ansi.
848 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
850 INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
851 WPARAM32 *pwparam32, LPARAM *plparam )
853 *pmsg32 = (UINT32)msg16;
854 *pwparam32 = (WPARAM32)wParam16;
855 switch(msg16)
857 case WM_ACTIVATE:
858 case WM_CHARTOITEM:
859 case WM_COMMAND:
860 case WM_VKEYTOITEM:
861 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
862 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
863 return 0;
864 case WM_HSCROLL:
865 case WM_VSCROLL:
866 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
867 *plparam = (LPARAM)(HWND32)HIWORD(*plparam);
868 return 0;
869 case WM_CTLCOLOR:
870 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
871 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
872 *pwparam32 = (WPARAM32)(HDC32)wParam16;
873 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
874 return 0;
875 case WM_COMPAREITEM:
877 COMPAREITEMSTRUCT16* cis16 = (COMPAREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
878 COMPAREITEMSTRUCT32 *cis = (COMPAREITEMSTRUCT32 *)
879 HeapAlloc(SystemHeap, 0, sizeof(*cis));
880 if (!cis) return -1;
881 cis->CtlType = cis16->CtlType;
882 cis->CtlID = cis16->CtlID;
883 cis->hwndItem = cis16->hwndItem;
884 cis->itemID1 = cis16->itemID1;
885 cis->itemData1 = cis16->itemData1;
886 cis->itemID2 = cis16->itemID2;
887 cis->itemData2 = cis16->itemData2;
888 cis->dwLocaleId = 0; /* FIXME */
889 *plparam = (LPARAM)cis;
891 return 1;
892 case WM_DELETEITEM:
894 DELETEITEMSTRUCT16* dis16 = (DELETEITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
895 DELETEITEMSTRUCT32 *dis = (DELETEITEMSTRUCT32 *)
896 HeapAlloc(SystemHeap, 0, sizeof(*dis));
897 if (!dis) return -1;
898 dis->CtlType = dis16->CtlType;
899 dis->CtlID = dis16->CtlID;
900 dis->hwndItem = dis16->hwndItem;
901 dis->itemData = dis16->itemData;
902 *plparam = (LPARAM)dis;
904 return 1;
905 case WM_MEASUREITEM:
907 MEASUREITEMSTRUCT16* mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
908 MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)
909 HeapAlloc(SystemHeap, 0,
910 sizeof(*mis) + sizeof(LPARAM));
911 if (!mis) return -1;
912 mis->CtlType = mis16->CtlType;
913 mis->CtlID = mis16->CtlID;
914 mis->itemID = mis16->itemID;
915 mis->itemWidth = mis16->itemWidth;
916 mis->itemHeight = mis16->itemHeight;
917 mis->itemData = mis16->itemData;
918 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
919 *plparam = (LPARAM)mis;
921 return 1;
922 case WM_DRAWITEM:
924 DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
925 DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
926 sizeof(*dis));
927 if (!dis) return -1;
928 dis->CtlType = dis16->CtlType;
929 dis->CtlID = dis16->CtlID;
930 dis->itemID = dis16->itemID;
931 dis->itemAction = dis16->itemAction;
932 dis->itemState = dis16->itemState;
933 dis->hwndItem = dis16->hwndItem;
934 dis->hDC = dis16->hDC;
935 dis->itemData = dis16->itemData;
936 CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
937 *plparam = (LPARAM)dis;
939 return 1;
940 case WM_GETMINMAXINFO:
942 MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
943 sizeof(*mmi) + sizeof(LPARAM));
944 if (!mmi) return -1;
945 STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
946 mmi );
947 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
948 *plparam = (LPARAM)mmi;
950 return 1;
951 case WM_GETTEXT:
952 case WM_SETTEXT:
953 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
954 return 0;
955 case WM_MDICREATE:
957 MDICREATESTRUCT16 *cs16 =
958 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
959 MDICREATESTRUCT32A *cs =
960 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
961 sizeof(*cs) + sizeof(LPARAM) );
962 if (!cs) return -1;
963 STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
964 cs->szTitle = (LPCSTR)PTR_SEG_TO_LIN(cs16->szTitle);
965 cs->szClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->szClass);
966 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
967 *plparam = (LPARAM)cs;
969 return 1;
970 case WM_MDIGETACTIVE:
971 *plparam = (LPARAM)HeapAlloc( SystemHeap, 0, sizeof(BOOL32) );
972 return 1;
973 case WM_MDISETMENU:
974 if(wParam16==TRUE)
975 *pmsg32=WM_MDIREFRESHMENU;
976 *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
977 *plparam = (LPARAM)(HMENU32)HIWORD(*plparam);
978 return 0;
979 case WM_MENUCHAR:
980 case WM_MENUSELECT:
981 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
982 *plparam = (LPARAM)(HMENU32)HIWORD(*plparam);
983 return 0;
984 case WM_MDIACTIVATE:
985 if( *plparam )
987 *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
988 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
990 else /* message sent to MDI client */
991 *pwparam32 = wParam16;
992 return 0;
993 case WM_NCCALCSIZE:
995 NCCALCSIZE_PARAMS16 *nc16;
996 NCCALCSIZE_PARAMS32 *nc;
998 nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
999 sizeof(*nc) + sizeof(LPARAM) );
1000 if (!nc) return -1;
1001 nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
1002 CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1003 if (wParam16)
1005 nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
1006 sizeof(*nc->lppos) );
1007 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1008 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1009 if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
1011 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1012 *plparam = (LPARAM)nc;
1014 return 1;
1015 case WM_NCCREATE:
1016 case WM_CREATE:
1018 CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1019 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
1020 sizeof(*cs) + sizeof(LPARAM) );
1021 if (!cs) return -1;
1022 STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1023 cs->lpszName = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1024 cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1025 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1026 *plparam = (LPARAM)cs;
1028 return 1;
1029 case WM_PARENTNOTIFY:
1030 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1032 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1033 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
1035 return 0;
1036 case WM_WINDOWPOSCHANGING:
1037 case WM_WINDOWPOSCHANGED:
1039 WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
1040 sizeof(*wp) + sizeof(LPARAM) );
1041 if (!wp) return -1;
1042 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
1043 wp );
1044 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1045 *plparam = (LPARAM)wp;
1047 return 1;
1048 case WM_GETDLGCODE:
1049 if (*plparam)
1051 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1052 LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1054 if (!msg32) return -1;
1055 msg32->hwnd = msg16->hwnd;
1056 msg32->lParam = msg16->lParam;
1057 msg32->time = msg16->time;
1058 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1059 /* this is right, right? */
1060 if (WINPROC_MapMsg16To32A(msg16->message,msg16->wParam,
1061 &msg32->message,&msg32->wParam,
1062 &msg32->lParam)<0) {
1063 HeapFree( SystemHeap, 0, msg32 );
1064 return -1;
1066 *plparam = (LPARAM)msg32;
1067 return 1;
1069 else return 0;
1070 case WM_NOTIFY:
1071 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1072 return 1;
1073 case WM_ASKCBFORMATNAME:
1074 case WM_DEVMODECHANGE:
1075 case WM_PAINTCLIPBOARD:
1076 case WM_SIZECLIPBOARD:
1077 case WM_WININICHANGE:
1078 FIXME( msg, "message %04x needs translation\n",msg16 );
1079 return -1;
1081 default: /* No translation needed */
1082 return 0;
1087 /**********************************************************************
1088 * WINPROC_UnmapMsg16To32A
1090 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1092 LRESULT WINPROC_UnmapMsg16To32A( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1093 LRESULT result )
1095 switch(msg)
1097 case WM_COMPAREITEM:
1098 case WM_DELETEITEM:
1099 case WM_DRAWITEM:
1100 HeapFree( SystemHeap, 0, (LPVOID)lParam );
1101 break;
1102 case WM_MEASUREITEM:
1104 MEASUREITEMSTRUCT16 *mis16;
1105 MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)lParam;
1106 lParam = *(LPARAM *)(mis + 1);
1107 mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
1108 mis16->itemWidth = (UINT16)mis->itemWidth;
1109 mis16->itemHeight = (UINT16)mis->itemHeight;
1110 HeapFree( SystemHeap, 0, mis );
1112 break;
1113 case WM_GETMINMAXINFO:
1115 MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
1116 lParam = *(LPARAM *)(mmi + 1);
1117 STRUCT32_MINMAXINFO32to16( mmi,
1118 (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
1119 HeapFree( SystemHeap, 0, mmi );
1121 break;
1122 case WM_MDICREATE:
1124 MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
1125 lParam = *(LPARAM *)(cs + 1);
1126 STRUCT32_MDICREATESTRUCT32Ato16( cs,
1127 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1128 HeapFree( SystemHeap, 0, cs );
1130 break;
1131 case WM_MDIGETACTIVE:
1132 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL32 *)lParam) );
1133 HeapFree( SystemHeap, 0, (BOOL32 *)lParam );
1134 break;
1135 case WM_NCCALCSIZE:
1137 NCCALCSIZE_PARAMS16 *nc16;
1138 NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
1139 lParam = *(LPARAM *)(nc + 1);
1140 nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
1141 CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1142 if (wParam)
1144 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1145 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1146 if (nc->lppos)
1148 STRUCT32_WINDOWPOS32to16( nc->lppos,
1149 (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
1150 HeapFree( SystemHeap, 0, nc->lppos );
1153 HeapFree( SystemHeap, 0, nc );
1155 break;
1156 case WM_NCCREATE:
1157 case WM_CREATE:
1159 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
1160 lParam = *(LPARAM *)(cs + 1);
1161 STRUCT32_CREATESTRUCT32Ato16( cs,
1162 (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1163 HeapFree( SystemHeap, 0, cs );
1165 break;
1166 case WM_WINDOWPOSCHANGING:
1167 case WM_WINDOWPOSCHANGED:
1169 WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
1170 lParam = *(LPARAM *)(wp + 1);
1171 STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
1172 HeapFree( SystemHeap, 0, wp );
1174 break;
1175 case WM_GETDLGCODE:
1176 if (lParam)
1178 LPMSG32 msg32 = (LPMSG32)lParam;
1180 WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1181 result);
1182 HeapFree( SystemHeap, 0, msg32 );
1184 break;
1186 return result;
1190 /**********************************************************************
1191 * WINPROC_MapMsg16To32W
1193 * Map a message from 16- to 32-bit Unicode.
1194 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1196 INT32 WINPROC_MapMsg16To32W( HWND16 hwnd, UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
1197 WPARAM32 *pwparam32, LPARAM *plparam )
1199 switch(msg16)
1201 case WM_GETTEXT:
1202 case WM_SETTEXT:
1203 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1204 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, *pwparam32, plparam );
1205 case WM_NCCREATE:
1206 case WM_CREATE:
1208 CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1209 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1210 sizeof(*cs) + sizeof(LPARAM) );
1211 if (!cs) return -1;
1212 STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
1213 cs->lpszName = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1214 cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1215 if (HIWORD(cs->lpszName))
1216 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
1217 (LPCSTR)cs->lpszName );
1218 if (HIWORD(cs->lpszClass))
1219 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
1220 (LPCSTR)cs->lpszClass );
1221 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1222 *plparam = (LPARAM)cs;
1224 return 1;
1225 case WM_MDICREATE:
1227 MDICREATESTRUCT16 *cs16 =
1228 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1229 MDICREATESTRUCT32W *cs =
1230 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1231 sizeof(*cs) + sizeof(LPARAM) );
1232 if (!cs) return -1;
1233 STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCT32A *)cs );
1234 cs->szTitle = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szTitle);
1235 cs->szClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szClass);
1236 if (HIWORD(cs->szTitle))
1237 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
1238 (LPCSTR)cs->szTitle );
1239 if (HIWORD(cs->szClass))
1240 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
1241 (LPCSTR)cs->szClass );
1242 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1243 *plparam = (LPARAM)cs;
1245 return 1;
1246 case WM_GETDLGCODE:
1247 if (*plparam)
1249 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1250 LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1252 if (!msg32) return -1;
1253 msg32->hwnd = msg16->hwnd;
1254 msg32->lParam = msg16->lParam;
1255 msg32->time = msg16->time;
1256 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1257 /* this is right, right? */
1258 if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1259 &msg32->message,&msg32->wParam,
1260 &msg32->lParam)<0) {
1261 HeapFree( SystemHeap, 0, msg32 );
1262 return -1;
1264 *plparam = (LPARAM)msg32;
1265 return 1;
1267 else return 0;
1268 default: /* No Unicode translation needed */
1269 return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
1270 pwparam32, plparam );
1275 /**********************************************************************
1276 * WINPROC_UnmapMsg16To32W
1278 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1280 LRESULT WINPROC_UnmapMsg16To32W( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1281 LRESULT result )
1283 switch(msg)
1285 case WM_GETTEXT:
1286 case WM_SETTEXT:
1287 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
1288 break;
1289 case WM_NCCREATE:
1290 case WM_CREATE:
1292 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
1293 lParam = *(LPARAM *)(cs + 1);
1294 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
1295 (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1296 if (HIWORD(cs->lpszName))
1297 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
1298 if (HIWORD(cs->lpszClass))
1299 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
1300 HeapFree( SystemHeap, 0, cs );
1302 break;
1303 case WM_MDICREATE:
1305 MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
1306 lParam = *(LPARAM *)(cs + 1);
1307 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs,
1308 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1309 if (HIWORD(cs->szTitle))
1310 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
1311 if (HIWORD(cs->szClass))
1312 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
1313 HeapFree( SystemHeap, 0, cs );
1315 break;
1316 case WM_GETDLGCODE:
1317 if (lParam)
1319 LPMSG32 msg32 = (LPMSG32)lParam;
1321 WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1322 result);
1323 HeapFree( SystemHeap, 0, msg32 );
1325 break;
1326 default:
1327 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1329 return result;
1333 /**********************************************************************
1334 * WINPROC_MapMsg32ATo16
1336 * Map a message from 32-bit Ansi to 16-bit.
1337 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1339 INT32 WINPROC_MapMsg32ATo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1340 UINT16 *pmsg16, WPARAM16 *pwparam16,
1341 LPARAM *plparam )
1343 *pmsg16 = (UINT16)msg32;
1344 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1345 switch(msg32)
1347 case BM_GETCHECK32:
1348 case BM_SETCHECK32:
1349 case BM_GETSTATE32:
1350 case BM_SETSTATE32:
1351 case BM_SETSTYLE32:
1352 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
1353 return 0;
1355 case EM_GETSEL32:
1356 case EM_GETRECT32:
1357 case EM_SETRECT32:
1358 case EM_SETRECTNP32:
1359 case EM_SCROLL32:
1360 case EM_LINESCROLL32:
1361 case EM_SCROLLCARET32:
1362 case EM_GETMODIFY32:
1363 case EM_SETMODIFY32:
1364 case EM_GETLINECOUNT32:
1365 case EM_LINEINDEX32:
1366 case EM_SETHANDLE32:
1367 case EM_GETHANDLE32:
1368 case EM_GETTHUMB32:
1369 case EM_LINELENGTH32:
1370 case EM_REPLACESEL32:
1371 case EM_GETLINE32:
1372 case EM_LIMITTEXT32:
1373 case EM_CANUNDO32:
1374 case EM_UNDO32:
1375 case EM_FMTLINES32:
1376 case EM_LINEFROMCHAR32:
1377 case EM_SETTABSTOPS32:
1378 case EM_SETPASSWORDCHAR32:
1379 case EM_EMPTYUNDOBUFFER32:
1380 case EM_GETFIRSTVISIBLELINE32:
1381 case EM_SETREADONLY32:
1382 case EM_SETWORDBREAKPROC32:
1383 case EM_GETWORDBREAKPROC32:
1384 case EM_GETPASSWORDCHAR32:
1385 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL32);
1386 return 0;
1388 case LB_CARETOFF32:
1389 case LB_CARETON32:
1390 case LB_DELETESTRING32:
1391 case LB_GETANCHORINDEX32:
1392 case LB_GETCARETINDEX32:
1393 case LB_GETCOUNT32:
1394 case LB_GETCURSEL32:
1395 case LB_GETHORIZONTALEXTENT32:
1396 case LB_GETITEMDATA32:
1397 case LB_GETITEMHEIGHT32:
1398 case LB_GETSEL32:
1399 case LB_GETSELCOUNT32:
1400 case LB_GETTEXTLEN32:
1401 case LB_GETTOPINDEX32:
1402 case LB_RESETCONTENT32:
1403 case LB_SELITEMRANGE32:
1404 case LB_SELITEMRANGEEX32:
1405 case LB_SETANCHORINDEX32:
1406 case LB_SETCARETINDEX32:
1407 case LB_SETCOLUMNWIDTH32:
1408 case LB_SETCURSEL32:
1409 case LB_SETHORIZONTALEXTENT32:
1410 case LB_SETITEMDATA32:
1411 case LB_SETITEMHEIGHT32:
1412 case LB_SETSEL32:
1413 case LB_SETTOPINDEX32:
1414 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1415 return 0;
1416 case CB_DELETESTRING32:
1417 case CB_GETCOUNT32:
1418 case CB_GETLBTEXTLEN32:
1419 case CB_LIMITTEXT32:
1420 case CB_RESETCONTENT32:
1421 case CB_SETEDITSEL32:
1422 case CB_GETCURSEL32:
1423 case CB_SETCURSEL32:
1424 case CB_SHOWDROPDOWN32:
1425 case CB_SETITEMDATA32:
1426 case CB_SETITEMHEIGHT32:
1427 case CB_GETITEMHEIGHT32:
1428 case CB_SETEXTENDEDUI32:
1429 case CB_GETEXTENDEDUI32:
1430 case CB_GETDROPPEDSTATE32:
1431 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1432 return 0;
1433 case CB_GETEDITSEL32:
1434 *pmsg16 = CB_GETEDITSEL16;
1435 return 1;
1437 case LB_ADDSTRING32:
1438 case LB_FINDSTRING32:
1439 case LB_FINDSTRINGEXACT32:
1440 case LB_INSERTSTRING32:
1441 case LB_SELECTSTRING32:
1442 case LB_DIR32:
1443 case LB_ADDFILE32:
1445 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1446 if (!str) return -1;
1447 *plparam = (LPARAM)SEGPTR_GET(str);
1449 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1450 return 1;
1452 case CB_ADDSTRING32:
1453 case CB_FINDSTRING32:
1454 case CB_FINDSTRINGEXACT32:
1455 case CB_INSERTSTRING32:
1456 case CB_SELECTSTRING32:
1457 case CB_DIR32:
1459 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1460 if (!str) return -1;
1461 *plparam = (LPARAM)SEGPTR_GET(str);
1463 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1464 return 1;
1466 case LB_GETITEMRECT32:
1468 RECT16 *rect;
1469 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1470 if (!rect) return -1;
1471 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1472 *plparam = (LPARAM)SEGPTR_GET(rect);
1474 *pmsg16 = LB_GETITEMRECT16;
1475 return 1;
1476 case LB_GETSELITEMS32:
1478 LPINT16 items;
1479 *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1480 if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1481 + sizeof(LPARAM)))) return -1;
1482 *((LPARAM *)items)++ = *plparam; /* Store the previous lParam */
1483 *plparam = (LPARAM)SEGPTR_GET(items);
1485 *pmsg16 = LB_GETSELITEMS16;
1486 return 1;
1487 case LB_SETTABSTOPS32:
1488 if (wParam32)
1490 INT32 i;
1491 LPINT16 stops;
1492 *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1493 if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1494 + sizeof(LPARAM)))) return -1;
1495 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i);
1496 *plparam = (LPARAM)SEGPTR_GET(stops);
1497 return 1;
1499 *pmsg16 = LB_SETTABSTOPS16;
1500 return 0;
1502 case CB_GETDROPPEDCONTROLRECT32:
1504 RECT16 *rect;
1505 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1506 if (!rect) return -1;
1507 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1508 *plparam = (LPARAM)SEGPTR_GET(rect);
1510 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1511 return 1;
1513 case LB_GETTEXT32:
1514 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1515 *pmsg16 = LB_GETTEXT16;
1516 return 1;
1518 case CB_GETLBTEXT32:
1519 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1520 *pmsg16 = CB_GETLBTEXT16;
1521 return 1;
1523 case EM_SETSEL32:
1524 *pwparam16 = 0;
1525 *plparam = MAKELONG( (INT16)(INT32)wParam32, (INT16)*plparam );
1526 *pmsg16 = EM_SETSEL16;
1527 return 0;
1529 case WM_ACTIVATE:
1530 case WM_CHARTOITEM:
1531 case WM_COMMAND:
1532 case WM_VKEYTOITEM:
1533 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1534 return 0;
1535 case WM_HSCROLL:
1536 case WM_VSCROLL:
1537 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1538 return 0;
1539 case WM_CTLCOLORMSGBOX:
1540 case WM_CTLCOLOREDIT:
1541 case WM_CTLCOLORLISTBOX:
1542 case WM_CTLCOLORBTN:
1543 case WM_CTLCOLORDLG:
1544 case WM_CTLCOLORSCROLLBAR:
1545 case WM_CTLCOLORSTATIC:
1546 *pmsg16 = WM_CTLCOLOR;
1547 *plparam = MAKELPARAM( (HWND16)*plparam,
1548 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1549 return 0;
1550 case WM_COMPAREITEM:
1552 COMPAREITEMSTRUCT32 *cis32 = (COMPAREITEMSTRUCT32 *)*plparam;
1553 COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1554 if (!cis) return -1;
1555 cis->CtlType = (UINT16)cis32->CtlType;
1556 cis->CtlID = (UINT16)cis32->CtlID;
1557 cis->hwndItem = (HWND16)cis32->hwndItem;
1558 cis->itemID1 = (UINT16)cis32->itemID1;
1559 cis->itemData1 = cis32->itemData1;
1560 cis->itemID2 = (UINT16)cis32->itemID2;
1561 cis->itemData2 = cis32->itemData2;
1562 *plparam = (LPARAM)SEGPTR_GET(cis);
1564 return 1;
1565 case WM_DELETEITEM:
1567 DELETEITEMSTRUCT32 *dis32 = (DELETEITEMSTRUCT32 *)*plparam;
1568 DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1569 if (!dis) return -1;
1570 dis->CtlType = (UINT16)dis32->CtlType;
1571 dis->CtlID = (UINT16)dis32->CtlID;
1572 dis->itemID = (UINT16)dis32->itemID;
1573 dis->hwndItem = (HWND16)dis32->hwndItem;
1574 dis->itemData = dis32->itemData;
1575 *plparam = (LPARAM)SEGPTR_GET(dis);
1577 return 1;
1578 case WM_DRAWITEM:
1580 DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
1581 DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1582 if (!dis) return -1;
1583 dis->CtlType = (UINT16)dis32->CtlType;
1584 dis->CtlID = (UINT16)dis32->CtlID;
1585 dis->itemID = (UINT16)dis32->itemID;
1586 dis->itemAction = (UINT16)dis32->itemAction;
1587 dis->itemState = (UINT16)dis32->itemState;
1588 dis->hwndItem = (HWND16)dis32->hwndItem;
1589 dis->hDC = (HDC16)dis32->hDC;
1590 dis->itemData = dis32->itemData;
1591 CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1592 *plparam = (LPARAM)SEGPTR_GET(dis);
1594 return 1;
1595 case WM_MEASUREITEM:
1597 MEASUREITEMSTRUCT32 *mis32 = (MEASUREITEMSTRUCT32 *)*plparam;
1598 MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1599 SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1600 if (!mis) return -1;
1601 mis->CtlType = (UINT16)mis32->CtlType;
1602 mis->CtlID = (UINT16)mis32->CtlID;
1603 mis->itemID = (UINT16)mis32->itemID;
1604 mis->itemWidth = (UINT16)mis32->itemWidth;
1605 mis->itemHeight = (UINT16)mis32->itemHeight;
1606 mis->itemData = mis32->itemData;
1607 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1608 *plparam = (LPARAM)SEGPTR_GET(mis);
1610 return 1;
1611 case WM_GETMINMAXINFO:
1613 MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1614 sizeof(LPARAM) );
1615 if (!mmi) return -1;
1616 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
1617 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1618 *plparam = (LPARAM)SEGPTR_GET(mmi);
1620 return 1;
1621 case WM_GETTEXT:
1623 LPSTR str;
1624 *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
1625 if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1626 *((LPARAM *)str)++ = *plparam; /* Store the previous lParam */
1627 *plparam = (LPARAM)SEGPTR_GET(str);
1629 return 1;
1630 case WM_MDICREATE:
1632 MDICREATESTRUCT16 *cs;
1633 MDICREATESTRUCT32A *cs32 = (MDICREATESTRUCT32A *)*plparam;
1634 LPSTR name, cls;
1636 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1637 STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1638 name = SEGPTR_STRDUP( cs32->szTitle );
1639 cls = SEGPTR_STRDUP( cs32->szClass );
1640 cs->szTitle = SEGPTR_GET(name);
1641 cs->szClass = SEGPTR_GET(cls);
1642 *plparam = (LPARAM)SEGPTR_GET(cs);
1644 return 1;
1645 case WM_MDIGETACTIVE:
1646 return 1;
1647 case WM_MDISETMENU:
1648 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1649 (HMENU16)LOWORD(*plparam) );
1650 *pwparam16 = (*plparam == 0);
1651 return 0;
1652 case WM_MENUCHAR:
1653 case WM_MENUSELECT:
1654 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1655 return 0;
1656 case WM_MDIACTIVATE:
1657 if( WIDGETS_IsControl32(WIN_FindWndPtr(hwnd), BIC32_MDICLIENT) )
1659 *pwparam16 = (HWND32)wParam32;
1660 *plparam = 0;
1662 else
1664 *pwparam16 = ((HWND32)*plparam == hwnd);
1665 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1666 (HWND16)LOWORD(wParam32) );
1668 return 0;
1669 case WM_NCCALCSIZE:
1671 NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
1672 NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1673 if (!nc) return -1;
1675 CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1676 if (wParam32)
1678 WINDOWPOS16 *wp;
1679 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1680 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1681 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1683 SEGPTR_FREE(nc);
1684 return -1;
1686 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1687 nc->lppos = SEGPTR_GET(wp);
1689 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1690 *plparam = (LPARAM)SEGPTR_GET(nc);
1692 return 1;
1693 case WM_NCCREATE:
1694 case WM_CREATE:
1696 CREATESTRUCT16 *cs;
1697 CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
1698 LPSTR name, cls;
1700 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1701 STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1702 name = SEGPTR_STRDUP( cs32->lpszName );
1703 cls = SEGPTR_STRDUP( cs32->lpszClass );
1704 cs->lpszName = SEGPTR_GET(name);
1705 cs->lpszClass = SEGPTR_GET(cls);
1706 *plparam = (LPARAM)SEGPTR_GET(cs);
1708 return 1;
1709 case WM_PARENTNOTIFY:
1710 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1711 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1712 /* else nothing to do */
1713 return 0;
1714 case WM_NOTIFY:
1715 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1716 return 1;
1717 case WM_SETTEXT:
1719 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1720 if (!str) return -1;
1721 *plparam = (LPARAM)SEGPTR_GET(str);
1723 return 1;
1724 case WM_WINDOWPOSCHANGING:
1725 case WM_WINDOWPOSCHANGED:
1727 WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1728 sizeof(LPARAM) );
1729 if (!wp) return -1;
1730 STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
1731 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1732 *plparam = (LPARAM)SEGPTR_GET(wp);
1734 return 1;
1735 case WM_GETDLGCODE:
1736 if (*plparam) {
1737 LPMSG32 msg32 = (LPMSG32) *plparam;
1738 LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
1740 if (!msg16) return -1;
1741 msg16->hwnd = msg32->hwnd;
1742 msg16->lParam = msg32->lParam;
1743 msg16->time = msg32->time;
1744 CONV_POINT32TO16(&msg32->pt,&msg16->pt);
1745 /* this is right, right? */
1746 if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
1747 &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
1748 SEGPTR_FREE( msg16 );
1749 return -1;
1751 *plparam = (LPARAM)SEGPTR_GET(msg16);
1752 return 1;
1754 return 0;
1756 case WM_ASKCBFORMATNAME:
1757 case WM_DEVMODECHANGE:
1758 case WM_PAINTCLIPBOARD:
1759 case WM_SIZECLIPBOARD:
1760 case WM_WININICHANGE:
1761 FIXME( msg, "message %04x needs translation\n", msg32 );
1762 return -1;
1763 default: /* No translation needed */
1764 return 0;
1769 /**********************************************************************
1770 * WINPROC_UnmapMsg32ATo16
1772 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1774 void WINPROC_UnmapMsg32ATo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1775 MSGPARAM16* p16 )
1777 switch(msg)
1779 case LB_ADDFILE32:
1780 case LB_ADDSTRING32:
1781 case LB_DIR32:
1782 case LB_FINDSTRING32:
1783 case LB_FINDSTRINGEXACT32:
1784 case LB_INSERTSTRING32:
1785 case LB_SELECTSTRING32:
1786 case LB_SETTABSTOPS32:
1787 case CB_ADDSTRING32:
1788 case CB_FINDSTRING32:
1789 case CB_FINDSTRINGEXACT32:
1790 case CB_INSERTSTRING32:
1791 case CB_SELECTSTRING32:
1792 case CB_DIR32:
1793 case WM_COMPAREITEM:
1794 case WM_DELETEITEM:
1795 case WM_DRAWITEM:
1796 case WM_SETTEXT:
1797 SEGPTR_FREE( PTR_SEG_TO_LIN(p16->lParam) );
1798 break;
1800 case CB_GETDROPPEDCONTROLRECT32:
1801 case LB_GETITEMRECT32:
1803 RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(p16->lParam);
1804 p16->lParam = *(LPARAM *)(rect + 1);
1805 CONV_RECT16TO32( rect, (RECT32 *)(p16->lParam));
1806 SEGPTR_FREE( rect );
1808 break;
1809 case LB_GETSELITEMS32:
1811 INT32 i;
1812 LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam);
1813 p16->lParam = *((LPARAM *)items - 1);
1814 for (i = 0; i < p16->wParam; i++) *((LPINT32)(p16->lParam) + i) = items[i];
1815 SEGPTR_FREE( (LPARAM *)items - 1 );
1817 break;
1819 case CB_GETEDITSEL32:
1820 if( wParam )
1821 *((LPUINT32)(wParam)) = LOWORD(p16->lResult);
1822 if( lParam )
1823 *((LPUINT32)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
1824 break;
1826 case LB_GETTEXT32:
1827 case CB_GETLBTEXT32:
1828 UnMapLS( (SEGPTR)(p16->lParam) );
1829 break;
1831 case WM_MEASUREITEM:
1833 MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1834 MEASUREITEMSTRUCT32 *mis32 = *(MEASUREITEMSTRUCT32 **)(mis + 1);
1835 mis32->itemWidth = mis->itemWidth;
1836 mis32->itemHeight = mis->itemHeight;
1837 SEGPTR_FREE(mis);
1839 break;
1840 case WM_GETMINMAXINFO:
1842 MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(p16->lParam);
1843 p16->lParam = *(LPARAM *)(mmi + 1);
1844 STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)(p16->lParam) );
1845 SEGPTR_FREE(mmi);
1847 break;
1848 case WM_GETTEXT:
1850 LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
1851 p16->lParam = *((LPARAM *)str - 1);
1852 lstrcpyn32A( (LPSTR)(p16->lParam), str, p16->wParam );
1853 SEGPTR_FREE( (LPARAM *)str - 1 );
1855 break;
1856 case WM_MDICREATE:
1858 MDICREATESTRUCT16 *cs = (MDICREATESTRUCT16*)PTR_SEG_TO_LIN(p16->lParam);
1859 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szTitle) );
1860 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szClass) );
1861 SEGPTR_FREE( cs );
1863 break;
1864 case WM_MDIGETACTIVE:
1865 if (lParam) *(BOOL32 *)lParam = (BOOL16)HIWORD(p16->lResult);
1866 p16->lResult = (HWND32)LOWORD(p16->lResult);
1867 break;
1868 case WM_NCCALCSIZE:
1870 NCCALCSIZE_PARAMS32 *nc32;
1871 NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(p16->lParam);
1872 p16->lParam = *(LPARAM *)(nc + 1);
1873 nc32 = (NCCALCSIZE_PARAMS32 *)(p16->lParam);
1874 CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
1875 if (p16->wParam)
1877 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
1878 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
1879 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
1880 nc32->lppos );
1881 SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
1883 SEGPTR_FREE(nc);
1885 break;
1886 case WM_NCCREATE:
1887 case WM_CREATE:
1889 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1890 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
1891 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
1892 SEGPTR_FREE( cs );
1894 break;
1895 case WM_WINDOWPOSCHANGING:
1896 case WM_WINDOWPOSCHANGED:
1898 WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(p16->lParam);
1899 p16->lParam = *(LPARAM *)(wp + 1);
1900 STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)p16->lParam );
1901 SEGPTR_FREE(wp);
1903 break;
1904 case WM_NOTIFY:
1905 UnMapLS(p16->lParam);
1906 break;
1907 case WM_GETDLGCODE:
1908 if (p16->lParam)
1910 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(p16->lParam);
1911 MSGPARAM16 msgp16;
1912 msgp16.wParam=msg16->wParam;
1913 msgp16.lParam=msg16->lParam;
1914 WINPROC_UnmapMsg32ATo16(((LPMSG32)lParam)->hwnd, ((LPMSG32)lParam)->message,
1915 ((LPMSG32)lParam)->wParam, ((LPMSG32)lParam)->lParam,
1916 &msgp16 );
1917 SEGPTR_FREE(msg16);
1919 break;
1924 /**********************************************************************
1925 * WINPROC_MapMsg32WTo16
1927 * Map a message from 32-bit Unicode to 16-bit.
1928 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1930 INT32 WINPROC_MapMsg32WTo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1931 UINT16 *pmsg16, WPARAM16 *pwparam16,
1932 LPARAM *plparam )
1934 switch(msg32)
1936 case LB_ADDSTRING32:
1937 case LB_FINDSTRING32:
1938 case LB_FINDSTRINGEXACT32:
1939 case LB_INSERTSTRING32:
1940 case LB_SELECTSTRING32:
1941 case LB_DIR32:
1942 case LB_ADDFILE32:
1944 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1945 if (!str) return -1;
1946 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1947 *plparam = (LPARAM)SEGPTR_GET(str);
1949 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1950 return 1;
1952 case CB_ADDSTRING32:
1953 case CB_FINDSTRING32:
1954 case CB_FINDSTRINGEXACT32:
1955 case CB_INSERTSTRING32:
1956 case CB_SELECTSTRING32:
1957 case CB_DIR32:
1959 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1960 if (!str) return -1;
1961 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1962 *plparam = (LPARAM)SEGPTR_GET(str);
1964 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING32);
1965 return 1;
1967 case WM_NCCREATE:
1968 case WM_CREATE:
1970 CREATESTRUCT16 *cs;
1971 CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
1972 LPSTR name, cls;
1974 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1975 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
1976 name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
1977 cls = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
1978 cs->lpszName = SEGPTR_GET(name);
1979 cs->lpszClass = SEGPTR_GET(cls);
1980 *pmsg16 = (UINT16)msg32;
1981 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1982 *plparam = (LPARAM)SEGPTR_GET(cs);
1984 return 1;
1985 case WM_MDICREATE:
1987 MDICREATESTRUCT16 *cs;
1988 MDICREATESTRUCT32W *cs32 = (MDICREATESTRUCT32W *)*plparam;
1989 LPSTR name, cls;
1991 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1992 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs32, cs );
1993 name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
1994 cls = SEGPTR_STRDUP_WtoA( cs32->szClass );
1995 cs->szTitle = SEGPTR_GET(name);
1996 cs->szClass = SEGPTR_GET(cls);
1997 *pmsg16 = (UINT16)msg32;
1998 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1999 *plparam = (LPARAM)SEGPTR_GET(cs);
2001 return 1;
2002 case WM_SETTEXT:
2004 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2005 if (!str) return -1;
2006 *pmsg16 = (UINT16)msg32;
2007 *pwparam16 = (WPARAM16)LOWORD(wParam32);
2008 *plparam = (LPARAM)SEGPTR_GET(str);
2010 return 1;
2011 default: /* No Unicode translation needed */
2012 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2013 pwparam16, plparam );
2018 /**********************************************************************
2019 * WINPROC_UnmapMsg32WTo16
2021 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2023 void WINPROC_UnmapMsg32WTo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
2024 MSGPARAM16* p16 )
2026 switch(msg)
2028 case WM_GETTEXT:
2030 LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
2031 p16->lParam = *((LPARAM *)str - 1);
2032 lstrcpyAtoW( (LPWSTR)(p16->lParam), str );
2033 SEGPTR_FREE( (LPARAM *)str - 1 );
2035 break;
2036 default:
2037 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2038 break;
2043 /**********************************************************************
2044 * WINPROC_CallProc32ATo32W
2046 * Call a window procedure, translating args from Ansi to Unicode.
2048 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
2049 UINT32 msg, WPARAM32 wParam,
2050 LPARAM lParam )
2052 LRESULT result;
2054 if (WINPROC_MapMsg32ATo32W( hwnd, msg, wParam, &lParam ) == -1) return 0;
2055 result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2056 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
2057 return result;
2061 /**********************************************************************
2062 * WINPROC_CallProc32WTo32A
2064 * Call a window procedure, translating args from Unicode to Ansi.
2066 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
2067 UINT32 msg, WPARAM32 wParam,
2068 LPARAM lParam )
2070 LRESULT result;
2072 if (WINPROC_MapMsg32WTo32A( hwnd, msg, wParam, &lParam ) == -1) return 0;
2073 result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2074 WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2075 return result;
2079 /**********************************************************************
2080 * WINPROC_CallProc16To32A
2082 * Call a 32-bit window procedure, translating the 16-bit args.
2084 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
2085 WPARAM16 wParam, LPARAM lParam,
2086 WNDPROC32 func )
2088 LRESULT result;
2089 UINT32 msg32;
2090 WPARAM32 wParam32;
2092 if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2093 return 0;
2094 result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2095 return WINPROC_UnmapMsg16To32A( hwnd, msg32, wParam32, lParam, result );
2099 /**********************************************************************
2100 * WINPROC_CallProc16To32W
2102 * Call a 32-bit window procedure, translating the 16-bit args.
2104 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
2105 WPARAM16 wParam, LPARAM lParam,
2106 WNDPROC32 func )
2108 LRESULT result;
2109 UINT32 msg32;
2110 WPARAM32 wParam32;
2112 if (WINPROC_MapMsg16To32W( hwnd, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2113 return 0;
2114 result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2115 return WINPROC_UnmapMsg16To32W( hwnd, msg32, wParam32, lParam, result );
2119 /**********************************************************************
2120 * WINPROC_CallProc32ATo16
2122 * Call a 16-bit window procedure, translating the 32-bit args.
2124 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
2125 UINT32 msg, WPARAM32 wParam,
2126 LPARAM lParam )
2128 UINT16 msg16;
2129 MSGPARAM16 mp16;
2131 mp16.lParam = lParam;
2132 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam,
2133 &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2134 return 0;
2135 mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2136 mp16.wParam, mp16.lParam );
2137 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2138 return mp16.lResult;
2142 /**********************************************************************
2143 * WINPROC_CallProc32WTo16
2145 * Call a 16-bit window procedure, translating the 32-bit args.
2147 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
2148 UINT32 msg, WPARAM32 wParam,
2149 LPARAM lParam )
2151 UINT16 msg16;
2152 MSGPARAM16 mp16;
2154 mp16.lParam = lParam;
2155 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2156 &mp16.lParam ) == -1)
2157 return 0;
2158 mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2159 mp16.wParam, mp16.lParam );
2160 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2161 return mp16.lResult;
2165 /**********************************************************************
2166 * CallWindowProc16 (USER.122)
2168 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2169 WPARAM16 wParam, LPARAM lParam )
2171 WINDOWPROC *proc = WINPROC_GetPtr( func );
2173 if (!proc)
2174 return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2176 #if testing
2177 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2178 return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2179 #endif
2181 switch(proc->type)
2183 case WIN_PROC_16:
2184 if (!proc->thunk.t_from32.proc) return 0;
2185 return Callbacks->CallWndProc( proc->thunk.t_from32.proc,
2186 hwnd, msg, wParam, lParam );
2187 case WIN_PROC_32A:
2188 if (!proc->thunk.t_from16.proc) return 0;
2189 return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
2190 proc->thunk.t_from16.proc );
2191 case WIN_PROC_32W:
2192 if (!proc->thunk.t_from16.proc) return 0;
2193 return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
2194 proc->thunk.t_from16.proc );
2195 default:
2196 WARN( relay, "Invalid proc %p\n", proc );
2197 return 0;
2202 /**********************************************************************
2203 * CallWindowProc32A (USER32.18)
2205 * The CallWindowProc() function invokes the windows procedure _func_,
2206 * with _hwnd_ as the target window, the message specified by _msg_, and
2207 * the message parameters _wParam_ and _lParam_.
2209 * Some kinds of argument conversion may be done, I'm not sure what.
2211 * CallWindowProc() may be used for windows subclassing. Use
2212 * SetWindowLong() to set a new windows procedure for windows of the
2213 * subclass, and handle subclassed messages in the new windows
2214 * procedure. The new windows procedure may then use CallWindowProc()
2215 * with _func_ set to the parent class's windows procedure to dispatch
2216 * the message to the superclass.
2218 * RETURNS
2220 * The return value is message dependent.
2222 * CONFORMANCE
2224 * ECMA-234, Win32
2226 LRESULT WINAPI CallWindowProc32A(
2227 WNDPROC32 func, /* window procedure */
2228 HWND32 hwnd, /* target window */
2229 UINT32 msg, /* message */
2230 WPARAM32 wParam, /* message dependent parameter */
2231 LPARAM lParam /* message dependent parameter */
2233 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2235 if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2237 #if testing
2238 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2239 return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2240 #endif
2242 switch(proc->type)
2244 case WIN_PROC_16:
2245 if (!proc->thunk.t_from32.proc) return 0;
2246 return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2247 hwnd, msg, wParam, lParam );
2248 case WIN_PROC_32A:
2249 if (!proc->thunk.t_from16.proc) return 0;
2250 return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2251 hwnd, msg, wParam, lParam );
2252 case WIN_PROC_32W:
2253 if (!proc->thunk.t_from16.proc) return 0;
2254 return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2255 hwnd, msg, wParam, lParam );
2256 default:
2257 WARN( relay, "Invalid proc %p\n", proc );
2258 return 0;
2263 /**********************************************************************
2264 * CallWindowProc32W (USER32.19)
2266 LRESULT WINAPI CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
2267 WPARAM32 wParam, LPARAM lParam )
2269 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2271 if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2273 #if testing
2274 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2275 return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2276 #endif
2278 switch(proc->type)
2280 case WIN_PROC_16:
2281 if (!proc->thunk.t_from32.proc) return 0;
2282 return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2283 hwnd, msg, wParam, lParam );
2284 case WIN_PROC_32A:
2285 if (!proc->thunk.t_from16.proc) return 0;
2286 return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2287 hwnd, msg, wParam, lParam );
2288 case WIN_PROC_32W:
2289 if (!proc->thunk.t_from16.proc) return 0;
2290 return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2291 hwnd, msg, wParam, lParam );
2292 default:
2293 WARN( relay, "Invalid proc %p\n", proc );
2294 return 0;