Release 960805
[wine] / windows / winproc.c
1 /*
2  * Window procedure callbacks
3  *
4  * Copyright 1995 Martin von Loewis
5  * Copyright 1996 Alexandre Julliard
6  */
7
8 #include <stdio.h>
9 #include "windows.h"
10 #include "callback.h"
11 #include "heap.h"
12 #include "ldt.h"
13 #include "registers.h"
14 #include "stackframe.h"
15 #include "string32.h"
16 #include "struct32.h"
17 #include "win.h"
18 #include "winproc.h"
19 #include "stddebug.h"
20 #include "debug.h"
21
22 /* Window procedure 16-bit thunk; see BuildSpec16Files() in tools/build.c */
23 typedef struct
24 {
25     BYTE       popl_eax;             /* popl  %eax (return address) */
26     BYTE       pushl_func;           /* pushl $proc */
27     WNDPROC32  proc WINE_PACKED;
28     BYTE       pushl_eax;            /* pushl %eax */
29     WORD       pushw_bp WINE_PACKED; /* pushw %bp */
30     BYTE       pushl_thunk;          /* pushl $thunkfrom16 */
31     void     (*thunk32)() WINE_PACKED;
32     BYTE       lcall;                /* lcall cs:relay */
33     void     (*relay)() WINE_PACKED;
34     WORD       cs WINE_PACKED;
35 } WINPROC_THUNK_FROM16;
36
37 /* Window procedure 32-bit thunk; see BuildSpec32Files() in tools/build.c */
38 typedef struct
39 {
40     BYTE       popl_eax;             /* popl  %eax (return address) */
41     BYTE       pushl_func;           /* pushl $proc */
42     WNDPROC16  proc WINE_PACKED;
43     BYTE       pushl_eax;            /* pushl %eax */
44     BYTE       pushl_ebp;            /* pushl %ebp */
45     BYTE       pushl_name;           /* pushl $name */
46     LPCSTR     name WINE_PACKED;
47     BYTE       pushl_thunk;          /* pushl $thunkfrom32 */
48     void     (*thunk32)() WINE_PACKED;
49     BYTE       jmp;                  /* jmp   relay (relative jump)*/
50     void     (*relay)() WINE_PACKED;
51 } WINPROC_THUNK_FROM32;
52
53 /* Simple jmp to call 32-bit procedure directly */
54 typedef struct
55 {
56     BYTE       jmp;                  /* jmp  proc (relative jump) */
57     WNDPROC32  proc WINE_PACKED;
58 } WINPROC_JUMP;
59
60 typedef union
61 {
62     WINPROC_THUNK_FROM16  t_from16;
63     WINPROC_THUNK_FROM32  t_from32;
64 } WINPROC_THUNK;
65
66 typedef struct tagWINDOWPROC
67 {
68     WINPROC_THUNK         thunk;    /* Thunk */
69     WINPROC_JUMP          jmp;      /* Jump */
70     struct tagWINDOWPROC *next;     /* Next window proc */
71     UINT32                magic;    /* Magic number */
72     WINDOWPROCTYPE        type;     /* Function type */
73 } WINDOWPROC;
74
75 #define WINPROC_MAGIC  ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
76
77 #define WINPROC_THUNKPROC(pproc) \
78     (((pproc)->type == WIN_PROC_16) ? \
79           (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
80           (WNDPROC16)((pproc)->thunk.t_from16.proc))
81
82 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
83                                  WPARAM16 wParam, LPARAM lParam,
84                                  WNDPROC32 func );
85 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
86                                  WPARAM16 wParam, LPARAM lParam,
87                                  WNDPROC32 func );
88 static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
89                                         UINT32 msg, WPARAM32 wParam,
90                                         LPARAM lParam );
91 static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
92                                         UINT32 msg, WPARAM32 wParam,
93                                         LPARAM lParam );
94
95 #ifndef WINELIB
96 extern void CallFrom16_long_wwwll(void);
97 extern void CallFrom32_stdcall_5(void);
98 #else
99 static void CallFrom16_long_wwwll(void) {}
100 static void CallFrom32_stdcall_5(void) {}
101 #endif  /* WINELIB */
102
103 static HANDLE32 WinProcHeap;
104
105 /**********************************************************************
106  *           WINPROC_Init
107  */
108 BOOL32 WINPROC_Init(void)
109 {
110     WinProcHeap = HeapCreate( HEAP_WINE_SEGPTR | HEAP_WINE_CODESEG, 0, 0 );
111     if (!WinProcHeap)
112     {
113         fprintf( stderr, "Unable to create winproc heap\n" );
114         return FALSE;
115     }
116     return TRUE;
117 }
118
119
120 /**********************************************************************
121  *           WINPROC_GetPtr
122  *
123  * Return a pointer to the win proc.
124  */
125 static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
126 {
127     BYTE *ptr;
128     WINDOWPROC *proc;
129
130     /* Check for a linear pointer */
131
132     if (HEAP_IsInsideHeap( WinProcHeap, 0, (LPVOID)handle ))
133     {
134         ptr = (BYTE *)handle;
135         /* First check if it is the jmp address */
136         if (*ptr == 0xe9 /* jmp */) ptr -= (int)&((WINDOWPROC *)0)->jmp -
137                                            (int)&((WINDOWPROC *)0)->thunk;
138         /* Now it must be the thunk address */
139         if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
140         /* Now we have a pointer to the WINDOWPROC struct */
141         if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
142             return (WINDOWPROC *)ptr;
143     }
144
145     /* Check for a segmented pointer */
146
147     if (!IsBadReadPtr( (SEGPTR)handle, sizeof(WINDOWPROC)-sizeof(proc->thunk)))
148     {
149         ptr = (BYTE *)PTR_SEG_TO_LIN(handle);
150         /* It must be the thunk address */
151         if (*ptr == 0x58 /* popl eax */) ptr -= (int)&((WINDOWPROC *)0)->thunk;
152         /* Now we have a pointer to the WINDOWPROC struct */
153         if (((WINDOWPROC *)ptr)->magic == WINPROC_MAGIC)
154             return (WINDOWPROC *)ptr;
155     }
156
157     return NULL;
158 }
159
160
161 /**********************************************************************
162  *           WINPROC_AllocWinProc
163  *
164  * Allocate a new window procedure.
165  */
166 static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type )
167 {
168     WINDOWPROC *proc, *oldproc;
169
170     /* Allocate a window procedure */
171
172     if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
173
174     /* Check if the function is already a win proc */
175
176     if ((oldproc = WINPROC_GetPtr( func )))
177     {
178         *proc = *oldproc;
179     }
180     else
181     {
182         switch(type)
183         {
184         case WIN_PROC_16:
185             proc->thunk.t_from32.popl_eax    = 0x58;   /* popl  %eax */
186             proc->thunk.t_from32.pushl_func  = 0x68;   /* pushl $proc */
187             proc->thunk.t_from32.proc        = func;
188             proc->thunk.t_from32.pushl_eax   = 0x50;   /* pushl %eax */
189             proc->thunk.t_from32.pushl_ebp   = 0x55;   /* pushl %ebp */
190             proc->thunk.t_from32.pushl_name  = 0x68;   /* pushl $name */
191             proc->thunk.t_from32.name        = "WINPROC_CallProc32ATo16";
192             proc->thunk.t_from32.pushl_thunk = 0x68;   /* pushl $thunkfrom32 */
193             proc->thunk.t_from32.thunk32     = (void(*)())WINPROC_CallProc32ATo16;
194             proc->thunk.t_from32.jmp         = 0xe9;   /* jmp   relay*/
195             proc->thunk.t_from32.relay =  /* relative jump */
196                 (void (*)())((DWORD)CallFrom32_stdcall_5 -
197                                      (DWORD)(&proc->thunk.t_from32.relay + 1));
198             break;
199         case WIN_PROC_32A:
200         case WIN_PROC_32W:
201             proc->thunk.t_from16.popl_eax    = 0x58;   /* popl  %eax */
202             proc->thunk.t_from16.pushl_func  = 0x68;   /* pushl $proc */
203             proc->thunk.t_from16.proc        = (FARPROC32)func;
204             proc->thunk.t_from16.pushl_eax   = 0x50;   /* pushl %eax */
205             proc->thunk.t_from16.pushw_bp    = 0x5566; /* pushw %bp */
206             proc->thunk.t_from16.pushl_thunk = 0x68;   /* pushl $thunkfrom16 */
207             proc->thunk.t_from16.thunk32     = (type == WIN_PROC_32A) ?
208                                            (void(*)())WINPROC_CallProc16To32A :
209                                            (void(*)())WINPROC_CallProc16To32W;
210             proc->thunk.t_from16.lcall       = 0x9a;   /* lcall cs:relay */
211             proc->thunk.t_from16.relay       = CallFrom16_long_wwwll;
212             proc->thunk.t_from16.cs          = WINE_CODE_SELECTOR;
213             proc->jmp.jmp  = 0xe9;
214             /* Fixup relative jump */
215             proc->jmp.proc = (WNDPROC32)((DWORD)func -
216                                                  (DWORD)(&proc->jmp.proc + 1));
217             break;
218         default:
219             /* Should not happen */
220             break;
221         }
222         proc->magic = WINPROC_MAGIC;
223         proc->type  = type;
224     }
225     proc->next  = NULL;
226     dprintf_win( stddeb, "WINPROC_AllocWinProc(%08x,%d): returning %08x\n",
227                  (UINT32)func, type, (UINT32)proc );
228     return proc;
229 }
230
231
232 /**********************************************************************
233  *           WINPROC_GetProc
234  *
235  * Get a window procedure pointer that can be passed to the Windows program.
236  */
237 WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
238 {
239     if (type == WIN_PROC_16)  /* We want a 16:16 address */
240     {
241         if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
242             return ((WINDOWPROC *)proc)->thunk.t_from32.proc;
243         else
244             return (WNDPROC16)HEAP_GetSegptr( WinProcHeap, 0,
245                                               &((WINDOWPROC *)proc)->thunk );
246     }
247     else  /* We want a 32-bit address */
248     {
249         if (((WINDOWPROC *)proc)->type == WIN_PROC_16)
250             return (WNDPROC16)&((WINDOWPROC *)proc)->thunk;
251         else
252             return (WNDPROC16)&((WINDOWPROC *)proc)->jmp;
253     }
254 }
255
256
257 /**********************************************************************
258  *           WINPROC_SetProc
259  *
260  * Set the window procedure for a window or class.
261  */
262 BOOL32 WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
263                         WINDOWPROCTYPE type )
264 {
265     WINDOWPROC *proc, **ppPrev;
266
267     /* Check if function is already in the list */
268
269     ppPrev = (WINDOWPROC **)pFirst;
270     proc = WINPROC_GetPtr( func );
271     while (*ppPrev)
272     {
273         if (proc)
274         {
275             if (*ppPrev == proc) break;
276         }
277         else
278         {
279             if (((*ppPrev)->type == type) &&
280                 (func == WINPROC_THUNKPROC(*ppPrev))) break;
281         }
282         ppPrev = &(*ppPrev)->next;
283     }
284
285     if (*ppPrev)  /* Remove it from the list */
286     {
287         proc = *ppPrev;
288         *ppPrev = proc->next;
289     }
290     else  /* Allocate a new one */
291     {
292         if (proc)  /* Was already a win proc */
293         {
294             type = proc->type;
295             func = WINPROC_THUNKPROC(proc);
296         }
297         proc = WINPROC_AllocWinProc( func, type );
298         if (!proc) return FALSE;
299     }
300
301     /* Add the win proc at the head of the list */
302
303     dprintf_win( stddeb, "WINPROC_SetProc(%08x,%08x,%d): res=%08x\n",
304                  (UINT32)*pFirst, (UINT32)func, type, (UINT32)proc );
305     proc->next  = *(WINDOWPROC **)pFirst;
306     *(WINDOWPROC **)pFirst = proc;
307     return TRUE;
308 }
309
310
311 /**********************************************************************
312  *           WINPROC_FreeProc
313  *
314  * Free a list of win procs.
315  */
316 void WINPROC_FreeProc( HWINDOWPROC proc )
317 {
318     while (proc)
319     {
320         WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
321         dprintf_win( stddeb, "WINPROC_FreeProc: freeing %08x\n", (UINT32)proc);
322         HeapFree( WinProcHeap, 0, proc );
323         proc = next;
324     }
325 }
326
327
328 /**********************************************************************
329  *           WINPROC_GetProcType
330  *
331  * Return the window procedure type.
332  */
333 WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
334 {
335     if (!proc ||
336         (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
337         return WIN_PROC_INVALID;
338     return ((WINDOWPROC *)proc)->type;
339 }
340
341
342 /**********************************************************************
343  *           WINPROC_MapMsg32ATo32W
344  *
345  * Map a message from Ansi to Unicode.
346  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
347  */
348 INT32 WINPROC_MapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
349 {
350     switch(msg)
351     {
352     case WM_GETTEXT:
353         {
354             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
355                                      wParam * sizeof(WCHAR) + sizeof(LPARAM) );
356             if (!ptr) return -1;
357             *ptr++ = *plparam;  /* Store previous lParam */
358             *plparam = (LPARAM)ptr;
359         }
360         return 1;
361     case WM_SETTEXT:
362         *plparam = (LPARAM)STRING32_DupAnsiToUni( (LPCSTR)*plparam );
363         return (*plparam ? 1 : -1);
364     case WM_NCCREATE:
365     case WM_CREATE:
366         {
367             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
368                                                                 sizeof(*cs) );
369             if (!cs) return -1;
370             *cs = *(CREATESTRUCT32W *)*plparam;
371             if (HIWORD(cs->lpszName))
372                 cs->lpszName = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszName );
373             if (HIWORD(cs->lpszClass))
374                 cs->lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszClass );
375             *plparam = (LPARAM)cs;
376         }
377         return 1;
378     case WM_MDICREATE:
379         {
380             MDICREATESTRUCT32W *cs =
381                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
382             if (!cs) return -1;
383             *cs = *(MDICREATESTRUCT32W *)*plparam;
384             if (HIWORD(cs->szClass))
385                 cs->szClass = STRING32_DupAnsiToUni( (LPCSTR)cs->szClass );
386             if (HIWORD(cs->szTitle))
387                 cs->szTitle = STRING32_DupAnsiToUni( (LPCSTR)cs->szTitle );
388             *plparam = (LPARAM)cs;
389         }
390         return 1;
391     case WM_ASKCBFORMATNAME:
392     case WM_COMPAREITEM:
393     case WM_DELETEITEM:
394     case WM_DEVMODECHANGE:
395     case WM_MDIACTIVATE:
396     case WM_MEASUREITEM:
397     case WM_PAINTCLIPBOARD:
398     case WM_SIZECLIPBOARD:
399     case WM_WININICHANGE:
400         fprintf( stderr, "MapMsg32ATo32W: message %04x needs translation\n",
401                  msg );
402         return -1;
403     default:  /* No translation needed */
404         return 0;
405     }
406 }
407
408
409 /**********************************************************************
410  *           WINPROC_UnmapMsg32ATo32W
411  *
412  * Unmap a message that was mapped from Ansi to Unicode.
413  */
414 void WINPROC_UnmapMsg32ATo32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
415 {
416     switch(msg)
417     {
418     case WM_GETTEXT:
419         {
420             LPARAM *ptr = (LPARAM *)lParam - 1;
421             lstrcpynWtoA( (LPSTR)*ptr, (LPWSTR)(ptr + 1), wParam );
422             HeapFree( SystemHeap, 0, ptr );
423         }
424         break;
425     case WM_SETTEXT:
426         free( (void *)lParam );
427         break;
428     case WM_NCCREATE:
429     case WM_CREATE:
430         {
431             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
432             if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
433             if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
434             HeapFree( SystemHeap, 0, cs );
435         }
436         break;
437     case WM_MDICREATE:
438         {
439             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
440             if (HIWORD(cs->szTitle)) free( (LPVOID)cs->szTitle );
441             if (HIWORD(cs->szClass)) free( (LPVOID)cs->szClass );
442             HeapFree( SystemHeap, 0, cs );
443         }
444         break;
445     }
446 }
447
448
449 /**********************************************************************
450  *           WINPROC_MapMsg32WTo32A
451  *
452  * Map a message from Unicode to Ansi.
453  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
454  */
455 INT32 WINPROC_MapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM *plparam )
456 {
457     switch(msg)
458     {
459     case WM_GETTEXT:
460         {
461             LPARAM *ptr = (LPARAM *)HeapAlloc( SystemHeap, 0,
462                                                wParam + sizeof(LPARAM) );
463             if (!ptr) return -1;
464             *ptr++ = *plparam;  /* Store previous lParam */
465             *plparam = (LPARAM)ptr;
466         }
467         return 1;
468     case WM_SETTEXT:
469         *plparam = (LPARAM)STRING32_DupUniToAnsi( (LPCWSTR)*plparam );
470         return (*plparam ? 1 : -1);
471     case WM_NCCREATE:
472     case WM_CREATE:
473         {
474             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
475                                                                 sizeof(*cs) );
476             if (!cs) return -1;
477             *cs = *(CREATESTRUCT32A *)*plparam;
478             if (HIWORD(cs->lpszName))
479                 cs->lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs->lpszName );
480             if (HIWORD(cs->lpszClass))
481                 cs->lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs->lpszClass);
482             *plparam = (LPARAM)cs;
483         }
484         return 1;
485     case WM_MDICREATE:
486         {
487             MDICREATESTRUCT32A *cs =
488                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0, sizeof(*cs) );
489             if (!cs) return -1;
490             *cs = *(MDICREATESTRUCT32A *)*plparam;
491             if (HIWORD(cs->szTitle))
492                 cs->szTitle = STRING32_DupUniToAnsi( (LPCWSTR)cs->szTitle );
493             if (HIWORD(cs->szClass))
494                 cs->szClass = STRING32_DupUniToAnsi( (LPCWSTR)cs->szClass );
495             *plparam = (LPARAM)cs;
496         }
497         return 1;
498     case WM_ASKCBFORMATNAME:
499     case WM_COMPAREITEM:
500     case WM_DELETEITEM:
501     case WM_DEVMODECHANGE:
502     case WM_MDIACTIVATE:
503     case WM_MEASUREITEM:
504     case WM_PAINTCLIPBOARD:
505     case WM_SIZECLIPBOARD:
506     case WM_WININICHANGE:
507         fprintf( stderr, "MapMsg32WTo32A: message %04x needs translation\n",
508                  msg );
509         return -1;
510     default:  /* No translation needed */
511         return 0;
512     }
513 }
514
515
516 /**********************************************************************
517  *           WINPROC_UnmapMsg32WTo32A
518  *
519  * Unmap a message that was mapped from Unicode to Ansi.
520  */
521 void WINPROC_UnmapMsg32WTo32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
522 {
523     switch(msg)
524     {
525     case WM_GETTEXT:
526         {
527             LPARAM *ptr = (LPARAM *)lParam - 1;
528             lstrcpynAtoW( (LPWSTR)*ptr, (LPSTR)(ptr + 1), wParam );
529             HeapFree( SystemHeap, 0, ptr );
530         }
531         break;
532     case WM_SETTEXT:
533         free( (void *)lParam );
534         break;
535     case WM_NCCREATE:
536     case WM_CREATE:
537         {
538             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
539             if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
540             if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
541             HeapFree( SystemHeap, 0, cs );
542         }
543         break;
544     case WM_MDICREATE:
545         {
546             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
547             if (HIWORD(cs->szTitle)) free( (LPVOID)cs->szTitle );
548             if (HIWORD(cs->szClass)) free( (LPVOID)cs->szClass );
549             HeapFree( SystemHeap, 0, cs );
550         }
551         break;
552     }
553 }
554
555
556 /**********************************************************************
557  *           WINPROC_MapMsg16To32A
558  *
559  * Map a message from 16- to 32-bit Ansi.
560  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
561  */
562 INT32 WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
563                              WPARAM32 *pwparam32, LPARAM *plparam )
564 {
565     *pmsg32 = (UINT32)msg16;
566     *pwparam32 = (WPARAM32)wParam16;
567     switch(msg16)
568     {
569     case WM_ACTIVATE:
570     case WM_CHARTOITEM:
571     case WM_COMMAND:
572     case WM_HSCROLL:
573     case WM_VKEYTOITEM:
574     case WM_VSCROLL:
575         *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
576         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
577         return 0;
578     case WM_CTLCOLOR:
579         *pmsg32    = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
580         *pwparam32 = (WPARAM32)(HDC32)wParam16;
581         *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
582         return 0;
583     case WM_DRAWITEM:
584         {
585             DRAWITEMSTRUCT16* dis16 = (DRAWITEMSTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
586             DRAWITEMSTRUCT32 *dis = (DRAWITEMSTRUCT32*)HeapAlloc(SystemHeap, 0,
587                                                                  sizeof(*dis));
588             if (!dis) return -1;
589             dis->CtlType    = dis16->CtlType;
590             dis->CtlID      = dis16->CtlID;
591             dis->itemID     = dis16->itemID;
592             dis->itemAction = dis16->itemAction;
593             dis->itemState  = dis16->itemState;
594             dis->hwndItem   = dis16->hwndItem;
595             dis->hDC        = dis16->hDC;
596             dis->itemData   = dis16->itemData;
597             CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
598             *plparam = (LPARAM)dis;
599         }
600         return 1;
601     case WM_GETMINMAXINFO:
602         {
603             MINMAXINFO32 *mmi = (MINMAXINFO32 *)HeapAlloc( SystemHeap, 0,
604                                                 sizeof(*mmi) + sizeof(LPARAM));
605             if (!mmi) return -1;
606             STRUCT32_MINMAXINFO16to32( (MINMAXINFO16*)PTR_SEG_TO_LIN(*plparam),
607                                        mmi );
608             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
609             *plparam = (LPARAM)mmi;
610         }
611         return 1;
612     case WM_GETTEXT:
613         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
614         return 0;
615     case WM_MDICREATE:
616         {
617             MDICREATESTRUCT16 *cs16 =
618                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
619             MDICREATESTRUCT32A *cs =
620                 (MDICREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
621                                                 sizeof(*cs) + sizeof(LPARAM) );
622             if (!cs) return -1;
623             STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
624             cs->szTitle = (LPCSTR)PTR_SEG_TO_LIN(cs16->szTitle);
625             cs->szClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->szClass);
626             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
627             *plparam = (LPARAM)cs;
628         }
629         return 1;
630     case WM_MDISETMENU:
631         *pwparam32 = (WPARAM32)(HMENU32)LOWORD(*plparam);
632         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
633         return 0;
634     case WM_MENUCHAR:
635     case WM_MENUSELECT:
636         *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
637         *plparam   = (LPARAM)(HMENU32)HIWORD(*plparam);
638         return 0;
639     case WM_NCCALCSIZE:
640         {
641             NCCALCSIZE_PARAMS16 *nc16;
642             NCCALCSIZE_PARAMS32 *nc;
643
644             nc = (NCCALCSIZE_PARAMS32 *)HeapAlloc( SystemHeap, 0,
645                                                 sizeof(*nc) + sizeof(LPARAM) );
646             if (!nc) return -1;
647             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(*plparam);
648             CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
649             if (wParam16)
650             {
651                 nc->lppos = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
652                                                       sizeof(*nc->lppos) );
653                 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
654                 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
655                 if (nc->lppos) STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos), nc->lppos );
656             }
657             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
658             *plparam = (LPARAM)nc;
659         }
660         return 1;
661     case WM_NCCREATE:
662     case WM_CREATE:
663         {
664             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
665             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)HeapAlloc( SystemHeap, 0,
666                                                 sizeof(*cs) + sizeof(LPARAM) );
667             if (!cs) return -1;
668             STRUCT32_CREATESTRUCT16to32A( cs16, cs );
669             cs->lpszName  = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszName);
670             cs->lpszClass = (LPCSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
671             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
672             *plparam = (LPARAM)cs;
673         }
674         return 1;
675     case WM_PARENTNOTIFY:
676         if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
677         {
678             *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
679             *plparam   = (LPARAM)(HWND32)LOWORD(*plparam);
680         }
681         else
682         {
683             *pwparam32 = MAKEWPARAM( wParam16, 0  /* FIXME? */ );
684         }
685         return 0;
686     case WM_SETTEXT:
687         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
688         return 0;
689     case WM_WINDOWPOSCHANGING:
690     case WM_WINDOWPOSCHANGED:
691         {
692             WINDOWPOS32 *wp = (WINDOWPOS32 *)HeapAlloc( SystemHeap, 0,
693                                                 sizeof(*wp) + sizeof(LPARAM) );
694             if (!wp) return -1;
695             STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(*plparam),
696                                       wp );
697             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
698             *plparam = (LPARAM)wp;
699         }
700         return 1;
701     case WM_ASKCBFORMATNAME:
702     case WM_COMPAREITEM:
703     case WM_DELETEITEM:
704     case WM_DEVMODECHANGE:
705     case WM_MDIACTIVATE:
706     case WM_MEASUREITEM:
707     case WM_PAINTCLIPBOARD:
708     case WM_SIZECLIPBOARD:
709     case WM_WININICHANGE:
710         fprintf( stderr, "MapMsg16To32A: message %04x needs translation\n",
711                  msg16 );
712         return -1;
713
714     default:  /* No translation needed */
715         return 0;
716     }
717 }
718
719
720 /**********************************************************************
721  *           WINPROC_UnmapMsg16To32A
722  *
723  * Unmap a message that was mapped from 16- to 32-bit Ansi.
724  */
725 void WINPROC_UnmapMsg16To32A( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
726 {
727     switch(msg)
728     {
729     case WM_DRAWITEM:
730         HeapFree( SystemHeap, 0, (LPVOID)lParam );
731         break;
732     case WM_GETMINMAXINFO:
733         {
734             MINMAXINFO32 *mmi = (MINMAXINFO32 *)lParam;
735             lParam = *(LPARAM *)(mmi + 1);
736             STRUCT32_MINMAXINFO32to16( mmi,
737                                        (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
738             HeapFree( SystemHeap, 0, mmi );
739         }
740         break;
741     case WM_MDICREATE:
742         {
743             MDICREATESTRUCT32A *cs = (MDICREATESTRUCT32A *)lParam;
744             lParam = *(LPARAM *)(cs + 1);
745             STRUCT32_MDICREATESTRUCT32Ato16( cs,
746                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
747             HeapFree( SystemHeap, 0, cs );
748         }
749         break;
750     case WM_NCCALCSIZE:
751         {
752             NCCALCSIZE_PARAMS16 *nc16;
753             NCCALCSIZE_PARAMS32 *nc = (NCCALCSIZE_PARAMS32 *)lParam;
754             lParam = *(LPARAM *)(nc + 1);
755             nc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
756             CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
757             if (wParam)
758             {
759                 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
760                 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
761                 if (nc->lppos)
762                 {
763                     STRUCT32_WINDOWPOS32to16( nc->lppos,
764                                    (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc16->lppos));
765                     HeapFree( SystemHeap, 0, nc->lppos );
766                 }
767             }
768             HeapFree( SystemHeap, 0, nc );
769         }
770         break;
771     case WM_NCCREATE:
772     case WM_CREATE:
773         {
774             CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
775             lParam = *(LPARAM *)(cs + 1);
776             STRUCT32_CREATESTRUCT32Ato16( cs,
777                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
778             HeapFree( SystemHeap, 0, cs );
779         }
780         break;
781     case WM_WINDOWPOSCHANGING:
782     case WM_WINDOWPOSCHANGED:
783         {
784             WINDOWPOS32 *wp = (WINDOWPOS32 *)lParam;
785             lParam = *(LPARAM *)(wp + 1);
786             STRUCT32_WINDOWPOS32to16(wp,(WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam));
787             HeapFree( SystemHeap, 0, wp );
788         }
789         break;
790     }
791 }
792
793
794 /**********************************************************************
795  *           WINPROC_MapMsg16To32W
796  *
797  * Map a message from 16- to 32-bit Unicode.
798  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
799  */
800 INT32 WINPROC_MapMsg16To32W( UINT16 msg16, WPARAM16 wParam16, UINT32 *pmsg32,
801                              WPARAM32 *pwparam32, LPARAM *plparam )
802 {
803     switch(msg16)
804     {
805     case WM_GETTEXT:
806     case WM_SETTEXT:
807         *plparam = (LPARAM)PTR_SEG_TO_LIN(*plparam);
808         return WINPROC_MapMsg32ATo32W( *pmsg32, *pwparam32, plparam );
809     case WM_NCCREATE:
810     case WM_CREATE:
811         {
812             CREATESTRUCT16 *cs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
813             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
814                                                 sizeof(*cs) + sizeof(LPARAM) );
815             if (!cs) return -1;
816             STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCT32A *)cs );
817             cs->lpszName  = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszName);
818             cs->lpszClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->lpszClass);
819             if (HIWORD(cs->lpszName))
820                 cs->lpszName = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszName );
821             if (HIWORD(cs->lpszClass))
822                 cs->lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs->lpszClass );
823             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
824             *plparam = (LPARAM)cs;
825         }
826         return 1;
827     case WM_MDICREATE:
828         {
829             MDICREATESTRUCT16 *cs16 =
830                 (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(*plparam);
831             MDICREATESTRUCT32W *cs =
832                 (MDICREATESTRUCT32W *)HeapAlloc( SystemHeap, 0,
833                                                 sizeof(*cs) + sizeof(LPARAM) );
834             if (!cs) return -1;
835             STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCT32A *)cs );
836             cs->szTitle = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szTitle);
837             cs->szClass = (LPCWSTR)PTR_SEG_TO_LIN(cs16->szClass);
838             if (HIWORD(cs->szTitle))
839                 cs->szTitle = STRING32_DupAnsiToUni( (LPCSTR)cs->szTitle );
840             if (HIWORD(cs->szClass))
841                 cs->szClass = STRING32_DupAnsiToUni( (LPCSTR)cs->szClass );
842             *(LPARAM *)(cs + 1) = *plparam;  /* Store the previous lParam */
843             *plparam = (LPARAM)cs;
844         }
845         return 1;
846     default:  /* No Unicode translation needed */
847         return WINPROC_MapMsg16To32A( msg16, wParam16, pmsg32,
848                                       pwparam32, plparam );
849     }
850 }
851
852
853 /**********************************************************************
854  *           WINPROC_UnmapMsg16To32W
855  *
856  * Unmap a message that was mapped from 16- to 32-bit Unicode.
857  */
858 void WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam, LPARAM lParam )
859 {
860     switch(msg)
861     {
862     case WM_GETTEXT:
863     case WM_SETTEXT:
864         WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
865         break;
866     case WM_NCCREATE:
867     case WM_CREATE:
868         {
869             CREATESTRUCT32W *cs = (CREATESTRUCT32W *)lParam;
870             lParam = *(LPARAM *)(cs + 1);
871             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs,
872                                     (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
873             if (HIWORD(cs->lpszName)) free( (LPVOID)cs->lpszName );
874             if (HIWORD(cs->lpszClass)) free( (LPVOID)cs->lpszClass );
875             HeapFree( SystemHeap, 0, cs );
876         }
877         break;
878     case WM_MDICREATE:
879         {
880             MDICREATESTRUCT32W *cs = (MDICREATESTRUCT32W *)lParam;
881             lParam = *(LPARAM *)(cs + 1);
882             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs,
883                                  (MDICREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam) );
884             if (HIWORD(cs->szTitle)) free( (LPVOID)cs->szTitle );
885             if (HIWORD(cs->szClass)) free( (LPVOID)cs->szClass );
886             HeapFree( SystemHeap, 0, cs );
887         }
888         break;
889     default:
890         WINPROC_UnmapMsg16To32A( msg, wParam, lParam );
891         break;
892     }
893 }
894
895
896 /**********************************************************************
897  *           WINPROC_MapMsg32ATo16
898  *
899  * Map a message from 32-bit Ansi to 16-bit.
900  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
901  */
902 INT32 WINPROC_MapMsg32ATo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16,
903                              WPARAM16 *pwparam16, LPARAM *plparam )
904 {
905     *pmsg16 = (UINT16)msg32;
906     *pwparam16 = (WPARAM16)LOWORD(wParam32);
907     switch(msg32)
908     {
909     case WM_ACTIVATE:
910     case WM_CHARTOITEM:
911     case WM_COMMAND:
912     case WM_VKEYTOITEM:
913         *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
914         return 0;
915     case WM_HSCROLL:
916     case WM_VSCROLL:
917         *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
918         return 0;
919     case WM_CTLCOLORMSGBOX:
920     case WM_CTLCOLOREDIT:
921     case WM_CTLCOLORLISTBOX:
922     case WM_CTLCOLORBTN:
923     case WM_CTLCOLORDLG:
924     case WM_CTLCOLORSCROLLBAR:
925     case WM_CTLCOLORSTATIC:
926         *pmsg16  = WM_CTLCOLOR;
927         *plparam = MAKELPARAM( (HWND16)*plparam,
928                                (WORD)msg32 - WM_CTLCOLORMSGBOX );
929         return 0;
930     case WM_DRAWITEM:
931         {
932             DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)*plparam;
933             DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
934             if (!dis) return -1;
935             dis->CtlType    = (UINT16)dis32->CtlType;
936             dis->CtlID      = (UINT16)dis32->CtlID;
937             dis->itemID     = (UINT16)dis32->itemID;
938             dis->itemAction = (UINT16)dis32->itemAction;
939             dis->itemState  = (UINT16)dis32->itemState;
940             dis->hwndItem   = (HWND16)dis32->hwndItem;
941             dis->hDC        = (HDC16)dis32->hDC;
942             dis->itemData   = dis32->itemData;
943             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
944             *plparam = (LPARAM)SEGPTR_GET(dis);
945         }
946         return 1;
947     case WM_GETMINMAXINFO:
948         {
949             MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
950                                                               sizeof(LPARAM) );
951             if (!mmi) return -1;
952             STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)*plparam, mmi );
953             *(LPARAM *)(mmi + 1) = *plparam;  /* Store the previous lParam */
954             *plparam = (LPARAM)SEGPTR_GET(mmi);
955         }
956         return 1;
957     case WM_GETTEXT:
958         {
959             LPSTR str;
960             *pwparam16 = (WPARAM16)MIN( wParam32, 0xff80 ); /* Must be < 64K */
961             if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
962             *((LPARAM *)str)++ = *plparam;  /* Store the previous lParam */
963             *plparam = (LPARAM)SEGPTR_GET(str);
964         }
965         return 1;
966     case WM_MDICREATE:
967         {
968             MDICREATESTRUCT16 *cs;
969             MDICREATESTRUCT32A *cs32 = (MDICREATESTRUCT32A *)*plparam;
970             LPSTR name, cls;
971
972             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
973             STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
974             name = SEGPTR_STRDUP( cs32->szTitle );
975             cls  = SEGPTR_STRDUP( cs32->szClass );
976             cs->szTitle = SEGPTR_GET(name);
977             cs->szClass = SEGPTR_GET(cls);
978             *plparam = (LPARAM)SEGPTR_GET(cs);
979         }
980         return 1;
981     case WM_MDISETMENU:
982         *pwparam16 = TRUE;  /* FIXME? */
983         *plparam   = MAKELPARAM( (HMENU16)LOWORD(wParam32),
984                                  (HMENU16)LOWORD(*plparam) );
985         return 0;
986     case WM_MENUCHAR:
987     case WM_MENUSELECT:
988         *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
989         return 0;
990     case WM_NCCALCSIZE:
991         {
992             NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)*plparam;
993             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
994             if (!nc) return -1;
995
996             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
997             if (wParam32)
998             {
999                 WINDOWPOS16 *wp;
1000                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1001                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1002                 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1003                 {
1004                     SEGPTR_FREE(nc);
1005                     return -1;
1006                 }
1007                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1008                 nc->lppos = SEGPTR_GET(wp);
1009             }
1010             *(LPARAM *)(nc + 1) = *plparam;  /* Store the previous lParam */
1011             *plparam = (LPARAM)SEGPTR_GET(nc);
1012         }
1013         return 1;
1014     case WM_NCCREATE:
1015     case WM_CREATE:
1016         {
1017             CREATESTRUCT16 *cs;
1018             CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)*plparam;
1019             LPSTR name, cls;
1020
1021             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1022             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1023             name = SEGPTR_STRDUP( cs32->lpszName );
1024             cls  = SEGPTR_STRDUP( cs32->lpszClass );
1025             cs->lpszName  = SEGPTR_GET(name);
1026             cs->lpszClass = SEGPTR_GET(cls);
1027             *plparam = (LPARAM)SEGPTR_GET(cs);
1028         }
1029         return 1;
1030     case WM_PARENTNOTIFY:
1031         if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1032             *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1033         /* else nothing to do */
1034         return 0;
1035     case WM_SETTEXT:
1036         {
1037             LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1038             if (!str) return -1;
1039             *plparam = (LPARAM)SEGPTR_GET(str);
1040         }
1041         return 1;
1042     case WM_WINDOWPOSCHANGING:
1043     case WM_WINDOWPOSCHANGED:
1044         {
1045             WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
1046                                                            sizeof(LPARAM) );
1047             if (!wp) return -1;
1048             STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)*plparam, wp );
1049             *(LPARAM *)(wp + 1) = *plparam;  /* Store the previous lParam */
1050             *plparam = (LPARAM)SEGPTR_GET(wp);
1051         }
1052         return 1;
1053     case WM_ASKCBFORMATNAME:
1054     case WM_COMPAREITEM:
1055     case WM_DELETEITEM:
1056     case WM_DEVMODECHANGE:
1057     case WM_MDIACTIVATE:
1058     case WM_MEASUREITEM:
1059     case WM_PAINTCLIPBOARD:
1060     case WM_SIZECLIPBOARD:
1061     case WM_WININICHANGE:
1062         fprintf( stderr, "MapMsg32ATo16: message %04x needs translation\n",
1063                  msg32 );
1064         return -1;
1065
1066     default:  /* No translation needed */
1067         return 0;
1068     }
1069 }
1070
1071
1072 /**********************************************************************
1073  *           WINPROC_UnmapMsg32ATo16
1074  *
1075  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1076  */
1077 void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1078 {
1079     switch(msg)
1080     {
1081     case WM_DRAWITEM:
1082         SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
1083         break;
1084     case WM_GETMINMAXINFO:
1085         {
1086             MINMAXINFO16 *mmi = (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam);
1087             lParam = *(LPARAM *)(mmi + 1);
1088             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)lParam );
1089             SEGPTR_FREE(mmi);
1090         }
1091         break;
1092     case WM_GETTEXT:
1093         {
1094             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lParam);
1095             lParam = *((LPARAM *)str - 1);
1096             strcpy( (LPSTR)lParam, str );
1097             SEGPTR_FREE( (LPARAM *)str - 1 );
1098         }
1099         break;
1100     case WM_MDICREATE:
1101         {
1102             MDICREATESTRUCT16 *cs = (MDICREATESTRUCT16*)PTR_SEG_TO_LIN(lParam);
1103             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szTitle) );
1104             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->szClass) );
1105             SEGPTR_FREE( cs );
1106         }
1107         break;
1108     case WM_NCCALCSIZE:
1109         {
1110             NCCALCSIZE_PARAMS32 *nc32;
1111             NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
1112             lParam = *(LPARAM *)(nc + 1);
1113             nc32 = (NCCALCSIZE_PARAMS32 *)lParam;
1114             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
1115             if (wParam)
1116             {
1117                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
1118                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
1119                 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
1120                                           nc32->lppos );
1121                 SEGPTR_FREE( PTR_SEG_TO_LIN(nc->lppos) );
1122             }
1123             SEGPTR_FREE(nc);
1124         }
1125         break;
1126     case WM_NCCREATE:
1127     case WM_CREATE:
1128         {
1129             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
1130             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszName) );
1131             SEGPTR_FREE( PTR_SEG_TO_LIN(cs->lpszClass) );
1132             SEGPTR_FREE( cs );
1133         }
1134         break;
1135     case WM_SETTEXT:
1136         SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
1137         break;
1138     case WM_WINDOWPOSCHANGING:
1139     case WM_WINDOWPOSCHANGED:
1140         {
1141             WINDOWPOS16 *wp = (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam);
1142             lParam = *(LPARAM *)(wp + 1);
1143             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)lParam );
1144             SEGPTR_FREE(wp);
1145         }
1146         break;
1147     }
1148 }
1149
1150
1151 /**********************************************************************
1152  *           WINPROC_MapMsg32WTo16
1153  *
1154  * Map a message from 32-bit Unicode to 16-bit.
1155  * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1156  */
1157 INT32 WINPROC_MapMsg32WTo16( UINT32 msg32, WPARAM32 wParam32, UINT16 *pmsg16,
1158                              WPARAM16 *pwparam16, LPARAM *plparam )
1159 {
1160     switch(msg32)
1161     {
1162     case WM_NCCREATE:
1163     case WM_CREATE:
1164         {
1165             CREATESTRUCT16 *cs;
1166             CREATESTRUCT32W *cs32 = (CREATESTRUCT32W *)*plparam;
1167
1168             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1169             STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCT32A *)cs32, cs );
1170             if (HIWORD(cs32->lpszName))
1171             {
1172                 LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->lpszName) + 1 );
1173                 STRING32_UniToAnsi( name, cs32->lpszName );
1174                 cs->lpszName = SEGPTR_GET(name);
1175             }
1176             else cs->lpszName = (SEGPTR)cs32->lpszName;
1177             if (HIWORD(cs32->lpszClass))
1178             {
1179                 LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->lpszClass) + 1 );
1180                 STRING32_UniToAnsi( name, cs32->lpszClass );
1181                 cs->lpszClass = SEGPTR_GET(name);
1182             }
1183             else cs->lpszClass = (SEGPTR)cs32->lpszClass;
1184             *pmsg16    = (UINT16)msg32;
1185             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1186             *plparam   = (LPARAM)SEGPTR_GET(cs);
1187         }
1188         return 1;
1189     case WM_MDICREATE:
1190         {
1191             MDICREATESTRUCT16 *cs;
1192             MDICREATESTRUCT32W *cs32 = (MDICREATESTRUCT32W *)*plparam;
1193
1194             if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1195             STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCT32A *)cs32, cs );
1196             if (HIWORD(cs32->szTitle))
1197             {
1198                 LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->szTitle) + 1 );
1199                 STRING32_UniToAnsi( name, cs32->szTitle );
1200                 cs->szTitle = SEGPTR_GET(name);
1201             }
1202             else cs->szTitle = (SEGPTR)cs32->szTitle;
1203             if (HIWORD(cs32->szClass))
1204             {
1205                 LPSTR name = SEGPTR_ALLOC( lstrlen32W(cs32->szClass) + 1 );
1206                 STRING32_UniToAnsi( name, cs32->szClass );
1207                 cs->szClass = SEGPTR_GET(name);
1208             }
1209             else cs->szClass = (SEGPTR)cs32->szClass;
1210             *pmsg16    = (UINT16)msg32;
1211             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1212             *plparam   = (LPARAM)SEGPTR_GET(cs);
1213         }
1214         return 1;
1215     case WM_SETTEXT:
1216         {
1217             LPSTR str = SEGPTR_ALLOC( lstrlen32W((LPWSTR)*plparam) + 1 );
1218             if (!str) return -1;
1219             STRING32_UniToAnsi( str, (LPWSTR)*plparam );
1220             *pmsg16    = (UINT16)msg32;
1221             *pwparam16 = (WPARAM16)LOWORD(wParam32);
1222             *plparam   = (LPARAM)SEGPTR_GET(str);
1223         }
1224         return 1;
1225     default:  /* No Unicode translation needed */
1226         return WINPROC_MapMsg32ATo16( msg32, wParam32, pmsg16,
1227                                       pwparam16, plparam );
1228     }
1229 }
1230
1231
1232 /**********************************************************************
1233  *           WINPROC_UnmapMsg32WTo16
1234  *
1235  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
1236  */
1237 void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
1238 {
1239     switch(msg)
1240     {
1241     case WM_GETTEXT:
1242         {
1243             LPSTR str = (LPSTR)PTR_SEG_TO_LIN(lParam);
1244             lParam = *((LPARAM *)str - 1);
1245             STRING32_AnsiToUni( (LPWSTR)lParam, str );
1246             SEGPTR_FREE( (LPARAM *)str - 1 );
1247         }
1248         break;
1249     default:
1250         WINPROC_UnmapMsg32ATo16( msg, wParam, lParam );
1251         break;
1252     }
1253 }
1254
1255
1256 /**********************************************************************
1257  *           WINPROC_CallProc32ATo32W
1258  *
1259  * Call a window procedure, translating args from Ansi to Unicode.
1260  */
1261 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
1262                                          UINT32 msg, WPARAM32 wParam,
1263                                          LPARAM lParam )
1264 {
1265     LRESULT result;
1266
1267     if (WINPROC_MapMsg32ATo32W( msg, wParam, &lParam ) == -1) return 0;
1268     result = CallWndProc32( func, hwnd, msg, wParam, lParam );
1269     WINPROC_UnmapMsg32ATo32W( msg, wParam, lParam );
1270     return result;
1271 }
1272
1273
1274 /**********************************************************************
1275  *           WINPROC_CallProc32WTo32A
1276  *
1277  * Call a window procedure, translating args from Unicode to Ansi.
1278  */
1279 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
1280                                          UINT32 msg, WPARAM32 wParam,
1281                                          LPARAM lParam )
1282 {
1283     LRESULT result;
1284
1285     if (WINPROC_MapMsg32WTo32A( msg, wParam, &lParam ) == -1) return 0;
1286     result = CallWndProc32( func, hwnd, msg, wParam, lParam );
1287     WINPROC_UnmapMsg32WTo32A( msg, wParam, lParam );
1288     return result;
1289 }
1290
1291
1292 /**********************************************************************
1293  *           WINPROC_CallProc16To32A
1294  *
1295  * Call a 32-bit window procedure, translating the 16-bit args.
1296  */
1297 LRESULT WINPROC_CallProc16To32A( HWND16 hwnd, UINT16 msg,
1298                                  WPARAM16 wParam, LPARAM lParam,
1299                                  WNDPROC32 func )
1300 {
1301     LRESULT result;
1302     UINT32 msg32;
1303     WPARAM32 wParam32;
1304
1305     if (WINPROC_MapMsg16To32A( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
1306         return 0;
1307     result = CallWndProc32( func, hwnd, msg32, wParam32, lParam );
1308     WINPROC_UnmapMsg16To32A( msg32, wParam32, lParam );
1309     return result;
1310 }
1311
1312
1313 /**********************************************************************
1314  *           WINPROC_CallProc16To32W
1315  *
1316  * Call a 32-bit window procedure, translating the 16-bit args.
1317  */
1318 LRESULT WINPROC_CallProc16To32W( HWND16 hwnd, UINT16 msg,
1319                                  WPARAM16 wParam, LPARAM lParam,
1320                                  WNDPROC32 func )
1321 {
1322     LRESULT result;
1323     UINT32 msg32;
1324     WPARAM32 wParam32;
1325
1326     if (WINPROC_MapMsg16To32W( msg, wParam, &msg32, &wParam32, &lParam ) == -1)
1327         return 0;
1328     result = CallWndProc32( func, hwnd, msg32, wParam32, lParam );
1329     WINPROC_UnmapMsg16To32W( msg32, wParam32, lParam );
1330     return result;
1331 }
1332
1333
1334 /**********************************************************************
1335  *           WINPROC_CallProc32ATo16
1336  *
1337  * Call a 16-bit window procedure, translating the 32-bit args.
1338  */
1339 static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND32 hwnd,
1340                                         UINT32 msg, WPARAM32 wParam,
1341                                         LPARAM lParam )
1342 {
1343     LRESULT result;
1344     UINT16 msg16;
1345     WPARAM16 wParam16;
1346     WND *wndPtr = WIN_FindWndPtr( hwnd );
1347     WORD ds = CURRENT_DS;
1348
1349     if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
1350         return 0;
1351     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
1352     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
1353     CURRENT_DS = ds;
1354     WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
1355     return result;
1356 }
1357
1358
1359 /**********************************************************************
1360  *           WINPROC_CallProc32WTo16
1361  *
1362  * Call a 16-bit window procedure, translating the 32-bit args.
1363  */
1364 static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND32 hwnd,
1365                                         UINT32 msg, WPARAM32 wParam,
1366                                         LPARAM lParam )
1367 {
1368     LRESULT result;
1369     UINT16 msg16;
1370     WPARAM16 wParam16;
1371     WND *wndPtr = WIN_FindWndPtr( hwnd );
1372     WORD ds = CURRENT_DS;
1373
1374     if (WINPROC_MapMsg32WTo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
1375         return 0;
1376     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
1377     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
1378     CURRENT_DS = ds;
1379     WINPROC_UnmapMsg32WTo16( msg16, wParam16, lParam );
1380     return result;
1381 }
1382
1383
1384 /**********************************************************************
1385  *           CallWindowProc16    (USER.122)
1386  */
1387 LRESULT CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
1388                           WPARAM16 wParam, LPARAM lParam )
1389 {
1390     LRESULT result;
1391     WND *wndPtr;
1392     WINDOWPROC *proc = WINPROC_GetPtr( func );
1393     WORD ds = CURRENT_DS;
1394
1395     if (!proc)
1396     {
1397         wndPtr = WIN_FindWndPtr( hwnd );
1398         if (wndPtr) CURRENT_DS = wndPtr->hInstance;
1399         result = CallWndProc16( (FARPROC16)func, hwnd, msg, wParam, lParam );
1400         CURRENT_DS = ds;
1401         return result;
1402     }
1403 #if testing
1404     wndPtr = WIN_FindWndPtr( hwnd );
1405     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
1406     result = CallWndProc16( WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16),
1407                             hwnd, msg, wParam, lParam );
1408     CURRENT_DS = ds;
1409     return result;
1410 #endif
1411     
1412     switch(proc->type)
1413     {
1414     case WIN_PROC_16:
1415         if (!proc->thunk.t_from32.proc) return 0;
1416         wndPtr = WIN_FindWndPtr( hwnd );
1417         if (wndPtr) CURRENT_DS = wndPtr->hInstance;
1418 #ifndef WINELIB
1419         if ((msg == WM_CREATE) || (msg == WM_NCCREATE))
1420         {
1421             CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
1422             /* Build the CREATESTRUCT on the 16-bit stack. */
1423             /* This is really ugly, but some programs (notably the */
1424             /* "Undocumented Windows" examples) want it that way.  */
1425             result = CallWndProcNCCREATE16( proc->thunk.t_from32.proc,
1426                     cs->dwExStyle, cs->lpszClass, cs->lpszName, cs->style,
1427                     cs->x, cs->y, cs->cx, cs->cy, cs->hwndParent, cs->hMenu,
1428                     cs->hInstance, (LONG)cs->lpCreateParams, hwnd, msg, wParam,
1429                     MAKELONG( IF1632_Saved16_sp-sizeof(CREATESTRUCT16),
1430                               IF1632_Saved16_ss ) );
1431             CURRENT_DS = ds;
1432             return result;
1433         }
1434 #endif
1435         result = CallWndProc16( proc->thunk.t_from32.proc,
1436                                 hwnd, msg, wParam, lParam );
1437         CURRENT_DS = ds;
1438         return result;
1439
1440     case WIN_PROC_32A:
1441         if (!proc->thunk.t_from16.proc) return 0;
1442         return WINPROC_CallProc16To32A( hwnd, msg, wParam, lParam,
1443                                         proc->thunk.t_from16.proc );
1444     case WIN_PROC_32W:
1445         if (!proc->thunk.t_from16.proc) return 0;
1446         return WINPROC_CallProc16To32W( hwnd, msg, wParam, lParam,
1447                                         proc->thunk.t_from16.proc );
1448     default:
1449         fprintf( stderr, "CallWindowProc16: invalid proc %p\n", proc );
1450         return 0;
1451     }
1452 }
1453
1454
1455 /**********************************************************************
1456  *           CallWindowProc32A    (USER32.17)
1457  */
1458 LRESULT CallWindowProc32A( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
1459                            WPARAM32 wParam, LPARAM lParam )
1460 {
1461     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
1462
1463     if (!proc) return CallWndProc32( func, hwnd, msg, wParam, lParam );
1464
1465 #if testing
1466     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
1467     return CallWndProc32( func, hwnd, msg, wParam, lParam );
1468 #endif
1469
1470     switch(proc->type)
1471     {
1472     case WIN_PROC_16:
1473         if (!proc->thunk.t_from32.proc) return 0;
1474         return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
1475                                         hwnd, msg, wParam, lParam );
1476     case WIN_PROC_32A:
1477         if (!proc->thunk.t_from16.proc) return 0;
1478         return CallWndProc32( proc->thunk.t_from16.proc,
1479                               hwnd, msg, wParam, lParam );
1480     case WIN_PROC_32W:
1481         if (!proc->thunk.t_from16.proc) return 0;
1482         return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
1483                                          hwnd, msg, wParam, lParam );
1484     default:
1485         fprintf( stderr, "CallWindowProc32A: invalid proc %p\n", proc );
1486         return 0;
1487     }
1488 }
1489
1490
1491 /**********************************************************************
1492  *           CallWindowProc32W    (USER32.18)
1493  */
1494 LRESULT CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
1495                            WPARAM32 wParam, LPARAM lParam )
1496 {
1497     WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
1498
1499     if (!proc) return CallWndProc32( func, hwnd, msg, wParam, lParam );
1500
1501 #if testing
1502     func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
1503     return CallWndProc32( func, hwnd, msg, wParam, lParam );
1504 #endif
1505
1506     switch(proc->type)
1507     {
1508     case WIN_PROC_16:
1509         if (!proc->thunk.t_from32.proc) return 0;
1510         return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
1511                                         hwnd, msg, wParam, lParam );
1512     case WIN_PROC_32A:
1513         if (!proc->thunk.t_from16.proc) return 0;
1514         return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
1515                                          hwnd, msg, wParam, lParam );
1516     case WIN_PROC_32W:
1517         if (!proc->thunk.t_from16.proc) return 0;
1518         return CallWndProc32( proc->thunk.t_from16.proc,
1519                               hwnd, msg, wParam, lParam );
1520     default:
1521         fprintf( stderr, "CallWindowProc32W: invalid proc %p\n", proc );
1522         return 0;
1523     }
1524 }