Added ability to turn on/off debug channels.
[wine.git] / windows / winproc.c
blob36ec3754f8d967cd47be5c220ead00174d03e078
1 /*
2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "stackframe.h"
33 #include "selectors.h"
34 #include "controls.h"
35 #include "heap.h"
36 #include "struct32.h"
37 #include "win.h"
38 #include "winproc.h"
39 #include "wine/debug.h"
40 #include "spy.h"
41 #include "task.h"
42 #include "thread.h"
43 #include "dde.h"
45 WINE_DECLARE_DEBUG_CHANNEL(msg);
46 WINE_DECLARE_DEBUG_CHANNEL(relay);
47 WINE_DECLARE_DEBUG_CHANNEL(win);
49 #include "pshpack1.h"
51 /* Window procedure 16-to-32-bit thunk */
52 typedef struct
54 BYTE popl_eax; /* popl %eax (return address) */
55 BYTE pushl_func; /* pushl $proc */
56 WNDPROC proc;
57 BYTE pushl_eax; /* pushl %eax */
58 BYTE ljmp; /* ljmp relay*/
59 DWORD relay_offset; /* __wine_call_wndproc_32A/W */
60 WORD relay_sel;
61 } WINPROC_THUNK_FROM16;
63 /* Window procedure 32-to-16-bit thunk */
64 typedef struct
66 BYTE popl_eax; /* popl %eax (return address) */
67 BYTE pushl_func; /* pushl $proc */
68 WNDPROC16 proc;
69 BYTE pushl_eax; /* pushl %eax */
70 BYTE jmp; /* jmp relay (relative jump)*/
71 void (*relay)(); /* WINPROC_CallProc32ATo16() */
72 } WINPROC_THUNK_FROM32;
74 /* Simple jmp to call 32-bit procedure directly */
75 typedef struct
77 BYTE jmp; /* jmp proc (relative jump) */
78 WNDPROC proc;
79 } WINPROC_JUMP;
80 #include "poppack.h"
82 typedef union
84 WINPROC_THUNK_FROM16 t_from16;
85 WINPROC_THUNK_FROM32 t_from32;
86 } WINPROC_THUNK;
88 typedef struct tagWINDOWPROC
90 WINPROC_THUNK thunk; /* Thunk */
91 WINPROC_JUMP jmp; /* Jump */
92 struct tagWINDOWPROC *next; /* Next window proc */
93 UINT magic; /* Magic number */
94 WINDOWPROCTYPE type; /* Function type */
95 WINDOWPROCUSER user; /* Function user */
96 } WINDOWPROC;
98 #define WINPROC_MAGIC ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
100 #define WINPROC_THUNKPROC(pproc) \
101 (((pproc)->type == WIN_PROC_16) ? \
102 (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
103 (WNDPROC16)((pproc)->thunk.t_from16.proc))
105 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
106 UINT msg, WPARAM wParam,
107 LPARAM lParam );
108 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
109 UINT msg, WPARAM wParam,
110 LPARAM lParam );
112 static HANDLE WinProcHeap;
113 static WORD WinProcSel;
116 /**********************************************************************
117 * WINPROC_Init
119 BOOL WINPROC_Init(void)
121 WinProcHeap = HeapCreate( 0, 0x10000, 0x10000 );
122 WinProcSel = SELECTOR_AllocBlock( (void *)WinProcHeap, 0x10000,
123 WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
124 if (!WinProcHeap || !WinProcSel)
126 WARN_(relay)("Unable to create winproc heap\n" );
127 return FALSE;
129 return TRUE;
133 #ifdef __i386__
134 /* Some window procedures modify register they shouldn't, or are not
135 * properly declared stdcall; so we need a small assembly wrapper to
136 * call them. */
137 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
138 WPARAM wParam, LPARAM lParam );
139 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
140 "pushl %ebp\n\t"
141 "movl %esp,%ebp\n\t"
142 "pushl %edi\n\t"
143 "pushl %esi\n\t"
144 "pushl %ebx\n\t"
145 "pushl 24(%ebp)\n\t"
146 "pushl 20(%ebp)\n\t"
147 "pushl 16(%ebp)\n\t"
148 "pushl 12(%ebp)\n\t"
149 "movl 8(%ebp),%eax\n\t"
150 "call *%eax\n\t"
151 "leal -12(%ebp),%esp\n\t"
152 "popl %ebx\n\t"
153 "popl %esi\n\t"
154 "popl %edi\n\t"
155 "leave\n\t"
156 "ret" );
157 #else
158 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
159 WPARAM wParam, LPARAM lParam )
161 return proc( hwnd, msg, wParam, lParam );
163 #endif /* __i386__ */
165 /**********************************************************************
166 * WINPROC_CallWndProc32
168 * Call a 32-bit WndProc.
170 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
171 WPARAM wParam, LPARAM lParam )
173 LRESULT retvalue;
174 int iWndsLocks;
176 hwnd = WIN_GetFullHandle( hwnd );
177 if (TRACE_ON(relay))
178 DPRINTF( "%08lx:Call window proc %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
179 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
180 /* To avoid any deadlocks, all the locks on the windows structures
181 must be suspended before the control is passed to the application */
182 iWndsLocks = WIN_SuspendWndsLock();
183 retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
184 WIN_RestoreWndsLock(iWndsLocks);
186 if (TRACE_ON(relay))
187 DPRINTF( "%08lx:Ret window proc %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
188 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
189 return retvalue;
192 /***********************************************************************
193 * WINPROC_CallWndProc16
195 * Call a 16-bit window procedure
197 static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
198 UINT16 msg, WPARAM16 wParam,
199 LPARAM lParam )
201 CONTEXT86 context;
202 LRESULT ret;
203 WORD *args;
204 DWORD offset = 0;
205 TEB *teb = NtCurrentTeb();
206 int iWndsLocks;
208 /* Window procedures want ax = hInstance, ds = es = ss */
210 memset(&context, '\0', sizeof(context));
211 context.SegDs = context.SegEs = SELECTOROF(teb->cur_stack);
212 if (!(context.Eax = GetWindowWord16( hwnd, GWL_HINSTANCE ))) context.Eax = context.SegDs;
213 context.SegCs = SELECTOROF(proc);
214 context.Eip = OFFSETOF(proc);
215 context.Ebp = OFFSETOF(teb->cur_stack)
216 + (WORD)&((STACK16FRAME*)0)->bp;
218 if (lParam)
220 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
221 work if structures passed in lParam are placed in the stack/data
222 segment. Programmers easily make the mistake of converting lParam
223 to a near rather than a far pointer, since Windows apparently
224 allows this. We copy the structures to the 16 bit stack; this is
225 ugly but makes these programs work. */
226 switch (msg)
228 case WM_CREATE:
229 case WM_NCCREATE:
230 offset = sizeof(CREATESTRUCT16); break;
231 case WM_DRAWITEM:
232 offset = sizeof(DRAWITEMSTRUCT16); break;
233 case WM_COMPAREITEM:
234 offset = sizeof(COMPAREITEMSTRUCT16); break;
236 if (offset)
238 void *s = MapSL(lParam);
239 lParam = stack16_push( offset );
240 memcpy( MapSL(lParam), s, offset );
244 iWndsLocks = WIN_SuspendWndsLock();
246 args = (WORD *)THREAD_STACK16(teb) - 5;
247 args[0] = LOWORD(lParam);
248 args[1] = HIWORD(lParam);
249 args[2] = wParam;
250 args[3] = msg;
251 args[4] = hwnd;
253 wine_call_to_16_regs_short( &context, 5 * sizeof(WORD) );
254 ret = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
255 if (offset) stack16_pop( offset );
257 WIN_RestoreWndsLock(iWndsLocks);
259 return ret;
263 /**********************************************************************
264 * WINPROC_GetPtr
266 * Return a pointer to the win proc.
268 static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
270 BYTE *ptr;
271 WINDOWPROC *proc;
273 /* ptr cannot be < 64K */
274 if (!HIWORD(handle)) return NULL;
276 /* Check for a linear pointer */
278 ptr = (BYTE *)handle;
279 /* First check if it is the jmp address */
280 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->jmp);
281 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
282 return proc;
283 /* Now it must be the thunk address */
284 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
285 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
286 return proc;
288 /* Check for a segmented pointer */
290 if (!IsBadReadPtr16( (SEGPTR)handle, sizeof(proc->thunk) ))
292 ptr = MapSL( (SEGPTR)handle );
293 /* It must be the thunk address */
294 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
295 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
296 return proc;
299 return NULL;
303 /**********************************************************************
304 * WINPROC_AllocWinProc
306 * Allocate a new window procedure.
308 static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type,
309 WINDOWPROCUSER user )
311 static FARPROC16 relay_32A, relay_32W;
313 WINDOWPROC *proc, *oldproc;
315 /* Allocate a window procedure */
317 if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
319 /* Check if the function is already a win proc */
321 if ((oldproc = WINPROC_GetPtr( func )))
323 *proc = *oldproc;
325 else
327 switch(type)
329 case WIN_PROC_16:
330 proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */
331 proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */
332 proc->thunk.t_from32.proc = func;
333 proc->thunk.t_from32.pushl_eax = 0x50; /* pushl %eax */
334 proc->thunk.t_from32.jmp = 0xe9; /* jmp relay*/
335 proc->thunk.t_from32.relay = /* relative jump */
336 (void(*)())((DWORD)WINPROC_CallProc32ATo16 -
337 (DWORD)(&proc->thunk.t_from32.relay + 1));
338 break;
339 case WIN_PROC_32A:
340 if (!relay_32A) relay_32A = GetProcAddress16( GetModuleHandle16("user"),
341 "__wine_call_wndproc_32A" );
342 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
343 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
344 proc->thunk.t_from16.proc = (WNDPROC)func;
345 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
346 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
347 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32A);
348 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A);
349 proc->jmp.jmp = 0xe9;
350 /* Fixup relative jump */
351 proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
352 break;
353 case WIN_PROC_32W:
354 if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"),
355 "__wine_call_wndproc_32W" );
356 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
357 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
358 proc->thunk.t_from16.proc = (WNDPROC)func;
359 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
360 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
361 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32W);
362 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W);
363 proc->jmp.jmp = 0xe9;
364 /* Fixup relative jump */
365 proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
366 break;
367 default:
368 /* Should not happen */
369 break;
371 proc->magic = WINPROC_MAGIC;
372 proc->type = type;
373 proc->user = user;
375 proc->next = NULL;
376 TRACE_(win)("(%08x,%d): returning %08x\n",
377 (UINT)func, type, (UINT)proc );
378 return proc;
382 /**********************************************************************
383 * WINPROC_GetProc
385 * Get a window procedure pointer that can be passed to the Windows program.
387 WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
389 WINDOWPROC *ptr = (WINDOWPROC *)proc;
391 if (!proc) return NULL;
392 if (type == WIN_PROC_16) /* We want a 16:16 address */
394 if (ptr->type == WIN_PROC_16)
395 return ptr->thunk.t_from32.proc;
396 else
397 return (WNDPROC16)MAKESEGPTR( WinProcSel, (char *)&ptr->thunk - (char *)WinProcHeap );
399 else /* We want a 32-bit address */
401 if (ptr->type == WIN_PROC_16)
402 return (WNDPROC16)&ptr->thunk;
403 else if (type != ptr->type)
404 /* Have to return the jmp address if types don't match */
405 return (WNDPROC16)&ptr->jmp;
406 else
407 /* Some Win16 programs want to get back the proc they set */
408 return (WNDPROC16)ptr->thunk.t_from16.proc;
413 /**********************************************************************
414 * WINPROC_SetProc
416 * Set the window procedure for a window or class. There are
417 * three tree classes of winproc callbacks:
419 * 1) class -> wp - not subclassed
420 * class -> wp -> wp -> wp -> wp - SetClassLong()
421 * / /
422 * 2) window -' / - not subclassed
423 * window -> wp -> wp ' - SetWindowLong()
425 * 3) timer -> wp - SetTimer()
427 * Initially, winproc of the window points to the current winproc
428 * thunk of its class. Subclassing prepends a new thunk to the
429 * window winproc chain at the head of the list. Thus, window thunk
430 * list includes class thunks and the latter are preserved when the
431 * window is destroyed.
434 BOOL WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
435 WINDOWPROCTYPE type, WINDOWPROCUSER user )
437 BOOL bRecycle = FALSE;
438 WINDOWPROC *proc, **ppPrev;
440 /* Check if function is already in the list */
442 ppPrev = (WINDOWPROC **)pFirst;
443 proc = WINPROC_GetPtr( func );
444 while (*ppPrev)
446 if (proc)
448 if (*ppPrev == proc)
450 if ((*ppPrev)->user != user)
452 /* terminal thunk is being restored */
454 WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
455 *(WINDOWPROC **)pFirst = *ppPrev;
456 return TRUE;
458 bRecycle = TRUE;
459 break;
462 else
464 if (((*ppPrev)->type == type) &&
465 (func == WINPROC_THUNKPROC(*ppPrev)))
467 if((*ppPrev)->user == user)
469 bRecycle = TRUE;
471 else
473 WINPROC_FreeProc( *ppPrev, user );
474 *ppPrev = NULL;
476 break;
480 /* WPF_CLASS thunk terminates window thunk list */
481 if ((*ppPrev)->user != user) break;
482 ppPrev = &(*ppPrev)->next;
485 if (bRecycle)
487 /* Extract this thunk from the list */
488 proc = *ppPrev;
489 *ppPrev = proc->next;
491 else /* Allocate a new one */
493 if (proc) /* Was already a win proc */
495 type = proc->type;
496 func = WINPROC_THUNKPROC(proc);
498 proc = WINPROC_AllocWinProc( func, type, user );
499 if (!proc) return FALSE;
502 /* Add the win proc at the head of the list */
504 TRACE_(win)("(%08x,%08x,%d): res=%08x\n",
505 (UINT)*pFirst, (UINT)func, type, (UINT)proc );
506 proc->next = *(WINDOWPROC **)pFirst;
507 *(WINDOWPROC **)pFirst = proc;
508 return TRUE;
512 /**********************************************************************
513 * WINPROC_FreeProc
515 * Free a list of win procs.
517 void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
519 while (proc)
521 WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
522 if (((WINDOWPROC *)proc)->user != user) break;
523 TRACE_(win)("freeing %08x\n", (UINT)proc);
524 HeapFree( WinProcHeap, 0, proc );
525 proc = next;
530 /**********************************************************************
531 * WINPROC_GetProcType
533 * Return the window procedure type.
535 WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
537 if (!proc ||
538 (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
539 return WIN_PROC_INVALID;
540 return ((WINDOWPROC *)proc)->type;
542 /**********************************************************************
543 * WINPROC_TestCBForStr
545 * Return TRUE if the lparam is a string
547 inline static BOOL WINPROC_TestCBForStr( HWND hwnd )
549 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
550 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
552 /**********************************************************************
553 * WINPROC_TestLBForStr
555 * Return TRUE if the lparam is a string
557 inline static BOOL WINPROC_TestLBForStr( HWND hwnd )
559 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
560 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
563 /**********************************************************************
564 * WINPROC_MapMsg32ATo32W
566 * Map a message from Ansi to Unicode.
567 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
569 * FIXME:
570 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
571 * the first four bytes are the handle of the icon
572 * when the WM_SETTEXT message has been used to set the icon
574 INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
576 switch(msg)
578 case WM_GETTEXT:
579 case WM_ASKCBFORMATNAME:
581 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
582 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
583 if (!ptr) return -1;
584 *ptr++ = *plparam; /* Store previous lParam */
585 *plparam = (LPARAM)ptr;
587 return 1;
588 /* lparam is string (0-terminated) */
589 case WM_SETTEXT:
590 case WM_WININICHANGE:
591 case WM_DEVMODECHANGE:
592 case CB_DIR:
593 case LB_DIR:
594 case LB_ADDFILE:
595 case EM_REPLACESEL:
596 if(!*plparam) return 0;
597 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
598 return (*plparam ? 1 : -1);
599 case WM_GETTEXTLENGTH:
600 case CB_GETLBTEXTLEN:
601 case LB_GETTEXTLEN:
602 return 1; /* need to map result */
603 case WM_NCCREATE:
604 case WM_CREATE:
606 struct s
607 { CREATESTRUCTW cs; /* new structure */
608 LPCWSTR lpszName; /* allocated Name */
609 LPCWSTR lpszClass; /* allocated Class */
612 struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
613 if (!xs) return -1;
614 xs->cs = *(CREATESTRUCTW *)*plparam;
615 if (HIWORD(xs->cs.lpszName))
616 xs->lpszName = xs->cs.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
617 (LPCSTR)xs->cs.lpszName );
618 if (HIWORD(xs->cs.lpszClass))
619 xs->lpszClass = xs->cs.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
620 (LPCSTR)xs->cs.lpszClass );
621 *plparam = (LPARAM)xs;
623 return 1;
624 case WM_MDICREATE:
626 MDICREATESTRUCTW *cs =
627 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
628 if (!cs) return -1;
629 *cs = *(MDICREATESTRUCTW *)*plparam;
630 if (HIWORD(cs->szClass))
631 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
632 (LPCSTR)cs->szClass );
633 if (HIWORD(cs->szTitle))
634 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
635 (LPCSTR)cs->szTitle );
636 *plparam = (LPARAM)cs;
638 return 1;
640 /* Listbox */
641 case LB_ADDSTRING:
642 case LB_INSERTSTRING:
643 case LB_FINDSTRING:
644 case LB_FINDSTRINGEXACT:
645 case LB_SELECTSTRING:
646 if(!*plparam) return 0;
647 if ( WINPROC_TestLBForStr( hwnd ))
648 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
649 return (*plparam ? 1 : -1);
651 case LB_GETTEXT: /* FIXME: fixed sized buffer */
652 { if ( WINPROC_TestLBForStr( hwnd ))
653 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
654 if (!ptr) return -1;
655 *ptr++ = *plparam; /* Store previous lParam */
656 *plparam = (LPARAM)ptr;
659 return 1;
661 /* Combobox */
662 case CB_ADDSTRING:
663 case CB_INSERTSTRING:
664 case CB_FINDSTRINGEXACT:
665 case CB_FINDSTRING:
666 case CB_SELECTSTRING:
667 if(!*plparam) return 0;
668 if ( WINPROC_TestCBForStr( hwnd ))
669 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
670 return (*plparam ? 1 : -1);
672 case CB_GETLBTEXT: /* FIXME: fixed sized buffer */
673 { if ( WINPROC_TestCBForStr( hwnd ))
674 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
675 if (!ptr) return -1;
676 *ptr++ = *plparam; /* Store previous lParam */
677 *plparam = (LPARAM)ptr;
680 return 1;
682 /* Multiline edit */
683 case EM_GETLINE:
684 { WORD len = (WORD)*plparam;
685 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
686 if (!ptr) return -1;
687 *ptr++ = *plparam; /* Store previous lParam */
688 *((WORD *) ptr) = len; /* Store the length */
689 *plparam = (LPARAM)ptr;
691 return 1;
693 case WM_CHARTOITEM:
694 case WM_MENUCHAR:
695 case WM_CHAR:
696 case WM_DEADCHAR:
697 case WM_SYSCHAR:
698 case WM_SYSDEADCHAR:
699 case EM_SETPASSWORDCHAR:
701 BYTE ch = LOWORD(*pwparam);
702 WCHAR wch;
703 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
704 *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
706 return 0;
708 case WM_PAINTCLIPBOARD:
709 case WM_SIZECLIPBOARD:
710 FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
711 return -1;
712 default: /* No translation needed */
713 return 0;
718 /**********************************************************************
719 * WINPROC_UnmapMsg32ATo32W
721 * Unmap a message that was mapped from Ansi to Unicode.
723 LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
724 LRESULT result )
726 switch(msg)
728 case WM_GETTEXT:
729 case WM_ASKCBFORMATNAME:
731 LPARAM *ptr = (LPARAM *)lParam - 1;
732 if (wParam > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
733 (LPSTR)*ptr, wParam, NULL, NULL ))
734 ((LPSTR)*ptr)[wParam-1] = 0;
735 HeapFree( GetProcessHeap(), 0, ptr );
737 break;
738 case WM_GETTEXTLENGTH:
739 case CB_GETLBTEXTLEN:
740 case LB_GETTEXTLEN:
741 /* there may be one DBCS char for each Unicode char */
742 return result * 2;
743 case WM_NCCREATE:
744 case WM_CREATE:
746 struct s
747 { CREATESTRUCTW cs; /* new structure */
748 LPWSTR lpszName; /* allocated Name */
749 LPWSTR lpszClass; /* allocated Class */
751 struct s *xs = (struct s *)lParam;
752 if (xs->lpszName) HeapFree( GetProcessHeap(), 0, xs->lpszName );
753 if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
754 HeapFree( GetProcessHeap(), 0, xs );
756 break;
758 case WM_MDICREATE:
760 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
761 if (HIWORD(cs->szTitle))
762 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
763 if (HIWORD(cs->szClass))
764 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
765 HeapFree( GetProcessHeap(), 0, cs );
767 break;
769 case WM_SETTEXT:
770 case WM_WININICHANGE:
771 case WM_DEVMODECHANGE:
772 case CB_DIR:
773 case LB_DIR:
774 case LB_ADDFILE:
775 case EM_REPLACESEL:
776 HeapFree( GetProcessHeap(), 0, (void *)lParam );
777 break;
779 /* Listbox */
780 case LB_ADDSTRING:
781 case LB_INSERTSTRING:
782 case LB_FINDSTRING:
783 case LB_FINDSTRINGEXACT:
784 case LB_SELECTSTRING:
785 if ( WINPROC_TestLBForStr( hwnd ))
786 HeapFree( GetProcessHeap(), 0, (void *)lParam );
787 break;
789 case LB_GETTEXT:
790 { if ( WINPROC_TestLBForStr( hwnd ))
791 { LPARAM *ptr = (LPARAM *)lParam - 1;
792 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
793 HeapFree( GetProcessHeap(), 0, ptr );
796 break;
798 /* Combobox */
799 case CB_ADDSTRING:
800 case CB_INSERTSTRING:
801 case CB_FINDSTRING:
802 case CB_FINDSTRINGEXACT:
803 case CB_SELECTSTRING:
804 if ( WINPROC_TestCBForStr( hwnd ))
805 HeapFree( GetProcessHeap(), 0, (void *)lParam );
806 break;
808 case CB_GETLBTEXT:
809 { if ( WINPROC_TestCBForStr( hwnd ))
810 { LPARAM *ptr = (LPARAM *)lParam - 1;
811 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
812 HeapFree( GetProcessHeap(), 0, ptr );
815 break;
817 /* Multiline edit */
818 case EM_GETLINE:
819 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
820 WORD len = *(WORD *) lParam;
821 if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
822 (LPSTR)*ptr, len, NULL, NULL ))
823 ((LPSTR)*ptr)[len-1] = 0;
824 HeapFree( GetProcessHeap(), 0, ptr );
826 break;
828 return result;
832 /**********************************************************************
833 * WINPROC_MapMsg32WTo32A
835 * Map a message from Unicode to Ansi.
836 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
838 INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
840 switch(msg)
842 case WM_GETTEXT:
843 case WM_ASKCBFORMATNAME:
845 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
846 *pwparam + sizeof(LPARAM) );
847 if (!ptr) return -1;
848 *ptr++ = *plparam; /* Store previous lParam */
849 *plparam = (LPARAM)ptr;
851 return 1;
853 case WM_SETTEXT:
854 case WM_WININICHANGE:
855 case WM_DEVMODECHANGE:
856 case CB_DIR:
857 case LB_DIR:
858 case LB_ADDFILE:
859 case EM_REPLACESEL:
860 if(!*plparam) return 0;
861 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
862 return (*plparam ? 1 : -1);
864 case WM_NCCREATE:
865 case WM_CREATE:
867 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
868 sizeof(*cs) );
869 if (!cs) return -1;
870 *cs = *(CREATESTRUCTA *)*plparam;
871 if (HIWORD(cs->lpszName))
872 cs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
873 (LPCWSTR)cs->lpszName );
874 if (HIWORD(cs->lpszClass))
875 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
876 (LPCWSTR)cs->lpszClass);
877 *plparam = (LPARAM)cs;
879 return 1;
880 case WM_MDICREATE:
882 MDICREATESTRUCTA *cs =
883 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
884 if (!cs) return -1;
885 *cs = *(MDICREATESTRUCTA *)*plparam;
886 if (HIWORD(cs->szTitle))
887 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
888 (LPCWSTR)cs->szTitle );
889 if (HIWORD(cs->szClass))
890 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
891 (LPCWSTR)cs->szClass );
892 *plparam = (LPARAM)cs;
894 return 1;
896 /* Listbox */
897 case LB_ADDSTRING:
898 case LB_INSERTSTRING:
899 case LB_FINDSTRING:
900 case LB_FINDSTRINGEXACT:
901 case LB_SELECTSTRING:
902 if(!*plparam) return 0;
903 if ( WINPROC_TestLBForStr( hwnd ))
904 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
905 return (*plparam ? 1 : -1);
907 case LB_GETTEXT: /* FIXME: fixed sized buffer */
908 { if ( WINPROC_TestLBForStr( hwnd ))
909 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
910 if (!ptr) return -1;
911 *ptr++ = *plparam; /* Store previous lParam */
912 *plparam = (LPARAM)ptr;
915 return 1;
917 /* Combobox */
918 case CB_ADDSTRING:
919 case CB_INSERTSTRING:
920 case CB_FINDSTRING:
921 case CB_FINDSTRINGEXACT:
922 case CB_SELECTSTRING:
923 if(!*plparam) return 0;
924 if ( WINPROC_TestCBForStr( hwnd ))
925 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
926 return (*plparam ? 1 : -1);
928 case CB_GETLBTEXT: /* FIXME: fixed sized buffer */
929 { if ( WINPROC_TestCBForStr( hwnd ))
930 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
931 if (!ptr) return -1;
932 *ptr++ = *plparam; /* Store previous lParam */
933 *plparam = (LPARAM)ptr;
936 return 1;
938 /* Multiline edit */
939 case EM_GETLINE:
940 { WORD len = (WORD)*plparam;
941 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
942 if (!ptr) return -1;
943 *ptr++ = *plparam; /* Store previous lParam */
944 *((WORD *) ptr) = len; /* Store the length */
945 *plparam = (LPARAM)ptr;
947 return 1;
949 case WM_CHARTOITEM:
950 case WM_MENUCHAR:
951 case WM_CHAR:
952 case WM_DEADCHAR:
953 case WM_SYSCHAR:
954 case WM_SYSDEADCHAR:
955 case EM_SETPASSWORDCHAR:
957 WCHAR wch = LOWORD(*pwparam);
958 BYTE ch;
959 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
960 *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
962 return 0;
964 case WM_PAINTCLIPBOARD:
965 case WM_SIZECLIPBOARD:
966 FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg, hwnd),msg );
967 return -1;
968 default: /* No translation needed */
969 return 0;
974 /**********************************************************************
975 * WINPROC_UnmapMsg32WTo32A
977 * Unmap a message that was mapped from Unicode to Ansi.
979 void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
981 switch(msg)
983 case WM_GETTEXT:
984 case WM_ASKCBFORMATNAME:
986 LPARAM *ptr = (LPARAM *)lParam - 1;
987 if (wParam)
989 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, wParam ))
990 ((LPWSTR)*ptr)[wParam-1] = 0;
992 HeapFree( GetProcessHeap(), 0, ptr );
994 break;
996 case WM_SETTEXT:
997 case WM_WININICHANGE:
998 case WM_DEVMODECHANGE:
999 case CB_DIR:
1000 case LB_DIR:
1001 case LB_ADDFILE:
1002 case EM_REPLACESEL:
1003 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1004 break;
1006 case WM_NCCREATE:
1007 case WM_CREATE:
1009 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1010 if (HIWORD(cs->lpszName))
1011 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
1012 if (HIWORD(cs->lpszClass))
1013 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
1014 HeapFree( GetProcessHeap(), 0, cs );
1016 break;
1018 case WM_MDICREATE:
1020 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1021 if (HIWORD(cs->szTitle))
1022 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1023 if (HIWORD(cs->szClass))
1024 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1025 HeapFree( GetProcessHeap(), 0, cs );
1027 break;
1029 /* Listbox */
1030 case LB_ADDSTRING:
1031 case LB_INSERTSTRING:
1032 case LB_FINDSTRING:
1033 case LB_FINDSTRINGEXACT:
1034 case LB_SELECTSTRING:
1035 if ( WINPROC_TestLBForStr( hwnd ))
1036 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1037 break;
1039 case LB_GETTEXT:
1040 if ( WINPROC_TestLBForStr( hwnd ))
1042 LPARAM *ptr = (LPARAM *)lParam - 1;
1043 MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1044 HeapFree( GetProcessHeap(), 0, ptr );
1046 break;
1048 /* Combobox */
1049 case CB_ADDSTRING:
1050 case CB_INSERTSTRING:
1051 case CB_FINDSTRING:
1052 case CB_FINDSTRINGEXACT:
1053 case CB_SELECTSTRING:
1054 if ( WINPROC_TestCBForStr( hwnd ))
1055 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1056 break;
1058 case CB_GETLBTEXT:
1059 if ( WINPROC_TestCBForStr( hwnd ))
1061 LPARAM *ptr = (LPARAM *)lParam - 1;
1062 MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1063 HeapFree( GetProcessHeap(), 0, ptr );
1065 break;
1067 /* Multiline edit */
1068 case EM_GETLINE:
1069 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
1070 WORD len = *(WORD *)ptr;
1071 if (len)
1073 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, len ))
1074 ((LPWSTR)*ptr)[len-1] = 0;
1076 HeapFree( GetProcessHeap(), 0, ptr );
1078 break;
1082 static HANDLE convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
1084 HANDLE dst;
1085 UINT sz = GlobalSize16(src);
1086 LPSTR ptr16, ptr32;
1088 if (!(dst = GlobalAlloc(flags, sz)))
1089 return 0;
1090 ptr16 = GlobalLock16(src);
1091 ptr32 = GlobalLock(dst);
1092 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
1093 GlobalUnlock16(src);
1094 GlobalUnlock(dst);
1096 return dst;
1099 /**********************************************************************
1100 * WINPROC_MapMsg16To32A
1102 * Map a message from 16- to 32-bit Ansi.
1103 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1105 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1106 WPARAM *pwparam32, LPARAM *plparam )
1108 *pmsg32 = (UINT)msg16;
1109 *pwparam32 = (WPARAM)wParam16;
1110 switch(msg16)
1112 case WM_ACTIVATE:
1113 case WM_CHARTOITEM:
1114 case WM_COMMAND:
1115 case WM_VKEYTOITEM:
1116 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1117 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1118 return 0;
1119 case WM_HSCROLL:
1120 case WM_VSCROLL:
1121 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1122 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1123 return 0;
1124 case WM_CTLCOLOR:
1125 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1126 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1127 *pwparam32 = (WPARAM)(HDC)wParam16;
1128 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1129 return 0;
1130 case WM_COMPAREITEM:
1132 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1133 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1134 HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1135 if (!cis) return -1;
1136 cis->CtlType = cis16->CtlType;
1137 cis->CtlID = cis16->CtlID;
1138 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
1139 cis->itemID1 = cis16->itemID1;
1140 cis->itemData1 = cis16->itemData1;
1141 cis->itemID2 = cis16->itemID2;
1142 cis->itemData2 = cis16->itemData2;
1143 cis->dwLocaleId = 0; /* FIXME */
1144 *plparam = (LPARAM)cis;
1146 return 1;
1147 case WM_DELETEITEM:
1149 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1150 DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1151 HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1152 if (!dis) return -1;
1153 dis->CtlType = dis16->CtlType;
1154 dis->CtlID = dis16->CtlID;
1155 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1156 dis->itemData = dis16->itemData;
1157 *plparam = (LPARAM)dis;
1159 return 1;
1160 case WM_MEASUREITEM:
1162 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1163 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1164 HeapAlloc(GetProcessHeap(), 0,
1165 sizeof(*mis) + sizeof(LPARAM));
1166 if (!mis) return -1;
1167 mis->CtlType = mis16->CtlType;
1168 mis->CtlID = mis16->CtlID;
1169 mis->itemID = mis16->itemID;
1170 mis->itemWidth = mis16->itemWidth;
1171 mis->itemHeight = mis16->itemHeight;
1172 mis->itemData = mis16->itemData;
1173 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1174 *plparam = (LPARAM)mis;
1176 return 1;
1177 case WM_DRAWITEM:
1179 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1180 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1181 sizeof(*dis));
1182 if (!dis) return -1;
1183 dis->CtlType = dis16->CtlType;
1184 dis->CtlID = dis16->CtlID;
1185 dis->itemID = dis16->itemID;
1186 dis->itemAction = dis16->itemAction;
1187 dis->itemState = dis16->itemState;
1188 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)(HMENU)dis16->hwndItem
1189 : WIN_Handle32( dis16->hwndItem );
1190 dis->hDC = dis16->hDC;
1191 dis->itemData = dis16->itemData;
1192 CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
1193 *plparam = (LPARAM)dis;
1195 return 1;
1196 case WM_GETMINMAXINFO:
1198 MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1199 sizeof(*mmi) + sizeof(LPARAM));
1200 if (!mmi) return -1;
1201 STRUCT32_MINMAXINFO16to32( MapSL(*plparam), mmi );
1202 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1203 *plparam = (LPARAM)mmi;
1205 return 1;
1206 case WM_GETTEXT:
1207 case WM_SETTEXT:
1208 case WM_WININICHANGE:
1209 case WM_DEVMODECHANGE:
1210 case WM_ASKCBFORMATNAME:
1211 *plparam = (LPARAM)MapSL(*plparam);
1212 return 0;
1213 case WM_MDICREATE:
1215 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1216 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1217 if (!cs) return -1;
1218 STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
1219 cs->szTitle = MapSL(cs16->szTitle);
1220 cs->szClass = MapSL(cs16->szClass);
1221 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1222 *plparam = (LPARAM)cs;
1224 return 1;
1225 case WM_MDIGETACTIVE:
1226 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1227 *(BOOL*)(*plparam) = 0;
1228 return 1;
1229 case WM_MDISETMENU:
1230 if(wParam16==TRUE)
1231 *pmsg32=WM_MDIREFRESHMENU;
1232 *pwparam32 = (WPARAM)(HMENU)LOWORD(*plparam);
1233 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1234 return 0;
1235 case WM_MENUCHAR:
1236 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1237 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1238 return 0;
1239 case WM_MENUSELECT:
1240 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1242 HMENU hmenu=(HMENU)HIWORD(*plparam);
1243 UINT Pos=MENU_FindSubMenu( &hmenu, wParam16);
1244 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1245 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1247 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1248 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1249 return 0;
1250 case WM_MDIACTIVATE:
1251 if( *plparam )
1253 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1254 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1256 else /* message sent to MDI client */
1257 *pwparam32 = wParam16;
1258 return 0;
1259 case WM_NCCALCSIZE:
1261 NCCALCSIZE_PARAMS16 *nc16;
1262 NCCALCSIZE_PARAMS *nc;
1264 nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1265 sizeof(*nc) + sizeof(LPARAM) );
1266 if (!nc) return -1;
1267 nc16 = MapSL(*plparam);
1268 CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1269 if (wParam16)
1271 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1272 sizeof(*nc->lppos) );
1273 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1274 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1275 if (nc->lppos) STRUCT32_WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1277 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1278 *plparam = (LPARAM)nc;
1280 return 1;
1281 case WM_NCCREATE:
1282 case WM_CREATE:
1284 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1285 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1286 sizeof(*cs) + sizeof(LPARAM) );
1287 if (!cs) return -1;
1288 STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1289 cs->lpszName = MapSL(cs16->lpszName);
1290 cs->lpszClass = MapSL(cs16->lpszClass);
1291 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1292 *plparam = (LPARAM)cs;
1294 return 1;
1295 case WM_PARENTNOTIFY:
1296 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1298 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1299 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1301 return 0;
1302 case WM_WINDOWPOSCHANGING:
1303 case WM_WINDOWPOSCHANGED:
1305 WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1306 sizeof(*wp) + sizeof(LPARAM) );
1307 if (!wp) return -1;
1308 STRUCT32_WINDOWPOS16to32( MapSL(*plparam), wp );
1309 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1310 *plparam = (LPARAM)wp;
1312 return 1;
1313 case WM_GETDLGCODE:
1314 if (*plparam)
1316 LPMSG16 msg16 = MapSL(*plparam);
1317 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1319 if (!msg32) return -1;
1320 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1321 msg32->lParam = msg16->lParam;
1322 msg32->time = msg16->time;
1323 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1324 /* this is right, right? */
1325 if (WINPROC_MapMsg16To32A( msg32->hwnd, msg16->message,msg16->wParam,
1326 &msg32->message,&msg32->wParam,
1327 &msg32->lParam)<0) {
1328 HeapFree( GetProcessHeap(), 0, msg32 );
1329 return -1;
1331 *plparam = (LPARAM)msg32;
1332 return 1;
1334 else return 0;
1335 case WM_NOTIFY:
1336 *plparam = (LPARAM)MapSL(*plparam);
1337 return 0;
1338 case WM_ACTIVATEAPP:
1339 if (*plparam)
1340 { /* We need this when SetActiveWindow sends a Sendmessage16() to
1341 a 32bit window. Might be superflous with 32bit interprocess
1342 message queues.
1344 HTASK16 htask = (HTASK16) *plparam;
1345 DWORD idThread = (DWORD)TASK_GetPtr(htask)->teb->tid;
1346 *plparam = (LPARAM) idThread;
1348 return 0;
1349 case WM_NEXTMENU:
1351 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1352 if (!next) return -1;
1353 next->hmenuIn = *plparam;
1354 next->hmenuNext = 0;
1355 next->hwndNext = 0;
1356 *plparam = (LPARAM)next;
1357 return 1;
1359 case WM_PAINTCLIPBOARD:
1360 case WM_SIZECLIPBOARD:
1361 FIXME_(msg)("message %04x needs translation\n",msg16 );
1362 return -1;
1363 case WM_DDE_INITIATE:
1364 case WM_DDE_TERMINATE:
1365 case WM_DDE_UNADVISE:
1366 case WM_DDE_REQUEST:
1367 *pwparam32 = WIN_Handle32(wParam16);
1368 return 0;
1369 case WM_DDE_ADVISE:
1370 case WM_DDE_DATA:
1371 case WM_DDE_POKE:
1373 HANDLE16 lo16;
1374 ATOM hi;
1375 HANDLE lo32 = 0;
1377 *pwparam32 = WIN_Handle32(wParam16);
1378 lo16 = LOWORD(*plparam);
1379 hi = HIWORD(*plparam);
1380 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1381 return -1;
1382 *plparam = PackDDElParam(msg16, lo32, hi);
1384 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1385 case WM_DDE_ACK:
1387 UINT lo, hi;
1388 int flag = 0;
1389 char buf[2];
1391 *pwparam32 = WIN_Handle32(wParam16);
1393 lo = LOWORD(*plparam);
1394 hi = HIWORD(*plparam);
1396 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1397 if (GlobalSize16(hi) != 0) flag |= 2;
1398 switch (flag)
1400 case 0:
1401 if (hi)
1403 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1404 hi = 0;
1406 break;
1407 case 1:
1408 break; /* atom, nothing to do */
1409 case 3:
1410 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1411 /* fall thru */
1412 case 2:
1413 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1414 break;
1416 *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1418 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1419 case WM_DDE_EXECUTE:
1420 *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1421 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1422 default: /* No translation needed */
1423 return 0;
1428 /**********************************************************************
1429 * WINPROC_UnmapMsg16To32A
1431 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1433 LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1434 LRESULT result )
1436 switch(msg)
1438 case WM_COMPAREITEM:
1439 case WM_DELETEITEM:
1440 case WM_DRAWITEM:
1441 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1442 break;
1443 case WM_MEASUREITEM:
1445 MEASUREITEMSTRUCT16 *mis16;
1446 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1447 lParam = *(LPARAM *)(mis + 1);
1448 mis16 = MapSL(lParam);
1449 mis16->itemWidth = (UINT16)mis->itemWidth;
1450 mis16->itemHeight = (UINT16)mis->itemHeight;
1451 HeapFree( GetProcessHeap(), 0, mis );
1453 break;
1454 case WM_GETMINMAXINFO:
1456 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1457 lParam = *(LPARAM *)(mmi + 1);
1458 STRUCT32_MINMAXINFO32to16( mmi, MapSL(lParam));
1459 HeapFree( GetProcessHeap(), 0, mmi );
1461 break;
1462 case WM_MDICREATE:
1464 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1465 lParam = *(LPARAM *)(cs + 1);
1466 STRUCT32_MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1467 HeapFree( GetProcessHeap(), 0, cs );
1469 break;
1470 case WM_MDIGETACTIVE:
1471 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1472 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1473 break;
1474 case WM_NCCALCSIZE:
1476 NCCALCSIZE_PARAMS16 *nc16;
1477 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1478 lParam = *(LPARAM *)(nc + 1);
1479 nc16 = MapSL(lParam);
1480 CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1481 if (wParam)
1483 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1484 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1485 if (nc->lppos)
1487 STRUCT32_WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1488 HeapFree( GetProcessHeap(), 0, nc->lppos );
1491 HeapFree( GetProcessHeap(), 0, nc );
1493 break;
1494 case WM_NCCREATE:
1495 case WM_CREATE:
1497 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1498 lParam = *(LPARAM *)(cs + 1);
1499 STRUCT32_CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1500 HeapFree( GetProcessHeap(), 0, cs );
1502 break;
1503 case WM_WINDOWPOSCHANGING:
1504 case WM_WINDOWPOSCHANGED:
1506 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1507 lParam = *(LPARAM *)(wp + 1);
1508 STRUCT32_WINDOWPOS32to16(wp, MapSL(lParam));
1509 HeapFree( GetProcessHeap(), 0, wp );
1511 break;
1512 case WM_GETDLGCODE:
1513 if (lParam)
1515 LPMSG msg32 = (LPMSG)lParam;
1517 WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1518 result);
1519 HeapFree( GetProcessHeap(), 0, msg32 );
1521 break;
1522 case WM_NEXTMENU:
1524 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1525 result = MAKELONG( next->hmenuNext, WIN_Handle16(next->hwndNext) );
1526 HeapFree( GetProcessHeap(), 0, next );
1528 break;
1530 return result;
1534 /**********************************************************************
1535 * WINPROC_MapMsg16To32W
1537 * Map a message from 16- to 32-bit Unicode.
1538 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1540 INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1541 WPARAM *pwparam32, LPARAM *plparam )
1543 BYTE ch;
1544 WCHAR wch;
1546 *pmsg32=(UINT)msg16;
1547 *pwparam32 = (WPARAM)wParam16;
1548 switch(msg16)
1550 case WM_GETTEXT:
1551 case WM_SETTEXT:
1552 case WM_WININICHANGE:
1553 case WM_DEVMODECHANGE:
1554 case WM_ASKCBFORMATNAME:
1555 *plparam = (LPARAM)MapSL(*plparam);
1556 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1557 case WM_GETTEXTLENGTH:
1558 case CB_GETLBTEXTLEN:
1559 case LB_GETTEXTLEN:
1560 return 1; /* need to map result */
1561 case WM_NCCREATE:
1562 case WM_CREATE:
1564 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1565 CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1566 sizeof(*cs) + sizeof(LPARAM) );
1567 if (!cs) return -1;
1568 STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1569 cs->lpszName = map_str_16_to_32W(cs16->lpszName);
1570 cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1571 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1572 *plparam = (LPARAM)cs;
1574 return 1;
1575 case WM_MDICREATE:
1577 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1578 MDICREATESTRUCTW *cs =
1579 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1580 sizeof(*cs) + sizeof(LPARAM) );
1581 if (!cs) return -1;
1582 STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1583 cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1584 cs->szClass = map_str_16_to_32W(cs16->szClass);
1585 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1586 *plparam = (LPARAM)cs;
1588 return 1;
1589 case WM_GETDLGCODE:
1590 if (*plparam)
1592 LPMSG16 msg16 = MapSL(*plparam);
1593 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1595 if (!msg32) return -1;
1596 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1597 msg32->lParam = msg16->lParam;
1598 msg32->time = msg16->time;
1599 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1600 /* this is right, right? */
1601 if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1602 &msg32->message,&msg32->wParam,
1603 &msg32->lParam)<0) {
1604 HeapFree( GetProcessHeap(), 0, msg32 );
1605 return -1;
1607 *plparam = (LPARAM)msg32;
1608 return 1;
1610 else return 0;
1612 case WM_CHARTOITEM:
1613 ch = wParam16;
1614 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1615 *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1616 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1617 return 0;
1618 case WM_MENUCHAR:
1619 ch = wParam16;
1620 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1621 *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1622 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1623 return 0;
1624 case WM_CHAR:
1625 case WM_DEADCHAR:
1626 case WM_SYSCHAR:
1627 case WM_SYSDEADCHAR:
1628 ch = wParam16;
1629 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1630 *pwparam32 = wch;
1631 return 0;
1633 default: /* No Unicode translation needed */
1634 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1635 pwparam32, plparam );
1640 /**********************************************************************
1641 * WINPROC_UnmapMsg16To32W
1643 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1645 LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1646 LRESULT result )
1648 switch(msg)
1650 case WM_GETTEXT:
1651 case WM_SETTEXT:
1652 case WM_GETTEXTLENGTH:
1653 case CB_GETLBTEXTLEN:
1654 case LB_GETTEXTLEN:
1655 case WM_ASKCBFORMATNAME:
1656 return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
1657 case WM_NCCREATE:
1658 case WM_CREATE:
1660 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1661 lParam = *(LPARAM *)(cs + 1);
1662 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1663 unmap_str_16_to_32W( cs->lpszName );
1664 unmap_str_16_to_32W( cs->lpszClass );
1665 HeapFree( GetProcessHeap(), 0, cs );
1667 break;
1668 case WM_MDICREATE:
1670 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1671 lParam = *(LPARAM *)(cs + 1);
1672 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1673 unmap_str_16_to_32W( cs->szTitle );
1674 unmap_str_16_to_32W( cs->szClass );
1675 HeapFree( GetProcessHeap(), 0, cs );
1677 break;
1678 case WM_GETDLGCODE:
1679 if (lParam)
1681 LPMSG msg32 = (LPMSG)lParam;
1683 WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1684 result);
1685 HeapFree( GetProcessHeap(), 0, msg32 );
1687 break;
1688 default:
1689 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1691 return result;
1694 static HANDLE16 convert_handle_32_to_16(HANDLE src, unsigned int flags)
1696 HANDLE16 dst;
1697 UINT sz = GlobalSize(src);
1698 LPSTR ptr16, ptr32;
1700 if (!(dst = GlobalAlloc16(flags, sz)))
1701 return 0;
1702 ptr32 = GlobalLock(src);
1703 ptr16 = GlobalLock16(dst);
1704 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1705 GlobalUnlock(src);
1706 GlobalUnlock16(dst);
1708 return dst;
1712 /**********************************************************************
1713 * WINPROC_MapMsg32ATo16
1715 * Map a message from 32-bit Ansi to 16-bit.
1716 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1718 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1719 UINT16 *pmsg16, WPARAM16 *pwparam16,
1720 LPARAM *plparam )
1722 *pmsg16 = (UINT16)msg32;
1723 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1724 switch(msg32)
1726 case BM_GETCHECK:
1727 case BM_SETCHECK:
1728 case BM_GETSTATE:
1729 case BM_SETSTATE:
1730 case BM_SETSTYLE:
1731 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1732 return 0;
1734 case EM_GETSEL:
1735 case EM_GETRECT:
1736 case EM_SETRECT:
1737 case EM_SETRECTNP:
1738 case EM_SCROLL:
1739 case EM_LINESCROLL:
1740 case EM_SCROLLCARET:
1741 case EM_GETMODIFY:
1742 case EM_SETMODIFY:
1743 case EM_GETLINECOUNT:
1744 case EM_LINEINDEX:
1745 case EM_SETHANDLE:
1746 case EM_GETHANDLE:
1747 case EM_GETTHUMB:
1748 case EM_LINELENGTH:
1749 case EM_REPLACESEL:
1750 case EM_GETLINE:
1751 case EM_LIMITTEXT:
1752 case EM_CANUNDO:
1753 case EM_UNDO:
1754 case EM_FMTLINES:
1755 case EM_LINEFROMCHAR:
1756 case EM_SETTABSTOPS:
1757 case EM_SETPASSWORDCHAR:
1758 case EM_EMPTYUNDOBUFFER:
1759 case EM_GETFIRSTVISIBLELINE:
1760 case EM_SETREADONLY:
1761 case EM_SETWORDBREAKPROC:
1762 case EM_GETWORDBREAKPROC:
1763 case EM_GETPASSWORDCHAR:
1764 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1765 return 0;
1767 case LB_CARETOFF:
1768 case LB_CARETON:
1769 case LB_DELETESTRING:
1770 case LB_GETANCHORINDEX:
1771 case LB_GETCARETINDEX:
1772 case LB_GETCOUNT:
1773 case LB_GETCURSEL:
1774 case LB_GETHORIZONTALEXTENT:
1775 case LB_GETITEMDATA:
1776 case LB_GETITEMHEIGHT:
1777 case LB_GETSEL:
1778 case LB_GETSELCOUNT:
1779 case LB_GETTEXTLEN:
1780 case LB_GETTOPINDEX:
1781 case LB_RESETCONTENT:
1782 case LB_SELITEMRANGE:
1783 case LB_SELITEMRANGEEX:
1784 case LB_SETANCHORINDEX:
1785 case LB_SETCARETINDEX:
1786 case LB_SETCOLUMNWIDTH:
1787 case LB_SETCURSEL:
1788 case LB_SETHORIZONTALEXTENT:
1789 case LB_SETITEMDATA:
1790 case LB_SETITEMHEIGHT:
1791 case LB_SETSEL:
1792 case LB_SETTOPINDEX:
1793 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1794 return 0;
1795 case CB_DELETESTRING:
1796 case CB_GETCOUNT:
1797 case CB_GETLBTEXTLEN:
1798 case CB_LIMITTEXT:
1799 case CB_RESETCONTENT:
1800 case CB_SETEDITSEL:
1801 case CB_GETCURSEL:
1802 case CB_SETCURSEL:
1803 case CB_SHOWDROPDOWN:
1804 case CB_SETITEMDATA:
1805 case CB_SETITEMHEIGHT:
1806 case CB_GETITEMHEIGHT:
1807 case CB_SETEXTENDEDUI:
1808 case CB_GETEXTENDEDUI:
1809 case CB_GETDROPPEDSTATE:
1810 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1811 return 0;
1812 case CB_GETEDITSEL:
1813 *pmsg16 = CB_GETEDITSEL16;
1814 return 1;
1816 case LB_ADDSTRING:
1817 case LB_FINDSTRING:
1818 case LB_FINDSTRINGEXACT:
1819 case LB_INSERTSTRING:
1820 case LB_SELECTSTRING:
1821 case LB_DIR:
1822 case LB_ADDFILE:
1823 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1824 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1825 return 1;
1827 case CB_ADDSTRING:
1828 case CB_FINDSTRING:
1829 case CB_FINDSTRINGEXACT:
1830 case CB_INSERTSTRING:
1831 case CB_SELECTSTRING:
1832 case CB_DIR:
1833 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1834 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1835 return 1;
1837 case LB_GETITEMRECT:
1839 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1840 if (!rect) return -1;
1841 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1842 *plparam = MapLS( rect );
1844 *pmsg16 = LB_GETITEMRECT16;
1845 return 1;
1846 case LB_GETSELITEMS:
1848 LPINT16 items;
1849 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1850 if (!(items = HeapAlloc( GetProcessHeap(), 0,
1851 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1852 *((LPARAM *)items)++ = *plparam; /* Store the previous lParam */
1853 *plparam = MapLS( items );
1855 *pmsg16 = LB_GETSELITEMS16;
1856 return 1;
1857 case LB_SETTABSTOPS:
1858 if (wParam32)
1860 INT i;
1861 LPINT16 stops;
1862 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1863 if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1864 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1865 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1866 *plparam = MapLS( stops );
1867 return 1;
1869 *pmsg16 = LB_SETTABSTOPS16;
1870 return 0;
1872 case CB_GETDROPPEDCONTROLRECT:
1874 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1875 if (!rect) return -1;
1876 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1877 *plparam = (LPARAM)MapLS(rect);
1879 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1880 return 1;
1882 case LB_GETTEXT:
1883 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1884 *pmsg16 = LB_GETTEXT16;
1885 return 1;
1887 case CB_GETLBTEXT:
1888 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1889 *pmsg16 = CB_GETLBTEXT16;
1890 return 1;
1892 case EM_SETSEL:
1893 *pwparam16 = 0;
1894 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1895 *pmsg16 = EM_SETSEL16;
1896 return 0;
1898 case WM_ACTIVATE:
1899 case WM_CHARTOITEM:
1900 case WM_COMMAND:
1901 case WM_VKEYTOITEM:
1902 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1903 return 0;
1904 case WM_HSCROLL:
1905 case WM_VSCROLL:
1906 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1907 return 0;
1908 case WM_CTLCOLORMSGBOX:
1909 case WM_CTLCOLOREDIT:
1910 case WM_CTLCOLORLISTBOX:
1911 case WM_CTLCOLORBTN:
1912 case WM_CTLCOLORDLG:
1913 case WM_CTLCOLORSCROLLBAR:
1914 case WM_CTLCOLORSTATIC:
1915 *pmsg16 = WM_CTLCOLOR;
1916 *plparam = MAKELPARAM( (HWND16)*plparam,
1917 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1918 return 0;
1919 case WM_COMPAREITEM:
1921 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1922 COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1923 if (!cis) return -1;
1924 cis->CtlType = (UINT16)cis32->CtlType;
1925 cis->CtlID = (UINT16)cis32->CtlID;
1926 cis->hwndItem = WIN_Handle16( cis32->hwndItem );
1927 cis->itemID1 = (UINT16)cis32->itemID1;
1928 cis->itemData1 = cis32->itemData1;
1929 cis->itemID2 = (UINT16)cis32->itemID2;
1930 cis->itemData2 = cis32->itemData2;
1931 *plparam = MapLS( cis );
1933 return 1;
1934 case WM_DELETEITEM:
1936 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1937 DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1938 if (!dis) return -1;
1939 dis->CtlType = (UINT16)dis32->CtlType;
1940 dis->CtlID = (UINT16)dis32->CtlID;
1941 dis->itemID = (UINT16)dis32->itemID;
1942 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1943 : WIN_Handle16( dis32->hwndItem );
1944 dis->itemData = dis32->itemData;
1945 *plparam = MapLS( dis );
1947 return 1;
1948 case WM_DRAWITEM:
1950 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1951 DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
1952 if (!dis) return -1;
1953 dis->CtlType = (UINT16)dis32->CtlType;
1954 dis->CtlID = (UINT16)dis32->CtlID;
1955 dis->itemID = (UINT16)dis32->itemID;
1956 dis->itemAction = (UINT16)dis32->itemAction;
1957 dis->itemState = (UINT16)dis32->itemState;
1958 dis->hwndItem = WIN_Handle16( dis32->hwndItem );
1959 dis->hDC = (HDC16)dis32->hDC;
1960 dis->itemData = dis32->itemData;
1961 CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1962 *plparam = MapLS( dis );
1964 return 1;
1965 case WM_MEASUREITEM:
1967 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1968 MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
1969 if (!mis) return -1;
1970 mis->CtlType = (UINT16)mis32->CtlType;
1971 mis->CtlID = (UINT16)mis32->CtlID;
1972 mis->itemID = (UINT16)mis32->itemID;
1973 mis->itemWidth = (UINT16)mis32->itemWidth;
1974 mis->itemHeight = (UINT16)mis32->itemHeight;
1975 mis->itemData = mis32->itemData;
1976 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1977 *plparam = MapLS( mis );
1979 return 1;
1980 case WM_GETMINMAXINFO:
1982 MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
1983 if (!mmi) return -1;
1984 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
1985 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1986 *plparam = MapLS( mmi );
1988 return 1;
1989 case WM_GETTEXT:
1990 case WM_ASKCBFORMATNAME:
1992 LPSTR str;
1993 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
1994 if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
1995 *((LPARAM *)str)++ = *plparam; /* Store the previous lParam */
1996 *plparam = MapLS( str );
1998 return 1;
1999 case WM_MDICREATE:
2001 MDICREATESTRUCT16 *cs;
2002 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
2004 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2005 STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
2006 cs->szTitle = MapLS( cs32->szTitle );
2007 cs->szClass = MapLS( cs32->szClass );
2008 *plparam = MapLS( cs );
2010 return 1;
2011 case WM_MDIGETACTIVE:
2012 return 1;
2013 case WM_MDISETMENU:
2014 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
2015 (HMENU16)LOWORD(*plparam) );
2016 *pwparam16 = (*plparam == 0);
2017 return 0;
2018 case WM_MENUSELECT:
2019 if(HIWORD(wParam32) & MF_POPUP)
2021 UINT16 hmenu;
2022 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
2024 if((hmenu = GetSubMenu((HMENU16)*plparam, *pwparam16)))
2025 *pwparam16=hmenu;
2028 /* fall through */
2029 case WM_MENUCHAR:
2030 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2031 return 0;
2032 case WM_MDIACTIVATE:
2033 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
2035 *pwparam16 = ((HWND)*plparam == hwnd);
2036 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
2037 (HWND16)LOWORD(wParam32) );
2039 else
2041 *pwparam16 = WIN_Handle16( (HWND)wParam32 );
2042 *plparam = 0;
2044 return 0;
2045 case WM_NCCALCSIZE:
2047 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
2048 NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
2049 if (!nc) return -1;
2051 CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
2052 if (wParam32)
2054 WINDOWPOS16 *wp;
2055 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
2056 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
2057 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
2059 HeapFree( GetProcessHeap(), 0, nc );
2060 return -1;
2062 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
2063 nc->lppos = MapLS( wp );
2065 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
2066 *plparam = MapLS( nc );
2068 return 1;
2069 case WM_NCCREATE:
2070 case WM_CREATE:
2072 CREATESTRUCT16 *cs;
2073 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
2075 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2076 STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
2077 cs->lpszName = MapLS( cs32->lpszName );
2078 cs->lpszClass = MapLS( cs32->lpszClass );
2079 *plparam = MapLS( cs );
2081 return 1;
2082 case WM_PARENTNOTIFY:
2083 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2084 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2085 /* else nothing to do */
2086 return 0;
2087 case WM_NOTIFY:
2088 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2089 return 1;
2090 case WM_SETTEXT:
2091 case WM_WININICHANGE:
2092 case WM_DEVMODECHANGE:
2093 *plparam = MapLS( (LPSTR)*plparam );
2094 return 1;
2095 case WM_WINDOWPOSCHANGING:
2096 case WM_WINDOWPOSCHANGED:
2098 WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
2099 if (!wp) return -1;
2100 STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2101 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
2102 *plparam = MapLS( wp );
2104 return 1;
2105 case WM_GETDLGCODE:
2106 if (*plparam) {
2107 LPMSG msg32 = (LPMSG) *plparam;
2108 LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
2110 if (!msg16) return -1;
2111 msg16->hwnd = WIN_Handle16( msg32->hwnd );
2112 msg16->lParam = msg32->lParam;
2113 msg16->time = msg32->time;
2114 CONV_POINT32TO16(&msg32->pt,&msg16->pt);
2115 /* this is right, right? */
2116 if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2117 &msg16->message,&msg16->wParam, &msg16->lParam)<0)
2119 HeapFree( GetProcessHeap(), 0, msg16 );
2120 return -1;
2122 *plparam = MapLS( msg16 );
2123 return 1;
2125 return 0;
2127 case WM_ACTIVATEAPP:
2128 if (*plparam) *plparam = (LPARAM)THREAD_IdToTEB((DWORD) *plparam)->htask16;
2129 return 0;
2130 case WM_NEXTMENU:
2132 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2133 *plparam = next->hmenuIn;
2134 return 1;
2136 case WM_PAINTCLIPBOARD:
2137 case WM_SIZECLIPBOARD:
2138 FIXME_(msg)("message %04x needs translation\n", msg32 );
2139 return -1;
2140 /* following messages should not be sent to 16-bit apps */
2141 case WM_SIZING:
2142 case WM_MOVING:
2143 case WM_CAPTURECHANGED:
2144 case WM_STYLECHANGING:
2145 case WM_STYLECHANGED:
2146 return -1;
2147 case WM_DDE_INITIATE:
2148 case WM_DDE_TERMINATE:
2149 case WM_DDE_UNADVISE:
2150 case WM_DDE_REQUEST:
2151 *pwparam16 = WIN_Handle16(wParam32);
2152 return 0;
2153 case WM_DDE_ADVISE:
2154 case WM_DDE_DATA:
2155 case WM_DDE_POKE:
2157 unsigned lo32, hi;
2158 HANDLE16 lo16 = 0;
2160 *pwparam16 = WIN_Handle16(wParam32);
2161 UnpackDDElParam(msg32, *plparam, &lo32, &hi);
2162 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
2163 return -1;
2164 *plparam = MAKELPARAM(lo16, hi);
2166 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2167 case WM_DDE_ACK:
2169 UINT lo, hi;
2170 int flag = 0;
2171 char buf[2];
2173 *pwparam16 = WIN_Handle16(wParam32);
2175 UnpackDDElParam(msg32, *plparam, &lo, &hi);
2177 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
2178 if (GlobalSize(hi) != 0) flag |= 2;
2179 switch (flag)
2181 case 0:
2182 if (hi)
2184 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2185 hi = 0;
2187 break;
2188 case 1:
2189 break; /* atom, nothing to do */
2190 case 3:
2191 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
2192 /* fall thru */
2193 case 2:
2194 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
2195 break;
2197 *plparam = MAKELPARAM(lo, hi);
2199 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2200 case WM_DDE_EXECUTE:
2201 *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
2202 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
2203 default: /* No translation needed */
2204 return 0;
2209 /**********************************************************************
2210 * WINPROC_UnmapMsg32ATo16
2212 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2214 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2215 MSGPARAM16* p16 )
2217 switch(msg)
2219 case LB_ADDFILE:
2220 case LB_ADDSTRING:
2221 case LB_DIR:
2222 case LB_FINDSTRING:
2223 case LB_FINDSTRINGEXACT:
2224 case LB_INSERTSTRING:
2225 case LB_SELECTSTRING:
2226 case LB_GETTEXT:
2227 case CB_ADDSTRING:
2228 case CB_FINDSTRING:
2229 case CB_FINDSTRINGEXACT:
2230 case CB_INSERTSTRING:
2231 case CB_SELECTSTRING:
2232 case CB_DIR:
2233 case CB_GETLBTEXT:
2234 case WM_SETTEXT:
2235 case WM_WININICHANGE:
2236 case WM_DEVMODECHANGE:
2237 UnMapLS( (SEGPTR)p16->lParam );
2238 break;
2239 case LB_SETTABSTOPS:
2240 case WM_COMPAREITEM:
2241 case WM_DELETEITEM:
2242 case WM_DRAWITEM:
2244 void *ptr = MapSL( p16->lParam );
2245 UnMapLS( p16->lParam );
2246 HeapFree( GetProcessHeap(), 0, ptr );
2248 break;
2249 case CB_GETDROPPEDCONTROLRECT:
2250 case LB_GETITEMRECT:
2252 RECT16 *rect = MapSL(p16->lParam);
2253 UnMapLS( p16->lParam );
2254 p16->lParam = *(LPARAM *)(rect + 1);
2255 CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2256 HeapFree( GetProcessHeap(), 0, rect );
2258 break;
2259 case LB_GETSELITEMS:
2261 INT i;
2262 LPINT16 items = MapSL(p16->lParam);
2263 UnMapLS( p16->lParam );
2264 p16->lParam = *((LPARAM *)items - 1);
2265 for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2266 HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
2268 break;
2270 case CB_GETEDITSEL:
2271 if( wParam )
2272 *((LPUINT)(wParam)) = LOWORD(p16->lResult);
2273 if( lParam )
2274 *((LPUINT)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
2275 break;
2277 case WM_MEASUREITEM:
2279 MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2280 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2281 mis32->itemWidth = mis->itemWidth;
2282 mis32->itemHeight = mis->itemHeight;
2283 UnMapLS( p16->lParam );
2284 HeapFree( GetProcessHeap(), 0, mis );
2286 break;
2287 case WM_GETMINMAXINFO:
2289 MINMAXINFO16 *mmi = MapSL(p16->lParam);
2290 UnMapLS( p16->lParam );
2291 p16->lParam = *(LPARAM *)(mmi + 1);
2292 STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2293 HeapFree( GetProcessHeap(), 0, mmi );
2295 break;
2296 case WM_GETTEXT:
2297 case WM_ASKCBFORMATNAME:
2299 LPSTR str = MapSL(p16->lParam);
2300 UnMapLS( p16->lParam );
2301 p16->lParam = *((LPARAM *)str - 1);
2302 lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2303 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2305 break;
2306 case WM_MDICREATE:
2308 MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2309 UnMapLS( cs->szTitle );
2310 UnMapLS( cs->szClass );
2311 UnMapLS( p16->lParam );
2312 HeapFree( GetProcessHeap(), 0, cs );
2314 break;
2315 case WM_MDIGETACTIVE:
2316 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2317 p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2318 break;
2319 case WM_NCCALCSIZE:
2321 NCCALCSIZE_PARAMS *nc32;
2322 NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2323 UnMapLS( p16->lParam );
2324 p16->lParam = *(LPARAM *)(nc + 1);
2325 nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2326 CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2327 if (p16->wParam)
2329 WINDOWPOS16 *pos = MapSL(nc->lppos);
2330 UnMapLS( nc->lppos );
2331 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2332 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2333 STRUCT32_WINDOWPOS16to32( pos, nc32->lppos );
2334 HeapFree( GetProcessHeap(), 0, pos );
2336 HeapFree( GetProcessHeap(), 0, nc );
2338 break;
2339 case WM_NCCREATE:
2340 case WM_CREATE:
2342 CREATESTRUCT16 *cs = MapSL(p16->lParam);
2343 UnMapLS( p16->lParam );
2344 UnMapLS( cs->lpszName );
2345 UnMapLS( cs->lpszClass );
2346 HeapFree( GetProcessHeap(), 0, cs );
2348 break;
2349 case WM_WINDOWPOSCHANGING:
2350 case WM_WINDOWPOSCHANGED:
2352 WINDOWPOS16 *wp = MapSL(p16->lParam);
2353 UnMapLS( p16->lParam );
2354 p16->lParam = *(LPARAM *)(wp + 1);
2355 STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2356 HeapFree( GetProcessHeap(), 0, wp );
2358 break;
2359 case WM_NOTIFY:
2360 UnMapLS(p16->lParam);
2361 break;
2362 case WM_GETDLGCODE:
2363 if (p16->lParam)
2365 LPMSG16 msg16 = MapSL(p16->lParam);
2366 MSGPARAM16 msgp16;
2367 UnMapLS( p16->lParam );
2368 msgp16.wParam=msg16->wParam;
2369 msgp16.lParam=msg16->lParam;
2370 WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2371 ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2372 &msgp16 );
2373 HeapFree( GetProcessHeap(), 0, msg16 );
2375 break;
2376 case WM_NEXTMENU:
2378 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2379 next->hmenuNext = LOWORD(p16->lResult);
2380 next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2381 p16->lResult = 0;
2383 break;
2388 /**********************************************************************
2389 * WINPROC_MapMsg32WTo16
2391 * Map a message from 32-bit Unicode to 16-bit.
2392 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2394 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2395 UINT16 *pmsg16, WPARAM16 *pwparam16,
2396 LPARAM *plparam )
2398 BYTE ch;
2399 WCHAR wch;
2401 *pmsg16 = LOWORD(msg32);
2402 *pwparam16 = LOWORD(wParam32);
2403 switch(msg32)
2405 case LB_ADDSTRING:
2406 case LB_FINDSTRING:
2407 case LB_FINDSTRINGEXACT:
2408 case LB_INSERTSTRING:
2409 case LB_SELECTSTRING:
2410 case LB_DIR:
2411 case LB_ADDFILE:
2412 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2413 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2414 return 1;
2416 case CB_ADDSTRING:
2417 case CB_FINDSTRING:
2418 case CB_FINDSTRINGEXACT:
2419 case CB_INSERTSTRING:
2420 case CB_SELECTSTRING:
2421 case CB_DIR:
2422 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2423 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2424 return 1;
2426 case WM_NCCREATE:
2427 case WM_CREATE:
2429 CREATESTRUCT16 *cs;
2430 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2432 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2433 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2434 cs->lpszName = map_str_32W_to_16( cs32->lpszName );
2435 cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2436 *plparam = MapLS(cs);
2438 return 1;
2439 case WM_MDICREATE:
2441 MDICREATESTRUCT16 *cs;
2442 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2444 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2445 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2446 cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2447 cs->szClass = map_str_32W_to_16( cs32->szClass );
2448 *plparam = MapLS(cs);
2450 return 1;
2451 case WM_SETTEXT:
2452 case WM_WININICHANGE:
2453 case WM_DEVMODECHANGE:
2454 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2455 return 1;
2456 case LB_GETTEXT:
2457 case CB_GETLBTEXT:
2458 if ( WINPROC_TestLBForStr( hwnd ))
2460 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 256 ); /* FIXME: fixed sized buffer */
2461 if (!str) return -1;
2462 *pmsg16 = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2463 *plparam = (LPARAM)MapLS(str);
2465 return 1;
2467 case WM_CHARTOITEM:
2468 wch = LOWORD(wParam32);
2469 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2470 *pwparam16 = ch;
2471 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2472 return 0;
2473 case WM_MENUCHAR:
2474 wch = LOWORD(wParam32);
2475 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2476 *pwparam16 = ch;
2477 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2478 return 0;
2479 case WM_CHAR:
2480 case WM_DEADCHAR:
2481 case WM_SYSCHAR:
2482 case WM_SYSDEADCHAR:
2483 wch = wParam32;
2484 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2485 *pwparam16 = ch;
2486 return 0;
2488 default: /* No Unicode translation needed (?) */
2489 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2490 pwparam16, plparam );
2495 /**********************************************************************
2496 * WINPROC_UnmapMsg32WTo16
2498 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2500 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2501 MSGPARAM16* p16 )
2503 switch(msg)
2505 case LB_ADDSTRING:
2506 case LB_FINDSTRING:
2507 case LB_FINDSTRINGEXACT:
2508 case LB_INSERTSTRING:
2509 case LB_SELECTSTRING:
2510 case LB_DIR:
2511 case LB_ADDFILE:
2512 case CB_ADDSTRING:
2513 case CB_FINDSTRING:
2514 case CB_FINDSTRINGEXACT:
2515 case CB_INSERTSTRING:
2516 case CB_SELECTSTRING:
2517 case CB_DIR:
2518 case WM_SETTEXT:
2519 case WM_WININICHANGE:
2520 case WM_DEVMODECHANGE:
2521 unmap_str_32W_to_16( p16->lParam );
2522 break;
2523 case WM_NCCREATE:
2524 case WM_CREATE:
2526 CREATESTRUCT16 *cs = MapSL(p16->lParam);
2527 UnMapLS( p16->lParam );
2528 unmap_str_32W_to_16( cs->lpszName );
2529 unmap_str_32W_to_16( cs->lpszClass );
2530 HeapFree( GetProcessHeap(), 0, cs );
2532 break;
2533 case WM_MDICREATE:
2535 MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2536 UnMapLS( p16->lParam );
2537 unmap_str_32W_to_16( cs->szTitle );
2538 unmap_str_32W_to_16( cs->szClass );
2539 HeapFree( GetProcessHeap(), 0, cs );
2541 break;
2542 case WM_GETTEXT:
2543 case WM_ASKCBFORMATNAME:
2545 LPSTR str = MapSL(p16->lParam);
2546 UnMapLS( p16->lParam );
2547 p16->lParam = *((LPARAM *)str - 1);
2548 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2549 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2551 break;
2552 case LB_GETTEXT:
2553 case CB_GETLBTEXT:
2554 if ( WINPROC_TestLBForStr( hwnd ))
2556 LPSTR str = MapSL(p16->lParam);
2557 UnMapLS( p16->lParam );
2558 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2559 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2561 break;
2562 default:
2563 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2564 break;
2569 /**********************************************************************
2570 * WINPROC_CallProc32ATo32W
2572 * Call a window procedure, translating args from Ansi to Unicode.
2574 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2575 UINT msg, WPARAM wParam,
2576 LPARAM lParam )
2578 LRESULT result;
2579 int unmap;
2581 TRACE_(msg)("func %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
2582 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2584 if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2585 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2586 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2587 return 0;
2589 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2590 if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2591 return result;
2595 /**********************************************************************
2596 * WINPROC_CallProc32WTo32A
2598 * Call a window procedure, translating args from Unicode to Ansi.
2600 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2601 UINT msg, WPARAM wParam,
2602 LPARAM lParam )
2604 LRESULT result;
2605 int unmap;
2607 TRACE_(msg)("func %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
2608 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2610 if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2611 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2612 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2613 return 0;
2615 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2616 if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2617 return result;
2621 /**********************************************************************
2622 * __wine_call_wndproc_32A (USER.1010)
2624 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2625 WNDPROC func )
2627 LRESULT result;
2628 UINT msg32;
2629 WPARAM wParam32;
2630 HWND hwnd32 = WIN_Handle32( hwnd );
2632 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2633 return 0;
2634 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2635 return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
2639 /**********************************************************************
2640 * __wine_call_wndproc_32W (USER.1011)
2642 LRESULT WINAPI __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2643 WNDPROC func )
2645 LRESULT result;
2646 UINT msg32;
2647 WPARAM wParam32;
2648 HWND hwnd32 = WIN_Handle32( hwnd );
2650 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2651 return 0;
2652 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2653 return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
2657 /**********************************************************************
2658 * WINPROC_CallProc32ATo16
2660 * Call a 16-bit window procedure, translating the 32-bit args.
2662 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2663 UINT msg, WPARAM wParam,
2664 LPARAM lParam )
2666 UINT16 msg16;
2667 MSGPARAM16 mp16;
2669 TRACE_(msg)("func %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
2670 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2672 mp16.lParam = lParam;
2673 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2674 return 0;
2675 mp16.lResult = WINPROC_CallWndProc16( func, WIN_Handle16(hwnd), msg16,
2676 mp16.wParam, mp16.lParam );
2677 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2678 return mp16.lResult;
2682 /**********************************************************************
2683 * WINPROC_CallProc32WTo16
2685 * Call a 16-bit window procedure, translating the 32-bit args.
2687 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2688 UINT msg, WPARAM wParam,
2689 LPARAM lParam )
2691 UINT16 msg16;
2692 MSGPARAM16 mp16;
2694 TRACE_(msg)("func %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
2695 func, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2697 mp16.lParam = lParam;
2698 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2699 &mp16.lParam ) == -1)
2700 return 0;
2701 mp16.lResult = WINPROC_CallWndProc16( func, WIN_Handle16(hwnd), msg16,
2702 mp16.wParam, mp16.lParam );
2703 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2704 return mp16.lResult;
2708 /**********************************************************************
2709 * CallWindowProc (USER.122)
2710 * CallWindowProc16 (USER32.@)
2712 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2713 WPARAM16 wParam, LPARAM lParam )
2715 WINDOWPROC *proc;
2717 if (!func) return 0;
2719 if (!(proc = WINPROC_GetPtr( func )))
2720 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2722 #if testing
2723 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2724 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2725 #endif
2727 switch(proc->type)
2729 case WIN_PROC_16:
2730 if (!proc->thunk.t_from32.proc) return 0;
2731 return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2732 hwnd, msg, wParam, lParam );
2733 case WIN_PROC_32A:
2734 if (!proc->thunk.t_from16.proc) return 0;
2735 return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2736 case WIN_PROC_32W:
2737 if (!proc->thunk.t_from16.proc) return 0;
2738 return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2739 default:
2740 WARN_(relay)("Invalid proc %p\n", proc );
2741 return 0;
2746 /**********************************************************************
2747 * CallWindowProcA (USER32.@)
2749 * The CallWindowProc() function invokes the windows procedure _func_,
2750 * with _hwnd_ as the target window, the message specified by _msg_, and
2751 * the message parameters _wParam_ and _lParam_.
2753 * Some kinds of argument conversion may be done, I'm not sure what.
2755 * CallWindowProc() may be used for windows subclassing. Use
2756 * SetWindowLong() to set a new windows procedure for windows of the
2757 * subclass, and handle subclassed messages in the new windows
2758 * procedure. The new windows procedure may then use CallWindowProc()
2759 * with _func_ set to the parent class's windows procedure to dispatch
2760 * the message to the superclass.
2762 * RETURNS
2764 * The return value is message dependent.
2766 * CONFORMANCE
2768 * ECMA-234, Win32
2770 LRESULT WINAPI CallWindowProcA(
2771 WNDPROC func, /* [in] window procedure */
2772 HWND hwnd, /* [in] target window */
2773 UINT msg, /* [in] message */
2774 WPARAM wParam, /* [in] message dependent parameter */
2775 LPARAM lParam /* [in] message dependent parameter */
2777 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2779 if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2781 #if testing
2782 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2783 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2784 #endif
2786 switch(proc->type)
2788 case WIN_PROC_16:
2789 if (!proc->thunk.t_from32.proc) return 0;
2790 return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2791 hwnd, msg, wParam, lParam );
2792 case WIN_PROC_32A:
2793 if (!proc->thunk.t_from16.proc) return 0;
2794 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2795 hwnd, msg, wParam, lParam );
2796 case WIN_PROC_32W:
2797 if (!proc->thunk.t_from16.proc) return 0;
2798 return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2799 hwnd, msg, wParam, lParam );
2800 default:
2801 WARN_(relay)("Invalid proc %p\n", proc );
2802 return 0;
2807 /**********************************************************************
2808 * CallWindowProcW (USER32.@)
2810 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2811 WPARAM wParam, LPARAM lParam )
2813 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2815 if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2817 #if testing
2818 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2819 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2820 #endif
2822 switch(proc->type)
2824 case WIN_PROC_16:
2825 if (!proc->thunk.t_from32.proc) return 0;
2826 return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2827 hwnd, msg, wParam, lParam );
2828 case WIN_PROC_32A:
2829 if (!proc->thunk.t_from16.proc) return 0;
2830 return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2831 hwnd, msg, wParam, lParam );
2832 case WIN_PROC_32W:
2833 if (!proc->thunk.t_from16.proc) return 0;
2834 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2835 hwnd, msg, wParam, lParam );
2836 default:
2837 WARN_(relay)("Invalid proc %p\n", proc );
2838 return 0;