New file, some helper functions for icon cache.
[wine/multimedia.git] / windows / winproc.c
blob09d50c2fc96e1889f29a73f0ef8b6e3e393d0547
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.
410 * fixme WM_CHAR, WM_CHARTOITEM, WM_DEADCHAR, WM_MENUCHAR, WM_SYSCHAR,
411 * WM_SYSDEADCHAR ???
413 INT32 WINPROC_MapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
414 { switch(msg)
416 case WM_GETTEXT:
418 LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
419 wParam * sizeof(WCHAR) + sizeof(LPARAM) );
420 if (!ptr) return -1;
421 *ptr++ = *plparam; /* Store previous lParam */
422 *plparam = (LPARAM)ptr;
424 return 1;
426 case WM_SETTEXT:
427 case CB_DIR32:
428 case CB_FINDSTRING32:
429 case CB_FINDSTRINGEXACT32:
430 case CB_SELECTSTRING32:
431 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
432 return (*plparam ? 1 : -1);
434 case WM_NCCREATE:
435 case WM_CREATE:
437 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
438 sizeof(*cs) );
439 if (!cs) return -1;
440 *cs = *(CREATESTRUCT32W *)*plparam;
441 if (HIWORD(cs->lpszName))
442 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
443 (LPCSTR)cs->lpszName );
444 if (HIWORD(cs->lpszClass))
445 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
446 (LPCSTR)cs->lpszClass );
447 *plparam = (LPARAM)cs;
449 return 1;
450 case WM_MDICREATE:
452 MDICREATESTRUCT32W *cs =
453 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
454 if (!cs) return -1;
455 *cs = *(MDICREATESTRUCT32W *)*plparam;
456 if (HIWORD(cs->szClass))
457 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
458 (LPCSTR)cs->szClass );
459 if (HIWORD(cs->szTitle))
460 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
461 (LPCSTR)cs->szTitle );
462 *plparam = (LPARAM)cs;
464 return 1;
466 /* Listbox */
467 case LB_ADDSTRING32:
468 case LB_INSERTSTRING32:
469 if ( WINPROC_TestLBForStr( hwnd ))
470 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
471 return (*plparam ? 1 : -1);
473 case LB_GETTEXT32: /* fixme: fixed sized buffer */
474 { if ( WINPROC_TestLBForStr( hwnd ))
475 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
476 if (!ptr) return -1;
477 *ptr++ = *plparam; /* Store previous lParam */
478 *plparam = (LPARAM)ptr;
481 return 1;
483 /* Combobox */
484 case CB_ADDSTRING32:
485 case CB_INSERTSTRING32:
486 if ( WINPROC_TestCBForStr( hwnd ))
487 *plparam = (LPARAM)HEAP_strdupAtoW( SystemHeap, 0, (LPCSTR)*plparam );
488 return (*plparam ? 1 : -1);
490 case CB_GETLBTEXT32: /* fixme: fixed sized buffer */
491 { if ( WINPROC_TestCBForStr( hwnd ))
492 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
493 if (!ptr) return -1;
494 *ptr++ = *plparam; /* Store previous lParam */
495 *plparam = (LPARAM)ptr;
498 return 1;
500 /* Multiline edit */
501 case EM_GETLINE32:
502 { WORD len = (WORD)*plparam;
503 LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
504 if (!ptr) return -1;
505 *ptr++ = *plparam; /* Store previous lParam */
506 (WORD)*ptr = len; /* Store the lenght */
507 *plparam = (LPARAM)ptr;
509 return 1;
511 case WM_ASKCBFORMATNAME:
512 case WM_DEVMODECHANGE:
513 case WM_PAINTCLIPBOARD:
514 case WM_SIZECLIPBOARD:
515 case WM_WININICHANGE:
516 case EM_REPLACESEL32:
517 case EM_SETPASSWORDCHAR32:
518 case LB_ADDFILE32:
519 case LB_DIR32:
520 case LB_FINDSTRING32:
521 case LB_SELECTSTRING32:
522 FIXME(msg, "message %s (0x%x) needs translation\n", SPY_GetMsgName(msg), msg );
523 return -1;
524 default: /* No translation needed */
525 return 0;
530 /**********************************************************************
531 * WINPROC_UnmapMsg32ATo32W
533 * Unmap a message that was mapped from Ansi to Unicode.
535 void WINPROC_UnmapMsg32ATo32W( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
536 { switch(msg)
538 case WM_GETTEXT:
540 LPARAM *ptr = (LPARAM *)lParam - 1;
541 lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)(ptr + 1), wParam ); /* fixme: shouldn't be there lParam instead of ptr ???*/
542 HeapFree( SystemHeap, 0, ptr );
544 break;
546 case WM_NCCREATE:
547 case WM_CREATE:
549 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
550 if (HIWORD(cs->lpszName))
551 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
552 if (HIWORD(cs->lpszClass))
553 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
554 HeapFree( SystemHeap, 0, cs );
556 break;
558 case WM_MDICREATE:
560 MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
561 if (HIWORD(cs->szTitle))
562 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
563 if (HIWORD(cs->szClass))
564 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
565 HeapFree( SystemHeap, 0, cs );
567 break;
569 case WM_SETTEXT:
570 case CB_DIR32:
571 case CB_FINDSTRING32:
572 case CB_FINDSTRINGEXACT32:
573 case CB_SELECTSTRING32:
574 HeapFree( SystemHeap, 0, (void *)lParam );
575 break;
577 /* Listbox */
578 case LB_ADDSTRING32:
579 case LB_INSERTSTRING32:
580 if ( WINPROC_TestLBForStr( hwnd ))
581 HeapFree( SystemHeap, 0, (void *)lParam );
582 break;
584 case LB_GETTEXT32:
585 { if ( WINPROC_TestLBForStr( hwnd ))
586 { LPARAM *ptr = (LPARAM *)lParam - 1;
587 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
588 HeapFree( SystemHeap, 0, ptr );
591 break;
593 /* Combobox */
594 case CB_ADDSTRING32:
595 case CB_INSERTSTRING32:
596 if ( WINPROC_TestCBForStr( hwnd ))
597 HeapFree( SystemHeap, 0, (void *)lParam );
598 break;
600 case CB_GETLBTEXT32:
601 { if ( WINPROC_TestCBForStr( hwnd ))
602 { LPARAM *ptr = (LPARAM *)lParam - 1;
603 lstrcpyWtoA( (LPSTR)*ptr, (LPWSTR)(lParam) );
604 HeapFree( SystemHeap, 0, ptr );
607 break;
609 /* Multiline edit */
610 case EM_GETLINE32:
611 { LPARAM *ptr = (LPARAM *)lParam - 1; /* get the old lParam */
612 WORD len = *(WORD *)ptr;
613 lstrcpynWtoA( ((LPSTR)*ptr)+2, ((LPWSTR)(lParam + 1))+1, len );
614 HeapFree( SystemHeap, 0, ptr );
616 break;
621 /**********************************************************************
622 * WINPROC_MapMsg32WTo32A
624 * Map a message from Unicode to Ansi.
625 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
627 INT32 WINPROC_MapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
628 { switch(msg)
630 case WM_GETTEXT:
632 LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
633 wParam + sizeof(LPARAM) );
634 if (!ptr) return -1;
635 *ptr++ = *plparam; /* Store previous lParam */
636 *plparam = (LPARAM)ptr;
638 return 1;
640 case WM_SETTEXT:
641 case CB_DIR32:
642 case CB_FINDSTRING32:
643 case CB_FINDSTRINGEXACT32:
644 case CB_SELECTSTRING32:
645 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
646 return (*plparam ? 1 : -1);
648 case WM_NCCREATE:
649 case WM_CREATE:
651 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
652 sizeof(*cs) );
653 if (!cs) return -1;
654 *cs = *(CREATESTRUCT32A *)*plparam;
655 if (HIWORD(cs->lpszName))
656 cs->lpszName = HEAP_strdupWtoA( SystemHeap, 0,
657 (LPCWSTR)cs->lpszName );
658 if (HIWORD(cs->lpszClass))
659 cs->lpszClass = HEAP_strdupWtoA( SystemHeap, 0,
660 (LPCWSTR)cs->lpszClass);
661 *plparam = (LPARAM)cs;
663 return 1;
664 case WM_MDICREATE:
666 MDICREATESTRUCT32A *cs =
667 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
668 if (!cs) return -1;
669 *cs = *(MDICREATESTRUCT32A *)*plparam;
670 if (HIWORD(cs->szTitle))
671 cs->szTitle = HEAP_strdupWtoA( SystemHeap, 0,
672 (LPCWSTR)cs->szTitle );
673 if (HIWORD(cs->szClass))
674 cs->szClass = HEAP_strdupWtoA( SystemHeap, 0,
675 (LPCWSTR)cs->szClass );
676 *plparam = (LPARAM)cs;
678 return 1;
680 /* Listbox */
681 case LB_ADDSTRING32:
682 case LB_INSERTSTRING32:
683 if ( WINPROC_TestLBForStr( hwnd ))
684 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
685 return (*plparam ? 1 : -1);
687 case LB_GETTEXT32: /* fixme: fixed sized buffer */
688 { if ( WINPROC_TestLBForStr( hwnd ))
689 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
690 if (!ptr) return -1;
691 *ptr++ = *plparam; /* Store previous lParam */
692 *plparam = (LPARAM)ptr;
695 return 1;
697 /* Combobox */
698 case CB_ADDSTRING32:
699 case CB_INSERTSTRING32:
700 if ( WINPROC_TestCBForStr( hwnd ))
701 *plparam = (LPARAM)HEAP_strdupWtoA( SystemHeap, 0, (LPCWSTR)*plparam );
702 return (*plparam ? 1 : -1);
704 case CB_GETLBTEXT32: /* fixme: fixed sized buffer */
705 { if ( WINPROC_TestCBForStr( hwnd ))
706 { LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0, 256 + sizeof(LPARAM) );
707 if (!ptr) return -1;
708 *ptr++ = *plparam; /* Store previous lParam */
709 *plparam = (LPARAM)ptr;
712 return 1;
714 /* Multiline edit */
715 case EM_GETLINE32:
716 { WORD len = (WORD)*plparam;
717 LPARAM *ptr = (LPARAM *) HEAP_xalloc( SystemHeap, 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
718 if (!ptr) return -1;
719 *ptr++ = *plparam; /* Store previous lParam */
720 (WORD)*ptr = len; /* Store the lenght */
721 *plparam = (LPARAM)ptr;
723 return 1;
725 case WM_ASKCBFORMATNAME:
726 case WM_DEVMODECHANGE:
727 case WM_PAINTCLIPBOARD:
728 case WM_SIZECLIPBOARD:
729 case WM_WININICHANGE:
730 case EM_REPLACESEL32:
731 case EM_SETPASSWORDCHAR32:
732 case LB_ADDFILE32:
733 case LB_DIR32:
734 case LB_FINDSTRING32:
735 case LB_SELECTSTRING32:
736 FIXME(msg, "message %04x needs translation\n",msg );
737 return -1;
738 default: /* No translation needed */
739 return 0;
744 /**********************************************************************
745 * WINPROC_UnmapMsg32WTo32A
747 * Unmap a message that was mapped from Unicode to Ansi.
749 void WINPROC_UnmapMsg32WTo32A( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam )
750 { switch(msg)
752 case WM_GETTEXT:
754 LPARAM *ptr = (LPARAM *)lParam - 1;
755 lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)(ptr + 1), wParam ); /* fixme: shouldn't be there lParam instead of ptr ???*/
756 HeapFree( SystemHeap, 0, ptr );
758 break;
760 case WM_SETTEXT:
761 case CB_DIR32:
762 case CB_FINDSTRING32:
763 case CB_FINDSTRINGEXACT32:
764 case CB_SELECTSTRING32:
765 HeapFree( SystemHeap, 0, (void *)lParam );
766 break;
768 case WM_NCCREATE:
769 case WM_CREATE:
771 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
772 if (HIWORD(cs->lpszName))
773 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
774 if (HIWORD(cs->lpszClass))
775 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
776 HeapFree( SystemHeap, 0, cs );
778 break;
780 case WM_MDICREATE:
782 MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
783 if (HIWORD(cs->szTitle))
784 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
785 if (HIWORD(cs->szClass))
786 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
787 HeapFree( SystemHeap, 0, cs );
789 break;
791 /* Listbox */
792 case LB_ADDSTRING32:
793 case LB_INSERTSTRING32:
794 if ( WINPROC_TestLBForStr( hwnd ))
795 HeapFree( SystemHeap, 0, (void *)lParam );
796 break;
798 case LB_GETTEXT32:
799 { if ( WINPROC_TestLBForStr( hwnd ))
800 { LPARAM *ptr = (LPARAM *)lParam - 1;
801 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
802 HeapFree( SystemHeap, 0, ptr );
805 break;
807 /* Combobox */
808 case CB_ADDSTRING32:
809 case CB_INSERTSTRING32:
810 if ( WINPROC_TestCBForStr( hwnd ))
811 HeapFree( SystemHeap, 0, (void *)lParam );
812 break;
814 case CB_GETLBTEXT32:
815 { if ( WINPROC_TestCBForStr( hwnd ))
816 { LPARAM *ptr = (LPARAM *)lParam - 1;
817 lstrcpyAtoW( (LPWSTR)*ptr, (LPSTR)(lParam) );
818 HeapFree( SystemHeap, 0, ptr );
821 break;
823 /* Multiline edit */
824 case EM_GETLINE32:
825 { LPARAM *ptr = (LPARAM *)lParam - 1; /* get the old lParam */
826 WORD len = *(WORD *)ptr;
827 lstrcpynAtoW( ((LPWSTR)*ptr)+1, ((LPSTR)(lParam + 1))+2, len );
828 HeapFree( SystemHeap, 0, ptr );
830 break;
835 /**********************************************************************
836 * WINPROC_MapMsg16To32A
838 * Map a message from 16- to 32-bit Ansi.
839 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
841 INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
842 WPARAM32 *pwparam32, LPARAM *plparam )
844 *pmsg32 = (UINT32)msg16;
845 *pwparam32 = (WPARAM32)wParam16;
846 switch(msg16)
848 case WM_ACTIVATE:
849 case WM_CHARTOITEM:
850 case WM_COMMAND:
851 case WM_VKEYTOITEM:
852 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
853 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
854 return 0;
855 case WM_HSCROLL:
856 case WM_VSCROLL:
857 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
858 *plparam = (LPARAM)(HWND32)HIWORD(*plparam);
859 return 0;
860 case WM_CTLCOLOR:
861 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
862 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
863 *pwparam32 = (WPARAM32)(HDC32)wParam16;
864 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
865 return 0;
866 case WM_COMPAREITEM:
868 COMPAREITEMSTRUCT16* cis16 = (COMPAREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
869 COMPAREITEMSTRUCT32 *cis = (COMPAREITEMSTRUCT32 *)
870 HeapAlloc(SystemHeap, 0, sizeof(*cis));
871 if (!cis) return -1;
872 cis->CtlType = cis16->CtlType;
873 cis->CtlID = cis16->CtlID;
874 cis->hwndItem = cis16->hwndItem;
875 cis->itemID1 = cis16->itemID1;
876 cis->itemData1 = cis16->itemData1;
877 cis->itemID2 = cis16->itemID2;
878 cis->itemData2 = cis16->itemData2;
879 cis->dwLocaleId = 0; /* FIXME */
880 *plparam = (LPARAM)cis;
882 return 1;
883 case WM_DELETEITEM:
885 DELETEITEMSTRUCT16* dis16 = (DELETEITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
886 DELETEITEMSTRUCT32 *dis = (DELETEITEMSTRUCT32 *)
887 HeapAlloc(SystemHeap, 0, sizeof(*dis));
888 if (!dis) return -1;
889 dis->CtlType = dis16->CtlType;
890 dis->CtlID = dis16->CtlID;
891 dis->hwndItem = dis16->hwndItem;
892 dis->itemData = dis16->itemData;
893 *plparam = (LPARAM)dis;
895 return 1;
896 case WM_MEASUREITEM:
898 MEASUREITEMSTRUCT16* mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
899 MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)
900 HeapAlloc(SystemHeap, 0,
901 sizeof(*mis) + sizeof(LPARAM));
902 if (!mis) return -1;
903 mis->CtlType = mis16->CtlType;
904 mis->CtlID = mis16->CtlID;
905 mis->itemID = mis16->itemID;
906 mis->itemWidth = mis16->itemWidth;
907 mis->itemHeight = mis16->itemHeight;
908 mis->itemData = mis16->itemData;
909 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
910 *plparam = (LPARAM)mis;
912 return 1;
913 case WM_DRAWITEM:
915 DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
916 DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
917 sizeof(*dis));
918 if (!dis) return -1;
919 dis->CtlType = dis16->CtlType;
920 dis->CtlID = dis16->CtlID;
921 dis->itemID = dis16->itemID;
922 dis->itemAction = dis16->itemAction;
923 dis->itemState = dis16->itemState;
924 dis->hwndItem = dis16->hwndItem;
925 dis->hDC = dis16->hDC;
926 dis->itemData = dis16->itemData;
927 CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
928 *plparam = (LPARAM)dis;
930 return 1;
931 case WM_GETMINMAXINFO:
933 MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
934 sizeof(*mmi) + sizeof(LPARAM));
935 if (!mmi) return -1;
936 STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
937 mmi );
938 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
939 *plparam = (LPARAM)mmi;
941 return 1;
942 case WM_GETTEXT:
943 case WM_SETTEXT:
944 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
945 return 0;
946 case WM_MDICREATE:
948 MDICREATESTRUCT16 *cs16 =
949 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
950 MDICREATESTRUCT32A *cs =
951 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
952 sizeof(*cs) + sizeof(LPARAM) );
953 if (!cs) return -1;
954 STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
955 cs->szTitle = (LPCSTR)PTR_SEG_TO_LIN(cs16->szTitle);
956 cs->szClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->szClass);
957 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
958 *plparam = (LPARAM)cs;
960 return 1;
961 case WM_MDIGETACTIVE:
962 *plparam = (LPARAM)HeapAlloc( SystemHeap, 0, sizeof(BOOL32) );
963 return 1;
964 case WM_MDISETMENU:
965 if(wParam16==TRUE)
966 *pmsg32=WM_MDIREFRESHMENU;
967 *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
968 *plparam = (LPARAM)(HMENU32)HIWORD(*plparam);
969 return 0;
970 case WM_MENUCHAR:
971 case WM_MENUSELECT:
972 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
973 *plparam = (LPARAM)(HMENU32)HIWORD(*plparam);
974 return 0;
975 case WM_MDIACTIVATE:
976 if( *plparam )
978 *pwparam32 = (WPARAM32)(HWND32)HIWORD(*plparam);
979 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
981 else /* message sent to MDI client */
982 *pwparam32 = wParam16;
983 return 0;
984 case WM_NCCALCSIZE:
986 NCCALCSIZE_PARAMS16 *nc16;
987 NCCALCSIZE_PARAMS32 *nc;
989 nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
990 sizeof(*nc) + sizeof(LPARAM) );
991 if (!nc) return -1;
992 nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
993 CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
994 if (wParam16)
996 nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
997 sizeof(*nc->lppos) );
998 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
999 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1000 if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
1002 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1003 *plparam = (LPARAM)nc;
1005 return 1;
1006 case WM_NCCREATE:
1007 case WM_CREATE:
1009 CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1010 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
1011 sizeof(*cs) + sizeof(LPARAM) );
1012 if (!cs) return -1;
1013 STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1014 cs->lpszName = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1015 cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1016 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1017 *plparam = (LPARAM)cs;
1019 return 1;
1020 case WM_PARENTNOTIFY:
1021 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1023 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1024 *plparam = (LPARAM)(HWND32)LOWORD(*plparam);
1026 return 0;
1027 case WM_WINDOWPOSCHANGING:
1028 case WM_WINDOWPOSCHANGED:
1030 WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
1031 sizeof(*wp) + sizeof(LPARAM) );
1032 if (!wp) return -1;
1033 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
1034 wp );
1035 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1036 *plparam = (LPARAM)wp;
1038 return 1;
1039 case WM_GETDLGCODE:
1040 if (*plparam)
1042 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1043 LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1045 if (!msg32) return -1;
1046 msg32->hwnd = msg16->hwnd;
1047 msg32->lParam = msg16->lParam;
1048 msg32->time = msg16->time;
1049 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1050 /* this is right, right? */
1051 if (WINPROC_MapMsg16To32A(msg16->message,msg16->wParam,
1052 &msg32->message,&msg32->wParam,
1053 &msg32->lParam)<0) {
1054 HeapFree( SystemHeap, 0, msg32 );
1055 return -1;
1057 *plparam = (LPARAM)msg32;
1058 return 1;
1060 else return 0;
1061 case WM_NOTIFY:
1062 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1063 return 1;
1064 case WM_ASKCBFORMATNAME:
1065 case WM_DEVMODECHANGE:
1066 case WM_PAINTCLIPBOARD:
1067 case WM_SIZECLIPBOARD:
1068 case WM_WININICHANGE:
1069 FIXME( msg, "message %04x needs translation\n",msg16 );
1070 return -1;
1072 default: /* No translation needed */
1073 return 0;
1078 /**********************************************************************
1079 * WINPROC_UnmapMsg16To32A
1081 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1083 LRESULT WINPROC_UnmapMsg16To32A( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1084 LRESULT result )
1086 switch(msg)
1088 case WM_COMPAREITEM:
1089 case WM_DELETEITEM:
1090 case WM_DRAWITEM:
1091 HeapFree( SystemHeap, 0, (LPVOID)lParam );
1092 break;
1093 case WM_MEASUREITEM:
1095 MEASUREITEMSTRUCT16 *mis16;
1096 MEASUREITEMSTRUCT32 *mis = (MEASUREITEMSTRUCT32 *)lParam;
1097 lParam = *(LPARAM *)(mis + 1);
1098 mis16 = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
1099 mis16->itemWidth = (UINT16)mis->itemWidth;
1100 mis16->itemHeight = (UINT16)mis->itemHeight;
1101 HeapFree( SystemHeap, 0, mis );
1103 break;
1104 case WM_GETMINMAXINFO:
1106 MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
1107 lParam = *(LPARAM *)(mmi + 1);
1108 STRUCT32_MINMAXINFO32to16( mmi,
1109 (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
1110 HeapFree( SystemHeap, 0, mmi );
1112 break;
1113 case WM_MDICREATE:
1115 MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
1116 lParam = *(LPARAM *)(cs + 1);
1117 STRUCT32_MDICREATESTRUCT32Ato16( cs,
1118 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1119 HeapFree( SystemHeap, 0, cs );
1121 break;
1122 case WM_MDIGETACTIVE:
1123 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL32 *)lParam) );
1124 HeapFree( SystemHeap, 0, (BOOL32 *)lParam );
1125 break;
1126 case WM_NCCALCSIZE:
1128 NCCALCSIZE_PARAMS16 *nc16;
1129 NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
1130 lParam = *(LPARAM *)(nc + 1);
1131 nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
1132 CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1133 if (wParam)
1135 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1136 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1137 if (nc->lppos)
1139 STRUCT32_WINDOWPOS32to16( nc->lppos,
1140 (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
1141 HeapFree( SystemHeap, 0, nc->lppos );
1144 HeapFree( SystemHeap, 0, nc );
1146 break;
1147 case WM_NCCREATE:
1148 case WM_CREATE:
1150 CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
1151 lParam = *(LPARAM *)(cs + 1);
1152 STRUCT32_CREATESTRUCT32Ato16( cs,
1153 (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1154 HeapFree( SystemHeap, 0, cs );
1156 break;
1157 case WM_WINDOWPOSCHANGING:
1158 case WM_WINDOWPOSCHANGED:
1160 WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
1161 lParam = *(LPARAM *)(wp + 1);
1162 STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
1163 HeapFree( SystemHeap, 0, wp );
1165 break;
1166 case WM_GETDLGCODE:
1167 if (lParam)
1169 LPMSG32 msg32 = (LPMSG32)lParam;
1171 WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1172 result);
1173 HeapFree( SystemHeap, 0, msg32 );
1175 break;
1177 return result;
1181 /**********************************************************************
1182 * WINPROC_MapMsg16To32W
1184 * Map a message from 16- to 32-bit Unicode.
1185 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1187 INT32 WINPROC_MapMsg16To32W( HWND16 hwnd, UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
1188 WPARAM32 *pwparam32, LPARAM *plparam )
1190 switch(msg16)
1192 case WM_GETTEXT:
1193 case WM_SETTEXT:
1194 *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
1195 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, *pwparam32, plparam );
1196 case WM_NCCREATE:
1197 case WM_CREATE:
1199 CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1200 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1201 sizeof(*cs) + sizeof(LPARAM) );
1202 if (!cs) return -1;
1203 STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
1204 cs->lpszName = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
1205 cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
1206 if (HIWORD(cs->lpszName))
1207 cs->lpszName = HEAP_strdupAtoW( SystemHeap, 0,
1208 (LPCSTR)cs->lpszName );
1209 if (HIWORD(cs->lpszClass))
1210 cs->lpszClass = HEAP_strdupAtoW( SystemHeap, 0,
1211 (LPCSTR)cs->lpszClass );
1212 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1213 *plparam = (LPARAM)cs;
1215 return 1;
1216 case WM_MDICREATE:
1218 MDICREATESTRUCT16 *cs16 =
1219 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
1220 MDICREATESTRUCT32W *cs =
1221 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
1222 sizeof(*cs) + sizeof(LPARAM) );
1223 if (!cs) return -1;
1224 STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCT32A *)cs );
1225 cs->szTitle = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szTitle);
1226 cs->szClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szClass);
1227 if (HIWORD(cs->szTitle))
1228 cs->szTitle = HEAP_strdupAtoW( SystemHeap, 0,
1229 (LPCSTR)cs->szTitle );
1230 if (HIWORD(cs->szClass))
1231 cs->szClass = HEAP_strdupAtoW( SystemHeap, 0,
1232 (LPCSTR)cs->szClass );
1233 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1234 *plparam = (LPARAM)cs;
1236 return 1;
1237 case WM_GETDLGCODE:
1238 if (*plparam)
1240 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(*plparam);
1241 LPMSG32 msg32 = (LPMSG32)HeapAlloc( SystemHeap, 0, sizeof(MSG32) );
1243 if (!msg32) return -1;
1244 msg32->hwnd = msg16->hwnd;
1245 msg32->lParam = msg16->lParam;
1246 msg32->time = msg16->time;
1247 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1248 /* this is right, right? */
1249 if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1250 &msg32->message,&msg32->wParam,
1251 &msg32->lParam)<0) {
1252 HeapFree( SystemHeap, 0, msg32 );
1253 return -1;
1255 *plparam = (LPARAM)msg32;
1256 return 1;
1258 else return 0;
1259 default: /* No Unicode translation needed */
1260 return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
1261 pwparam32, plparam );
1266 /**********************************************************************
1267 * WINPROC_UnmapMsg16To32W
1269 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1271 LRESULT WINPROC_UnmapMsg16To32W( HWND16 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1272 LRESULT result )
1274 switch(msg)
1276 case WM_GETTEXT:
1277 case WM_SETTEXT:
1278 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
1279 break;
1280 case WM_NCCREATE:
1281 case WM_CREATE:
1283 CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
1284 lParam = *(LPARAM *)(cs + 1);
1285 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
1286 (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1287 if (HIWORD(cs->lpszName))
1288 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszName );
1289 if (HIWORD(cs->lpszClass))
1290 HeapFree( SystemHeap, 0, (LPVOID)cs->lpszClass );
1291 HeapFree( SystemHeap, 0, cs );
1293 break;
1294 case WM_MDICREATE:
1296 MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
1297 lParam = *(LPARAM *)(cs + 1);
1298 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs,
1299 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
1300 if (HIWORD(cs->szTitle))
1301 HeapFree( SystemHeap, 0, (LPVOID)cs->szTitle );
1302 if (HIWORD(cs->szClass))
1303 HeapFree( SystemHeap, 0, (LPVOID)cs->szClass );
1304 HeapFree( SystemHeap, 0, cs );
1306 break;
1307 case WM_GETDLGCODE:
1308 if (lParam)
1310 LPMSG32 msg32 = (LPMSG32)lParam;
1312 WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1313 result);
1314 HeapFree( SystemHeap, 0, msg32 );
1316 break;
1317 default:
1318 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1320 return result;
1324 /**********************************************************************
1325 * WINPROC_MapMsg32ATo16
1327 * Map a message from 32-bit Ansi to 16-bit.
1328 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1330 INT32 WINPROC_MapMsg32ATo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1331 UINT16 *pmsg16, WPARAM16 *pwparam16,
1332 LPARAM *plparam )
1334 *pmsg16 = (UINT16)msg32;
1335 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1336 switch(msg32)
1338 case BM_GETCHECK32:
1339 case BM_SETCHECK32:
1340 case BM_GETSTATE32:
1341 case BM_SETSTATE32:
1342 case BM_SETSTYLE32:
1343 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
1344 return 0;
1346 case EM_GETSEL32:
1347 case EM_GETRECT32:
1348 case EM_SETRECT32:
1349 case EM_SETRECTNP32:
1350 case EM_SCROLL32:
1351 case EM_LINESCROLL32:
1352 case EM_SCROLLCARET32:
1353 case EM_GETMODIFY32:
1354 case EM_SETMODIFY32:
1355 case EM_GETLINECOUNT32:
1356 case EM_LINEINDEX32:
1357 case EM_SETHANDLE32:
1358 case EM_GETHANDLE32:
1359 case EM_GETTHUMB32:
1360 case EM_LINELENGTH32:
1361 case EM_REPLACESEL32:
1362 case EM_GETLINE32:
1363 case EM_LIMITTEXT32:
1364 case EM_CANUNDO32:
1365 case EM_UNDO32:
1366 case EM_FMTLINES32:
1367 case EM_LINEFROMCHAR32:
1368 case EM_SETTABSTOPS32:
1369 case EM_SETPASSWORDCHAR32:
1370 case EM_EMPTYUNDOBUFFER32:
1371 case EM_GETFIRSTVISIBLELINE32:
1372 case EM_SETREADONLY32:
1373 case EM_SETWORDBREAKPROC32:
1374 case EM_GETWORDBREAKPROC32:
1375 case EM_GETPASSWORDCHAR32:
1376 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL32);
1377 return 0;
1379 case LB_CARETOFF32:
1380 case LB_CARETON32:
1381 case LB_DELETESTRING32:
1382 case LB_GETANCHORINDEX32:
1383 case LB_GETCARETINDEX32:
1384 case LB_GETCOUNT32:
1385 case LB_GETCURSEL32:
1386 case LB_GETHORIZONTALEXTENT32:
1387 case LB_GETITEMDATA32:
1388 case LB_GETITEMHEIGHT32:
1389 case LB_GETSEL32:
1390 case LB_GETSELCOUNT32:
1391 case LB_GETTEXTLEN32:
1392 case LB_GETTOPINDEX32:
1393 case LB_RESETCONTENT32:
1394 case LB_SELITEMRANGE32:
1395 case LB_SELITEMRANGEEX32:
1396 case LB_SETANCHORINDEX32:
1397 case LB_SETCARETINDEX32:
1398 case LB_SETCOLUMNWIDTH32:
1399 case LB_SETCURSEL32:
1400 case LB_SETHORIZONTALEXTENT32:
1401 case LB_SETITEMDATA32:
1402 case LB_SETITEMHEIGHT32:
1403 case LB_SETSEL32:
1404 case LB_SETTOPINDEX32:
1405 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1406 return 0;
1407 case CB_DELETESTRING32:
1408 case CB_GETCOUNT32:
1409 case CB_GETLBTEXTLEN32:
1410 case CB_LIMITTEXT32:
1411 case CB_RESETCONTENT32:
1412 case CB_SETEDITSEL32:
1413 case CB_GETCURSEL32:
1414 case CB_SETCURSEL32:
1415 case CB_SHOWDROPDOWN32:
1416 case CB_SETITEMDATA32:
1417 case CB_SETITEMHEIGHT32:
1418 case CB_GETITEMHEIGHT32:
1419 case CB_SETEXTENDEDUI32:
1420 case CB_GETEXTENDEDUI32:
1421 case CB_GETDROPPEDSTATE32:
1422 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1423 return 0;
1424 case CB_GETEDITSEL32:
1425 *pmsg16 = CB_GETEDITSEL16;
1426 return 1;
1428 case LB_ADDSTRING32:
1429 case LB_FINDSTRING32:
1430 case LB_FINDSTRINGEXACT32:
1431 case LB_INSERTSTRING32:
1432 case LB_SELECTSTRING32:
1433 case LB_DIR32:
1434 case LB_ADDFILE32:
1436 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1437 if (!str) return -1;
1438 *plparam = (LPARAM)SEGPTR_GET(str);
1440 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1441 return 1;
1443 case CB_ADDSTRING32:
1444 case CB_FINDSTRING32:
1445 case CB_FINDSTRINGEXACT32:
1446 case CB_INSERTSTRING32:
1447 case CB_SELECTSTRING32:
1448 case CB_DIR32:
1450 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1451 if (!str) return -1;
1452 *plparam = (LPARAM)SEGPTR_GET(str);
1454 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL32);
1455 return 1;
1457 case LB_GETITEMRECT32:
1459 RECT16 *rect;
1460 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1461 if (!rect) return -1;
1462 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1463 *plparam = (LPARAM)SEGPTR_GET(rect);
1465 *pmsg16 = LB_GETITEMRECT16;
1466 return 1;
1467 case LB_GETSELITEMS32:
1469 LPINT16 items;
1470 *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1471 if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1472 + sizeof(LPARAM)))) return -1;
1473 *((LPARAM *)items)++ = *plparam; /* Store the previous lParam */
1474 *plparam = (LPARAM)SEGPTR_GET(items);
1476 *pmsg16 = LB_GETSELITEMS16;
1477 return 1;
1478 case LB_SETTABSTOPS32:
1479 if (wParam32)
1481 INT32 i;
1482 LPINT16 stops;
1483 *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
1484 if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1485 + sizeof(LPARAM)))) return -1;
1486 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i);
1487 *plparam = (LPARAM)SEGPTR_GET(stops);
1488 return 1;
1490 *pmsg16 = LB_SETTABSTOPS16;
1491 return 0;
1493 case CB_GETDROPPEDCONTROLRECT32:
1495 RECT16 *rect;
1496 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1497 if (!rect) return -1;
1498 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1499 *plparam = (LPARAM)SEGPTR_GET(rect);
1501 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1502 return 1;
1504 case LB_GETTEXT32:
1505 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1506 *pmsg16 = LB_GETTEXT16;
1507 return 1;
1509 case CB_GETLBTEXT32:
1510 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1511 *pmsg16 = CB_GETLBTEXT16;
1512 return 1;
1514 case EM_SETSEL32:
1515 *pwparam16 = 0;
1516 *plparam = MAKELONG( (INT16)(INT32)wParam32, (INT16)*plparam );
1517 *pmsg16 = EM_SETSEL16;
1518 return 0;
1520 case WM_ACTIVATE:
1521 case WM_CHARTOITEM:
1522 case WM_COMMAND:
1523 case WM_VKEYTOITEM:
1524 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1525 return 0;
1526 case WM_HSCROLL:
1527 case WM_VSCROLL:
1528 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1529 return 0;
1530 case WM_CTLCOLORMSGBOX:
1531 case WM_CTLCOLOREDIT:
1532 case WM_CTLCOLORLISTBOX:
1533 case WM_CTLCOLORBTN:
1534 case WM_CTLCOLORDLG:
1535 case WM_CTLCOLORSCROLLBAR:
1536 case WM_CTLCOLORSTATIC:
1537 *pmsg16 = WM_CTLCOLOR;
1538 *plparam = MAKELPARAM( (HWND16)*plparam,
1539 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1540 return 0;
1541 case WM_COMPAREITEM:
1543 COMPAREITEMSTRUCT32 *cis32 = (COMPAREITEMSTRUCT32 *)*plparam;
1544 COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1545 if (!cis) return -1;
1546 cis->CtlType = (UINT16)cis32->CtlType;
1547 cis->CtlID = (UINT16)cis32->CtlID;
1548 cis->hwndItem = (HWND16)cis32->hwndItem;
1549 cis->itemID1 = (UINT16)cis32->itemID1;
1550 cis->itemData1 = cis32->itemData1;
1551 cis->itemID2 = (UINT16)cis32->itemID2;
1552 cis->itemData2 = cis32->itemData2;
1553 *plparam = (LPARAM)SEGPTR_GET(cis);
1555 return 1;
1556 case WM_DELETEITEM:
1558 DELETEITEMSTRUCT32 *dis32 = (DELETEITEMSTRUCT32 *)*plparam;
1559 DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1560 if (!dis) return -1;
1561 dis->CtlType = (UINT16)dis32->CtlType;
1562 dis->CtlID = (UINT16)dis32->CtlID;
1563 dis->itemID = (UINT16)dis32->itemID;
1564 dis->hwndItem = (HWND16)dis32->hwndItem;
1565 dis->itemData = dis32->itemData;
1566 *plparam = (LPARAM)SEGPTR_GET(dis);
1568 return 1;
1569 case WM_DRAWITEM:
1571 DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
1572 DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1573 if (!dis) return -1;
1574 dis->CtlType = (UINT16)dis32->CtlType;
1575 dis->CtlID = (UINT16)dis32->CtlID;
1576 dis->itemID = (UINT16)dis32->itemID;
1577 dis->itemAction = (UINT16)dis32->itemAction;
1578 dis->itemState = (UINT16)dis32->itemState;
1579 dis->hwndItem = (HWND16)dis32->hwndItem;
1580 dis->hDC = (HDC16)dis32->hDC;
1581 dis->itemData = dis32->itemData;
1582 CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1583 *plparam = (LPARAM)SEGPTR_GET(dis);
1585 return 1;
1586 case WM_MEASUREITEM:
1588 MEASUREITEMSTRUCT32 *mis32 = (MEASUREITEMSTRUCT32 *)*plparam;
1589 MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1590 SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1591 if (!mis) return -1;
1592 mis->CtlType = (UINT16)mis32->CtlType;
1593 mis->CtlID = (UINT16)mis32->CtlID;
1594 mis->itemID = (UINT16)mis32->itemID;
1595 mis->itemWidth = (UINT16)mis32->itemWidth;
1596 mis->itemHeight = (UINT16)mis32->itemHeight;
1597 mis->itemData = mis32->itemData;
1598 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1599 *plparam = (LPARAM)SEGPTR_GET(mis);
1601 return 1;
1602 case WM_GETMINMAXINFO:
1604 MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1605 sizeof(LPARAM) );
1606 if (!mmi) return -1;
1607 STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
1608 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1609 *plparam = (LPARAM)SEGPTR_GET(mmi);
1611 return 1;
1612 case WM_GETTEXT:
1614 LPSTR str;
1615 *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
1616 if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1617 *((LPARAM *)str)++ = *plparam; /* Store the previous lParam */
1618 *plparam = (LPARAM)SEGPTR_GET(str);
1620 return 1;
1621 case WM_MDICREATE:
1623 MDICREATESTRUCT16 *cs;
1624 MDICREATESTRUCT32A *cs32 = (MDICREATESTRUCT32A *)*plparam;
1625 LPSTR name, cls;
1627 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1628 STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1629 name = SEGPTR_STRDUP( cs32->szTitle );
1630 cls = SEGPTR_STRDUP( cs32->szClass );
1631 cs->szTitle = SEGPTR_GET(name);
1632 cs->szClass = SEGPTR_GET(cls);
1633 *plparam = (LPARAM)SEGPTR_GET(cs);
1635 return 1;
1636 case WM_MDIGETACTIVE:
1637 return 1;
1638 case WM_MDISETMENU:
1639 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1640 (HMENU16)LOWORD(*plparam) );
1641 *pwparam16 = (*plparam == 0);
1642 return 0;
1643 case WM_MENUCHAR:
1644 case WM_MENUSELECT:
1645 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1646 return 0;
1647 case WM_MDIACTIVATE:
1648 if( WIDGETS_IsControl32(WIN_FindWndPtr(hwnd), BIC32_MDICLIENT) )
1650 *pwparam16 = (HWND32)wParam32;
1651 *plparam = 0;
1653 else
1655 *pwparam16 = ((HWND32)*plparam == hwnd);
1656 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1657 (HWND16)LOWORD(wParam32) );
1659 return 0;
1660 case WM_NCCALCSIZE:
1662 NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
1663 NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1664 if (!nc) return -1;
1666 CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1667 if (wParam32)
1669 WINDOWPOS16 *wp;
1670 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1671 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1672 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1674 SEGPTR_FREE(nc);
1675 return -1;
1677 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1678 nc->lppos = SEGPTR_GET(wp);
1680 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1681 *plparam = (LPARAM)SEGPTR_GET(nc);
1683 return 1;
1684 case WM_NCCREATE:
1685 case WM_CREATE:
1687 CREATESTRUCT16 *cs;
1688 CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
1689 LPSTR name, cls;
1691 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1692 STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1693 name = SEGPTR_STRDUP( cs32->lpszName );
1694 cls = SEGPTR_STRDUP( cs32->lpszClass );
1695 cs->lpszName = SEGPTR_GET(name);
1696 cs->lpszClass = SEGPTR_GET(cls);
1697 *plparam = (LPARAM)SEGPTR_GET(cs);
1699 return 1;
1700 case WM_PARENTNOTIFY:
1701 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1702 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1703 /* else nothing to do */
1704 return 0;
1705 case WM_NOTIFY:
1706 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1707 return 1;
1708 case WM_SETTEXT:
1710 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1711 if (!str) return -1;
1712 *plparam = (LPARAM)SEGPTR_GET(str);
1714 return 1;
1715 case WM_WINDOWPOSCHANGING:
1716 case WM_WINDOWPOSCHANGED:
1718 WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1719 sizeof(LPARAM) );
1720 if (!wp) return -1;
1721 STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
1722 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1723 *plparam = (LPARAM)SEGPTR_GET(wp);
1725 return 1;
1726 case WM_GETDLGCODE:
1727 if (*plparam) {
1728 LPMSG32 msg32 = (LPMSG32) *plparam;
1729 LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
1731 if (!msg16) return -1;
1732 msg16->hwnd = msg32->hwnd;
1733 msg16->lParam = msg32->lParam;
1734 msg16->time = msg32->time;
1735 CONV_POINT32TO16(&msg32->pt,&msg16->pt);
1736 /* this is right, right? */
1737 if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
1738 &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
1739 SEGPTR_FREE( msg16 );
1740 return -1;
1742 *plparam = (LPARAM)SEGPTR_GET(msg16);
1743 return 1;
1745 return 0;
1747 case WM_ASKCBFORMATNAME:
1748 case WM_DEVMODECHANGE:
1749 case WM_PAINTCLIPBOARD:
1750 case WM_SIZECLIPBOARD:
1751 case WM_WININICHANGE:
1752 FIXME( msg, "message %04x needs translation\n", msg32 );
1753 return -1;
1754 default: /* No translation needed */
1755 return 0;
1760 /**********************************************************************
1761 * WINPROC_UnmapMsg32ATo16
1763 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1765 void WINPROC_UnmapMsg32ATo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
1766 MSGPARAM16* p16 )
1768 switch(msg)
1770 case LB_ADDFILE32:
1771 case LB_ADDSTRING32:
1772 case LB_DIR32:
1773 case LB_FINDSTRING32:
1774 case LB_FINDSTRINGEXACT32:
1775 case LB_INSERTSTRING32:
1776 case LB_SELECTSTRING32:
1777 case LB_SETTABSTOPS32:
1778 case CB_ADDSTRING32:
1779 case CB_FINDSTRING32:
1780 case CB_FINDSTRINGEXACT32:
1781 case CB_INSERTSTRING32:
1782 case CB_SELECTSTRING32:
1783 case CB_DIR32:
1784 case WM_COMPAREITEM:
1785 case WM_DELETEITEM:
1786 case WM_DRAWITEM:
1787 case WM_SETTEXT:
1788 SEGPTR_FREE( PTR_SEG_TO_LIN(p16->lParam) );
1789 break;
1791 case CB_GETDROPPEDCONTROLRECT32:
1792 case LB_GETITEMRECT32:
1794 RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(p16->lParam);
1795 p16->lParam = *(LPARAM *)(rect + 1);
1796 CONV_RECT16TO32( rect, (RECT32 *)(p16->lParam));
1797 SEGPTR_FREE( rect );
1799 break;
1800 case LB_GETSELITEMS32:
1802 INT32 i;
1803 LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam);
1804 p16->lParam = *((LPARAM *)items - 1);
1805 for (i = 0; i < p16->wParam; i++) *((LPINT32)(p16->lParam) + i) = items[i];
1806 SEGPTR_FREE( (LPARAM *)items - 1 );
1808 break;
1810 case CB_GETEDITSEL32:
1811 if( wParam )
1812 *((LPUINT32)(wParam)) = LOWORD(p16->lResult);
1813 if( lParam )
1814 *((LPUINT32)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
1815 break;
1817 case LB_GETTEXT32:
1818 case CB_GETLBTEXT32:
1819 UnMapLS( (SEGPTR)(p16->lParam) );
1820 break;
1822 case WM_MEASUREITEM:
1824 MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1825 MEASUREITEMSTRUCT32 *mis32 = *(MEASUREITEMSTRUCT32 **)(mis + 1);
1826 mis32->itemWidth = mis->itemWidth;
1827 mis32->itemHeight = mis->itemHeight;
1828 SEGPTR_FREE(mis);
1830 break;
1831 case WM_GETMINMAXINFO:
1833 MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(p16->lParam);
1834 p16->lParam = *(LPARAM *)(mmi + 1);
1835 STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)(p16->lParam) );
1836 SEGPTR_FREE(mmi);
1838 break;
1839 case WM_GETTEXT:
1841 LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
1842 p16->lParam = *((LPARAM *)str - 1);
1843 lstrcpyn32A( (LPSTR)(p16->lParam), str, p16->wParam );
1844 SEGPTR_FREE( (LPARAM *)str - 1 );
1846 break;
1847 case WM_MDICREATE:
1849 MDICREATESTRUCT16 *cs = (MDICREATESTRUCT16*)PTR_SEG_TO_LIN(p16->lParam);
1850 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szTitle) );
1851 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szClass) );
1852 SEGPTR_FREE( cs );
1854 break;
1855 case WM_MDIGETACTIVE:
1856 if (lParam) *(BOOL32 *)lParam = (BOOL16)HIWORD(p16->lResult);
1857 p16->lResult = (HWND32)LOWORD(p16->lResult);
1858 break;
1859 case WM_NCCALCSIZE:
1861 NCCALCSIZE_PARAMS32 *nc32;
1862 NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(p16->lParam);
1863 p16->lParam = *(LPARAM *)(nc + 1);
1864 nc32 = (NCCALCSIZE_PARAMS32 *)(p16->lParam);
1865 CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
1866 if (p16->wParam)
1868 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
1869 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
1870 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
1871 nc32->lppos );
1872 SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
1874 SEGPTR_FREE(nc);
1876 break;
1877 case WM_NCCREATE:
1878 case WM_CREATE:
1880 CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(p16->lParam);
1881 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
1882 SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
1883 SEGPTR_FREE( cs );
1885 break;
1886 case WM_WINDOWPOSCHANGING:
1887 case WM_WINDOWPOSCHANGED:
1889 WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(p16->lParam);
1890 p16->lParam = *(LPARAM *)(wp + 1);
1891 STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)p16->lParam );
1892 SEGPTR_FREE(wp);
1894 break;
1895 case WM_NOTIFY:
1896 UnMapLS(p16->lParam);
1897 break;
1898 case WM_GETDLGCODE:
1899 if (p16->lParam)
1901 LPMSG16 msg16 = (LPMSG16)PTR_SEG_TO_LIN(p16->lParam);
1902 MSGPARAM16 msgp16;
1903 msgp16.wParam=msg16->wParam;
1904 msgp16.lParam=msg16->lParam;
1905 WINPROC_UnmapMsg32ATo16(((LPMSG32)lParam)->hwnd, ((LPMSG32)lParam)->message,
1906 ((LPMSG32)lParam)->wParam, ((LPMSG32)lParam)->lParam,
1907 &msgp16 );
1908 SEGPTR_FREE(msg16);
1910 break;
1915 /**********************************************************************
1916 * WINPROC_MapMsg32WTo16
1918 * Map a message from 32-bit Unicode to 16-bit.
1919 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1921 INT32 WINPROC_MapMsg32WTo16( HWND32 hwnd, UINT32 msg32, WPARAM32 wParam32,
1922 UINT16 *pmsg16, WPARAM16 *pwparam16,
1923 LPARAM *plparam )
1925 switch(msg32)
1927 case LB_ADDSTRING32:
1928 case LB_FINDSTRING32:
1929 case LB_FINDSTRINGEXACT32:
1930 case LB_INSERTSTRING32:
1931 case LB_SELECTSTRING32:
1932 case LB_DIR32:
1933 case LB_ADDFILE32:
1935 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1936 if (!str) return -1;
1937 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1938 *plparam = (LPARAM)SEGPTR_GET(str);
1940 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
1941 return 1;
1943 case CB_ADDSTRING32:
1944 case CB_FINDSTRING32:
1945 case CB_FINDSTRINGEXACT32:
1946 case CB_INSERTSTRING32:
1947 case CB_SELECTSTRING32:
1948 case CB_DIR32:
1950 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1951 if (!str) return -1;
1952 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1953 *plparam = (LPARAM)SEGPTR_GET(str);
1955 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING32);
1956 return 1;
1958 case WM_NCCREATE:
1959 case WM_CREATE:
1961 CREATESTRUCT16 *cs;
1962 CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
1963 LPSTR name, cls;
1965 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1966 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
1967 name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
1968 cls = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
1969 cs->lpszName = SEGPTR_GET(name);
1970 cs->lpszClass = SEGPTR_GET(cls);
1971 *pmsg16 = (UINT16)msg32;
1972 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1973 *plparam = (LPARAM)SEGPTR_GET(cs);
1975 return 1;
1976 case WM_MDICREATE:
1978 MDICREATESTRUCT16 *cs;
1979 MDICREATESTRUCT32W *cs32 = (MDICREATESTRUCT32W *)*plparam;
1980 LPSTR name, cls;
1982 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1983 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs32, cs );
1984 name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
1985 cls = SEGPTR_STRDUP_WtoA( cs32->szClass );
1986 cs->szTitle = SEGPTR_GET(name);
1987 cs->szClass = SEGPTR_GET(cls);
1988 *pmsg16 = (UINT16)msg32;
1989 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1990 *plparam = (LPARAM)SEGPTR_GET(cs);
1992 return 1;
1993 case WM_SETTEXT:
1995 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
1996 if (!str) return -1;
1997 *pmsg16 = (UINT16)msg32;
1998 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1999 *plparam = (LPARAM)SEGPTR_GET(str);
2001 return 1;
2002 default: /* No Unicode translation needed */
2003 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2004 pwparam16, plparam );
2009 /**********************************************************************
2010 * WINPROC_UnmapMsg32WTo16
2012 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2014 void WINPROC_UnmapMsg32WTo16( HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam,
2015 MSGPARAM16* p16 )
2017 switch(msg)
2019 case WM_GETTEXT:
2021 LPSTR str = (LPSTR)PTR_SEG_TO_LIN(p16->lParam);
2022 p16->lParam = *((LPARAM *)str - 1);
2023 lstrcpyAtoW( (LPWSTR)(p16->lParam), str );
2024 SEGPTR_FREE( (LPARAM *)str - 1 );
2026 break;
2027 default:
2028 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2029 break;
2034 /**********************************************************************
2035 * WINPROC_CallProc32ATo32W
2037 * Call a window procedure, translating args from Ansi to Unicode.
2039 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
2040 UINT32 msg, WPARAM32 wParam,
2041 LPARAM lParam )
2043 LRESULT result;
2045 if (WINPROC_MapMsg32ATo32W( hwnd, msg, wParam, &lParam ) == -1) return 0;
2046 result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2047 WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam );
2048 return result;
2052 /**********************************************************************
2053 * WINPROC_CallProc32WTo32A
2055 * Call a window procedure, translating args from Unicode to Ansi.
2057 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
2058 UINT32 msg, WPARAM32 wParam,
2059 LPARAM lParam )
2061 LRESULT result;
2063 if (WINPROC_MapMsg32WTo32A( hwnd, msg, wParam, &lParam ) == -1) return 0;
2064 result = WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2065 WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2066 return result;
2070 /**********************************************************************
2071 * WINPROC_CallProc16To32A
2073 * Call a 32-bit window procedure, translating the 16-bit args.
2075 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
2076 WPARAM16 wParam, LPARAM lParam,
2077 WNDPROC32 func )
2079 LRESULT result;
2080 UINT32 msg32;
2081 WPARAM32 wParam32;
2083 if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2084 return 0;
2085 result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2086 return WINPROC_UnmapMsg16To32A( hwnd, msg32, wParam32, lParam, result );
2090 /**********************************************************************
2091 * WINPROC_CallProc16To32W
2093 * Call a 32-bit window procedure, translating the 16-bit args.
2095 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
2096 WPARAM16 wParam, LPARAM lParam,
2097 WNDPROC32 func )
2099 LRESULT result;
2100 UINT32 msg32;
2101 WPARAM32 wParam32;
2103 if (WINPROC_MapMsg16To32W( hwnd, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2104 return 0;
2105 result = WINPROC_CallWndProc32( func, hwnd, msg32, wParam32, lParam );
2106 return WINPROC_UnmapMsg16To32W( hwnd, msg32, wParam32, lParam, result );
2110 /**********************************************************************
2111 * WINPROC_CallProc32ATo16
2113 * Call a 16-bit window procedure, translating the 32-bit args.
2115 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
2116 UINT32 msg, WPARAM32 wParam,
2117 LPARAM lParam )
2119 UINT16 msg16;
2120 MSGPARAM16 mp16;
2122 mp16.lParam = lParam;
2123 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam,
2124 &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2125 return 0;
2126 mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2127 mp16.wParam, mp16.lParam );
2128 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2129 return mp16.lResult;
2133 /**********************************************************************
2134 * WINPROC_CallProc32WTo16
2136 * Call a 16-bit window procedure, translating the 32-bit args.
2138 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
2139 UINT32 msg, WPARAM32 wParam,
2140 LPARAM lParam )
2142 UINT16 msg16;
2143 MSGPARAM16 mp16;
2145 mp16.lParam = lParam;
2146 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2147 &mp16.lParam ) == -1)
2148 return 0;
2149 mp16.lResult = Callbacks->CallWndProc( func, hwnd, msg16,
2150 mp16.wParam, mp16.lParam );
2151 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2152 return mp16.lResult;
2156 /**********************************************************************
2157 * CallWindowProc16 (USER.122)
2159 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2160 WPARAM16 wParam, LPARAM lParam )
2162 WINDOWPROC *proc = WINPROC_GetPtr( func );
2164 if (!proc)
2165 return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2167 #if testing
2168 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2169 return Callbacks->CallWndProc( func, hwnd, msg, wParam, lParam );
2170 #endif
2172 switch(proc->type)
2174 case WIN_PROC_16:
2175 if (!proc->thunk.t_from32.proc) return 0;
2176 return Callbacks->CallWndProc( proc->thunk.t_from32.proc,
2177 hwnd, msg, wParam, lParam );
2178 case WIN_PROC_32A:
2179 if (!proc->thunk.t_from16.proc) return 0;
2180 return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
2181 proc->thunk.t_from16.proc );
2182 case WIN_PROC_32W:
2183 if (!proc->thunk.t_from16.proc) return 0;
2184 return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
2185 proc->thunk.t_from16.proc );
2186 default:
2187 WARN( relay, "Invalid proc %p\n", proc );
2188 return 0;
2193 /**********************************************************************
2194 * CallWindowProc32A (USER32.18)
2196 * The CallWindowProc() function invokes the windows procedure _func_,
2197 * with _hwnd_ as the target window, the message specified by _msg_, and
2198 * the message parameters _wParam_ and _lParam_.
2200 * Some kinds of argument conversion may be done, I'm not sure what.
2202 * CallWindowProc() may be used for windows subclassing. Use
2203 * SetWindowLong() to set a new windows procedure for windows of the
2204 * subclass, and handle subclassed messages in the new windows
2205 * procedure. The new windows procedure may then use CallWindowProc()
2206 * with _func_ set to the parent class's windows procedure to dispatch
2207 * the message to the superclass.
2209 * RETURNS
2211 * The return value is message dependent.
2213 * CONFORMANCE
2215 * ECMA-234, Win32
2217 LRESULT WINAPI CallWindowProc32A(
2218 WNDPROC32 func, /* window procedure */
2219 HWND32 hwnd, /* target window */
2220 UINT32 msg, /* message */
2221 WPARAM32 wParam, /* message dependent parameter */
2222 LPARAM lParam /* message dependent parameter */
2224 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2226 if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2228 #if testing
2229 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2230 return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2231 #endif
2233 switch(proc->type)
2235 case WIN_PROC_16:
2236 if (!proc->thunk.t_from32.proc) return 0;
2237 return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2238 hwnd, msg, wParam, lParam );
2239 case WIN_PROC_32A:
2240 if (!proc->thunk.t_from16.proc) return 0;
2241 return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2242 hwnd, msg, wParam, lParam );
2243 case WIN_PROC_32W:
2244 if (!proc->thunk.t_from16.proc) return 0;
2245 return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2246 hwnd, msg, wParam, lParam );
2247 default:
2248 WARN( relay, "Invalid proc %p\n", proc );
2249 return 0;
2254 /**********************************************************************
2255 * CallWindowProc32W (USER32.19)
2257 LRESULT WINAPI CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
2258 WPARAM32 wParam, LPARAM lParam )
2260 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2262 if (!proc) return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2264 #if testing
2265 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2266 return WINPROC_CallWndProc32( func, hwnd, msg, wParam, lParam );
2267 #endif
2269 switch(proc->type)
2271 case WIN_PROC_16:
2272 if (!proc->thunk.t_from32.proc) return 0;
2273 return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2274 hwnd, msg, wParam, lParam );
2275 case WIN_PROC_32A:
2276 if (!proc->thunk.t_from16.proc) return 0;
2277 return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2278 hwnd, msg, wParam, lParam );
2279 case WIN_PROC_32W:
2280 if (!proc->thunk.t_from16.proc) return 0;
2281 return WINPROC_CallWndProc32( proc->thunk.t_from16.proc,
2282 hwnd, msg, wParam, lParam );
2283 default:
2284 WARN( relay, "Invalid proc %p\n", proc );
2285 return 0;