Release 960521
[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 "stackframe.h"
14 #include "string32.h"
15 #include "struct32.h"
16 #include "win.h"
17 #include "winproc.h"
18
19
20 typedef struct
21 {
22     WNDPROC32       func;        /* 32-bit function, or 0 if free */
23     unsigned int    count : 30;  /* Reference count, or next free if func==0 */
24     WINDOWPROCTYPE  type : 2;    /* Function type */
25 } WINDOWPROC;
26
27 #define NB_WINPROCS    1024  /* Must be < 64K; 1024 should be enough for now */
28
29 static WINDOWPROC winProcs[NB_WINPROCS];
30 static int lastWinProc = 0;
31 static int freeWinProc = NB_WINPROCS;
32
33 /* Check if a win proc was created by WINPROC_AllocWinProc */
34 #define IS_ALLOCATED_WINPROC(func)  (HIWORD(func) == 0xffff)
35
36 /**********************************************************************
37  *           WINPROC_AllocWinProc
38  *
39  * Allocate a new window procedure.
40  */
41 WNDPROC16 WINPROC_AllocWinProc( WNDPROC32 func, WINDOWPROCTYPE type )
42 {
43     WINDOWPROC *proc;
44     if (!func) return (WNDPROC16)0;  /* Null win proc remains null */
45     if (IS_ALLOCATED_WINPROC(func))  /* Already allocated? */
46     {
47         if (LOWORD(func) >= NB_WINPROCS) return (WNDPROC16)0;
48         proc = &winProcs[LOWORD(func)];
49         if (!proc->func) return (WNDPROC16)0;
50         proc->count++;
51         return (WNDPROC16)func;
52     }
53     if (freeWinProc < NB_WINPROCS)  /* There is a free entry */
54     {
55         proc = &winProcs[freeWinProc];
56         proc->func = func;
57         func = (WNDPROC32)MAKELONG( freeWinProc, 0xffff );
58         freeWinProc = proc->count;  /* Next free entry */
59         proc->count = 1;
60         proc->type  = type;
61         return (WNDPROC16)func;
62     }
63     if (lastWinProc < NB_WINPROCS)  /* There's a free entry at the end */
64     {
65         proc = &winProcs[lastWinProc];
66         proc->func = func;
67         func = (WNDPROC32)MAKELONG( lastWinProc, 0xffff );
68         lastWinProc++;
69         proc->count = 1;
70         proc->type  = type;
71         return (WNDPROC16)func;
72     }
73     fprintf( stderr, "WINPROC_AllocWinProc: out of window procedures.\n"
74                      "Please augment NB_WINPROCS in winproc.c\n" );
75     return (WNDPROC16)0;
76 }
77
78
79 /**********************************************************************
80  *           WINPROC_GetWinProcType
81  *
82  * Return the type of a window procedure.
83  */
84 WINDOWPROCTYPE WINPROC_GetWinProcType( WNDPROC16 func )
85 {
86     WORD id = LOWORD(func);
87     if (!IS_ALLOCATED_WINPROC(func)) return WIN_PROC_16;
88     if ((id >= NB_WINPROCS) || !winProcs[id].func) return WIN_PROC_INVALID;
89     return winProcs[id].type;
90 }
91
92
93 /**********************************************************************
94  *           WINPROC_GetWinProcFunc
95  *
96  * Return the 32-bit window procedure for a winproc.
97  */
98 WNDPROC32 WINPROC_GetWinProcFunc( WNDPROC16 func )
99 {
100     WORD id = LOWORD(func);
101     if (!IS_ALLOCATED_WINPROC(func)) return NULL;
102     if (id >= NB_WINPROCS) return NULL;
103     return winProcs[id].func;
104 }
105
106
107 /**********************************************************************
108  *           WINPROC_FreeWinProc
109  *
110  * Free a window procedure.
111  */
112 void WINPROC_FreeWinProc( WNDPROC16 func )
113 {
114     WORD id = LOWORD(func);
115     if (!IS_ALLOCATED_WINPROC(func)) return;
116     if ((id >= NB_WINPROCS) || !winProcs[id].func)
117     {
118         fprintf( stderr, "WINPROC_FreeWinProc: invalid proc %08x\n",
119                  (UINT32)func );
120         return;
121     }
122     if (--winProcs[id].count == 0)
123     {
124         winProcs[id].func = 0;
125         winProcs[id].count = freeWinProc;
126         freeWinProc = id;
127     }
128 }
129
130
131 /**********************************************************************
132  *           WINPROC_CallProc32ATo32W
133  *
134  * Call a window procedure, translating args from Ansi to Unicode.
135  */
136 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd,
137                                          UINT32 msg, WPARAM32 wParam,
138                                          LPARAM lParam )
139 {
140     LRESULT result;
141
142     switch(msg)
143     {
144     case WM_GETTEXT:
145         {
146             LPWSTR str = (LPWSTR)HeapAlloc(SystemHeap,0,wParam*sizeof(WCHAR));
147             if (!str) return 0;
148             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
149             STRING32_UniToAnsi( (LPSTR)lParam, str );
150             HeapFree( SystemHeap, 0, str );
151             return strlen( (LPSTR)lParam ) + 1;
152         }
153
154     case WM_SETTEXT:
155         {
156             LPWSTR str = STRING32_DupAnsiToUni( (LPCSTR)lParam );
157             if (!str) return 0;
158             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
159             free( str );
160         }
161         return result;
162
163     case WM_NCCREATE:
164     case WM_CREATE:
165         {
166             CREATESTRUCT32W cs = *(CREATESTRUCT32W *)lParam;
167             cs.lpszName  = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName );
168             cs.lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName );
169             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
170             free( (LPVOID)cs.lpszName );
171             free( (LPVOID)cs.lpszClass );
172         }
173         return result;
174         
175     default:  /* No translation needed */
176         return CallWndProc32( func, hwnd, msg, wParam, lParam );
177     }
178 }
179
180
181 /**********************************************************************
182  *           WINPROC_CallProc32WTo32A
183  *
184  * Call a window procedure, translating args from Unicode to Ansi.
185  */
186 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd,
187                                          UINT32 msg, WPARAM32 wParam,
188                                          LPARAM lParam )
189 {
190     LRESULT result;
191
192     switch(msg)
193     {
194     case WM_GETTEXT:
195         {
196             LPSTR str = (LPSTR)HeapAlloc( SystemHeap, 0, wParam );
197             if (!str) return 0;
198             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
199             STRING32_AnsiToUni( (LPWSTR)lParam, str );
200             HeapFree( SystemHeap, 0, str );
201             return STRING32_lstrlenW( (LPWSTR)lParam ) + 1;  /* FIXME? */
202         }
203
204     case WM_SETTEXT:
205         {
206             LPSTR str = STRING32_DupUniToAnsi( (LPCWSTR)lParam );
207             if (!str) return 0;
208             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str );
209             free( str );
210         }
211         return result;
212
213     case WM_NCCREATE:
214     case WM_CREATE:
215         {
216             CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam;
217             cs.lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
218             cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
219             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
220             free( (LPVOID)cs.lpszName );
221             free( (LPVOID)cs.lpszClass );
222         }
223         return result;
224         
225     default:  /* No translation needed */
226         return CallWndProc32( func, hwnd, msg, wParam, lParam );
227     }
228 }
229
230
231 /**********************************************************************
232  *           WINPROC_CallProc16To32A
233  *
234  * Call a 32-bit window procedure, translating the 16-bit args.
235  */
236 static LRESULT WINPROC_CallProc16To32A(WNDPROC32 func, HWND16 hwnd, UINT16 msg,
237                                        WPARAM16 wParam, LPARAM lParam )
238 {
239     LRESULT result;
240
241     switch(msg)
242     {
243     case WM_ACTIVATE:
244     case WM_CHARTOITEM:
245     case WM_COMMAND:
246     case WM_HSCROLL:
247     case WM_VKEYTOITEM:
248     case WM_VSCROLL:
249         return CallWndProc32( func, hwnd, msg,
250                               MAKEWPARAM( wParam, HIWORD(lParam) ),
251                               (LPARAM)(HWND32)LOWORD(lParam) );
252     case WM_CTLCOLOR:
253         return CallWndProc32( func, hwnd, WM_CTLCOLORMSGBOX + HIWORD(lParam),
254                               (WPARAM32)(HDC32)wParam,
255                               (LPARAM)(HWND32)LOWORD(lParam) );
256     case WM_DRAWITEM:
257         {
258             DRAWITEMSTRUCT16*dis16 = (DRAWITEMSTRUCT16*)PTR_SEG_TO_LIN(lParam);
259             DRAWITEMSTRUCT32 dis;
260             dis.CtlType    = dis16->CtlType;
261             dis.CtlID      = dis16->CtlID;
262             dis.itemID     = dis16->itemID;
263             dis.itemAction = dis16->itemAction;
264             dis.itemState  = dis16->itemState;
265             dis.hwndItem   = dis16->hwndItem;
266             dis.hDC        = dis16->hDC;
267             dis.itemData   = dis16->itemData;
268             CONV_RECT16TO32( &dis16->rcItem, &dis.rcItem );
269             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&dis );
270             /* We don't bother to translate it back */
271         }
272         return result;
273
274     case WM_GETMINMAXINFO:
275         {
276             MINMAXINFO32 mmi;
277             STRUCT32_MINMAXINFO16to32( (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam),
278                                        &mmi );
279             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&mmi);
280             STRUCT32_MINMAXINFO32to16( &mmi,
281                                        (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam));
282         }
283         return result;
284
285     case WM_GETTEXT:
286         return CallWndProc32( func, hwnd, msg, wParam,
287                               (LPARAM)PTR_SEG_TO_LIN(lParam) );
288     case WM_MDISETMENU:
289         return CallWndProc32( func, hwnd, msg,
290                               (WPARAM32)(HMENU32)LOWORD(lParam),
291                               (LPARAM)(HMENU32)HIWORD(lParam) );
292     case WM_MENUCHAR:
293     case WM_MENUSELECT:
294         return CallWndProc32( func, hwnd, msg,
295                               MAKEWPARAM( wParam, LOWORD(lParam) ),
296                               (LPARAM)(HMENU32)HIWORD(lParam) );
297     case WM_NCCALCSIZE:
298         {
299             NCCALCSIZE_PARAMS16 *pnc16;
300             NCCALCSIZE_PARAMS32 nc;
301             WINDOWPOS32 wp;
302
303             pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
304             CONV_RECT16TO32( &pnc16->rgrc[0], &nc.rgrc[0] );
305             if (wParam)
306             {
307                 CONV_RECT16TO32( &pnc16->rgrc[1], &nc.rgrc[1] );
308                 CONV_RECT16TO32( &pnc16->rgrc[2], &nc.rgrc[2] );
309                 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos),
310                                           &wp );
311                 nc.lppos = &wp;
312             }
313
314             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&nc );
315
316             pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam);
317             CONV_RECT32TO16( &nc.rgrc[0], &pnc16->rgrc[0] );
318             if (wParam)
319             {
320                 CONV_RECT32TO16( &nc.rgrc[1], &pnc16->rgrc[1] );
321                 CONV_RECT32TO16( &nc.rgrc[2], &pnc16->rgrc[2] );
322                 STRUCT32_WINDOWPOS32to16( nc.lppos,
323                                   (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos));
324             }
325         }
326         return result;
327         
328     case WM_NCCREATE:
329     case WM_CREATE:
330         {
331             CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
332             CREATESTRUCT32A cs;
333
334             STRUCT32_CREATESTRUCT16to32A( pcs16, &cs );
335             /* FIXME: Unicode */
336             cs.lpszName       = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName);
337             cs.lpszClass      = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass);
338             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs );
339             pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
340             STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 );
341
342             if (cs.lpszName != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName))
343                 fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszName (%p->%p), please report.\n",
344                     msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName), cs.lpszName);
345             if (cs.lpszClass != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass))
346                 fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszClass (%p->%p), please report.\n",
347                   msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass), cs.lpszClass);
348         }
349         return result;
350
351     case WM_PARENTNOTIFY:
352         if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
353             return CallWndProc32( func, hwnd, msg,
354                                   MAKEWPARAM( wParam, HIWORD(lParam) ),
355                                   (LPARAM)(HWND32)LOWORD(lParam) );
356         else return CallWndProc32( func, hwnd, msg,
357                                    MAKEWPARAM( wParam, 0  /* FIXME? */ ),
358                                    lParam );
359     case WM_SETTEXT:
360         /* FIXME: Unicode */
361         return CallWndProc32( func, hwnd, msg, wParam,
362                               (LPARAM)PTR_SEG_TO_LIN(lParam) );
363
364     case WM_WINDOWPOSCHANGING:
365     case WM_WINDOWPOSCHANGED:
366         {
367             WINDOWPOS32 wp;
368             STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam),
369                                       &wp );
370             result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&wp );
371             STRUCT32_WINDOWPOS32to16( &wp,
372                                       (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam) );
373         }
374         return result;
375
376     case WM_ASKCBFORMATNAME:
377     case WM_COMPAREITEM:
378     case WM_DELETEITEM:
379     case WM_DEVMODECHANGE:
380     case WM_MDIACTIVATE:
381     case WM_MDICREATE:
382     case WM_MEASUREITEM:
383     case WM_PAINTCLIPBOARD:
384     case WM_SIZECLIPBOARD:
385     case WM_WININICHANGE:
386         fprintf( stderr, "CallWindowProc16To32: message %04x needs translation\n", msg );
387
388     default:  /* No translation needed */
389         return CallWndProc32( func, hwnd, msg, (WPARAM32)wParam, lParam );
390     }
391 }
392
393
394 /**********************************************************************
395  *           WINPROC_CallProc16To32W
396  *
397  * Call a 32-bit window procedure, translating the 16-bit args.
398  */
399 static LRESULT WINPROC_CallProc16To32W(WNDPROC32 func, HWND16 hwnd, UINT16 msg,
400                                        WPARAM16 wParam, LPARAM lParam )
401 {
402     LRESULT result = 0;
403
404     switch(msg)
405     {
406     case WM_GETTEXT:
407     case WM_SETTEXT:
408         return WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam,
409                                          (LPARAM)PTR_SEG_TO_LIN(lParam) );
410
411     case WM_NCCREATE:
412     case WM_CREATE:
413         {
414             CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
415             CREATESTRUCT32A cs;
416
417             STRUCT32_CREATESTRUCT16to32A( pcs16, &cs );
418             cs.lpszName       = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName);
419             cs.lpszClass      = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass);
420             result = WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam,
421                                                (LPARAM)&cs );
422             pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
423             STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 );
424         }
425         return result;
426
427     default:  /* No Unicode translation needed */
428         return WINPROC_CallProc16To32A( func, hwnd, msg, wParam, lParam );
429     }
430 }
431
432
433 /**********************************************************************
434  *           WINPROC_CallProc32ATo16
435  *
436  * Call a 16-bit window procedure, translating the 32-bit args.
437  */
438 static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, WORD ds, HWND32 hwnd,
439                                         UINT32 msg, WPARAM32 wParam,
440                                         LPARAM lParam )
441 {
442     LRESULT result;
443
444     switch(msg)
445     {
446     case WM_ACTIVATE:
447     case WM_CHARTOITEM:
448     case WM_COMMAND:
449     case WM_HSCROLL:
450     case WM_VKEYTOITEM:
451     case WM_VSCROLL:
452         return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
453                               MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) );
454         
455     case WM_CTLCOLORMSGBOX:
456     case WM_CTLCOLOREDIT:
457     case WM_CTLCOLORLISTBOX:
458     case WM_CTLCOLORBTN:
459     case WM_CTLCOLORDLG:
460     case WM_CTLCOLORSCROLLBAR:
461     case WM_CTLCOLORSTATIC:
462         return CallWndProc16( func, ds, hwnd, WM_CTLCOLOR, (WPARAM16)wParam,
463                               MAKELPARAM( (HWND16)lParam,
464                                           (WORD)msg - WM_CTLCOLORMSGBOX ) );
465     case WM_DRAWITEM:
466         {
467             DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)lParam;
468             DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
469             if (!dis) return 0;
470             dis->CtlType    = (UINT16)dis32->CtlType;
471             dis->CtlID      = (UINT16)dis32->CtlID;
472             dis->itemID     = (UINT16)dis32->itemID;
473             dis->itemAction = (UINT16)dis32->itemAction;
474             dis->itemState  = (UINT16)dis32->itemState;
475             dis->hwndItem   = (HWND16)dis32->hwndItem;
476             dis->hDC        = (HDC16)dis32->hDC;
477             dis->itemData   = dis32->itemData;
478             CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
479             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
480                                     (LPARAM)SEGPTR_GET(dis) );
481             /* We don't bother to translate it back */
482             SEGPTR_FREE(dis);
483         }
484         return result;
485
486     case WM_GETMINMAXINFO:
487         {
488             MINMAXINFO16 *mmi = SEGPTR_NEW(MINMAXINFO16);
489             if (!mmi) return 0;
490             STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)lParam, mmi );
491             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
492                                     (LPARAM)SEGPTR_GET(mmi) );
493             STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)lParam );
494             SEGPTR_FREE(mmi);
495         }
496         return result;
497
498     case WM_GETTEXT:
499         {
500             LPSTR str;
501             wParam = MIN( wParam, 0xff80 );  /* Size must be < 64K */
502             if (!(str = SEGPTR_ALLOC( wParam ))) return 0;
503             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
504                                     (LPARAM)SEGPTR_GET(str) );
505             if (result > 0) memcpy( (LPSTR)lParam, str, result );
506             SEGPTR_FREE(str);
507         }
508         return result;
509
510     case WM_MDISETMENU:
511         return CallWndProc16( func, ds, hwnd, msg, TRUE /* FIXME? */,
512                               MAKELPARAM( (HMENU16)LOWORD(lParam),
513                                           (HMENU16)HIWORD(lParam) ) );
514     case WM_MENUCHAR:
515     case WM_MENUSELECT:
516         return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)LOWORD(wParam),
517                               MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ) );
518     case WM_NCCALCSIZE:
519         {
520             NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)lParam;
521             NCCALCSIZE_PARAMS16 *nc;
522             WINDOWPOS16 *wp = NULL;
523
524             if (!(nc = SEGPTR_NEW(NCCALCSIZE_PARAMS16))) return 0;
525             CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
526             if (wParam)
527             {
528                 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
529                 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
530                 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
531                 {
532                     SEGPTR_FREE(nc);
533                     return 0;
534                 }
535                 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
536                 nc->lppos = SEGPTR_GET(wp);
537             }
538             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
539                                     (LPARAM)SEGPTR_GET(nc) );
540             CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
541             if (wParam)
542             {
543                 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
544                 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
545                 STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos),
546                                           nc32->lppos );
547                 SEGPTR_FREE(wp);
548             }
549             SEGPTR_FREE(nc);
550         }
551         return result;
552
553     case WM_NCCREATE:
554     case WM_CREATE:
555         {
556             CREATESTRUCT16 *cs;
557             CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)lParam;
558             LPSTR name, cls;
559
560             if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return 0;
561             STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
562             name = SEGPTR_STRDUP( cs32->lpszName );
563             cls  = SEGPTR_STRDUP( cs32->lpszClass );
564             cs->lpszName  = SEGPTR_GET(name);
565             cs->lpszClass = SEGPTR_GET(cls);
566             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
567                                     (LPARAM)SEGPTR_GET(cs) );
568             STRUCT32_CREATESTRUCT16to32A( cs, cs32 );
569             if (PTR_SEG_TO_LIN(cs->lpszName) != name)
570                 cs32->lpszName  = (LPCSTR)PTR_SEG_TO_LIN( cs->lpszName );
571             if (PTR_SEG_TO_LIN(cs->lpszClass) != cls)
572                 cs32->lpszClass = (LPCSTR)PTR_SEG_TO_LIN( cs->lpszClass );
573             SEGPTR_FREE(name);
574             SEGPTR_FREE(cls);
575             SEGPTR_FREE(cs);
576         }
577         return result;
578         
579     case WM_PARENTNOTIFY:
580         if ((wParam == WM_CREATE) || (wParam == WM_DESTROY))
581             return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
582                                   MAKELPARAM( (HWND16)lParam, LOWORD(wParam)));
583     case WM_SETTEXT:
584         {
585             LPSTR str = SEGPTR_STRDUP( (LPSTR)lParam );
586             if (!str) return 0;
587             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
588                                     (LPARAM)SEGPTR_GET(str) );
589             SEGPTR_FREE(str);
590         }
591         return result;
592
593     case WM_WINDOWPOSCHANGING:
594     case WM_WINDOWPOSCHANGED:
595         {
596             WINDOWPOS16 *wp;
597             if (!(wp = SEGPTR_NEW(WINDOWPOS16))) return 0;
598             STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)lParam, wp );
599             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
600                                     (LPARAM)SEGPTR_GET(wp) );
601             STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)lParam );
602             SEGPTR_FREE(wp);
603         }
604         return result;
605
606     case WM_ASKCBFORMATNAME:
607     case WM_COMPAREITEM:
608     case WM_DELETEITEM:
609     case WM_DEVMODECHANGE:
610     case WM_MDIACTIVATE:
611     case WM_MDICREATE:
612     case WM_MEASUREITEM:
613     case WM_PAINTCLIPBOARD:
614     case WM_SIZECLIPBOARD:
615     case WM_WININICHANGE:
616         fprintf( stderr, "CallWindowProc32To16: message %04x needs translation\n", msg );
617
618     default:  /* No translation needed */
619         return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, lParam );
620     }
621 }
622
623
624 /**********************************************************************
625  *           WINPROC_CallProc32WTo16
626  *
627  * Call a 16-bit window procedure, translating the 32-bit args.
628  */
629 static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, WORD ds, HWND32 hwnd,
630                                         UINT32 msg, WPARAM32 wParam,
631                                         LPARAM lParam )
632 {
633     LRESULT result;
634
635     switch(msg)
636     {
637     case WM_GETTEXT:
638         {
639             LPSTR str;
640             wParam = MIN( wParam, 0xff80 );  /* Size must be < 64K */
641             if (!(str = SEGPTR_ALLOC( wParam ))) return 0;
642             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
643                                     (LPARAM)SEGPTR_GET(str) );
644             if (result > 0) STRING32_AnsiToUni( (LPWSTR)lParam, str );
645             SEGPTR_FREE(str);
646         }
647         return result;
648
649     case WM_NCCREATE:
650     case WM_CREATE:
651         {
652             CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam;
653             cs.lpszName  = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
654             cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName );
655             result = WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam,
656                                               (LPARAM)&cs );
657             free( (LPVOID)cs.lpszName );
658             free( (LPVOID)cs.lpszClass );
659         }
660         return result;
661         
662     case WM_SETTEXT:
663         {
664             LPSTR str = SEGPTR_ALLOC( STRING32_lstrlenW( (LPWSTR)lParam ) );
665             if (!str) return 0;
666             STRING32_UniToAnsi( str, (LPWSTR)lParam );
667             result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam,
668                                     (LPARAM)SEGPTR_GET(str) );
669             SEGPTR_FREE(str);
670         }
671         return result;
672
673     default:  /* No Unicode translation needed */
674         return WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam, lParam );
675     }
676 }
677
678
679 /**********************************************************************
680  *           CallWindowProc16    (USER.122)
681  */
682 LRESULT CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
683                           WPARAM16 wParam, LPARAM lParam )
684 {
685     WND *wndPtr;
686
687     switch(WINPROC_GetWinProcType(func))
688     {
689     case WIN_PROC_16:
690         wndPtr = WIN_FindWndPtr( hwnd );
691         return CallWndProc16( (FARPROC)func,
692                               wndPtr ? wndPtr->hInstance : CURRENT_DS,
693                               hwnd, msg, wParam, lParam );
694     case WIN_PROC_32A:
695         return WINPROC_CallProc16To32A( WINPROC_GetWinProcFunc(func),
696                                         hwnd, msg, wParam, lParam );
697     case WIN_PROC_32W:
698         return WINPROC_CallProc16To32W( WINPROC_GetWinProcFunc(func),
699                                         hwnd, msg, wParam, lParam );
700     default:
701         fprintf(stderr, "CallWindowProc16: invalid func %08x\n", (UINT32)func);
702         return 0;
703     }
704 }
705
706
707 /**********************************************************************
708  *           CallWindowProc32A    (USER32.17)
709  */
710 LRESULT CallWindowProc32A( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
711                            WPARAM32 wParam, LPARAM lParam )
712 {
713     WND *wndPtr;
714
715     switch(WINPROC_GetWinProcType( (WNDPROC16)func ))
716     {
717     case WIN_PROC_16:
718         wndPtr = WIN_FindWndPtr( hwnd );
719         return WINPROC_CallProc32ATo16( (FARPROC)func,
720                                        wndPtr ? wndPtr->hInstance : CURRENT_DS,
721                                        hwnd, msg, wParam, lParam );
722     case WIN_PROC_32A:
723         return CallWndProc32( WINPROC_GetWinProcFunc( (WNDPROC16)func ),
724                               hwnd, msg, wParam, lParam );
725     case WIN_PROC_32W:
726         return WINPROC_CallProc32ATo32W(WINPROC_GetWinProcFunc((WNDPROC16)func),
727                                         hwnd, msg, wParam, lParam );
728     default:
729         fprintf(stderr,"CallWindowProc32A: invalid func %08x\n",(UINT32)func);
730         return 0;
731     }
732 }
733
734
735 /**********************************************************************
736  *           CallWindowProc32W    (USER32.18)
737  */
738 LRESULT CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
739                            WPARAM32 wParam, LPARAM lParam )
740 {
741     WND *wndPtr;
742
743     switch(WINPROC_GetWinProcType( (WNDPROC16)func ))
744     {
745     case WIN_PROC_16:
746         wndPtr = WIN_FindWndPtr( hwnd );
747         return WINPROC_CallProc32WTo16( (FARPROC)func,
748                                        wndPtr ? wndPtr->hInstance : CURRENT_DS,
749                                        hwnd, msg, wParam, lParam );
750     case WIN_PROC_32A:
751         return WINPROC_CallProc32WTo32A(WINPROC_GetWinProcFunc((WNDPROC16)func),
752                                         hwnd, msg, wParam, lParam );
753     case WIN_PROC_32W:
754         return CallWndProc32( WINPROC_GetWinProcFunc( (WNDPROC16)func ),
755                               hwnd, msg, wParam, lParam );
756     default:
757         fprintf(stderr,"CallWindowProc32W: invalid func %08x\n",(UINT32)func);
758         return 0;
759     }
760 }