Correctly size the spi_loaded array prevents overwriting of system
[wine] / windows / defwnd.c
1 /*
2  * Default window procedure
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  *           1995 Alex Korobka
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <string.h>
26
27 #include "win.h"
28 #include "user.h"
29 #include "nonclient.h"
30 #include "winpos.h"
31 #include "dce.h"
32 #include "windef.h"
33 #include "wingdi.h"
34 #include "winnls.h"
35 #include "imm.h"
36 #include "message.h"
37 #include "wine/unicode.h"
38 #include "wine/winuser16.h"
39 #include "wine/server.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(win);
43
44   /* bits in the dwKeyData */
45 #define KEYDATA_ALT             0x2000
46 #define KEYDATA_PREVSTATE       0x4000
47
48 static short iF10Key = 0;
49 static short iMenuSysKey = 0;
50
51 /***********************************************************************
52  *           DEFWND_HandleWindowPosChanged
53  *
54  * Handle the WM_WINDOWPOSCHANGED message.
55  */
56 static void DEFWND_HandleWindowPosChanged( HWND hwnd, UINT flags )
57 {
58     RECT rect;
59     WND *wndPtr = WIN_GetPtr( hwnd );
60
61     rect = wndPtr->rectClient;
62     WIN_ReleasePtr( wndPtr );
63
64     if (!(flags & SWP_NOCLIENTMOVE))
65         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
66
67     if (!(flags & SWP_NOCLIENTSIZE))
68     {
69         WPARAM wp = SIZE_RESTORED;
70         if (IsZoomed(hwnd)) wp = SIZE_MAXIMIZED;
71         else if (IsIconic(hwnd)) wp = SIZE_MINIMIZED;
72
73         SendMessageW( hwnd, WM_SIZE, wp, MAKELONG(rect.right-rect.left, rect.bottom-rect.top) );
74     }
75 }
76
77
78 /***********************************************************************
79  *           DEFWND_SetTextA
80  *
81  * Set the window text.
82  */
83 static void DEFWND_SetTextA( HWND hwnd, LPCSTR text )
84 {
85     int count;
86     WCHAR *textW;
87     WND *wndPtr;
88
89     if (!text) text = "";
90     count = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
91
92     if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
93     if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
94     {
95         if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
96         wndPtr->text = textW;
97         MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
98         SERVER_START_REQ( set_window_text )
99         {
100             req->handle = hwnd;
101             wine_server_add_data( req, textW, (count-1) * sizeof(WCHAR) );
102             wine_server_call( req );
103         }
104         SERVER_END_REQ;
105     }
106     else
107         ERR("Not enough memory for window text\n");
108     WIN_ReleasePtr( wndPtr );
109
110     if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, textW );
111 }
112
113 /***********************************************************************
114  *           DEFWND_SetTextW
115  *
116  * Set the window text.
117  */
118 static void DEFWND_SetTextW( HWND hwnd, LPCWSTR text )
119 {
120     static const WCHAR empty_string[] = {0};
121     WND *wndPtr;
122     int count;
123
124     if (!text) text = empty_string;
125     count = strlenW(text) + 1;
126
127     if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
128     if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
129     if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
130     {
131         strcpyW( wndPtr->text, text );
132         SERVER_START_REQ( set_window_text )
133         {
134             req->handle = hwnd;
135             wine_server_add_data( req, wndPtr->text, (count-1) * sizeof(WCHAR) );
136             wine_server_call( req );
137         }
138         SERVER_END_REQ;
139     }
140     else
141         ERR("Not enough memory for window text\n");
142     text = wndPtr->text;
143     WIN_ReleasePtr( wndPtr );
144
145     if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, text );
146 }
147
148 /***********************************************************************
149  *           DEFWND_ControlColor
150  *
151  * Default colors for control painting.
152  */
153 HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType )
154 {
155     if( ctlType == CTLCOLOR_SCROLLBAR)
156     {
157         HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
158         if (TWEAK_WineLook == WIN31_LOOK) {
159            SetTextColor( hDC, RGB(0, 0, 0) );
160            SetBkColor( hDC, RGB(255, 255, 255) );
161         } else {
162            COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
163            SetTextColor( hDC, GetSysColor(COLOR_3DFACE));
164            SetBkColor( hDC, bk);
165
166            /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
167             * we better use 0x55aa bitmap brush to make scrollbar's background
168             * look different from the window background.
169             */
170            if (bk == GetSysColor(COLOR_WINDOW)) {
171                return CACHE_GetPattern55AABrush();
172            }
173         }
174         UnrealizeObject( hb );
175         return hb;
176     }
177
178     SetTextColor( hDC, GetSysColor(COLOR_WINDOWTEXT));
179
180     if (TWEAK_WineLook > WIN31_LOOK) {
181         if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
182             SetBkColor( hDC, GetSysColor(COLOR_WINDOW) );
183         else {
184             SetBkColor( hDC, GetSysColor(COLOR_3DFACE) );
185             return GetSysColorBrush(COLOR_3DFACE);
186         }
187     }
188     else
189         SetBkColor( hDC, GetSysColor(COLOR_WINDOW) );
190     return GetSysColorBrush(COLOR_WINDOW);
191 }
192
193
194 /***********************************************************************
195  *           DEFWND_SetRedraw
196  */
197 static void DEFWND_SetRedraw( HWND hwnd, WPARAM wParam )
198 {
199     WND *wndPtr = WIN_FindWndPtr( hwnd );
200     BOOL bVisible = wndPtr->dwStyle & WS_VISIBLE;
201
202     TRACE("%p %i\n", hwnd, (wParam!=0) );
203
204     if( wParam )
205     {
206         if( !bVisible )
207         {
208             WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE );
209             DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
210         }
211     }
212     else if( bVisible )
213     {
214         if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
215         else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
216
217         RedrawWindow( hwnd, NULL, 0, wParam );
218         DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
219         WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
220     }
221     WIN_ReleaseWndPtr( wndPtr );
222 }
223
224 /***********************************************************************
225  *           DEFWND_Print
226  *
227  * This method handles the default behavior for the WM_PRINT message.
228  */
229 static void DEFWND_Print( HWND hwnd, HDC hdc, ULONG uFlags)
230 {
231   /*
232    * Visibility flag.
233    */
234   if ( (uFlags & PRF_CHECKVISIBLE) &&
235        !IsWindowVisible(hwnd) )
236       return;
237
238   /*
239    * Unimplemented flags.
240    */
241   if ( (uFlags & PRF_CHILDREN) ||
242        (uFlags & PRF_OWNED)    ||
243        (uFlags & PRF_NONCLIENT) )
244   {
245     WARN("WM_PRINT message with unsupported flags\n");
246   }
247
248   /*
249    * Background
250    */
251   if ( uFlags & PRF_ERASEBKGND)
252     SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
253
254   /*
255    * Client area
256    */
257   if ( uFlags & PRF_CLIENT)
258     SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
259 }
260
261
262 /*
263  * helpers for calling IMM32
264  *
265  * WM_IME_* messages are generated only by IMM32,
266  * so I assume imm32 is already LoadLibrary-ed.
267  */
268 static HWND DEFWND_ImmGetDefaultIMEWnd( HWND hwnd )
269 {
270     HINSTANCE hInstIMM = GetModuleHandleA( "imm32" );
271     HWND (WINAPI *pFunc)(HWND);
272     HWND hwndRet = 0;
273
274     if (!hInstIMM)
275     {
276         ERR( "cannot get IMM32 handle\n" );
277         return 0;
278     }
279
280     pFunc = (void*)GetProcAddress(hInstIMM,"ImmGetDefaultIMEWnd");
281     if ( pFunc != NULL )
282         hwndRet = (*pFunc)( hwnd );
283
284     return hwndRet;
285 }
286
287 static BOOL DEFWND_ImmIsUIMessageA( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam )
288 {
289     HINSTANCE hInstIMM = GetModuleHandleA( "imm32" );
290     BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
291     BOOL fRet = FALSE;
292
293     if (!hInstIMM)
294     {
295         ERR( "cannot get IMM32 handle\n" );
296         return FALSE;
297     }
298
299     pFunc = (void*)GetProcAddress(hInstIMM,"ImmIsUIMessageA");
300     if ( pFunc != NULL )
301         fRet = (*pFunc)( hwndIME, msg, wParam, lParam );
302
303     return fRet;
304 }
305
306 static BOOL DEFWND_ImmIsUIMessageW( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam )
307 {
308     HINSTANCE hInstIMM = GetModuleHandleA( "imm32" );
309     BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
310     BOOL fRet = FALSE;
311
312     if (!hInstIMM)
313     {
314         ERR( "cannot get IMM32 handle\n" );
315         return FALSE;
316     }
317
318     pFunc = (void*)GetProcAddress(hInstIMM,"ImmIsUIMessageW");
319     if ( pFunc != NULL )
320         fRet = (*pFunc)( hwndIME, msg, wParam, lParam );
321
322     return fRet;
323 }
324
325
326
327 /***********************************************************************
328  *           DEFWND_DefWinProc
329  *
330  * Default window procedure for messages that are the same in Win16 and Win32.
331  */
332 static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
333 {
334     switch(msg)
335     {
336     case WM_NCPAINT:
337         return NC_HandleNCPaint( hwnd, (HRGN)wParam );
338
339     case WM_NCHITTEST:
340         {
341             POINT pt;
342             pt.x = (short)LOWORD(lParam);
343             pt.y = (short)HIWORD(lParam);
344             return NC_HandleNCHitTest( hwnd, pt );
345         }
346
347     case WM_NCLBUTTONDOWN:
348         return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
349
350     case WM_LBUTTONDBLCLK:
351     case WM_NCLBUTTONDBLCLK:
352         return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
353
354     case WM_NCRBUTTONDOWN:
355         /* in Windows, capture is taken when right-clicking on the caption bar */
356         if (wParam==HTCAPTION)
357         {
358             SetCapture(hwnd);
359         }
360         break;
361
362     case WM_RBUTTONUP:
363         {
364             POINT pt;
365
366             if (hwnd == GetCapture())
367                 /* release capture if we took it on WM_NCRBUTTONDOWN */
368                 ReleaseCapture();
369
370             pt.x = (short)LOWORD(lParam);
371             pt.y = (short)HIWORD(lParam);
372             ClientToScreen(hwnd, &pt);
373             SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELPARAM(pt.x, pt.y) );
374         }
375         break;
376
377     case WM_NCRBUTTONUP:
378         /*
379          * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
380          * in Windows), but what _should_ we do? According to MSDN :
381          * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
382          * message to the window". When is it appropriate?
383          */
384         break;
385
386     case WM_CONTEXTMENU:
387         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
388             SendMessageW( GetParent(hwnd), msg, wParam, lParam );
389         else
390         {
391             LONG hitcode;
392             POINT pt;
393             WND *wndPtr = WIN_GetPtr( hwnd );
394             HMENU hMenu = wndPtr->hSysMenu;
395             WIN_ReleasePtr( wndPtr );
396             if (!hMenu) return 0;
397             pt.x = (short)LOWORD(lParam);
398             pt.y = (short)HIWORD(lParam);
399             hitcode = NC_HandleNCHitTest(hwnd, pt);
400
401             /* Track system popup if click was in the caption area. */
402             if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
403                TrackPopupMenu(GetSystemMenu(hwnd, FALSE),
404                                TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
405                                pt.x, pt.y, 0, hwnd, NULL);
406         }
407         break;
408
409     case WM_NCACTIVATE:
410         return NC_HandleNCActivate( hwnd, wParam );
411
412     case WM_NCDESTROY:
413         {
414             WND *wndPtr = WIN_GetPtr( hwnd );
415             if (!wndPtr) return 0;
416             if (wndPtr->text) HeapFree( GetProcessHeap(), 0, wndPtr->text );
417             wndPtr->text = NULL;
418             if (wndPtr->pVScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pVScroll );
419             if (wndPtr->pHScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pHScroll );
420             wndPtr->pVScroll = wndPtr->pHScroll = NULL;
421             WIN_ReleasePtr( wndPtr );
422             return 0;
423         }
424
425     case WM_PRINT:
426         DEFWND_Print(hwnd, (HDC)wParam, lParam);
427         return 0;
428
429     case WM_PAINTICON:
430     case WM_PAINT:
431         {
432             PAINTSTRUCT ps;
433             HDC hdc = BeginPaint( hwnd, &ps );
434             if( hdc )
435             {
436               HICON hIcon;
437               if (IsIconic(hwnd) && ((hIcon = (HICON)GetClassLongW( hwnd, GCL_HICON))) )
438               {
439                   RECT rc;
440                   int x, y;
441
442                   GetClientRect( hwnd, &rc );
443                   x = (rc.right - rc.left - GetSystemMetrics(SM_CXICON))/2;
444                   y = (rc.bottom - rc.top - GetSystemMetrics(SM_CYICON))/2;
445                   TRACE("Painting class icon: vis rect=(%ld,%ld - %ld,%ld)\n",
446                         ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom );
447                   DrawIcon( hdc, x, y, hIcon );
448               }
449               EndPaint( hwnd, &ps );
450             }
451             return 0;
452         }
453
454     case WM_SYNCPAINT:
455         RedrawWindow ( hwnd, NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN );
456         return 0;
457
458     case WM_SETREDRAW:
459         DEFWND_SetRedraw( hwnd, wParam );
460         return 0;
461
462     case WM_CLOSE:
463         DestroyWindow( hwnd );
464         return 0;
465
466     case WM_MOUSEACTIVATE:
467         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
468         {
469             LONG ret = SendMessageW( GetParent(hwnd), WM_MOUSEACTIVATE, wParam, lParam );
470             if (ret) return ret;
471         }
472
473         /* Caption clicks are handled by the NC_HandleNCLButtonDown() */
474         return (LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE;
475
476     case WM_ACTIVATE:
477         /* The default action in Windows is to set the keyboard focus to
478          * the window, if it's being activated and not minimized */
479         if (LOWORD(wParam) != WA_INACTIVE) {
480             if (!IsIconic(hwnd)) SetFocus(hwnd);
481         }
482         break;
483
484     case WM_MOUSEWHEEL:
485         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
486             return SendMessageW( GetParent(hwnd), WM_MOUSEWHEEL, wParam, lParam );
487         break;
488
489     case WM_ERASEBKGND:
490     case WM_ICONERASEBKGND:
491         {
492             RECT rect;
493             HDC hdc = (HDC)wParam;
494             HBRUSH hbr = (HBRUSH)GetClassLongW( hwnd, GCL_HBRBACKGROUND );
495             if (!hbr) return 0;
496
497             if (GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC)
498             {
499                 /* can't use GetClipBox with a parent DC or we fill the whole parent */
500                 GetClientRect( hwnd, &rect );
501                 DPtoLP( hdc, (LPPOINT)&rect, 2 );
502             }
503             else GetClipBox( hdc, &rect );
504             FillRect( hdc, &rect, hbr );
505             return 1;
506         }
507
508     case WM_GETDLGCODE:
509         return 0;
510
511     case WM_CTLCOLORMSGBOX:
512     case WM_CTLCOLOREDIT:
513     case WM_CTLCOLORLISTBOX:
514     case WM_CTLCOLORBTN:
515     case WM_CTLCOLORDLG:
516     case WM_CTLCOLORSTATIC:
517     case WM_CTLCOLORSCROLLBAR:
518         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, msg - WM_CTLCOLORMSGBOX );
519
520     case WM_CTLCOLOR:
521         return (LRESULT)DEFWND_ControlColor( (HDC)wParam, HIWORD(lParam) );
522
523     case WM_SETCURSOR:
524         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
525         {
526             /* with the exception of the border around a resizable wnd,
527              * give the parent first chance to set the cursor */
528             if ((LOWORD(lParam) < HTSIZEFIRST) || (LOWORD(lParam) > HTSIZELAST))
529             {
530                 if (SendMessageW(GetParent(hwnd), WM_SETCURSOR, wParam, lParam)) return TRUE;
531             }
532         }
533         NC_HandleSetCursor( hwnd, wParam, lParam );
534         break;
535
536     case WM_SYSCOMMAND:
537         return NC_HandleSysCommand( hwnd, wParam, lParam );
538
539     case WM_KEYDOWN:
540         if(wParam == VK_F10) iF10Key = VK_F10;
541         break;
542
543     case WM_SYSKEYDOWN:
544         if( HIWORD(lParam) & KEYDATA_ALT )
545         {
546             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
547               if( wParam == VK_MENU && !iMenuSysKey )
548                 iMenuSysKey = 1;
549               else
550                 iMenuSysKey = 0;
551
552             iF10Key = 0;
553
554             if( wParam == VK_F4 )       /* try to close the window */
555             {
556                 HWND top = GetAncestor( hwnd, GA_ROOT );
557                 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
558                     PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
559             }
560         }
561         else if( wParam == VK_F10 )
562                 iF10Key = 1;
563              else
564                 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
565                     SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
566         break;
567
568     case WM_KEYUP:
569     case WM_SYSKEYUP:
570         /* Press and release F10 or ALT */
571         if (((wParam == VK_MENU) && iMenuSysKey) ||
572             ((wParam == VK_F10) && iF10Key))
573               SendMessageW( GetAncestor( hwnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
574         iMenuSysKey = iF10Key = 0;
575         break;
576
577     case WM_SYSCHAR:
578     {
579         iMenuSysKey = 0;
580         if (wParam == '\r' && IsIconic(hwnd))
581         {
582             PostMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
583             break;
584         }
585         if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
586         {
587             if (wParam == '\t' || wParam == '\x1b') break;
588             if (wParam == ' ' && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD))
589                 SendMessageW( GetParent(hwnd), msg, wParam, lParam );
590             else
591                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
592         }
593         else /* check for Ctrl-Esc */
594             if (wParam != '\x1b') MessageBeep(0);
595         break;
596     }
597
598     case WM_SHOWWINDOW:
599         {
600             LONG style = GetWindowLongW( hwnd, GWL_STYLE );
601             if (!lParam) return 0; /* sent from ShowWindow */
602             if (!(style & WS_POPUP)) return 0;
603             if ((style & WS_VISIBLE) && wParam) return 0;
604             if (!(style & WS_VISIBLE) && !wParam) return 0;
605             if (!GetWindow( hwnd, GW_OWNER )) return 0;
606             ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
607             break;
608         }
609
610     case WM_CANCELMODE:
611         if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
612         if (GetCapture() == hwnd) ReleaseCapture();
613         break;
614
615     case WM_VKEYTOITEM:
616     case WM_CHARTOITEM:
617         return -1;
618
619     case WM_DROPOBJECT:
620         return DRAG_FILE;
621
622     case WM_QUERYDROPOBJECT:
623         return (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
624
625     case WM_QUERYDRAGICON:
626         {
627             UINT len;
628
629             HICON hIcon = (HICON)GetClassLongW( hwnd, GCL_HICON );
630             HINSTANCE instance = (HINSTANCE)GetWindowLongW( hwnd, GWL_HINSTANCE );
631             if (hIcon) return (LRESULT)hIcon;
632             for(len=1; len<64; len++)
633                 if((hIcon = LoadIconW(instance, MAKEINTRESOURCEW(len))))
634                     return (LRESULT)hIcon;
635             return (LRESULT)LoadIconW(0, (LPWSTR)IDI_APPLICATION);
636         }
637         break;
638
639     case WM_ISACTIVEICON:
640         {
641             WND *wndPtr = WIN_GetPtr( hwnd );
642             BOOL ret = (wndPtr->flags & WIN_NCACTIVATED) != 0;
643             WIN_ReleasePtr( wndPtr );
644             return ret;
645         }
646
647     case WM_NOTIFYFORMAT:
648       if (IsWindowUnicode(hwnd)) return NFR_UNICODE;
649       else return NFR_ANSI;
650
651     case WM_QUERYOPEN:
652     case WM_QUERYENDSESSION:
653         return 1;
654
655     case WM_SETICON:
656         {
657             HICON ret;
658             WND *wndPtr = WIN_GetPtr( hwnd );
659
660             switch(wParam)
661             {
662             case ICON_SMALL:
663                 ret = wndPtr->hIconSmall;
664                 wndPtr->hIconSmall = (HICON)lParam;
665                 break;
666             case ICON_BIG:
667                 ret = wndPtr->hIcon;
668                 wndPtr->hIcon = (HICON)lParam;
669                 break;
670             default:
671                 ret = 0;
672                 break;
673             }
674             WIN_ReleasePtr( wndPtr );
675
676             if (USER_Driver.pSetWindowIcon)
677                 USER_Driver.pSetWindowIcon( hwnd, wParam, (HICON)lParam );
678
679             SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
680                          SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
681
682             return (LRESULT)ret;
683         }
684
685     case WM_GETICON:
686         {
687             HICON ret;
688             WND *wndPtr = WIN_GetPtr( hwnd );
689
690             switch(wParam)
691             {
692             case ICON_SMALL:
693                 ret = wndPtr->hIconSmall;
694                 break;
695             case ICON_BIG:
696                 ret = wndPtr->hIcon;
697                 break;
698             case ICON_SMALL2:
699                 ret = wndPtr->hIconSmall;
700                 if (!ret) ret = (HICON)GetClassLongA( hwnd, GCL_HICONSM );
701                 /* FIXME: should have a default here if class icon is null */
702                 break;
703             default:
704                 ret = 0;
705                 break;
706             }
707             WIN_ReleasePtr( wndPtr );
708             return (LRESULT)ret;
709         }
710
711     case WM_HELP:
712         SendMessageW( GetParent(hwnd), msg, wParam, lParam );
713         break;
714     }
715
716     return 0;
717 }
718
719
720
721 /***********************************************************************
722  *              DefWindowProc (USER.107)
723  */
724 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam,
725                                 LPARAM lParam )
726 {
727     LRESULT result = 0;
728     HWND hwnd = WIN_Handle32( hwnd16 );
729
730     if (!WIN_IsCurrentProcess( hwnd ))
731     {
732         if (!IsWindow( hwnd )) return 0;
733         ERR( "called for other process window %p\n", hwnd );
734         return 0;
735     }
736     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
737
738     switch(msg)
739     {
740     case WM_NCCREATE:
741         {
742             CREATESTRUCT16 *cs = MapSL(lParam);
743             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
744              * may have child window IDs instead of window name */
745             if (HIWORD(cs->lpszName))
746                 DEFWND_SetTextA( hwnd, MapSL(cs->lpszName) );
747             result = 1;
748         }
749         break;
750
751     case WM_NCCALCSIZE:
752         {
753             RECT rect32;
754             CONV_RECT16TO32( MapSL(lParam), &rect32 );
755             result = NC_HandleNCCalcSize( hwnd, &rect32 );
756             CONV_RECT32TO16( &rect32, MapSL(lParam) );
757         }
758         break;
759
760     case WM_WINDOWPOSCHANGING:
761         result = WINPOS_HandleWindowPosChanging16( hwnd, MapSL(lParam) );
762         break;
763
764     case WM_WINDOWPOSCHANGED:
765         {
766             WINDOWPOS16 * winPos = MapSL(lParam);
767             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
768         }
769         break;
770
771     case WM_GETTEXT:
772     case WM_SETTEXT:
773         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
774         break;
775
776     default:
777         result = DefWindowProcA( hwnd, msg, wParam, lParam );
778         break;
779     }
780
781     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
782     return result;
783 }
784
785
786 /***********************************************************************
787  *              DefWindowProcA (USER32.@)
788  *
789  */
790 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
791 {
792     LRESULT result = 0;
793     HWND full_handle;
794
795     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
796     {
797         if (!IsWindow( hwnd )) return 0;
798         ERR( "called for other process window %p\n", hwnd );
799         return 0;
800     }
801     hwnd = full_handle;
802
803     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
804
805     switch(msg)
806     {
807     case WM_NCCREATE:
808         {
809             CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
810             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
811              * may have child window IDs instead of window name */
812             if (HIWORD(cs->lpszName))
813                 DEFWND_SetTextA( hwnd, cs->lpszName );
814             result = 1;
815         }
816         break;
817
818     case WM_NCCALCSIZE:
819         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
820         break;
821
822     case WM_WINDOWPOSCHANGING:
823         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
824         break;
825
826     case WM_WINDOWPOSCHANGED:
827         {
828             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
829             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
830         }
831         break;
832
833     case WM_GETTEXTLENGTH:
834         {
835             WND *wndPtr = WIN_GetPtr( hwnd );
836             if (wndPtr && wndPtr->text)
837                 result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
838                                               NULL, 0, NULL, NULL );
839             WIN_ReleasePtr( wndPtr );
840         }
841         break;
842
843     case WM_GETTEXT:
844         if (wParam)
845         {
846             LPSTR dest = (LPSTR)lParam;
847             WND *wndPtr = WIN_GetPtr( hwnd );
848
849             if (!wndPtr) break;
850             if (wndPtr->text)
851             {
852                 if (!WideCharToMultiByte( CP_ACP, 0, wndPtr->text, -1,
853                                           dest, wParam, NULL, NULL )) dest[wParam-1] = 0;
854                 result = strlen( dest );
855             }
856             else dest[0] = '\0';
857             WIN_ReleasePtr( wndPtr );
858         }
859         break;
860
861     case WM_SETTEXT:
862         DEFWND_SetTextA( hwnd, (LPCSTR)lParam );
863         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
864             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
865         result = 1; /* success. FIXME: check text length */
866         break;
867
868     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
869     case WM_IME_CHAR:
870         {
871             CHAR    chChar1 = (CHAR)( (wParam>>8) & 0xff );
872             CHAR    chChar2 = (CHAR)( wParam & 0xff );
873
874             if (chChar1)
875                 SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar1, lParam );
876             SendMessageA( hwnd, WM_CHAR, (WPARAM)chChar2, lParam );
877         }
878         break;
879     case WM_IME_KEYDOWN:
880         result = SendMessageA( hwnd, WM_KEYDOWN, wParam, lParam );
881         break;
882     case WM_IME_KEYUP:
883         result = SendMessageA( hwnd, WM_KEYUP, wParam, lParam );
884         break;
885
886     case WM_IME_STARTCOMPOSITION:
887     case WM_IME_COMPOSITION:
888     case WM_IME_ENDCOMPOSITION:
889     case WM_IME_SELECT:
890         {
891             HWND hwndIME;
892
893             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
894             if (hwndIME)
895                 result = SendMessageA( hwndIME, msg, wParam, lParam );
896         }
897         break;
898     case WM_IME_SETCONTEXT:
899         {
900             HWND hwndIME;
901
902             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
903             if (hwndIME)
904                 result = DEFWND_ImmIsUIMessageA( hwndIME, msg, wParam, lParam );
905         }
906         break;
907
908     case WM_INPUTLANGCHANGEREQUEST:
909         /* notify about the switch only if it's really our current layout */
910         if ((HKL)lParam == GetKeyboardLayout(0))
911             result = SendMessageA( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
912         else
913             result = 0;
914         break;
915
916     case WM_SYSCHAR:
917     {
918         BYTE ch = LOWORD(wParam);
919         WCHAR wch;
920         MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
921         wParam = MAKEWPARAM( wch, HIWORD(wParam) );
922     }
923     /* fall through */
924     default:
925         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
926         break;
927     }
928
929     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
930     return result;
931 }
932
933
934 /***********************************************************************
935  *              DefWindowProcW (USER32.@) Calls default window message handler
936  *
937  * Calls default window procedure for messages not processed
938  *  by application.
939  *
940  *  RETURNS
941  *     Return value is dependent upon the message.
942 */
943 LRESULT WINAPI DefWindowProcW(
944     HWND hwnd,      /* [in] window procedure receiving message */
945     UINT msg,       /* [in] message identifier */
946     WPARAM wParam,  /* [in] first message parameter */
947     LPARAM lParam )   /* [in] second message parameter */
948 {
949     LRESULT result = 0;
950     HWND full_handle;
951
952     if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
953     {
954         if (!IsWindow( hwnd )) return 0;
955         ERR( "called for other process window %p\n", hwnd );
956         return 0;
957     }
958     hwnd = full_handle;
959     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
960
961     switch(msg)
962     {
963     case WM_NCCREATE:
964         {
965             CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
966             /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
967              * may have child window IDs instead of window name */
968             if (HIWORD(cs->lpszName))
969                 DEFWND_SetTextW( hwnd, cs->lpszName );
970             result = 1;
971         }
972         break;
973
974     case WM_NCCALCSIZE:
975         result = NC_HandleNCCalcSize( hwnd, (RECT *)lParam );
976         break;
977
978     case WM_WINDOWPOSCHANGING:
979         result = WINPOS_HandleWindowPosChanging( hwnd, (WINDOWPOS *)lParam );
980         break;
981
982     case WM_WINDOWPOSCHANGED:
983         {
984             WINDOWPOS * winPos = (WINDOWPOS *)lParam;
985             DEFWND_HandleWindowPosChanged( hwnd, winPos->flags );
986         }
987         break;
988
989     case WM_GETTEXTLENGTH:
990         {
991             WND *wndPtr = WIN_GetPtr( hwnd );
992             if (wndPtr && wndPtr->text) result = (LRESULT)strlenW(wndPtr->text);
993             WIN_ReleasePtr( wndPtr );
994         }
995         break;
996
997     case WM_GETTEXT:
998         if (wParam)
999         {
1000             LPWSTR dest = (LPWSTR)lParam;
1001             WND *wndPtr = WIN_GetPtr( hwnd );
1002
1003             if (!wndPtr) break;
1004             if (wndPtr->text)
1005             {
1006                 lstrcpynW( dest, wndPtr->text, wParam );
1007                 result = strlenW( dest );
1008             }
1009             else dest[0] = '\0';
1010             WIN_ReleasePtr( wndPtr );
1011         }
1012         break;
1013
1014     case WM_SETTEXT:
1015         DEFWND_SetTextW( hwnd, (LPCWSTR)lParam );
1016         if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION )
1017             NC_HandleNCPaint( hwnd , (HRGN)1 );  /* Repaint caption */
1018         result = 1; /* success. FIXME: check text length */
1019         break;
1020
1021     /* for far east users (IMM32) - <hidenori@a2.ctktv.ne.jp> */
1022     case WM_IME_CHAR:
1023         SendMessageW( hwnd, WM_CHAR, wParam, lParam );
1024         break;
1025     case WM_IME_SETCONTEXT:
1026         {
1027             HWND hwndIME;
1028
1029             hwndIME = DEFWND_ImmGetDefaultIMEWnd( hwnd );
1030             if (hwndIME)
1031                 result = DEFWND_ImmIsUIMessageW( hwndIME, msg, wParam, lParam );
1032         }
1033         break;
1034
1035     case WM_INPUTLANGCHANGEREQUEST:
1036         /* notify about the switch only if it's really our current layout */
1037         if ((HKL)lParam == GetKeyboardLayout(0))
1038             result = SendMessageW( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
1039         else
1040             result = 0;
1041         break;
1042
1043     default:
1044         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
1045         break;
1046     }
1047     SPY_ExitMessage( SPY_RESULT_DEFWND, hwnd, msg, result, wParam, lParam );
1048     return result;
1049 }