And in addition to Mingw32 we will want the _ versions.
[wine/wine-kai.git] / windows / winproc.c
blob9a00e30613275c5fbb0bc647755c1ae66729f7f2
1 /*
2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include "config.h"
10 #include <string.h>
12 #include "windef.h"
13 #include "winbase.h"
14 #include "wingdi.h"
15 #include "wine/winbase16.h"
16 #include "wine/winuser16.h"
17 #include "stackframe.h"
18 #include "selectors.h"
19 #include "controls.h"
20 #include "heap.h"
21 #include "struct32.h"
22 #include "win.h"
23 #include "winproc.h"
24 #include "debugtools.h"
25 #include "spy.h"
26 #include "task.h"
27 #include "thread.h"
29 DECLARE_DEBUG_CHANNEL(msg);
30 DECLARE_DEBUG_CHANNEL(relay);
31 DECLARE_DEBUG_CHANNEL(win);
33 #include "pshpack1.h"
35 /* Window procedure 16-to-32-bit thunk */
36 typedef struct
38 BYTE popl_eax; /* popl %eax (return address) */
39 BYTE pushl_func; /* pushl $proc */
40 WNDPROC proc;
41 BYTE pushl_eax; /* pushl %eax */
42 BYTE ljmp; /* ljmp relay*/
43 DWORD relay_offset; /* __wine_call_wndproc_32A/W */
44 WORD relay_sel;
45 } WINPROC_THUNK_FROM16;
47 /* Window procedure 32-to-16-bit thunk */
48 typedef struct
50 BYTE popl_eax; /* popl %eax (return address) */
51 BYTE pushl_func; /* pushl $proc */
52 WNDPROC16 proc;
53 BYTE pushl_eax; /* pushl %eax */
54 BYTE jmp; /* jmp relay (relative jump)*/
55 void (*relay)(); /* WINPROC_CallProc32ATo16() */
56 } WINPROC_THUNK_FROM32;
58 /* Simple jmp to call 32-bit procedure directly */
59 typedef struct
61 BYTE jmp; /* jmp proc (relative jump) */
62 WNDPROC proc;
63 } WINPROC_JUMP;
64 #include "poppack.h"
66 typedef union
68 WINPROC_THUNK_FROM16 t_from16;
69 WINPROC_THUNK_FROM32 t_from32;
70 } WINPROC_THUNK;
72 typedef struct tagWINDOWPROC
74 WINPROC_THUNK thunk; /* Thunk */
75 WINPROC_JUMP jmp; /* Jump */
76 struct tagWINDOWPROC *next; /* Next window proc */
77 UINT magic; /* Magic number */
78 WINDOWPROCTYPE type; /* Function type */
79 WINDOWPROCUSER user; /* Function user */
80 } WINDOWPROC;
82 #define WINPROC_MAGIC ('W' | ('P' << 8) | ('R' << 16) | ('C' << 24))
84 #define WINPROC_THUNKPROC(pproc) \
85 (((pproc)->type == WIN_PROC_16) ? \
86 (WNDPROC16)((pproc)->thunk.t_from32.proc) : \
87 (WNDPROC16)((pproc)->thunk.t_from16.proc))
89 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
90 UINT msg, WPARAM wParam,
91 LPARAM lParam );
92 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
93 UINT msg, WPARAM wParam,
94 LPARAM lParam );
96 static HANDLE WinProcHeap;
97 static WORD WinProcSel;
100 /**********************************************************************
101 * WINPROC_Init
103 BOOL WINPROC_Init(void)
105 WinProcHeap = HeapCreate( 0, 0x10000, 0x10000 );
106 WinProcSel = SELECTOR_AllocBlock( (void *)WinProcHeap, 0x10000,
107 WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
108 if (!WinProcHeap || !WinProcSel)
110 WARN_(relay)("Unable to create winproc heap\n" );
111 return FALSE;
113 return TRUE;
117 #ifdef __i386__
118 /* Some window procedures modify register they shouldn't, or are not
119 * properly declared stdcall; so we need a small assembly wrapper to
120 * call them. */
121 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
122 WPARAM wParam, LPARAM lParam );
123 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
124 "pushl %ebp\n\t"
125 "movl %esp,%ebp\n\t"
126 "pushl %edi\n\t"
127 "pushl %esi\n\t"
128 "pushl %ebx\n\t"
129 "pushl 24(%ebp)\n\t"
130 "pushl 20(%ebp)\n\t"
131 "pushl 16(%ebp)\n\t"
132 "pushl 12(%ebp)\n\t"
133 "movl 8(%ebp),%eax\n\t"
134 "call *%eax\n\t"
135 "leal -12(%ebp),%esp\n\t"
136 "popl %ebx\n\t"
137 "popl %esi\n\t"
138 "popl %edi\n\t"
139 "leave\n\t"
140 "ret" );
141 #else
142 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
143 WPARAM wParam, LPARAM lParam )
145 return proc( hwnd, msg, wParam, lParam );
147 #endif /* __i386__ */
149 /**********************************************************************
150 * WINPROC_CallWndProc32
152 * Call a 32-bit WndProc.
154 static LRESULT WINPROC_CallWndProc( WNDPROC proc, HWND hwnd, UINT msg,
155 WPARAM wParam, LPARAM lParam )
157 LRESULT retvalue;
158 int iWndsLocks;
160 hwnd = WIN_GetFullHandle( hwnd );
161 if (TRACE_ON(relay))
162 DPRINTF( "%08lx:Call window proc %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx)\n",
163 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
164 /* To avoid any deadlocks, all the locks on the windows structures
165 must be suspended before the control is passed to the application */
166 iWndsLocks = WIN_SuspendWndsLock();
167 retvalue = WINPROC_wrapper( proc, hwnd, msg, wParam, lParam );
168 WIN_RestoreWndsLock(iWndsLocks);
170 if (TRACE_ON(relay))
171 DPRINTF( "%08lx:Ret window proc %p (hwnd=%08x,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
172 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam, retvalue );
173 return retvalue;
176 /***********************************************************************
177 * WINPROC_CallWndProc16
179 * Call a 16-bit window procedure
181 static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
182 UINT16 msg, WPARAM16 wParam,
183 LPARAM lParam )
185 CONTEXT86 context;
186 LRESULT ret;
187 WORD *args;
188 DWORD offset = 0;
189 TEB *teb = NtCurrentTeb();
190 int iWndsLocks;
192 /* Window procedures want ax = hInstance, ds = es = ss */
194 memset(&context, '\0', sizeof(context));
195 context.SegDs = context.SegEs = SELECTOROF(teb->cur_stack);
196 if (!(context.Eax = GetWindowWord16( hwnd, GWL_HINSTANCE ))) context.Eax = context.SegDs;
197 context.SegCs = SELECTOROF(proc);
198 context.Eip = OFFSETOF(proc);
199 context.Ebp = OFFSETOF(teb->cur_stack)
200 + (WORD)&((STACK16FRAME*)0)->bp;
202 if (lParam)
204 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
205 work if structures passed in lParam are placed in the stack/data
206 segment. Programmers easily make the mistake of converting lParam
207 to a near rather than a far pointer, since Windows apparently
208 allows this. We copy the structures to the 16 bit stack; this is
209 ugly but makes these programs work. */
210 switch (msg)
212 case WM_CREATE:
213 case WM_NCCREATE:
214 offset = sizeof(CREATESTRUCT16); break;
215 case WM_DRAWITEM:
216 offset = sizeof(DRAWITEMSTRUCT16); break;
217 case WM_COMPAREITEM:
218 offset = sizeof(COMPAREITEMSTRUCT16); break;
220 if (offset)
222 void *s = MapSL(lParam);
223 lParam = stack16_push( offset );
224 memcpy( MapSL(lParam), s, offset );
228 iWndsLocks = WIN_SuspendWndsLock();
230 args = (WORD *)THREAD_STACK16(teb) - 5;
231 args[0] = LOWORD(lParam);
232 args[1] = HIWORD(lParam);
233 args[2] = wParam;
234 args[3] = msg;
235 args[4] = hwnd;
237 wine_call_to_16_regs_short( &context, 5 * sizeof(WORD) );
238 ret = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
239 if (offset) stack16_pop( offset );
241 WIN_RestoreWndsLock(iWndsLocks);
243 return ret;
247 /**********************************************************************
248 * WINPROC_GetPtr
250 * Return a pointer to the win proc.
252 static WINDOWPROC *WINPROC_GetPtr( WNDPROC16 handle )
254 BYTE *ptr;
255 WINDOWPROC *proc;
257 /* ptr cannot be < 64K */
258 if (!HIWORD(handle)) return NULL;
260 /* Check for a linear pointer */
262 ptr = (BYTE *)handle;
263 /* First check if it is the jmp address */
264 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->jmp);
265 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
266 return proc;
267 /* Now it must be the thunk address */
268 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
269 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
270 return proc;
272 /* Check for a segmented pointer */
274 if (!IsBadReadPtr16( (SEGPTR)handle, sizeof(proc->thunk) ))
276 ptr = MapSL( (SEGPTR)handle );
277 /* It must be the thunk address */
278 proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk);
279 if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC))
280 return proc;
283 return NULL;
287 /**********************************************************************
288 * WINPROC_AllocWinProc
290 * Allocate a new window procedure.
292 static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC16 func, WINDOWPROCTYPE type,
293 WINDOWPROCUSER user )
295 static FARPROC16 relay_32A, relay_32W;
297 WINDOWPROC *proc, *oldproc;
299 /* Allocate a window procedure */
301 if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0;
303 /* Check if the function is already a win proc */
305 if ((oldproc = WINPROC_GetPtr( func )))
307 *proc = *oldproc;
309 else
311 switch(type)
313 case WIN_PROC_16:
314 proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */
315 proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */
316 proc->thunk.t_from32.proc = func;
317 proc->thunk.t_from32.pushl_eax = 0x50; /* pushl %eax */
318 proc->thunk.t_from32.jmp = 0xe9; /* jmp relay*/
319 proc->thunk.t_from32.relay = /* relative jump */
320 (void(*)())((DWORD)WINPROC_CallProc32ATo16 -
321 (DWORD)(&proc->thunk.t_from32.relay + 1));
322 break;
323 case WIN_PROC_32A:
324 if (!relay_32A) relay_32A = GetProcAddress16( GetModuleHandle16("user"),
325 "__wine_call_wndproc_32A" );
326 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
327 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
328 proc->thunk.t_from16.proc = (WNDPROC)func;
329 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
330 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
331 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32A);
332 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A);
333 proc->jmp.jmp = 0xe9;
334 /* Fixup relative jump */
335 proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
336 break;
337 case WIN_PROC_32W:
338 if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"),
339 "__wine_call_wndproc_32W" );
340 proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
341 proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
342 proc->thunk.t_from16.proc = (WNDPROC)func;
343 proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
344 proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
345 proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32W);
346 proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W);
347 proc->jmp.jmp = 0xe9;
348 /* Fixup relative jump */
349 proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
350 break;
351 default:
352 /* Should not happen */
353 break;
355 proc->magic = WINPROC_MAGIC;
356 proc->type = type;
357 proc->user = user;
359 proc->next = NULL;
360 TRACE_(win)("(%08x,%d): returning %08x\n",
361 (UINT)func, type, (UINT)proc );
362 return proc;
366 /**********************************************************************
367 * WINPROC_GetProc
369 * Get a window procedure pointer that can be passed to the Windows program.
371 WNDPROC16 WINPROC_GetProc( HWINDOWPROC proc, WINDOWPROCTYPE type )
373 WINDOWPROC *ptr = (WINDOWPROC *)proc;
375 if (!proc) return NULL;
376 if (type == WIN_PROC_16) /* We want a 16:16 address */
378 if (ptr->type == WIN_PROC_16)
379 return ptr->thunk.t_from32.proc;
380 else
381 return (WNDPROC16)MAKESEGPTR( WinProcSel, (char *)&ptr->thunk - (char *)WinProcHeap );
383 else /* We want a 32-bit address */
385 if (ptr->type == WIN_PROC_16)
386 return (WNDPROC16)&ptr->thunk;
387 else if (type != ptr->type)
388 /* Have to return the jmp address if types don't match */
389 return (WNDPROC16)&ptr->jmp;
390 else
391 /* Some Win16 programs want to get back the proc they set */
392 return (WNDPROC16)ptr->thunk.t_from16.proc;
397 /**********************************************************************
398 * WINPROC_SetProc
400 * Set the window procedure for a window or class. There are
401 * three tree classes of winproc callbacks:
403 * 1) class -> wp - not subclassed
404 * class -> wp -> wp -> wp -> wp - SetClassLong()
405 * / /
406 * 2) window -' / - not subclassed
407 * window -> wp -> wp ' - SetWindowLong()
409 * 3) timer -> wp - SetTimer()
411 * Initially, winproc of the window points to the current winproc
412 * thunk of its class. Subclassing prepends a new thunk to the
413 * window winproc chain at the head of the list. Thus, window thunk
414 * list includes class thunks and the latter are preserved when the
415 * window is destroyed.
418 BOOL WINPROC_SetProc( HWINDOWPROC *pFirst, WNDPROC16 func,
419 WINDOWPROCTYPE type, WINDOWPROCUSER user )
421 BOOL bRecycle = FALSE;
422 WINDOWPROC *proc, **ppPrev;
424 /* Check if function is already in the list */
426 ppPrev = (WINDOWPROC **)pFirst;
427 proc = WINPROC_GetPtr( func );
428 while (*ppPrev)
430 if (proc)
432 if (*ppPrev == proc)
434 if ((*ppPrev)->user != user)
436 /* terminal thunk is being restored */
438 WINPROC_FreeProc( *pFirst, (*ppPrev)->user );
439 *(WINDOWPROC **)pFirst = *ppPrev;
440 return TRUE;
442 bRecycle = TRUE;
443 break;
446 else
448 if (((*ppPrev)->type == type) &&
449 (func == WINPROC_THUNKPROC(*ppPrev)))
451 bRecycle = TRUE;
452 break;
456 /* WPF_CLASS thunk terminates window thunk list */
457 if ((*ppPrev)->user != user) break;
458 ppPrev = &(*ppPrev)->next;
461 if (bRecycle)
463 /* Extract this thunk from the list */
464 proc = *ppPrev;
465 *ppPrev = proc->next;
467 else /* Allocate a new one */
469 if (proc) /* Was already a win proc */
471 type = proc->type;
472 func = WINPROC_THUNKPROC(proc);
474 proc = WINPROC_AllocWinProc( func, type, user );
475 if (!proc) return FALSE;
478 /* Add the win proc at the head of the list */
480 TRACE_(win)("(%08x,%08x,%d): res=%08x\n",
481 (UINT)*pFirst, (UINT)func, type, (UINT)proc );
482 proc->next = *(WINDOWPROC **)pFirst;
483 *(WINDOWPROC **)pFirst = proc;
484 return TRUE;
488 /**********************************************************************
489 * WINPROC_FreeProc
491 * Free a list of win procs.
493 void WINPROC_FreeProc( HWINDOWPROC proc, WINDOWPROCUSER user )
495 while (proc)
497 WINDOWPROC *next = ((WINDOWPROC *)proc)->next;
498 if (((WINDOWPROC *)proc)->user != user) break;
499 TRACE_(win)("freeing %08x\n", (UINT)proc);
500 HeapFree( WinProcHeap, 0, proc );
501 proc = next;
506 /**********************************************************************
507 * WINPROC_GetProcType
509 * Return the window procedure type.
511 WINDOWPROCTYPE WINPROC_GetProcType( HWINDOWPROC proc )
513 if (!proc ||
514 (((WINDOWPROC *)proc)->magic != WINPROC_MAGIC))
515 return WIN_PROC_INVALID;
516 return ((WINDOWPROC *)proc)->type;
518 /**********************************************************************
519 * WINPROC_TestCBForStr
521 * Return TRUE if the lparam is a string
523 inline static BOOL WINPROC_TestCBForStr( HWND hwnd )
525 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
526 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
528 /**********************************************************************
529 * WINPROC_TestLBForStr
531 * Return TRUE if the lparam is a string
533 inline static BOOL WINPROC_TestLBForStr( HWND hwnd )
535 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
536 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
539 /**********************************************************************
540 * WINPROC_MapMsg32ATo32W
542 * Map a message from Ansi to Unicode.
543 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
545 * FIXME:
546 * WM_GETTEXT/WM_SETTEXT and static control with SS_ICON style:
547 * the first four bytes are the handle of the icon
548 * when the WM_SETTEXT message has been used to set the icon
550 INT WINPROC_MapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
552 switch(msg)
554 case WM_GETTEXT:
555 case WM_ASKCBFORMATNAME:
557 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
558 *pwparam * sizeof(WCHAR) + sizeof(LPARAM) );
559 if (!ptr) return -1;
560 *ptr++ = *plparam; /* Store previous lParam */
561 *plparam = (LPARAM)ptr;
563 return 1;
564 /* lparam is string (0-terminated) */
565 case WM_SETTEXT:
566 case WM_WININICHANGE:
567 case WM_DEVMODECHANGE:
568 case CB_DIR:
569 case CB_FINDSTRING:
570 case CB_FINDSTRINGEXACT:
571 case CB_SELECTSTRING:
572 case LB_DIR:
573 case LB_ADDFILE:
574 case LB_FINDSTRING:
575 case LB_FINDSTRINGEXACT:
576 case LB_SELECTSTRING:
577 case EM_REPLACESEL:
578 if(!*plparam) return 0;
579 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
580 return (*plparam ? 1 : -1);
581 case WM_GETTEXTLENGTH:
582 case CB_GETLBTEXTLEN:
583 case LB_GETTEXTLEN:
584 return 1; /* need to map result */
585 case WM_NCCREATE:
586 case WM_CREATE:
588 struct s
589 { CREATESTRUCTW cs; /* new structure */
590 LPCWSTR lpszName; /* allocated Name */
591 LPCWSTR lpszClass; /* allocated Class */
594 struct s *xs = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct s));
595 if (!xs) return -1;
596 xs->cs = *(CREATESTRUCTW *)*plparam;
597 if (HIWORD(xs->cs.lpszName))
598 xs->lpszName = xs->cs.lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
599 (LPCSTR)xs->cs.lpszName );
600 if (HIWORD(xs->cs.lpszClass))
601 xs->lpszClass = xs->cs.lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
602 (LPCSTR)xs->cs.lpszClass );
603 *plparam = (LPARAM)xs;
605 return 1;
606 case WM_MDICREATE:
608 MDICREATESTRUCTW *cs =
609 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
610 if (!cs) return -1;
611 *cs = *(MDICREATESTRUCTW *)*plparam;
612 if (HIWORD(cs->szClass))
613 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
614 (LPCSTR)cs->szClass );
615 if (HIWORD(cs->szTitle))
616 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
617 (LPCSTR)cs->szTitle );
618 *plparam = (LPARAM)cs;
620 return 1;
622 /* Listbox */
623 case LB_ADDSTRING:
624 case LB_INSERTSTRING:
625 if(!*plparam) return 0;
626 if ( WINPROC_TestLBForStr( hwnd ))
627 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
628 return (*plparam ? 1 : -1);
630 case LB_GETTEXT: /* fixme: fixed sized buffer */
631 { if ( WINPROC_TestLBForStr( hwnd ))
632 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
633 if (!ptr) return -1;
634 *ptr++ = *plparam; /* Store previous lParam */
635 *plparam = (LPARAM)ptr;
638 return 1;
640 /* Combobox */
641 case CB_ADDSTRING:
642 case CB_INSERTSTRING:
643 if(!*plparam) return 0;
644 if ( WINPROC_TestCBForStr( hwnd ))
645 *plparam = (LPARAM)HEAP_strdupAtoW( GetProcessHeap(), 0, (LPCSTR)*plparam );
646 return (*plparam ? 1 : -1);
648 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
649 { if ( WINPROC_TestCBForStr( hwnd ))
650 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 * sizeof(WCHAR) + sizeof(LPARAM) );
651 if (!ptr) return -1;
652 *ptr++ = *plparam; /* Store previous lParam */
653 *plparam = (LPARAM)ptr;
656 return 1;
658 /* Multiline edit */
659 case EM_GETLINE:
660 { WORD len = (WORD)*plparam;
661 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(WCHAR) );
662 if (!ptr) return -1;
663 *ptr++ = *plparam; /* Store previous lParam */
664 *((WORD *) ptr) = len; /* Store the length */
665 *plparam = (LPARAM)ptr;
667 return 1;
669 case WM_CHARTOITEM:
670 case WM_MENUCHAR:
671 case WM_CHAR:
672 case WM_DEADCHAR:
673 case WM_SYSCHAR:
674 case WM_SYSDEADCHAR:
675 case EM_SETPASSWORDCHAR:
677 char ch = LOWORD(*pwparam);
678 WCHAR wch;
679 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
680 *pwparam = MAKEWPARAM( wch, HIWORD(*pwparam) );
682 return 0;
684 case WM_PAINTCLIPBOARD:
685 case WM_SIZECLIPBOARD:
686 FIXME_(msg)("message %s (0x%x) needs translation, please report\n", SPY_GetMsgName(msg, hwnd), msg );
687 return -1;
688 default: /* No translation needed */
689 return 0;
694 /**********************************************************************
695 * WINPROC_UnmapMsg32ATo32W
697 * Unmap a message that was mapped from Ansi to Unicode.
699 LRESULT WINPROC_UnmapMsg32ATo32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
700 LRESULT result )
702 switch(msg)
704 case WM_GETTEXT:
705 case WM_ASKCBFORMATNAME:
707 LPARAM *ptr = (LPARAM *)lParam - 1;
708 if (wParam > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
709 (LPSTR)*ptr, wParam, NULL, NULL ))
710 ((LPSTR)*ptr)[wParam-1] = 0;
711 HeapFree( GetProcessHeap(), 0, ptr );
713 break;
714 case WM_GETTEXTLENGTH:
715 case CB_GETLBTEXTLEN:
716 case LB_GETTEXTLEN:
717 /* there may be one DBCS char for each Unicode char */
718 return result * 2;
719 case WM_NCCREATE:
720 case WM_CREATE:
722 struct s
723 { CREATESTRUCTW cs; /* new structure */
724 LPWSTR lpszName; /* allocated Name */
725 LPWSTR lpszClass; /* allocated Class */
727 struct s *xs = (struct s *)lParam;
728 if (xs->lpszName) HeapFree( GetProcessHeap(), 0, xs->lpszName );
729 if (xs->lpszClass) HeapFree( GetProcessHeap(), 0, xs->lpszClass );
730 HeapFree( GetProcessHeap(), 0, xs );
732 break;
734 case WM_MDICREATE:
736 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
737 if (HIWORD(cs->szTitle))
738 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
739 if (HIWORD(cs->szClass))
740 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
741 HeapFree( GetProcessHeap(), 0, cs );
743 break;
745 case WM_SETTEXT:
746 case WM_WININICHANGE:
747 case WM_DEVMODECHANGE:
748 case CB_DIR:
749 case CB_FINDSTRING:
750 case CB_FINDSTRINGEXACT:
751 case CB_SELECTSTRING:
752 case LB_DIR:
753 case LB_ADDFILE:
754 case LB_FINDSTRING:
755 case LB_FINDSTRINGEXACT:
756 case LB_SELECTSTRING:
757 case EM_REPLACESEL:
758 HeapFree( GetProcessHeap(), 0, (void *)lParam );
759 break;
761 /* Listbox */
762 case LB_ADDSTRING:
763 case LB_INSERTSTRING:
764 if ( WINPROC_TestLBForStr( hwnd ))
765 HeapFree( GetProcessHeap(), 0, (void *)lParam );
766 break;
768 case LB_GETTEXT:
769 { if ( WINPROC_TestLBForStr( hwnd ))
770 { LPARAM *ptr = (LPARAM *)lParam - 1;
771 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
772 HeapFree( GetProcessHeap(), 0, ptr );
775 break;
777 /* Combobox */
778 case CB_ADDSTRING:
779 case CB_INSERTSTRING:
780 if ( WINPROC_TestCBForStr( hwnd ))
781 HeapFree( GetProcessHeap(), 0, (void *)lParam );
782 break;
784 case CB_GETLBTEXT:
785 { if ( WINPROC_TestCBForStr( hwnd ))
786 { LPARAM *ptr = (LPARAM *)lParam - 1;
787 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1, (LPSTR)*ptr, 0x7fffffff, NULL, NULL );
788 HeapFree( GetProcessHeap(), 0, ptr );
791 break;
793 /* Multiline edit */
794 case EM_GETLINE:
795 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lParam */
796 WORD len = *(WORD *) lParam;
797 if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lParam, -1,
798 (LPSTR)*ptr, len, NULL, NULL ))
799 ((LPSTR)*ptr)[len-1] = 0;
800 HeapFree( GetProcessHeap(), 0, ptr );
802 break;
804 return result;
808 /**********************************************************************
809 * WINPROC_MapMsg32WTo32A
811 * Map a message from Unicode to Ansi.
812 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
814 INT WINPROC_MapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM *pwparam, LPARAM *plparam )
816 switch(msg)
818 case WM_GETTEXT:
819 case WM_ASKCBFORMATNAME:
821 LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0,
822 *pwparam + sizeof(LPARAM) );
823 if (!ptr) return -1;
824 *ptr++ = *plparam; /* Store previous lParam */
825 *plparam = (LPARAM)ptr;
827 return 1;
829 case WM_SETTEXT:
830 case WM_WININICHANGE:
831 case WM_DEVMODECHANGE:
832 case CB_DIR:
833 case CB_FINDSTRING:
834 case CB_FINDSTRINGEXACT:
835 case CB_SELECTSTRING:
836 case LB_DIR:
837 case LB_ADDFILE:
838 case LB_FINDSTRING:
839 case LB_FINDSTRINGEXACT:
840 case LB_SELECTSTRING:
841 case EM_REPLACESEL:
842 if(!*plparam) return 0;
843 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
844 return (*plparam ? 1 : -1);
846 case WM_NCCREATE:
847 case WM_CREATE:
849 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
850 sizeof(*cs) );
851 if (!cs) return -1;
852 *cs = *(CREATESTRUCTA *)*plparam;
853 if (HIWORD(cs->lpszName))
854 cs->lpszName = HEAP_strdupWtoA( GetProcessHeap(), 0,
855 (LPCWSTR)cs->lpszName );
856 if (HIWORD(cs->lpszClass))
857 cs->lpszClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
858 (LPCWSTR)cs->lpszClass);
859 *plparam = (LPARAM)cs;
861 return 1;
862 case WM_MDICREATE:
864 MDICREATESTRUCTA *cs =
865 (MDICREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) );
866 if (!cs) return -1;
867 *cs = *(MDICREATESTRUCTA *)*plparam;
868 if (HIWORD(cs->szTitle))
869 cs->szTitle = HEAP_strdupWtoA( GetProcessHeap(), 0,
870 (LPCWSTR)cs->szTitle );
871 if (HIWORD(cs->szClass))
872 cs->szClass = HEAP_strdupWtoA( GetProcessHeap(), 0,
873 (LPCWSTR)cs->szClass );
874 *plparam = (LPARAM)cs;
876 return 1;
878 /* Listbox */
879 case LB_ADDSTRING:
880 case LB_INSERTSTRING:
881 if(!*plparam) return 0;
882 if ( WINPROC_TestLBForStr( hwnd ))
883 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
884 return (*plparam ? 1 : -1);
886 case LB_GETTEXT: /* fixme: fixed sized buffer */
887 { if ( WINPROC_TestLBForStr( hwnd ))
888 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
889 if (!ptr) return -1;
890 *ptr++ = *plparam; /* Store previous lParam */
891 *plparam = (LPARAM)ptr;
894 return 1;
896 /* Combobox */
897 case CB_ADDSTRING:
898 case CB_INSERTSTRING:
899 if(!*plparam) return 0;
900 if ( WINPROC_TestCBForStr( hwnd ))
901 *plparam = (LPARAM)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)*plparam );
902 return (*plparam ? 1 : -1);
904 case CB_GETLBTEXT: /* fixme: fixed sized buffer */
905 { if ( WINPROC_TestCBForStr( hwnd ))
906 { LPARAM *ptr = (LPARAM *)HeapAlloc( GetProcessHeap(), 0, 256 + sizeof(LPARAM) );
907 if (!ptr) return -1;
908 *ptr++ = *plparam; /* Store previous lParam */
909 *plparam = (LPARAM)ptr;
912 return 1;
914 /* Multiline edit */
915 case EM_GETLINE:
916 { WORD len = (WORD)*plparam;
917 LPARAM *ptr = (LPARAM *) HeapAlloc( GetProcessHeap(), 0, sizeof(LPARAM) + sizeof (WORD) + len*sizeof(CHAR) );
918 if (!ptr) return -1;
919 *ptr++ = *plparam; /* Store previous lParam */
920 *((WORD *) ptr) = len; /* Store the length */
921 *plparam = (LPARAM)ptr;
923 return 1;
925 case WM_CHARTOITEM:
926 case WM_MENUCHAR:
927 case WM_CHAR:
928 case WM_DEADCHAR:
929 case WM_SYSCHAR:
930 case WM_SYSDEADCHAR:
931 case EM_SETPASSWORDCHAR:
933 WCHAR wch = LOWORD(*pwparam);
934 char ch;
935 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
936 *pwparam = MAKEWPARAM( ch, HIWORD(*pwparam) );
938 return 0;
940 case WM_PAINTCLIPBOARD:
941 case WM_SIZECLIPBOARD:
942 FIXME_(msg)("message %s (%04x) needs translation, please report\n",SPY_GetMsgName(msg, hwnd),msg );
943 return -1;
944 default: /* No translation needed */
945 return 0;
950 /**********************************************************************
951 * WINPROC_UnmapMsg32WTo32A
953 * Unmap a message that was mapped from Unicode to Ansi.
955 void WINPROC_UnmapMsg32WTo32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
957 switch(msg)
959 case WM_GETTEXT:
960 case WM_ASKCBFORMATNAME:
962 LPARAM *ptr = (LPARAM *)lParam - 1;
963 if (wParam)
965 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, wParam ))
966 ((LPWSTR)*ptr)[wParam-1] = 0;
968 HeapFree( GetProcessHeap(), 0, ptr );
970 break;
972 case WM_SETTEXT:
973 case WM_WININICHANGE:
974 case WM_DEVMODECHANGE:
975 case CB_DIR:
976 case CB_FINDSTRING:
977 case CB_FINDSTRINGEXACT:
978 case CB_SELECTSTRING:
979 case LB_DIR:
980 case LB_ADDFILE:
981 case LB_FINDSTRING:
982 case LB_FINDSTRINGEXACT:
983 case LB_SELECTSTRING:
984 case EM_REPLACESEL:
985 HeapFree( GetProcessHeap(), 0, (void *)lParam );
986 break;
988 case WM_NCCREATE:
989 case WM_CREATE:
991 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
992 if (HIWORD(cs->lpszName))
993 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
994 if (HIWORD(cs->lpszClass))
995 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
996 HeapFree( GetProcessHeap(), 0, cs );
998 break;
1000 case WM_MDICREATE:
1002 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1003 if (HIWORD(cs->szTitle))
1004 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1005 if (HIWORD(cs->szClass))
1006 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1007 HeapFree( GetProcessHeap(), 0, cs );
1009 break;
1011 /* Listbox */
1012 case LB_ADDSTRING:
1013 case LB_INSERTSTRING:
1014 if ( WINPROC_TestLBForStr( hwnd ))
1015 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1016 break;
1018 case LB_GETTEXT:
1019 if ( WINPROC_TestLBForStr( hwnd ))
1021 LPARAM *ptr = (LPARAM *)lParam - 1;
1022 MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1023 HeapFree( GetProcessHeap(), 0, ptr );
1025 break;
1027 /* Combobox */
1028 case CB_ADDSTRING:
1029 case CB_INSERTSTRING:
1030 if ( WINPROC_TestCBForStr( hwnd ))
1031 HeapFree( GetProcessHeap(), 0, (void *)lParam );
1032 break;
1034 case CB_GETLBTEXT:
1035 if ( WINPROC_TestCBForStr( hwnd ))
1037 LPARAM *ptr = (LPARAM *)lParam - 1;
1038 MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, 0x7fffffff );
1039 HeapFree( GetProcessHeap(), 0, ptr );
1041 break;
1043 /* Multiline edit */
1044 case EM_GETLINE:
1045 { LPARAM * ptr = (LPARAM *)lParam - 1; /* get the old lparam */
1046 WORD len = *(WORD *)ptr;
1047 if (len)
1049 if (!MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, (LPWSTR)*ptr, len ))
1050 ((LPWSTR)*ptr)[len-1] = 0;
1052 HeapFree( GetProcessHeap(), 0, ptr );
1054 break;
1059 /**********************************************************************
1060 * WINPROC_MapMsg16To32A
1062 * Map a message from 16- to 32-bit Ansi.
1063 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1065 INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1066 WPARAM *pwparam32, LPARAM *plparam )
1068 *pmsg32 = (UINT)msg16;
1069 *pwparam32 = (WPARAM)wParam16;
1070 switch(msg16)
1072 case WM_ACTIVATE:
1073 case WM_CHARTOITEM:
1074 case WM_COMMAND:
1075 case WM_VKEYTOITEM:
1076 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1077 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1078 return 0;
1079 case WM_HSCROLL:
1080 case WM_VSCROLL:
1081 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1082 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
1083 return 0;
1084 case WM_CTLCOLOR:
1085 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
1086 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
1087 *pwparam32 = (WPARAM)(HDC)wParam16;
1088 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1089 return 0;
1090 case WM_COMPAREITEM:
1092 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
1093 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)
1094 HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
1095 if (!cis) return -1;
1096 cis->CtlType = cis16->CtlType;
1097 cis->CtlID = cis16->CtlID;
1098 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
1099 cis->itemID1 = cis16->itemID1;
1100 cis->itemData1 = cis16->itemData1;
1101 cis->itemID2 = cis16->itemID2;
1102 cis->itemData2 = cis16->itemData2;
1103 cis->dwLocaleId = 0; /* FIXME */
1104 *plparam = (LPARAM)cis;
1106 return 1;
1107 case WM_DELETEITEM:
1109 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
1110 DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)
1111 HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
1112 if (!dis) return -1;
1113 dis->CtlType = dis16->CtlType;
1114 dis->CtlID = dis16->CtlID;
1115 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
1116 dis->itemData = dis16->itemData;
1117 *plparam = (LPARAM)dis;
1119 return 1;
1120 case WM_MEASUREITEM:
1122 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
1123 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)
1124 HeapAlloc(GetProcessHeap(), 0,
1125 sizeof(*mis) + sizeof(LPARAM));
1126 if (!mis) return -1;
1127 mis->CtlType = mis16->CtlType;
1128 mis->CtlID = mis16->CtlID;
1129 mis->itemID = mis16->itemID;
1130 mis->itemWidth = mis16->itemWidth;
1131 mis->itemHeight = mis16->itemHeight;
1132 mis->itemData = mis16->itemData;
1133 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1134 *plparam = (LPARAM)mis;
1136 return 1;
1137 case WM_DRAWITEM:
1139 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
1140 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)HeapAlloc(GetProcessHeap(), 0,
1141 sizeof(*dis));
1142 if (!dis) return -1;
1143 dis->CtlType = dis16->CtlType;
1144 dis->CtlID = dis16->CtlID;
1145 dis->itemID = dis16->itemID;
1146 dis->itemAction = dis16->itemAction;
1147 dis->itemState = dis16->itemState;
1148 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)(HMENU)dis16->hwndItem
1149 : WIN_Handle32( dis16->hwndItem );
1150 dis->hDC = dis16->hDC;
1151 dis->itemData = dis16->itemData;
1152 CONV_RECT16TO32( &dis16->rcItem, &dis->rcItem );
1153 *plparam = (LPARAM)dis;
1155 return 1;
1156 case WM_GETMINMAXINFO:
1158 MINMAXINFO *mmi = (MINMAXINFO *)HeapAlloc( GetProcessHeap(), 0,
1159 sizeof(*mmi) + sizeof(LPARAM));
1160 if (!mmi) return -1;
1161 STRUCT32_MINMAXINFO16to32( MapSL(*plparam), mmi );
1162 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1163 *plparam = (LPARAM)mmi;
1165 return 1;
1166 case WM_GETTEXT:
1167 case WM_SETTEXT:
1168 case WM_WININICHANGE:
1169 case WM_DEVMODECHANGE:
1170 case WM_ASKCBFORMATNAME:
1171 *plparam = (LPARAM)MapSL(*plparam);
1172 return 0;
1173 case WM_MDICREATE:
1175 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1176 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1177 if (!cs) return -1;
1178 STRUCT32_MDICREATESTRUCT16to32A( cs16, cs );
1179 cs->szTitle = MapSL(cs16->szTitle);
1180 cs->szClass = MapSL(cs16->szClass);
1181 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1182 *plparam = (LPARAM)cs;
1184 return 1;
1185 case WM_MDIGETACTIVE:
1186 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
1187 *(BOOL*)(*plparam) = 0;
1188 return 1;
1189 case WM_MDISETMENU:
1190 if(wParam16==TRUE)
1191 *pmsg32=WM_MDIREFRESHMENU;
1192 *pwparam32 = (WPARAM)(HMENU)LOWORD(*plparam);
1193 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1194 return 0;
1195 case WM_MENUCHAR:
1196 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1197 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1198 return 0;
1199 case WM_MENUSELECT:
1200 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
1202 HMENU hmenu=(HMENU)HIWORD(*plparam);
1203 UINT Pos=MENU_FindSubMenu( &hmenu, wParam16);
1204 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
1205 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
1207 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
1208 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1209 return 0;
1210 case WM_MDIACTIVATE:
1211 if( *plparam )
1213 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
1214 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1216 else /* message sent to MDI client */
1217 *pwparam32 = wParam16;
1218 return 0;
1219 case WM_NCCALCSIZE:
1221 NCCALCSIZE_PARAMS16 *nc16;
1222 NCCALCSIZE_PARAMS *nc;
1224 nc = (NCCALCSIZE_PARAMS *)HeapAlloc( GetProcessHeap(), 0,
1225 sizeof(*nc) + sizeof(LPARAM) );
1226 if (!nc) return -1;
1227 nc16 = MapSL(*plparam);
1228 CONV_RECT16TO32( &nc16->rgrc[0], &nc->rgrc[0] );
1229 if (wParam16)
1231 nc->lppos = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1232 sizeof(*nc->lppos) );
1233 CONV_RECT16TO32( &nc16->rgrc[1], &nc->rgrc[1] );
1234 CONV_RECT16TO32( &nc16->rgrc[2], &nc->rgrc[2] );
1235 if (nc->lppos) STRUCT32_WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
1237 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1238 *plparam = (LPARAM)nc;
1240 return 1;
1241 case WM_NCCREATE:
1242 case WM_CREATE:
1244 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1245 CREATESTRUCTA *cs = (CREATESTRUCTA *)HeapAlloc( GetProcessHeap(), 0,
1246 sizeof(*cs) + sizeof(LPARAM) );
1247 if (!cs) return -1;
1248 STRUCT32_CREATESTRUCT16to32A( cs16, cs );
1249 cs->lpszName = MapSL(cs16->lpszName);
1250 cs->lpszClass = MapSL(cs16->lpszClass);
1251 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1252 *plparam = (LPARAM)cs;
1254 return 1;
1255 case WM_PARENTNOTIFY:
1256 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
1258 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
1259 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1261 return 0;
1262 case WM_WINDOWPOSCHANGING:
1263 case WM_WINDOWPOSCHANGED:
1265 WINDOWPOS *wp = (WINDOWPOS *)HeapAlloc( GetProcessHeap(), 0,
1266 sizeof(*wp) + sizeof(LPARAM) );
1267 if (!wp) return -1;
1268 STRUCT32_WINDOWPOS16to32( MapSL(*plparam), wp );
1269 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1270 *plparam = (LPARAM)wp;
1272 return 1;
1273 case WM_GETDLGCODE:
1274 if (*plparam)
1276 LPMSG16 msg16 = MapSL(*plparam);
1277 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1279 if (!msg32) return -1;
1280 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1281 msg32->lParam = msg16->lParam;
1282 msg32->time = msg16->time;
1283 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1284 /* this is right, right? */
1285 if (WINPROC_MapMsg16To32A( msg32->hwnd, msg16->message,msg16->wParam,
1286 &msg32->message,&msg32->wParam,
1287 &msg32->lParam)<0) {
1288 HeapFree( GetProcessHeap(), 0, msg32 );
1289 return -1;
1291 *plparam = (LPARAM)msg32;
1292 return 1;
1294 else return 0;
1295 case WM_NOTIFY:
1296 *plparam = (LPARAM)MapSL(*plparam);
1297 return 0;
1298 case WM_ACTIVATEAPP:
1299 if (*plparam)
1300 { /* We need this when SetActiveWindow sends a Sendmessage16() to
1301 a 32bit window. Might be superflous with 32bit interprocess
1302 message queues.
1304 HTASK16 htask = (HTASK16) *plparam;
1305 DWORD idThread = (DWORD)TASK_GetPtr(htask)->teb->tid;
1306 *plparam = (LPARAM) idThread;
1308 return 0;
1309 case WM_NEXTMENU:
1311 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
1312 if (!next) return -1;
1313 next->hmenuIn = *plparam;
1314 next->hmenuNext = 0;
1315 next->hwndNext = 0;
1316 *plparam = (LPARAM)next;
1317 return 1;
1319 case WM_PAINTCLIPBOARD:
1320 case WM_SIZECLIPBOARD:
1321 FIXME_(msg)("message %04x needs translation\n",msg16 );
1322 return -1;
1324 default: /* No translation needed */
1325 return 0;
1330 /**********************************************************************
1331 * WINPROC_UnmapMsg16To32A
1333 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1335 LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1336 LRESULT result )
1338 switch(msg)
1340 case WM_COMPAREITEM:
1341 case WM_DELETEITEM:
1342 case WM_DRAWITEM:
1343 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1344 break;
1345 case WM_MEASUREITEM:
1347 MEASUREITEMSTRUCT16 *mis16;
1348 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1349 lParam = *(LPARAM *)(mis + 1);
1350 mis16 = MapSL(lParam);
1351 mis16->itemWidth = (UINT16)mis->itemWidth;
1352 mis16->itemHeight = (UINT16)mis->itemHeight;
1353 HeapFree( GetProcessHeap(), 0, mis );
1355 break;
1356 case WM_GETMINMAXINFO:
1358 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1359 lParam = *(LPARAM *)(mmi + 1);
1360 STRUCT32_MINMAXINFO32to16( mmi, MapSL(lParam));
1361 HeapFree( GetProcessHeap(), 0, mmi );
1363 break;
1364 case WM_MDICREATE:
1366 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1367 lParam = *(LPARAM *)(cs + 1);
1368 STRUCT32_MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1369 HeapFree( GetProcessHeap(), 0, cs );
1371 break;
1372 case WM_MDIGETACTIVE:
1373 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1374 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1375 break;
1376 case WM_NCCALCSIZE:
1378 NCCALCSIZE_PARAMS16 *nc16;
1379 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1380 lParam = *(LPARAM *)(nc + 1);
1381 nc16 = MapSL(lParam);
1382 CONV_RECT32TO16( &nc->rgrc[0], &nc16->rgrc[0] );
1383 if (wParam)
1385 CONV_RECT32TO16( &nc->rgrc[1], &nc16->rgrc[1] );
1386 CONV_RECT32TO16( &nc->rgrc[2], &nc16->rgrc[2] );
1387 if (nc->lppos)
1389 STRUCT32_WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1390 HeapFree( GetProcessHeap(), 0, nc->lppos );
1393 HeapFree( GetProcessHeap(), 0, nc );
1395 break;
1396 case WM_NCCREATE:
1397 case WM_CREATE:
1399 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1400 lParam = *(LPARAM *)(cs + 1);
1401 STRUCT32_CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1402 HeapFree( GetProcessHeap(), 0, cs );
1404 break;
1405 case WM_WINDOWPOSCHANGING:
1406 case WM_WINDOWPOSCHANGED:
1408 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1409 lParam = *(LPARAM *)(wp + 1);
1410 STRUCT32_WINDOWPOS32to16(wp, MapSL(lParam));
1411 HeapFree( GetProcessHeap(), 0, wp );
1413 break;
1414 case WM_GETDLGCODE:
1415 if (lParam)
1417 LPMSG msg32 = (LPMSG)lParam;
1419 WINPROC_UnmapMsg16To32A( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1420 result);
1421 HeapFree( GetProcessHeap(), 0, msg32 );
1423 break;
1424 case WM_NEXTMENU:
1426 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1427 result = MAKELONG( next->hmenuNext, WIN_Handle16(next->hwndNext) );
1428 HeapFree( GetProcessHeap(), 0, next );
1430 break;
1432 return result;
1436 /**********************************************************************
1437 * WINPROC_MapMsg16To32W
1439 * Map a message from 16- to 32-bit Unicode.
1440 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1442 INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1443 WPARAM *pwparam32, LPARAM *plparam )
1445 char ch;
1446 WCHAR wch;
1448 *pmsg32=(UINT)msg16;
1449 *pwparam32 = (WPARAM)wParam16;
1450 switch(msg16)
1452 case WM_GETTEXT:
1453 case WM_SETTEXT:
1454 case WM_WININICHANGE:
1455 case WM_DEVMODECHANGE:
1456 case WM_ASKCBFORMATNAME:
1457 *plparam = (LPARAM)MapSL(*plparam);
1458 return WINPROC_MapMsg32ATo32W( hwnd, *pmsg32, pwparam32, plparam );
1459 case WM_GETTEXTLENGTH:
1460 case CB_GETLBTEXTLEN:
1461 case LB_GETTEXTLEN:
1462 return 1; /* need to map result */
1463 case WM_NCCREATE:
1464 case WM_CREATE:
1466 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1467 CREATESTRUCTW *cs = (CREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1468 sizeof(*cs) + sizeof(LPARAM) );
1469 if (!cs) return -1;
1470 STRUCT32_CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1471 cs->lpszName = MapSL(cs16->lpszName);
1472 cs->lpszClass = MapSL(cs16->lpszClass);
1473 if (HIWORD(cs->lpszName))
1474 cs->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0,
1475 (LPCSTR)cs->lpszName );
1476 if (HIWORD(cs->lpszClass))
1477 cs->lpszClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
1478 (LPCSTR)cs->lpszClass );
1479 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1480 *plparam = (LPARAM)cs;
1482 return 1;
1483 case WM_MDICREATE:
1485 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1486 MDICREATESTRUCTW *cs =
1487 (MDICREATESTRUCTW *)HeapAlloc( GetProcessHeap(), 0,
1488 sizeof(*cs) + sizeof(LPARAM) );
1489 if (!cs) return -1;
1490 STRUCT32_MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1491 cs->szTitle = MapSL(cs16->szTitle);
1492 cs->szClass = MapSL(cs16->szClass);
1493 if (HIWORD(cs->szTitle))
1494 cs->szTitle = HEAP_strdupAtoW( GetProcessHeap(), 0,
1495 (LPCSTR)cs->szTitle );
1496 if (HIWORD(cs->szClass))
1497 cs->szClass = HEAP_strdupAtoW( GetProcessHeap(), 0,
1498 (LPCSTR)cs->szClass );
1499 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1500 *plparam = (LPARAM)cs;
1502 return 1;
1503 case WM_GETDLGCODE:
1504 if (*plparam)
1506 LPMSG16 msg16 = MapSL(*plparam);
1507 LPMSG msg32 = (LPMSG)HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1509 if (!msg32) return -1;
1510 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1511 msg32->lParam = msg16->lParam;
1512 msg32->time = msg16->time;
1513 CONV_POINT16TO32(&msg16->pt,&msg32->pt);
1514 /* this is right, right? */
1515 if (WINPROC_MapMsg16To32W(hwnd, msg16->message,msg16->wParam,
1516 &msg32->message,&msg32->wParam,
1517 &msg32->lParam)<0) {
1518 HeapFree( GetProcessHeap(), 0, msg32 );
1519 return -1;
1521 *plparam = (LPARAM)msg32;
1522 return 1;
1524 else return 0;
1526 case WM_CHARTOITEM:
1527 ch = wParam16;
1528 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1529 *pwparam32 = MAKEWPARAM( wch, HIWORD(*plparam) );
1530 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1531 return 0;
1532 case WM_MENUCHAR:
1533 ch = wParam16;
1534 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1535 *pwparam32 = MAKEWPARAM( wch, LOWORD(*plparam) );
1536 *plparam = (LPARAM)(HMENU)HIWORD(*plparam);
1537 return 0;
1538 case WM_CHAR:
1539 case WM_DEADCHAR:
1540 case WM_SYSCHAR:
1541 case WM_SYSDEADCHAR:
1542 ch = wParam16;
1543 MultiByteToWideChar( CP_ACP, 0, &ch, 1, &wch, 1);
1544 *pwparam32 = wch;
1545 return 0;
1547 default: /* No Unicode translation needed */
1548 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1549 pwparam32, plparam );
1554 /**********************************************************************
1555 * WINPROC_UnmapMsg16To32W
1557 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1559 LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1560 LRESULT result )
1562 switch(msg)
1564 case WM_GETTEXT:
1565 case WM_SETTEXT:
1566 case WM_GETTEXTLENGTH:
1567 case CB_GETLBTEXTLEN:
1568 case LB_GETTEXTLEN:
1569 case WM_ASKCBFORMATNAME:
1570 return WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
1571 case WM_NCCREATE:
1572 case WM_CREATE:
1574 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1575 lParam = *(LPARAM *)(cs + 1);
1576 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1577 if (HIWORD(cs->lpszName))
1578 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszName );
1579 if (HIWORD(cs->lpszClass))
1580 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->lpszClass );
1581 HeapFree( GetProcessHeap(), 0, cs );
1583 break;
1584 case WM_MDICREATE:
1586 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1587 lParam = *(LPARAM *)(cs + 1);
1588 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1589 if (HIWORD(cs->szTitle))
1590 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szTitle );
1591 if (HIWORD(cs->szClass))
1592 HeapFree( GetProcessHeap(), 0, (LPVOID)cs->szClass );
1593 HeapFree( GetProcessHeap(), 0, cs );
1595 break;
1596 case WM_GETDLGCODE:
1597 if (lParam)
1599 LPMSG msg32 = (LPMSG)lParam;
1601 WINPROC_UnmapMsg16To32W( hwnd, msg32->message, msg32->wParam, msg32->lParam,
1602 result);
1603 HeapFree( GetProcessHeap(), 0, msg32 );
1605 break;
1606 default:
1607 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1609 return result;
1613 /**********************************************************************
1614 * WINPROC_MapMsg32ATo16
1616 * Map a message from 32-bit Ansi to 16-bit.
1617 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1619 INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1620 UINT16 *pmsg16, WPARAM16 *pwparam16,
1621 LPARAM *plparam )
1623 *pmsg16 = (UINT16)msg32;
1624 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1625 switch(msg32)
1627 case BM_GETCHECK:
1628 case BM_SETCHECK:
1629 case BM_GETSTATE:
1630 case BM_SETSTATE:
1631 case BM_SETSTYLE:
1632 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1633 return 0;
1635 case EM_GETSEL:
1636 case EM_GETRECT:
1637 case EM_SETRECT:
1638 case EM_SETRECTNP:
1639 case EM_SCROLL:
1640 case EM_LINESCROLL:
1641 case EM_SCROLLCARET:
1642 case EM_GETMODIFY:
1643 case EM_SETMODIFY:
1644 case EM_GETLINECOUNT:
1645 case EM_LINEINDEX:
1646 case EM_SETHANDLE:
1647 case EM_GETHANDLE:
1648 case EM_GETTHUMB:
1649 case EM_LINELENGTH:
1650 case EM_REPLACESEL:
1651 case EM_GETLINE:
1652 case EM_LIMITTEXT:
1653 case EM_CANUNDO:
1654 case EM_UNDO:
1655 case EM_FMTLINES:
1656 case EM_LINEFROMCHAR:
1657 case EM_SETTABSTOPS:
1658 case EM_SETPASSWORDCHAR:
1659 case EM_EMPTYUNDOBUFFER:
1660 case EM_GETFIRSTVISIBLELINE:
1661 case EM_SETREADONLY:
1662 case EM_SETWORDBREAKPROC:
1663 case EM_GETWORDBREAKPROC:
1664 case EM_GETPASSWORDCHAR:
1665 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1666 return 0;
1668 case LB_CARETOFF:
1669 case LB_CARETON:
1670 case LB_DELETESTRING:
1671 case LB_GETANCHORINDEX:
1672 case LB_GETCARETINDEX:
1673 case LB_GETCOUNT:
1674 case LB_GETCURSEL:
1675 case LB_GETHORIZONTALEXTENT:
1676 case LB_GETITEMDATA:
1677 case LB_GETITEMHEIGHT:
1678 case LB_GETSEL:
1679 case LB_GETSELCOUNT:
1680 case LB_GETTEXTLEN:
1681 case LB_GETTOPINDEX:
1682 case LB_RESETCONTENT:
1683 case LB_SELITEMRANGE:
1684 case LB_SELITEMRANGEEX:
1685 case LB_SETANCHORINDEX:
1686 case LB_SETCARETINDEX:
1687 case LB_SETCOLUMNWIDTH:
1688 case LB_SETCURSEL:
1689 case LB_SETHORIZONTALEXTENT:
1690 case LB_SETITEMDATA:
1691 case LB_SETITEMHEIGHT:
1692 case LB_SETSEL:
1693 case LB_SETTOPINDEX:
1694 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1695 return 0;
1696 case CB_DELETESTRING:
1697 case CB_GETCOUNT:
1698 case CB_GETLBTEXTLEN:
1699 case CB_LIMITTEXT:
1700 case CB_RESETCONTENT:
1701 case CB_SETEDITSEL:
1702 case CB_GETCURSEL:
1703 case CB_SETCURSEL:
1704 case CB_SHOWDROPDOWN:
1705 case CB_SETITEMDATA:
1706 case CB_SETITEMHEIGHT:
1707 case CB_GETITEMHEIGHT:
1708 case CB_SETEXTENDEDUI:
1709 case CB_GETEXTENDEDUI:
1710 case CB_GETDROPPEDSTATE:
1711 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1712 return 0;
1713 case CB_GETEDITSEL:
1714 *pmsg16 = CB_GETEDITSEL16;
1715 return 1;
1717 case LB_ADDSTRING:
1718 case LB_FINDSTRING:
1719 case LB_FINDSTRINGEXACT:
1720 case LB_INSERTSTRING:
1721 case LB_SELECTSTRING:
1722 case LB_DIR:
1723 case LB_ADDFILE:
1725 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1726 if (!str) return -1;
1727 *plparam = (LPARAM)SEGPTR_GET(str);
1729 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1730 return 1;
1732 case CB_ADDSTRING:
1733 case CB_FINDSTRING:
1734 case CB_FINDSTRINGEXACT:
1735 case CB_INSERTSTRING:
1736 case CB_SELECTSTRING:
1737 case CB_DIR:
1739 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
1740 if (!str) return -1;
1741 *plparam = (LPARAM)SEGPTR_GET(str);
1743 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1744 return 1;
1746 case LB_GETITEMRECT:
1748 RECT16 *rect;
1749 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1750 if (!rect) return -1;
1751 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1752 *plparam = (LPARAM)SEGPTR_GET(rect);
1754 *pmsg16 = LB_GETITEMRECT16;
1755 return 1;
1756 case LB_GETSELITEMS:
1758 LPINT16 items;
1759 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1760 if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1761 + sizeof(LPARAM)))) return -1;
1762 *((LPARAM *)items)++ = *plparam; /* Store the previous lParam */
1763 *plparam = (LPARAM)SEGPTR_GET(items);
1765 *pmsg16 = LB_GETSELITEMS16;
1766 return 1;
1767 case LB_SETTABSTOPS:
1768 if (wParam32)
1770 INT i;
1771 LPINT16 stops;
1772 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1773 if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
1774 + sizeof(LPARAM)))) return -1;
1775 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1776 *plparam = (LPARAM)SEGPTR_GET(stops);
1777 return 1;
1779 *pmsg16 = LB_SETTABSTOPS16;
1780 return 0;
1782 case CB_GETDROPPEDCONTROLRECT:
1784 RECT16 *rect;
1785 rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
1786 if (!rect) return -1;
1787 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1788 *plparam = (LPARAM)SEGPTR_GET(rect);
1790 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1791 return 1;
1793 case LB_GETTEXT:
1794 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1795 *pmsg16 = LB_GETTEXT16;
1796 return 1;
1798 case CB_GETLBTEXT:
1799 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1800 *pmsg16 = CB_GETLBTEXT16;
1801 return 1;
1803 case EM_SETSEL:
1804 *pwparam16 = 0;
1805 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1806 *pmsg16 = EM_SETSEL16;
1807 return 0;
1809 case WM_ACTIVATE:
1810 case WM_CHARTOITEM:
1811 case WM_COMMAND:
1812 case WM_VKEYTOITEM:
1813 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1814 return 0;
1815 case WM_HSCROLL:
1816 case WM_VSCROLL:
1817 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1818 return 0;
1819 case WM_CTLCOLORMSGBOX:
1820 case WM_CTLCOLOREDIT:
1821 case WM_CTLCOLORLISTBOX:
1822 case WM_CTLCOLORBTN:
1823 case WM_CTLCOLORDLG:
1824 case WM_CTLCOLORSCROLLBAR:
1825 case WM_CTLCOLORSTATIC:
1826 *pmsg16 = WM_CTLCOLOR;
1827 *plparam = MAKELPARAM( (HWND16)*plparam,
1828 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1829 return 0;
1830 case WM_COMPAREITEM:
1832 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1833 COMPAREITEMSTRUCT16 *cis = SEGPTR_NEW(COMPAREITEMSTRUCT16);
1834 if (!cis) return -1;
1835 cis->CtlType = (UINT16)cis32->CtlType;
1836 cis->CtlID = (UINT16)cis32->CtlID;
1837 cis->hwndItem = WIN_Handle16( cis32->hwndItem );
1838 cis->itemID1 = (UINT16)cis32->itemID1;
1839 cis->itemData1 = cis32->itemData1;
1840 cis->itemID2 = (UINT16)cis32->itemID2;
1841 cis->itemData2 = cis32->itemData2;
1842 *plparam = (LPARAM)SEGPTR_GET(cis);
1844 return 1;
1845 case WM_DELETEITEM:
1847 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1848 DELETEITEMSTRUCT16 *dis = SEGPTR_NEW(DELETEITEMSTRUCT16);
1849 if (!dis) return -1;
1850 dis->CtlType = (UINT16)dis32->CtlType;
1851 dis->CtlID = (UINT16)dis32->CtlID;
1852 dis->itemID = (UINT16)dis32->itemID;
1853 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1854 : WIN_Handle16( dis32->hwndItem );
1855 dis->itemData = dis32->itemData;
1856 *plparam = (LPARAM)SEGPTR_GET(dis);
1858 return 1;
1859 case WM_DRAWITEM:
1861 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1862 DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16);
1863 if (!dis) return -1;
1864 dis->CtlType = (UINT16)dis32->CtlType;
1865 dis->CtlID = (UINT16)dis32->CtlID;
1866 dis->itemID = (UINT16)dis32->itemID;
1867 dis->itemAction = (UINT16)dis32->itemAction;
1868 dis->itemState = (UINT16)dis32->itemState;
1869 dis->hwndItem = WIN_Handle16( dis32->hwndItem );
1870 dis->hDC = (HDC16)dis32->hDC;
1871 dis->itemData = dis32->itemData;
1872 CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem );
1873 *plparam = (LPARAM)SEGPTR_GET(dis);
1875 return 1;
1876 case WM_MEASUREITEM:
1878 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1879 MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)
1880 SEGPTR_ALLOC(sizeof(*mis)+sizeof(LPARAM));
1881 if (!mis) return -1;
1882 mis->CtlType = (UINT16)mis32->CtlType;
1883 mis->CtlID = (UINT16)mis32->CtlID;
1884 mis->itemID = (UINT16)mis32->itemID;
1885 mis->itemWidth = (UINT16)mis32->itemWidth;
1886 mis->itemHeight = (UINT16)mis32->itemHeight;
1887 mis->itemData = mis32->itemData;
1888 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1889 *plparam = (LPARAM)SEGPTR_GET(mis);
1891 return 1;
1892 case WM_GETMINMAXINFO:
1894 MINMAXINFO16 *mmi = (MINMAXINFO16 *)SEGPTR_ALLOC( sizeof(*mmi) +
1895 sizeof(LPARAM) );
1896 if (!mmi) return -1;
1897 STRUCT32_MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
1898 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1899 *plparam = (LPARAM)SEGPTR_GET(mmi);
1901 return 1;
1902 case WM_GETTEXT:
1903 case WM_ASKCBFORMATNAME:
1905 LPSTR str;
1906 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
1907 if (!(str = SEGPTR_ALLOC(*pwparam16 + sizeof(LPARAM)))) return -1;
1908 *((LPARAM *)str)++ = *plparam; /* Store the previous lParam */
1909 *plparam = (LPARAM)SEGPTR_GET(str);
1911 return 1;
1912 case WM_MDICREATE:
1914 MDICREATESTRUCT16 *cs;
1915 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
1916 LPSTR name, cls;
1918 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
1919 STRUCT32_MDICREATESTRUCT32Ato16( cs32, cs );
1920 name = SEGPTR_STRDUP( cs32->szTitle );
1921 cls = SEGPTR_STRDUP( cs32->szClass );
1922 cs->szTitle = SEGPTR_GET(name);
1923 cs->szClass = SEGPTR_GET(cls);
1924 *plparam = (LPARAM)SEGPTR_GET(cs);
1926 return 1;
1927 case WM_MDIGETACTIVE:
1928 return 1;
1929 case WM_MDISETMENU:
1930 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1931 (HMENU16)LOWORD(*plparam) );
1932 *pwparam16 = (*plparam == 0);
1933 return 0;
1934 case WM_MENUSELECT:
1935 if(HIWORD(wParam32) & MF_POPUP)
1937 UINT16 hmenu;
1938 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
1940 if((hmenu = GetSubMenu((HMENU16)*plparam, *pwparam16)))
1941 *pwparam16=hmenu;
1944 /* fall through */
1945 case WM_MENUCHAR:
1946 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1947 return 0;
1948 case WM_MDIACTIVATE:
1949 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
1951 *pwparam16 = ((HWND)*plparam == hwnd);
1952 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1953 (HWND16)LOWORD(wParam32) );
1955 else
1957 *pwparam16 = WIN_Handle16( (HWND)wParam32 );
1958 *plparam = 0;
1960 return 0;
1961 case WM_NCCALCSIZE:
1963 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
1964 NCCALCSIZE_PARAMS16 *nc = (NCCALCSIZE_PARAMS16 *)SEGPTR_ALLOC( sizeof(*nc) + sizeof(LPARAM) );
1965 if (!nc) return -1;
1967 CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] );
1968 if (wParam32)
1970 WINDOWPOS16 *wp;
1971 CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] );
1972 CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] );
1973 if (!(wp = SEGPTR_NEW(WINDOWPOS16)))
1975 SEGPTR_FREE(nc);
1976 return -1;
1978 STRUCT32_WINDOWPOS32to16( nc32->lppos, wp );
1979 nc->lppos = SEGPTR_GET(wp);
1981 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1982 *plparam = (LPARAM)SEGPTR_GET(nc);
1984 return 1;
1985 case WM_NCCREATE:
1986 case WM_CREATE:
1988 CREATESTRUCT16 *cs;
1989 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
1990 LPSTR name, cls;
1992 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
1993 STRUCT32_CREATESTRUCT32Ato16( cs32, cs );
1994 name = SEGPTR_STRDUP( cs32->lpszName );
1995 cls = SEGPTR_STRDUP( cs32->lpszClass );
1996 cs->lpszName = SEGPTR_GET(name);
1997 cs->lpszClass = SEGPTR_GET(cls);
1998 *plparam = (LPARAM)SEGPTR_GET(cs);
2000 return 1;
2001 case WM_PARENTNOTIFY:
2002 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
2003 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
2004 /* else nothing to do */
2005 return 0;
2006 case WM_NOTIFY:
2007 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
2008 return 1;
2009 case WM_SETTEXT:
2010 case WM_WININICHANGE:
2011 case WM_DEVMODECHANGE:
2013 LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
2014 if (!str) return -1;
2015 *plparam = (LPARAM)SEGPTR_GET(str);
2017 return 1;
2018 case WM_WINDOWPOSCHANGING:
2019 case WM_WINDOWPOSCHANGED:
2021 WINDOWPOS16 *wp = (WINDOWPOS16 *)SEGPTR_ALLOC( sizeof(*wp) +
2022 sizeof(LPARAM) );
2023 if (!wp) return -1;
2024 STRUCT32_WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
2025 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
2026 *plparam = (LPARAM)SEGPTR_GET(wp);
2028 return 1;
2029 case WM_GETDLGCODE:
2030 if (*plparam) {
2031 LPMSG msg32 = (LPMSG) *plparam;
2032 LPMSG16 msg16 = (LPMSG16) SEGPTR_NEW( MSG16 );
2034 if (!msg16) return -1;
2035 msg16->hwnd = WIN_Handle16( msg32->hwnd );
2036 msg16->lParam = msg32->lParam;
2037 msg16->time = msg32->time;
2038 CONV_POINT32TO16(&msg32->pt,&msg16->pt);
2039 /* this is right, right? */
2040 if (WINPROC_MapMsg32ATo16(msg32->hwnd,msg32->message,msg32->wParam,
2041 &msg16->message,&msg16->wParam, &msg16->lParam)<0) {
2042 SEGPTR_FREE( msg16 );
2043 return -1;
2045 *plparam = (LPARAM)SEGPTR_GET(msg16);
2046 return 1;
2048 return 0;
2050 case WM_ACTIVATEAPP:
2051 if (*plparam) *plparam = (LPARAM)THREAD_IdToTEB((DWORD) *plparam)->htask16;
2052 return 0;
2053 case WM_NEXTMENU:
2055 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
2056 *plparam = next->hmenuIn;
2057 return 1;
2059 case WM_PAINTCLIPBOARD:
2060 case WM_SIZECLIPBOARD:
2061 FIXME_(msg)("message %04x needs translation\n", msg32 );
2062 return -1;
2063 /* following messages should not be sent to 16-bit apps */
2064 case WM_SIZING:
2065 case WM_MOVING:
2066 case WM_CAPTURECHANGED:
2067 case WM_STYLECHANGING:
2068 case WM_STYLECHANGED:
2069 return -1;
2070 default: /* No translation needed */
2071 return 0;
2076 /**********************************************************************
2077 * WINPROC_UnmapMsg32ATo16
2079 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
2081 void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2082 MSGPARAM16* p16 )
2084 switch(msg)
2086 case LB_ADDFILE:
2087 case LB_ADDSTRING:
2088 case LB_DIR:
2089 case LB_FINDSTRING:
2090 case LB_FINDSTRINGEXACT:
2091 case LB_INSERTSTRING:
2092 case LB_SELECTSTRING:
2093 case LB_SETTABSTOPS:
2094 case CB_ADDSTRING:
2095 case CB_FINDSTRING:
2096 case CB_FINDSTRINGEXACT:
2097 case CB_INSERTSTRING:
2098 case CB_SELECTSTRING:
2099 case CB_DIR:
2100 case WM_COMPAREITEM:
2101 case WM_DELETEITEM:
2102 case WM_DRAWITEM:
2103 case WM_SETTEXT:
2104 case WM_WININICHANGE:
2105 case WM_DEVMODECHANGE:
2106 SEGPTR_FREE( MapSL(p16->lParam) );
2107 break;
2109 case CB_GETDROPPEDCONTROLRECT:
2110 case LB_GETITEMRECT:
2112 RECT16 *rect = MapSL(p16->lParam);
2113 p16->lParam = *(LPARAM *)(rect + 1);
2114 CONV_RECT16TO32( rect, (RECT *)(p16->lParam));
2115 SEGPTR_FREE( rect );
2117 break;
2118 case LB_GETSELITEMS:
2120 INT i;
2121 LPINT16 items = MapSL(lParam);
2122 p16->lParam = *((LPARAM *)items - 1);
2123 for (i = 0; i < p16->wParam; i++) *((LPINT)(p16->lParam) + i) = items[i];
2124 SEGPTR_FREE( (LPARAM *)items - 1 );
2126 break;
2128 case CB_GETEDITSEL:
2129 if( wParam )
2130 *((LPUINT)(wParam)) = LOWORD(p16->lResult);
2131 if( lParam )
2132 *((LPUINT)(lParam)) = HIWORD(p16->lResult); /* FIXME: substract 1? */
2133 break;
2135 case LB_GETTEXT:
2136 case CB_GETLBTEXT:
2137 UnMapLS( (SEGPTR)(p16->lParam) );
2138 break;
2140 case WM_MEASUREITEM:
2142 MEASUREITEMSTRUCT16 *mis = MapSL(p16->lParam);
2143 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2144 mis32->itemWidth = mis->itemWidth;
2145 mis32->itemHeight = mis->itemHeight;
2146 SEGPTR_FREE(mis);
2148 break;
2149 case WM_GETMINMAXINFO:
2151 MINMAXINFO16 *mmi = MapSL(p16->lParam);
2152 p16->lParam = *(LPARAM *)(mmi + 1);
2153 STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO *)(p16->lParam) );
2154 SEGPTR_FREE(mmi);
2156 break;
2157 case WM_GETTEXT:
2158 case WM_ASKCBFORMATNAME:
2160 LPSTR str = MapSL(p16->lParam);
2161 p16->lParam = *((LPARAM *)str - 1);
2162 lstrcpynA( (LPSTR)(p16->lParam), str, p16->wParam );
2163 SEGPTR_FREE( (LPARAM *)str - 1 );
2165 break;
2166 case WM_MDICREATE:
2168 MDICREATESTRUCT16 *cs = MapSL(p16->lParam);
2169 SEGPTR_FREE( MapSL(cs->szTitle) );
2170 SEGPTR_FREE( MapSL(cs->szClass) );
2171 SEGPTR_FREE( cs );
2173 break;
2174 case WM_MDIGETACTIVE:
2175 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(p16->lResult);
2176 p16->lResult = (LRESULT)WIN_Handle32( LOWORD(p16->lResult) );
2177 break;
2178 case WM_NCCALCSIZE:
2180 NCCALCSIZE_PARAMS *nc32;
2181 NCCALCSIZE_PARAMS16 *nc = MapSL(p16->lParam);
2182 p16->lParam = *(LPARAM *)(nc + 1);
2183 nc32 = (NCCALCSIZE_PARAMS *)(p16->lParam);
2184 CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] );
2185 if (p16->wParam)
2187 CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] );
2188 CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] );
2189 STRUCT32_WINDOWPOS16to32( MapSL(nc->lppos), nc32->lppos );
2190 SEGPTR_FREE( MapSL(nc->lppos) );
2192 SEGPTR_FREE(nc);
2194 break;
2195 case WM_NCCREATE:
2196 case WM_CREATE:
2198 CREATESTRUCT16 *cs = MapSL(p16->lParam);
2199 SEGPTR_FREE( MapSL(cs->lpszName) );
2200 SEGPTR_FREE( MapSL(cs->lpszClass) );
2201 SEGPTR_FREE( cs );
2203 break;
2204 case WM_WINDOWPOSCHANGING:
2205 case WM_WINDOWPOSCHANGED:
2207 WINDOWPOS16 *wp = MapSL(p16->lParam);
2208 p16->lParam = *(LPARAM *)(wp + 1);
2209 STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS *)p16->lParam );
2210 SEGPTR_FREE(wp);
2212 break;
2213 case WM_NOTIFY:
2214 UnMapLS(p16->lParam);
2215 break;
2216 case WM_GETDLGCODE:
2217 if (p16->lParam)
2219 LPMSG16 msg16 = MapSL(p16->lParam);
2220 MSGPARAM16 msgp16;
2221 msgp16.wParam=msg16->wParam;
2222 msgp16.lParam=msg16->lParam;
2223 WINPROC_UnmapMsg32ATo16(((LPMSG)lParam)->hwnd, ((LPMSG)lParam)->message,
2224 ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam,
2225 &msgp16 );
2226 SEGPTR_FREE(msg16);
2228 break;
2229 case WM_NEXTMENU:
2231 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2232 next->hmenuNext = LOWORD(p16->lResult);
2233 next->hwndNext = WIN_Handle32( HIWORD(p16->lResult) );
2234 p16->lResult = 0;
2236 break;
2241 /**********************************************************************
2242 * WINPROC_MapMsg32WTo16
2244 * Map a message from 32-bit Unicode to 16-bit.
2245 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2247 INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2248 UINT16 *pmsg16, WPARAM16 *pwparam16,
2249 LPARAM *plparam )
2251 char ch;
2252 WCHAR wch;
2254 *pmsg16 = LOWORD(msg32);
2255 *pwparam16 = LOWORD(wParam32);
2256 switch(msg32)
2258 case LB_ADDSTRING:
2259 case LB_FINDSTRING:
2260 case LB_FINDSTRINGEXACT:
2261 case LB_INSERTSTRING:
2262 case LB_SELECTSTRING:
2263 case LB_DIR:
2264 case LB_ADDFILE:
2266 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2267 if (!str) return -1;
2268 *plparam = (LPARAM)SEGPTR_GET(str);
2270 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2271 return 1;
2273 case CB_ADDSTRING:
2274 case CB_FINDSTRING:
2275 case CB_FINDSTRINGEXACT:
2276 case CB_INSERTSTRING:
2277 case CB_SELECTSTRING:
2278 case CB_DIR:
2280 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2281 if (!str) return -1;
2282 *plparam = (LPARAM)SEGPTR_GET(str);
2284 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2285 return 1;
2287 case WM_NCCREATE:
2288 case WM_CREATE:
2290 CREATESTRUCT16 *cs;
2291 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2292 LPSTR name, cls;
2294 if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return -1;
2295 STRUCT32_CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2296 name = SEGPTR_STRDUP_WtoA( cs32->lpszName );
2297 cls = SEGPTR_STRDUP_WtoA( cs32->lpszClass );
2298 cs->lpszName = SEGPTR_GET(name);
2299 cs->lpszClass = SEGPTR_GET(cls);
2300 *plparam = (LPARAM)SEGPTR_GET(cs);
2302 return 1;
2303 case WM_MDICREATE:
2305 MDICREATESTRUCT16 *cs;
2306 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2307 LPSTR name, cls;
2309 if (!(cs = SEGPTR_NEW(MDICREATESTRUCT16))) return -1;
2310 STRUCT32_MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2311 name = SEGPTR_STRDUP_WtoA( cs32->szTitle );
2312 cls = SEGPTR_STRDUP_WtoA( cs32->szClass );
2313 cs->szTitle = SEGPTR_GET(name);
2314 cs->szClass = SEGPTR_GET(cls);
2315 *plparam = (LPARAM)SEGPTR_GET(cs);
2317 return 1;
2318 case WM_SETTEXT:
2320 LPSTR str = SEGPTR_STRDUP_WtoA( (LPWSTR)*plparam );
2321 if (!str) return -1;
2322 *plparam = (LPARAM)SEGPTR_GET(str);
2324 return 1;
2325 case LB_GETTEXT:
2326 case CB_GETLBTEXT:
2327 if ( WINPROC_TestLBForStr( hwnd ))
2329 LPSTR str = (LPSTR) SEGPTR_ALLOC( 256 ); /* fixme: fixed sized buffer */
2330 if (!str) return -1;
2331 *pmsg16 = (msg32 == LB_GETTEXT)? LB_GETTEXT16 : CB_GETLBTEXT16;
2332 *plparam = (LPARAM)SEGPTR_GET(str);
2334 return 1;
2336 case WM_CHARTOITEM:
2337 wch = LOWORD(wParam32);
2338 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2339 *pwparam16 = ch;
2340 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2341 return 0;
2342 case WM_MENUCHAR:
2343 wch = LOWORD(wParam32);
2344 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2345 *pwparam16 = ch;
2346 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2347 return 0;
2348 case WM_CHAR:
2349 case WM_DEADCHAR:
2350 case WM_SYSCHAR:
2351 case WM_SYSDEADCHAR:
2352 wch = wParam32;
2353 WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL);
2354 *pwparam16 = ch;
2355 return 0;
2357 default: /* No Unicode translation needed (?) */
2358 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2359 pwparam16, plparam );
2364 /**********************************************************************
2365 * WINPROC_UnmapMsg32WTo16
2367 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2369 void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2370 MSGPARAM16* p16 )
2372 switch(msg)
2374 case WM_GETTEXT:
2375 case WM_ASKCBFORMATNAME:
2377 LPSTR str = MapSL(p16->lParam);
2378 p16->lParam = *((LPARAM *)str - 1);
2379 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)p16->lParam, 0x7fffffff );
2380 SEGPTR_FREE( (LPARAM *)str - 1 );
2382 break;
2383 case LB_GETTEXT:
2384 case CB_GETLBTEXT:
2385 if ( WINPROC_TestLBForStr( hwnd ))
2387 LPSTR str = MapSL(p16->lParam);
2388 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff );
2389 SEGPTR_FREE( (LPARAM *) str );
2391 break;
2392 default:
2393 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, p16 );
2394 break;
2399 /**********************************************************************
2400 * WINPROC_CallProc32ATo32W
2402 * Call a window procedure, translating args from Ansi to Unicode.
2404 static LRESULT WINPROC_CallProc32ATo32W( WNDPROC func, HWND hwnd,
2405 UINT msg, WPARAM wParam,
2406 LPARAM lParam )
2408 LRESULT result;
2409 int unmap;
2411 if( (unmap = WINPROC_MapMsg32ATo32W( hwnd, msg, &wParam, &lParam )) == -1) {
2412 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2413 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2414 return 0;
2416 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2417 if (unmap) result = WINPROC_UnmapMsg32ATo32W( hwnd, msg, wParam, lParam, result );
2418 return result;
2422 /**********************************************************************
2423 * WINPROC_CallProc32WTo32A
2425 * Call a window procedure, translating args from Unicode to Ansi.
2427 static LRESULT WINPROC_CallProc32WTo32A( WNDPROC func, HWND hwnd,
2428 UINT msg, WPARAM wParam,
2429 LPARAM lParam )
2431 LRESULT result;
2432 int unmap;
2434 if ((unmap = WINPROC_MapMsg32WTo32A( hwnd, msg, &wParam, &lParam )) == -1) {
2435 ERR_(msg)("Message translation failed. (msg=%s,wp=%08x,lp=%08lx)\n",
2436 SPY_GetMsgName(msg, hwnd), wParam, lParam );
2437 return 0;
2439 result = WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2440 if( unmap ) WINPROC_UnmapMsg32WTo32A( hwnd, msg, wParam, lParam );
2441 return result;
2445 /**********************************************************************
2446 * __wine_call_wndproc_32A (USER.1010)
2448 LRESULT WINAPI __wine_call_wndproc_32A( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2449 WNDPROC func )
2451 LRESULT result;
2452 UINT msg32;
2453 WPARAM wParam32;
2454 HWND hwnd32 = WIN_Handle32( hwnd );
2456 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2457 return 0;
2458 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2459 return WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, result );
2463 /**********************************************************************
2464 * __wine_call_wndproc_32W (USER.1011)
2466 LRESULT WINAPI __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2467 WNDPROC func )
2469 LRESULT result;
2470 UINT msg32;
2471 WPARAM wParam32;
2472 HWND hwnd32 = WIN_Handle32( hwnd );
2474 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2475 return 0;
2476 result = WINPROC_CallWndProc( func, hwnd32, msg32, wParam32, lParam );
2477 return WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, result );
2481 /**********************************************************************
2482 * WINPROC_CallProc32ATo16
2484 * Call a 16-bit window procedure, translating the 32-bit args.
2486 static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd,
2487 UINT msg, WPARAM wParam,
2488 LPARAM lParam )
2490 UINT16 msg16;
2491 MSGPARAM16 mp16;
2493 mp16.lParam = lParam;
2494 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &mp16.wParam, &mp16.lParam ) == -1)
2495 return 0;
2496 mp16.lResult = WINPROC_CallWndProc16( func, WIN_Handle16(hwnd), msg16,
2497 mp16.wParam, mp16.lParam );
2498 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, &mp16 );
2499 return mp16.lResult;
2503 /**********************************************************************
2504 * WINPROC_CallProc32WTo16
2506 * Call a 16-bit window procedure, translating the 32-bit args.
2508 static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd,
2509 UINT msg, WPARAM wParam,
2510 LPARAM lParam )
2512 UINT16 msg16;
2513 MSGPARAM16 mp16;
2515 mp16.lParam = lParam;
2516 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &mp16.wParam,
2517 &mp16.lParam ) == -1)
2518 return 0;
2519 mp16.lResult = WINPROC_CallWndProc16( func, WIN_Handle16(hwnd), msg16,
2520 mp16.wParam, mp16.lParam );
2521 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, &mp16 );
2522 return mp16.lResult;
2526 /**********************************************************************
2527 * CallWindowProc (USER.122)
2528 * CallWindowProc16 (USER32.@)
2530 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2531 WPARAM16 wParam, LPARAM lParam )
2533 WINDOWPROC *proc = WINPROC_GetPtr( func );
2535 if (!proc)
2536 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2538 #if testing
2539 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_16 );
2540 return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam );
2541 #endif
2543 switch(proc->type)
2545 case WIN_PROC_16:
2546 if (!proc->thunk.t_from32.proc) return 0;
2547 return WINPROC_CallWndProc16( proc->thunk.t_from32.proc,
2548 hwnd, msg, wParam, lParam );
2549 case WIN_PROC_32A:
2550 if (!proc->thunk.t_from16.proc) return 0;
2551 return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2552 case WIN_PROC_32W:
2553 if (!proc->thunk.t_from16.proc) return 0;
2554 return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc );
2555 default:
2556 WARN_(relay)("Invalid proc %p\n", proc );
2557 return 0;
2562 /**********************************************************************
2563 * CallWindowProcA (USER32.@)
2565 * The CallWindowProc() function invokes the windows procedure _func_,
2566 * with _hwnd_ as the target window, the message specified by _msg_, and
2567 * the message parameters _wParam_ and _lParam_.
2569 * Some kinds of argument conversion may be done, I'm not sure what.
2571 * CallWindowProc() may be used for windows subclassing. Use
2572 * SetWindowLong() to set a new windows procedure for windows of the
2573 * subclass, and handle subclassed messages in the new windows
2574 * procedure. The new windows procedure may then use CallWindowProc()
2575 * with _func_ set to the parent class's windows procedure to dispatch
2576 * the message to the superclass.
2578 * RETURNS
2580 * The return value is message dependent.
2582 * CONFORMANCE
2584 * ECMA-234, Win32
2586 LRESULT WINAPI CallWindowProcA(
2587 WNDPROC func, /* [in] window procedure */
2588 HWND hwnd, /* [in] target window */
2589 UINT msg, /* [in] message */
2590 WPARAM wParam, /* [in] message dependent parameter */
2591 LPARAM lParam /* [in] message dependent parameter */
2593 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2595 if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2597 #if testing
2598 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32A );
2599 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2600 #endif
2602 switch(proc->type)
2604 case WIN_PROC_16:
2605 if (!proc->thunk.t_from32.proc) return 0;
2606 return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc,
2607 hwnd, msg, wParam, lParam );
2608 case WIN_PROC_32A:
2609 if (!proc->thunk.t_from16.proc) return 0;
2610 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2611 hwnd, msg, wParam, lParam );
2612 case WIN_PROC_32W:
2613 if (!proc->thunk.t_from16.proc) return 0;
2614 return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc,
2615 hwnd, msg, wParam, lParam );
2616 default:
2617 WARN_(relay)("Invalid proc %p\n", proc );
2618 return 0;
2623 /**********************************************************************
2624 * CallWindowProcW (USER32.@)
2626 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
2627 WPARAM wParam, LPARAM lParam )
2629 WINDOWPROC *proc = WINPROC_GetPtr( (WNDPROC16)func );
2631 if (!proc) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2633 #if testing
2634 func = WINPROC_GetProc( (HWINDOWPROC)proc, WIN_PROC_32W );
2635 return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam );
2636 #endif
2638 switch(proc->type)
2640 case WIN_PROC_16:
2641 if (!proc->thunk.t_from32.proc) return 0;
2642 return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc,
2643 hwnd, msg, wParam, lParam );
2644 case WIN_PROC_32A:
2645 if (!proc->thunk.t_from16.proc) return 0;
2646 return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc,
2647 hwnd, msg, wParam, lParam );
2648 case WIN_PROC_32W:
2649 if (!proc->thunk.t_from16.proc) return 0;
2650 return WINPROC_CallWndProc( proc->thunk.t_from16.proc,
2651 hwnd, msg, wParam, lParam );
2652 default:
2653 WARN_(relay)("Invalid proc %p\n", proc );
2654 return 0;