mlang/tests: Reduce the size of the test output a little.
[wine] / dlls / user32 / win.c
1 /*
2  * Window related functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "controls.h"
38 #include "winerror.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
42
43 #define NB_USER_HANDLES  ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
45
46 /**********************************************************************/
47
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
50 {
51     if (size == sizeof(WORD))
52     {
53         WORD ret;
54         memcpy( &ret, ptr, sizeof(ret) );
55         return ret;
56     }
57     else if (size == sizeof(DWORD))
58     {
59         DWORD ret;
60         memcpy( &ret, ptr, sizeof(ret) );
61         return ret;
62     }
63     else
64     {
65         LONG_PTR ret;
66         memcpy( &ret, ptr, sizeof(ret) );
67         return ret;
68     }
69 }
70
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
73 {
74     if (size == sizeof(WORD))
75     {
76         WORD newval = val;
77         memcpy( ptr, &newval, sizeof(newval) );
78     }
79     else if (size == sizeof(DWORD))
80     {
81         DWORD newval = val;
82         memcpy( ptr, &newval, sizeof(newval) );
83     }
84     else
85     {
86         memcpy( ptr, &val, sizeof(val) );
87     }
88 }
89
90
91 static void *user_handles[NB_USER_HANDLES];
92
93 /***********************************************************************
94  *           create_window_handle
95  *
96  * Create a window handle with the server.
97  */
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99                                   HINSTANCE instance, BOOL unicode )
100 {
101     WORD index;
102     WND *win;
103     HWND full_parent = 0, full_owner = 0;
104     struct tagCLASS *class = NULL;
105     user_handle_t handle = 0;
106     int extra_bytes = 0;
107
108     /* if 16-bit instance, map to module handle */
109     if (instance && !HIWORD(instance))
110         instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111
112     SERVER_START_REQ( create_window )
113     {
114         req->parent   = parent;
115         req->owner    = owner;
116         req->instance = instance;
117         if (!(req->atom = get_int_atom_value( name )) && name)
118             wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119         if (!wine_server_call_err( req ))
120         {
121             handle = reply->handle;
122             full_parent = reply->parent;
123             full_owner  = reply->owner;
124             extra_bytes = reply->extra;
125             class = reply->class_ptr;
126         }
127     }
128     SERVER_END_REQ;
129
130     if (!handle)
131     {
132         WARN( "error %d creating window\n", GetLastError() );
133         return NULL;
134     }
135
136     if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
137                            sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138     {
139         SERVER_START_REQ( destroy_window )
140         {
141             req->handle = handle;
142             wine_server_call( req );
143         }
144         SERVER_END_REQ;
145         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
146         return NULL;
147     }
148
149     if (!parent)  /* if parent is 0 we don't have a desktop window yet */
150     {
151         struct user_thread_info *thread_info = get_user_thread_info();
152
153         if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
154         else assert( full_parent == thread_info->desktop );
155         if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
156             ERR( "failed to create desktop window\n" );
157     }
158
159     USER_Lock();
160
161     index = USER_HANDLE_TO_INDEX(handle);
162     assert( index < NB_USER_HANDLES );
163     user_handles[index] = win;
164     win->hwndSelf   = handle;
165     win->parent     = full_parent;
166     win->owner      = full_owner;
167     win->class      = class;
168     win->winproc    = get_class_winproc( class );
169     win->dwMagic    = WND_MAGIC;
170     win->cbWndExtra = extra_bytes;
171     if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
172     return win;
173 }
174
175
176 /***********************************************************************
177  *           free_window_handle
178  *
179  * Free a window handle.
180  */
181 static WND *free_window_handle( HWND hwnd )
182 {
183     WND *ptr;
184     WORD index = USER_HANDLE_TO_INDEX(hwnd);
185
186     if (index >= NB_USER_HANDLES) return NULL;
187     USER_Lock();
188     if ((ptr = user_handles[index]))
189     {
190         SERVER_START_REQ( destroy_window )
191         {
192             req->handle = hwnd;
193             if (!wine_server_call_err( req ))
194             {
195                 user_handles[index] = NULL;
196                 ptr->dwMagic = 0;
197             }
198             else
199                 ptr = NULL;
200         }
201         SERVER_END_REQ;
202     }
203     USER_Unlock();
204     HeapFree( GetProcessHeap(), 0, ptr );
205     return ptr;
206 }
207
208
209 /*******************************************************************
210  *           list_window_children
211  *
212  * Build an array of the children of a given window. The array must be
213  * freed with HeapFree. Returns NULL when no windows are found.
214  */
215 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
216 {
217     HWND *list;
218     int size = 128;
219
220     for (;;)
221     {
222         int count = 0;
223
224         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225
226         SERVER_START_REQ( get_window_children )
227         {
228             req->desktop = desktop;
229             req->parent = hwnd;
230             req->tid = tid;
231             if (!(req->atom = get_int_atom_value( class )) && class)
232                 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234             if (!wine_server_call( req )) count = reply->count;
235         }
236         SERVER_END_REQ;
237         if (count && count < size)
238         {
239             list[count] = 0;
240             return list;
241         }
242         HeapFree( GetProcessHeap(), 0, list );
243         if (!count) break;
244         size = count + 1;  /* restart with a large enough buffer */
245     }
246     return NULL;
247 }
248
249
250 /*******************************************************************
251  *           list_window_parents
252  *
253  * Build an array of all parents of a given window, starting with
254  * the immediate parent. The array must be freed with HeapFree.
255  */
256 static HWND *list_window_parents( HWND hwnd )
257 {
258     WND *win;
259     HWND current, *list;
260     int pos = 0, size = 16, count = 0;
261
262     if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
263
264     current = hwnd;
265     for (;;)
266     {
267         if (!(win = WIN_GetPtr( current ))) goto empty;
268         if (win == WND_OTHER_PROCESS) break;  /* need to do it the hard way */
269         if (win == WND_DESKTOP)
270         {
271             if (!pos) goto empty;
272             list[pos] = 0;
273             return list;
274         }
275         list[pos] = current = win->parent;
276         WIN_ReleasePtr( win );
277         if (!current) return list;
278         if (++pos == size - 1)
279         {
280             /* need to grow the list */
281             HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
282             if (!new_list) goto empty;
283             list = new_list;
284             size += 16;
285         }
286     }
287
288     /* at least one parent belongs to another process, have to query the server */
289
290     for (;;)
291     {
292         count = 0;
293         SERVER_START_REQ( get_window_parents )
294         {
295             req->handle = hwnd;
296             wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
297             if (!wine_server_call( req )) count = reply->count;
298         }
299         SERVER_END_REQ;
300         if (!count) goto empty;
301         if (size > count)
302         {
303             list[count] = 0;
304             return list;
305         }
306         HeapFree( GetProcessHeap(), 0, list );
307         size = count + 1;
308         if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
309     }
310
311  empty:
312     HeapFree( GetProcessHeap(), 0, list );
313     return NULL;
314 }
315
316
317 /*******************************************************************
318  *           send_parent_notify
319  */
320 static void send_parent_notify( HWND hwnd, UINT msg )
321 {
322     if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
323         !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324     {
325         HWND parent = GetParent(hwnd);
326         if (parent && parent != GetDesktopWindow())
327             SendMessageW( parent, WM_PARENTNOTIFY,
328                           MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329     }
330 }
331
332
333 /*******************************************************************
334  *              get_server_window_text
335  *
336  * Retrieve the window text from the server.
337  */
338 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
339 {
340     size_t len = 0;
341
342     SERVER_START_REQ( get_window_text )
343     {
344         req->handle = hwnd;
345         wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
346         if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
347     }
348     SERVER_END_REQ;
349     text[len / sizeof(WCHAR)] = 0;
350 }
351
352
353 /***********************************************************************
354  *           WIN_GetPtr
355  *
356  * Return a pointer to the WND structure if local to the process,
357  * or WND_OTHER_PROCESS if handle may be valid in other process.
358  * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359  */
360 WND *WIN_GetPtr( HWND hwnd )
361 {
362     WND * ptr;
363     WORD index = USER_HANDLE_TO_INDEX(hwnd);
364
365     if (index >= NB_USER_HANDLES) return NULL;
366
367     USER_Lock();
368     if ((ptr = user_handles[index]))
369     {
370         if (ptr->dwMagic == WND_MAGIC &&
371             (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
372             return ptr;
373         ptr = NULL;
374     }
375     else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376     {
377         if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
378         else ptr = NULL;
379     }
380     else ptr = WND_OTHER_PROCESS;
381     USER_Unlock();
382     return ptr;
383 }
384
385
386 /***********************************************************************
387  *           WIN_IsCurrentProcess
388  *
389  * Check whether a given window belongs to the current process (and return the full handle).
390  */
391 HWND WIN_IsCurrentProcess( HWND hwnd )
392 {
393     WND *ptr;
394     HWND ret;
395
396     if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
397     ret = ptr->hwndSelf;
398     WIN_ReleasePtr( ptr );
399     return ret;
400 }
401
402
403 /***********************************************************************
404  *           WIN_IsCurrentThread
405  *
406  * Check whether a given window belongs to the current thread (and return the full handle).
407  */
408 HWND WIN_IsCurrentThread( HWND hwnd )
409 {
410     WND *ptr;
411     HWND ret = 0;
412
413     if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
414     if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
415     WIN_ReleasePtr( ptr );
416     return ret;
417 }
418
419
420 /***********************************************************************
421  *           WIN_Handle32
422  *
423  * Convert a 16-bit window handle to a full 32-bit handle.
424  */
425 HWND WIN_Handle32( HWND16 hwnd16 )
426 {
427     WND *ptr;
428     HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429
430     if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
431     /* do sign extension for -2 and -3 */
432     if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433
434     if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435
436     if (ptr == WND_DESKTOP) return GetDesktopWindow();
437
438     if (ptr != WND_OTHER_PROCESS)
439     {
440         hwnd = ptr->hwndSelf;
441         WIN_ReleasePtr( ptr );
442     }
443     else  /* may belong to another process */
444     {
445         SERVER_START_REQ( get_window_info )
446         {
447             req->handle = hwnd;
448             if (!wine_server_call_err( req )) hwnd = reply->full_handle;
449         }
450         SERVER_END_REQ;
451     }
452     return hwnd;
453 }
454
455
456 /***********************************************************************
457  *           WIN_SetOwner
458  *
459  * Change the owner of a window.
460  */
461 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 {
463     WND *win = WIN_GetPtr( hwnd );
464     HWND ret = 0;
465
466     if (!win || win == WND_DESKTOP) return 0;
467     if (win == WND_OTHER_PROCESS)
468     {
469         if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
470         return 0;
471     }
472     SERVER_START_REQ( set_window_owner )
473     {
474         req->handle = hwnd;
475         req->owner  = owner;
476         if (!wine_server_call( req ))
477         {
478             win->owner = reply->full_owner;
479             ret = reply->prev_owner;
480         }
481     }
482     SERVER_END_REQ;
483     WIN_ReleasePtr( win );
484     return ret;
485 }
486
487
488 /***********************************************************************
489  *           WIN_SetStyle
490  *
491  * Change the style of a window.
492  */
493 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
494 {
495     BOOL ok;
496     ULONG new_style, old_style = 0;
497     WND *win = WIN_GetPtr( hwnd );
498
499     if (!win || win == WND_DESKTOP) return 0;
500     if (win == WND_OTHER_PROCESS)
501     {
502         if (IsWindow(hwnd))
503             ERR( "cannot set style %x/%x on other process window %p\n",
504                  set_bits, clear_bits, hwnd );
505         return 0;
506     }
507     new_style = (win->dwStyle | set_bits) & ~clear_bits;
508     if (new_style == win->dwStyle)
509     {
510         WIN_ReleasePtr( win );
511         return new_style;
512     }
513     SERVER_START_REQ( set_window_info )
514     {
515         req->handle = hwnd;
516         req->flags  = SET_WIN_STYLE;
517         req->style  = new_style;
518         req->extra_offset = -1;
519         if ((ok = !wine_server_call( req )))
520         {
521             old_style = reply->old_style;
522             win->dwStyle = new_style;
523         }
524     }
525     SERVER_END_REQ;
526     WIN_ReleasePtr( win );
527     if (ok)
528     {
529         USER_Driver->pSetWindowStyle( hwnd, old_style );
530         if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
531     }
532     return old_style;
533 }
534
535
536 /***********************************************************************
537  *           WIN_GetRectangles
538  *
539  * Get the window and client rectangles.
540  */
541 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
542 {
543     WND *win = WIN_GetPtr( hwnd );
544     BOOL ret = TRUE;
545
546     if (!win) return FALSE;
547     if (win == WND_DESKTOP)
548     {
549         RECT rect;
550         rect.left = rect.top = 0;
551         rect.right  = GetSystemMetrics(SM_CXSCREEN);
552         rect.bottom = GetSystemMetrics(SM_CYSCREEN);
553         if (rectWindow) *rectWindow = rect;
554         if (rectClient) *rectClient = rect;
555     }
556     else if (win == WND_OTHER_PROCESS)
557     {
558         SERVER_START_REQ( get_window_rectangles )
559         {
560             req->handle = hwnd;
561             if ((ret = !wine_server_call( req )))
562             {
563                 if (rectWindow)
564                 {
565                     rectWindow->left   = reply->window.left;
566                     rectWindow->top    = reply->window.top;
567                     rectWindow->right  = reply->window.right;
568                     rectWindow->bottom = reply->window.bottom;
569                 }
570                 if (rectClient)
571                 {
572                     rectClient->left   = reply->client.left;
573                     rectClient->top    = reply->client.top;
574                     rectClient->right  = reply->client.right;
575                     rectClient->bottom = reply->client.bottom;
576                 }
577             }
578         }
579         SERVER_END_REQ;
580     }
581     else
582     {
583         if (rectWindow) *rectWindow = win->rectWindow;
584         if (rectClient) *rectClient = win->rectClient;
585         WIN_ReleasePtr( win );
586     }
587     return ret;
588 }
589
590
591 /***********************************************************************
592  *           WIN_DestroyWindow
593  *
594  * Destroy storage associated to a window. "Internals" p.358
595  */
596 LRESULT WIN_DestroyWindow( HWND hwnd )
597 {
598     WND *wndPtr;
599     HWND *list;
600     HMENU menu = 0, sys_menu;
601     HWND icon_title;
602
603     TRACE("%p\n", hwnd );
604
605     /* free child windows */
606     if ((list = WIN_ListChildren( hwnd )))
607     {
608         int i;
609         for (i = 0; list[i]; i++)
610         {
611             if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
612             else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
613         }
614         HeapFree( GetProcessHeap(), 0, list );
615     }
616
617     /* Unlink now so we won't bother with the children later on */
618     SERVER_START_REQ( set_parent )
619     {
620         req->handle = hwnd;
621         req->parent = 0;
622         wine_server_call( req );
623     }
624     SERVER_END_REQ;
625
626     /*
627      * Send the WM_NCDESTROY to the window being destroyed.
628      */
629     SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
630
631     /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
632
633     /* free resources associated with the window */
634
635     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
636     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
637         menu = (HMENU)wndPtr->wIDmenu;
638     sys_menu = wndPtr->hSysMenu;
639     free_dce( wndPtr->dce, hwnd );
640     wndPtr->dce = NULL;
641     icon_title = wndPtr->icon_title;
642     WIN_ReleasePtr( wndPtr );
643
644     if (icon_title) DestroyWindow( icon_title );
645     if (menu) DestroyMenu( menu );
646     if (sys_menu) DestroyMenu( sys_menu );
647
648     USER_Driver->pDestroyWindow( hwnd );
649
650     free_window_handle( hwnd );
651     return 0;
652 }
653
654 /***********************************************************************
655  *           WIN_DestroyThreadWindows
656  *
657  * Destroy all children of 'wnd' owned by the current thread.
658  */
659 void WIN_DestroyThreadWindows( HWND hwnd )
660 {
661     HWND *list;
662     int i;
663
664     if (!(list = WIN_ListChildren( hwnd ))) return;
665     for (i = 0; list[i]; i++)
666     {
667         if (WIN_IsCurrentThread( list[i] ))
668             DestroyWindow( list[i] );
669         else
670             WIN_DestroyThreadWindows( list[i] );
671     }
672     HeapFree( GetProcessHeap(), 0, list );
673 }
674
675
676 /***********************************************************************
677  *           WIN_FixCoordinates
678  *
679  * Fix the coordinates - Helper for WIN_CreateWindowEx.
680  * returns default show mode in sw.
681  */
682 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
683 {
684 #define IS_DEFAULT(x)  ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
685     POINT pos[2];
686
687     if (cs->dwExStyle & WS_EX_MDICHILD)
688     {
689         UINT id = 0;
690
691         MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
692         if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
693
694         TRACE("MDI child id %04x\n", id);
695     }
696
697     if (cs->style & (WS_CHILD | WS_POPUP))
698     {
699         if (cs->dwExStyle & WS_EX_MDICHILD)
700         {
701             if (IS_DEFAULT(cs->x))
702             {
703                 cs->x = pos[0].x;
704                 cs->y = pos[0].y;
705             }
706             if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
707             if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
708         }
709         else
710         {
711             if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
712             if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
713         }
714     }
715     else  /* overlapped window */
716     {
717         HMONITOR monitor;
718         MONITORINFO mon_info;
719         STARTUPINFOW info;
720
721         if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
722
723         monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
724         mon_info.cbSize = sizeof(mon_info);
725         GetMonitorInfoW( monitor, &mon_info );
726         GetStartupInfoW( &info );
727
728         if (IS_DEFAULT(cs->x))
729         {
730             if (!IS_DEFAULT(cs->y)) *sw = cs->y;
731             cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
732             cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
733         }
734
735         if (IS_DEFAULT(cs->cx))
736         {
737             if (info.dwFlags & STARTF_USESIZE)
738             {
739                 cs->cx = info.dwXSize;
740                 cs->cy = info.dwYSize;
741             }
742             else
743             {
744                 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
745                 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
746             }
747         }
748         /* neither x nor cx are default. Check the y values .
749          * In the trace we see Outlook and Outlook Express using
750          * cy set to CW_USEDEFAULT when opening the address book.
751          */
752         else if (IS_DEFAULT(cs->cy))
753         {
754             FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
755             cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
756         }
757     }
758 #undef IS_DEFAULT
759 }
760
761 /***********************************************************************
762  *           dump_window_styles
763  */
764 static void dump_window_styles( DWORD style, DWORD exstyle )
765 {
766     TRACE( "style:" );
767     if(style & WS_POPUP) TRACE(" WS_POPUP");
768     if(style & WS_CHILD) TRACE(" WS_CHILD");
769     if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
770     if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
771     if(style & WS_DISABLED) TRACE(" WS_DISABLED");
772     if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
773     if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
774     if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
775     if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
776     else
777     {
778         if(style & WS_BORDER) TRACE(" WS_BORDER");
779         if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
780     }
781     if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
782     if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
783     if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
784     if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
785     if (style & WS_CHILD)
786     {
787         if(style & WS_GROUP) TRACE(" WS_GROUP");
788         if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
789     }
790     else
791     {
792         if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
793         if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
794     }
795
796     /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
797 #define DUMPED_STYLES \
798     (WS_POPUP | \
799      WS_CHILD | \
800      WS_MINIMIZE | \
801      WS_VISIBLE | \
802      WS_DISABLED | \
803      WS_CLIPSIBLINGS | \
804      WS_CLIPCHILDREN | \
805      WS_MAXIMIZE | \
806      WS_BORDER | \
807      WS_DLGFRAME | \
808      WS_VSCROLL | \
809      WS_HSCROLL | \
810      WS_SYSMENU | \
811      WS_THICKFRAME | \
812      WS_GROUP | \
813      WS_TABSTOP | \
814      WS_MINIMIZEBOX | \
815      WS_MAXIMIZEBOX)
816
817     if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
818     TRACE("\n");
819 #undef DUMPED_STYLES
820
821     TRACE( "exstyle:" );
822     if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
823     if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
824     if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
825     if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
826     if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
827     if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
828     if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
829     if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
830     if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
831     if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
832     if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
833     if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
834     if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
835     if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
836     if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
837     if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
838     if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
839     if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
840
841 #define DUMPED_EX_STYLES \
842     (WS_EX_DLGMODALFRAME | \
843      WS_EX_DRAGDETECT | \
844      WS_EX_NOPARENTNOTIFY | \
845      WS_EX_TOPMOST | \
846      WS_EX_ACCEPTFILES | \
847      WS_EX_TRANSPARENT | \
848      WS_EX_MDICHILD | \
849      WS_EX_TOOLWINDOW | \
850      WS_EX_WINDOWEDGE | \
851      WS_EX_CLIENTEDGE | \
852      WS_EX_CONTEXTHELP | \
853      WS_EX_RIGHT | \
854      WS_EX_RTLREADING | \
855      WS_EX_LEFTSCROLLBAR | \
856      WS_EX_CONTROLPARENT | \
857      WS_EX_STATICEDGE | \
858      WS_EX_APPWINDOW | \
859      WS_EX_LAYERED)
860
861     if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
862     TRACE("\n");
863 #undef DUMPED_EX_STYLES
864 }
865
866
867 /***********************************************************************
868  *           WIN_CreateWindowEx
869  *
870  * Implementation of CreateWindowEx().
871  */
872 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
873 {
874     INT cx, cy, style, sw = SW_SHOW;
875     LRESULT result;
876     RECT rect;
877     WND *wndPtr;
878     HWND hwnd, parent, owner, top_child = 0;
879     BOOL unicode = (flags & WIN_ISUNICODE) != 0;
880     MDICREATESTRUCTA mdi_cs;
881     CBT_CREATEWNDA cbtc;
882     CREATESTRUCTA cbcs;
883
884     TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
885           unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
886           debugstr_w(className),
887           cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
888           cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
889     if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
890
891     /* Fix the styles for MDI children */
892     if (cs->dwExStyle & WS_EX_MDICHILD)
893     {
894         UINT flags = 0;
895
896         wndPtr = WIN_GetPtr(cs->hwndParent);
897         if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
898         {
899             flags = wndPtr->flags;
900             WIN_ReleasePtr(wndPtr);
901         }
902
903         if (!(flags & WIN_ISMDICLIENT))
904         {
905             WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
906             return 0;
907         }
908
909         /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
910          * MDICREATESTRUCT members have the originally passed values.
911          *
912          * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
913          * have the same layout.
914          */
915         mdi_cs.szClass = cs->lpszClass;
916         mdi_cs.szTitle = cs->lpszName;
917         mdi_cs.hOwner = cs->hInstance;
918         mdi_cs.x = cs->x;
919         mdi_cs.y = cs->y;
920         mdi_cs.cx = cs->cx;
921         mdi_cs.cy = cs->cy;
922         mdi_cs.style = cs->style;
923         mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
924
925         cs->lpCreateParams = (LPVOID)&mdi_cs;
926
927         if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
928         {
929             if (cs->style & WS_POPUP)
930             {
931                 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
932                 return 0;
933             }
934             cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
935         }
936         else
937         {
938             cs->style &= ~WS_POPUP;
939             cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
940                 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
941         }
942
943         top_child = GetWindow(cs->hwndParent, GW_CHILD);
944
945         if (top_child)
946         {
947             /* Restore current maximized child */
948             if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
949             {
950                 TRACE("Restoring current maximized child %p\n", top_child);
951                 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
952                 ShowWindow( top_child, SW_SHOWNORMAL );
953                 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
954             }
955         }
956     }
957
958     /* Find the parent window */
959
960     parent = cs->hwndParent;
961     owner = 0;
962
963     if (cs->hwndParent == HWND_MESSAGE)
964     {
965       /* native ole32.OleInitialize uses HWND_MESSAGE to create the
966        * message window (style: WS_POPUP|WS_DISABLED)
967        */
968       FIXME("Parent is HWND_MESSAGE\n");
969       parent = GetDesktopWindow();
970     }
971     else if (cs->hwndParent)
972     {
973         if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
974         {
975             parent = GetDesktopWindow();
976             owner = cs->hwndParent;
977         }
978     }
979     else
980     {
981         if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
982         {
983             WARN("No parent for child window\n" );
984             SetLastError(ERROR_TLW_WITH_WSCHILD);
985             return 0;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
986         }
987         if (className != (LPCWSTR)DESKTOP_CLASS_ATOM)  /* are we creating the desktop itself? */
988             parent = GetDesktopWindow();
989     }
990
991     WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992
993     if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
994         ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
995           (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
996         cs->dwExStyle |= WS_EX_WINDOWEDGE;
997     else
998         cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999
1000     /* Create the window structure */
1001
1002     if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1003         return 0;
1004     hwnd = wndPtr->hwndSelf;
1005
1006     /* Fill the window structure */
1007
1008     wndPtr->tid            = GetCurrentThreadId();
1009     wndPtr->hInstance      = cs->hInstance;
1010     wndPtr->text           = NULL;
1011     wndPtr->dwStyle        = cs->style & ~WS_VISIBLE;
1012     wndPtr->dwExStyle      = cs->dwExStyle;
1013     wndPtr->wIDmenu        = 0;
1014     wndPtr->helpContext    = 0;
1015     wndPtr->pVScroll       = NULL;
1016     wndPtr->pHScroll       = NULL;
1017     wndPtr->userdata       = 0;
1018     wndPtr->hIcon          = 0;
1019     wndPtr->hIconSmall     = 0;
1020     wndPtr->hSysMenu       = 0;
1021     wndPtr->flags         |= (flags & WIN_ISWIN32);
1022
1023     if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1024
1025     /*
1026      * Correct the window styles.
1027      *
1028      * It affects only the style loaded into the WIN structure.
1029      */
1030
1031     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1032     {
1033         wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1034         if (!(wndPtr->dwStyle & WS_POPUP))
1035             wndPtr->dwStyle |= WS_CAPTION;
1036     }
1037
1038     /*
1039      * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1040      * why does the user get to set it?
1041      */
1042
1043     if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1044           (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1045         wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1046     else
1047         wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048
1049     if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1050         wndPtr->flags |= WIN_NEED_SIZE;
1051
1052     SERVER_START_REQ( set_window_info )
1053     {
1054         req->handle    = hwnd;
1055         req->flags     = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1056         req->style     = wndPtr->dwStyle;
1057         req->ex_style  = wndPtr->dwExStyle;
1058         req->instance  = (void *)wndPtr->hInstance;
1059         req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1060         req->extra_offset = -1;
1061         wine_server_call( req );
1062     }
1063     SERVER_END_REQ;
1064
1065     /* Set the window menu */
1066
1067     if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1068     {
1069         if (cs->hMenu)
1070         {
1071             if (!MENU_SetMenu(hwnd, cs->hMenu))
1072             {
1073                 WIN_ReleasePtr( wndPtr );
1074                 free_window_handle( hwnd );
1075                 return 0;
1076             }
1077         }
1078         else
1079         {
1080             LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1081             if (menuName)
1082             {
1083                 if (!cs->hInstance || HIWORD(cs->hInstance))
1084                     cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1085                 else
1086                     cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1087
1088                 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089             }
1090         }
1091     }
1092     else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1093
1094     /* call the WH_CBT hook */
1095
1096     /* the window style passed to the hook must be the real window style,
1097      * rather than just the window style that the caller to CreateWindowEx
1098      * passed in, so we have to copy the original CREATESTRUCT and get the
1099      * the real style. */
1100     cbcs = *cs;
1101     cbcs.style = wndPtr->dwStyle;
1102     cbtc.lpcs = &cbcs;
1103     cbtc.hwndInsertAfter = HWND_TOP;
1104     WIN_ReleasePtr( wndPtr );
1105     if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1106
1107     /* send the WM_GETMINMAXINFO message and fix the size if needed */
1108
1109     cx = cs->cx;
1110     cy = cs->cy;
1111     if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1112     {
1113         POINT maxSize, maxPos, minTrack, maxTrack;
1114         WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1115         if (maxTrack.x < cx) cx = maxTrack.x;
1116         if (maxTrack.y < cy) cy = maxTrack.y;
1117     }
1118
1119     if (cx < 0) cx = 0;
1120     if (cy < 0) cy = 0;
1121     SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1122     /* check for wraparound */
1123     if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1124     if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1125     if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1126
1127     /* send WM_NCCREATE */
1128
1129     TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1130     if (unicode)
1131         result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1132     else
1133         result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1134     if (!result)
1135     {
1136         WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1137         goto failed;
1138     }
1139
1140     /* send WM_NCCALCSIZE */
1141
1142     if ((wndPtr = WIN_GetPtr(hwnd)))
1143     {
1144         /* yes, even if the CBT hook was called with HWND_TOP */
1145         POINT pt;
1146         HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1147         RECT window_rect = wndPtr->rectWindow;
1148         RECT client_rect = window_rect;
1149         WIN_ReleasePtr( wndPtr );
1150
1151         /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1152         pt.x = pt.y = 0;
1153         MapWindowPoints( parent, 0, &pt, 1 );
1154         OffsetRect( &client_rect, pt.x, pt.y );
1155         SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1156         OffsetRect( &client_rect, -pt.x, -pt.y );
1157         set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1158     }
1159     else return 0;
1160
1161     /* send WM_CREATE */
1162
1163     if (unicode)
1164         result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1165     else
1166         result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1167     if (result == -1) goto failed;
1168
1169     /* call the driver */
1170
1171     if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1172
1173     NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1174
1175     /* send the size messages */
1176
1177     if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1178     if (!(wndPtr->flags & WIN_NEED_SIZE))
1179     {
1180         rect = wndPtr->rectClient;
1181         WIN_ReleasePtr( wndPtr );
1182         SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1183                       MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1184         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1185     }
1186     else WIN_ReleasePtr( wndPtr );
1187
1188     /* Show the window, maximizing or minimizing if needed */
1189
1190     style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1191     if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1192     {
1193         RECT newPos;
1194         UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1195
1196         swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1197         swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1198         if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1199         SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1200     }
1201
1202     /* Notify the parent window only */
1203
1204     send_parent_notify( hwnd, WM_CREATE );
1205     if (!IsWindow( hwnd )) return 0;
1206
1207     if (cs->style & WS_VISIBLE)
1208     {
1209         if (cs->style & WS_MAXIMIZE)
1210             sw = SW_SHOW;
1211         else if (cs->style & WS_MINIMIZE)
1212             sw = SW_SHOWMINIMIZED;
1213
1214         ShowWindow( hwnd, sw );
1215         if (cs->dwExStyle & WS_EX_MDICHILD)
1216         {
1217             SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1218             /* ShowWindow won't activate child windows */
1219             SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1220         }
1221     }
1222
1223     /* Call WH_SHELL hook */
1224
1225     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1226         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1227
1228     TRACE("created window %p\n", hwnd);
1229     return hwnd;
1230
1231 failed:
1232     WIN_DestroyWindow( hwnd );
1233     return 0;
1234 }
1235
1236
1237 /***********************************************************************
1238  *              CreateWindow (USER.41)
1239  */
1240 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1241                               DWORD style, INT16 x, INT16 y, INT16 width,
1242                               INT16 height, HWND16 parent, HMENU16 menu,
1243                               HINSTANCE16 instance, LPVOID data )
1244 {
1245     return CreateWindowEx16( 0, className, windowName, style,
1246                              x, y, width, height, parent, menu, instance, data );
1247 }
1248
1249
1250 /***********************************************************************
1251  *              CreateWindowEx (USER.452)
1252  */
1253 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1254                                 LPCSTR windowName, DWORD style, INT16 x,
1255                                 INT16 y, INT16 width, INT16 height,
1256                                 HWND16 parent, HMENU16 menu,
1257                                 HINSTANCE16 instance, LPVOID data )
1258 {
1259     CREATESTRUCTA cs;
1260     char buffer[256];
1261
1262     /* Fix the coordinates */
1263
1264     cs.x  = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1265     cs.y  = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1266     cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1267     cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1268
1269     /* Create the window */
1270
1271     cs.lpCreateParams = data;
1272     cs.hInstance      = HINSTANCE_32(instance);
1273     cs.hMenu          = HMENU_32(menu);
1274     cs.hwndParent     = WIN_Handle32( parent );
1275     cs.style          = style;
1276     cs.lpszName       = windowName;
1277     cs.lpszClass      = className;
1278     cs.dwExStyle      = exStyle;
1279
1280     if (!IS_INTRESOURCE(className))
1281     {
1282         WCHAR bufferW[256];
1283
1284         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1285             return 0;
1286         return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1287     }
1288     else
1289     {
1290         if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1291         {
1292             ERR( "bad atom %x\n", LOWORD(className));
1293             return 0;
1294         }
1295         cs.lpszClass = buffer;
1296         return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1297     }
1298 }
1299
1300
1301 /***********************************************************************
1302  *              CreateWindowExA (USER32.@)
1303  */
1304 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1305                                  LPCSTR windowName, DWORD style, INT x,
1306                                  INT y, INT width, INT height,
1307                                  HWND parent, HMENU menu,
1308                                  HINSTANCE instance, LPVOID data )
1309 {
1310     CREATESTRUCTA cs;
1311
1312     cs.lpCreateParams = data;
1313     cs.hInstance      = instance;
1314     cs.hMenu          = menu;
1315     cs.hwndParent     = parent;
1316     cs.x              = x;
1317     cs.y              = y;
1318     cs.cx             = width;
1319     cs.cy             = height;
1320     cs.style          = style;
1321     cs.lpszName       = windowName;
1322     cs.lpszClass      = className;
1323     cs.dwExStyle      = exStyle;
1324
1325     if (!IS_INTRESOURCE(className))
1326     {
1327         WCHAR bufferW[256];
1328         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1329             return 0;
1330         return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1331     }
1332     return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1333 }
1334
1335
1336 /***********************************************************************
1337  *              CreateWindowExW (USER32.@)
1338  */
1339 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1340                                  LPCWSTR windowName, DWORD style, INT x,
1341                                  INT y, INT width, INT height,
1342                                  HWND parent, HMENU menu,
1343                                  HINSTANCE instance, LPVOID data )
1344 {
1345     CREATESTRUCTW cs;
1346
1347     cs.lpCreateParams = data;
1348     cs.hInstance      = instance;
1349     cs.hMenu          = menu;
1350     cs.hwndParent     = parent;
1351     cs.x              = x;
1352     cs.y              = y;
1353     cs.cx             = width;
1354     cs.cy             = height;
1355     cs.style          = style;
1356     cs.lpszName       = windowName;
1357     cs.lpszClass      = className;
1358     cs.dwExStyle      = exStyle;
1359
1360     /* Note: we rely on the fact that CREATESTRUCTA and */
1361     /* CREATESTRUCTW have the same layout. */
1362     return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1363 }
1364
1365
1366 /***********************************************************************
1367  *           WIN_SendDestroyMsg
1368  */
1369 static void WIN_SendDestroyMsg( HWND hwnd )
1370 {
1371     GUITHREADINFO info;
1372
1373     if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1374     {
1375         if (hwnd == info.hwndCaret) DestroyCaret();
1376         if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1377     }
1378
1379     /*
1380      * Send the WM_DESTROY to the window.
1381      */
1382     SendMessageW( hwnd, WM_DESTROY, 0, 0);
1383
1384     /*
1385      * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1386      * make sure that the window still exists when we come back.
1387      */
1388     if (IsWindow(hwnd))
1389     {
1390         HWND* pWndArray;
1391         int i;
1392
1393         if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1394
1395         for (i = 0; pWndArray[i]; i++)
1396         {
1397             if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1398         }
1399         HeapFree( GetProcessHeap(), 0, pWndArray );
1400     }
1401     else
1402       WARN("\tdestroyed itself while in WM_DESTROY!\n");
1403 }
1404
1405
1406 /***********************************************************************
1407  *              DestroyWindow (USER32.@)
1408  */
1409 BOOL WINAPI DestroyWindow( HWND hwnd )
1410 {
1411     BOOL is_child;
1412
1413     if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1414     {
1415         SetLastError( ERROR_ACCESS_DENIED );
1416         return FALSE;
1417     }
1418
1419     TRACE("(%p)\n", hwnd);
1420
1421       /* Call hooks */
1422
1423     if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1424
1425     if (MENU_IsMenuActive() == hwnd)
1426         EndMenu();
1427
1428     is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1429
1430     if (is_child)
1431     {
1432         if (!USER_IsExitingThread( GetCurrentThreadId() ))
1433             send_parent_notify( hwnd, WM_DESTROY );
1434     }
1435     else if (!GetWindow( hwnd, GW_OWNER ))
1436     {
1437         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1438         /* FIXME: clean up palette - see "Internals" p.352 */
1439     }
1440
1441     if (!IsWindow(hwnd)) return TRUE;
1442
1443       /* Hide the window */
1444     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1445     {
1446         /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1447         if (is_child)
1448             ShowWindow( hwnd, SW_HIDE );
1449         else
1450             SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1451                           SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1452     }
1453
1454     if (!IsWindow(hwnd)) return TRUE;
1455
1456       /* Recursively destroy owned windows */
1457
1458     if (!is_child)
1459     {
1460         for (;;)
1461         {
1462             int i, got_one = 0;
1463             HWND *list = WIN_ListChildren( GetDesktopWindow() );
1464             if (list)
1465             {
1466                 for (i = 0; list[i]; i++)
1467                 {
1468                     if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1469                     if (WIN_IsCurrentThread( list[i] ))
1470                     {
1471                         DestroyWindow( list[i] );
1472                         got_one = 1;
1473                         continue;
1474                     }
1475                     WIN_SetOwner( list[i], 0 );
1476                 }
1477                 HeapFree( GetProcessHeap(), 0, list );
1478             }
1479             if (!got_one) break;
1480         }
1481     }
1482
1483       /* Send destroy messages */
1484
1485     WIN_SendDestroyMsg( hwnd );
1486     if (!IsWindow( hwnd )) return TRUE;
1487
1488     if (GetClipboardOwner() == hwnd)
1489         CLIPBOARD_ReleaseOwner();
1490
1491       /* Destroy the window storage */
1492
1493     WIN_DestroyWindow( hwnd );
1494     return TRUE;
1495 }
1496
1497
1498 /***********************************************************************
1499  *              CloseWindow (USER32.@)
1500  */
1501 BOOL WINAPI CloseWindow( HWND hwnd )
1502 {
1503     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1504     ShowWindow( hwnd, SW_MINIMIZE );
1505     return TRUE;
1506 }
1507
1508
1509 /***********************************************************************
1510  *              OpenIcon (USER32.@)
1511  */
1512 BOOL WINAPI OpenIcon( HWND hwnd )
1513 {
1514     if (!IsIconic( hwnd )) return FALSE;
1515     ShowWindow( hwnd, SW_SHOWNORMAL );
1516     return TRUE;
1517 }
1518
1519
1520 /***********************************************************************
1521  *              FindWindowExW (USER32.@)
1522  */
1523 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1524 {
1525     HWND *list = NULL;
1526     HWND retvalue = 0;
1527     int i = 0, len = 0;
1528     WCHAR *buffer = NULL;
1529
1530     if (!parent) parent = GetDesktopWindow();
1531     if (title)
1532     {
1533         len = strlenW(title) + 1;  /* one extra char to check for chars beyond the end */
1534         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1535     }
1536
1537     if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1538
1539     if (child)
1540     {
1541         child = WIN_GetFullHandle( child );
1542         while (list[i] && list[i] != child) i++;
1543         if (!list[i]) goto done;
1544         i++;  /* start from next window */
1545     }
1546
1547     if (title)
1548     {
1549         while (list[i])
1550         {
1551             if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1552             i++;
1553         }
1554     }
1555     retvalue = list[i];
1556
1557  done:
1558     HeapFree( GetProcessHeap(), 0, list );
1559     HeapFree( GetProcessHeap(), 0, buffer );
1560     return retvalue;
1561 }
1562
1563
1564
1565 /***********************************************************************
1566  *              FindWindowA (USER32.@)
1567  */
1568 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1569 {
1570     HWND ret = FindWindowExA( 0, 0, className, title );
1571     if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1572     return ret;
1573 }
1574
1575
1576 /***********************************************************************
1577  *              FindWindowExA (USER32.@)
1578  */
1579 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1580 {
1581     LPWSTR titleW = NULL;
1582     HWND hwnd = 0;
1583
1584     if (title)
1585     {
1586         DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1587         if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1588         MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1589     }
1590
1591     if (!IS_INTRESOURCE(className))
1592     {
1593         WCHAR classW[256];
1594         if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1595             hwnd = FindWindowExW( parent, child, classW, titleW );
1596     }
1597     else
1598     {
1599         hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1600     }
1601
1602     HeapFree( GetProcessHeap(), 0, titleW );
1603     return hwnd;
1604 }
1605
1606
1607 /***********************************************************************
1608  *              FindWindowW (USER32.@)
1609  */
1610 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1611 {
1612     return FindWindowExW( 0, 0, className, title );
1613 }
1614
1615
1616 /**********************************************************************
1617  *              GetDesktopWindow (USER32.@)
1618  */
1619 HWND WINAPI GetDesktopWindow(void)
1620 {
1621     struct user_thread_info *thread_info = get_user_thread_info();
1622
1623     if (thread_info->desktop) return thread_info->desktop;
1624
1625     SERVER_START_REQ( get_desktop_window )
1626     {
1627         req->force = 0;
1628         if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1629     }
1630     SERVER_END_REQ;
1631
1632     if (!thread_info->desktop)
1633     {
1634         USEROBJECTFLAGS flags;
1635         if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1636                                         sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1637         {
1638             static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1639             STARTUPINFOW si;
1640             PROCESS_INFORMATION pi;
1641             WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1642
1643             memset( &si, 0, sizeof(si) );
1644             si.cb = sizeof(si);
1645             si.dwFlags = STARTF_USESTDHANDLES;
1646             si.hStdInput  = 0;
1647             si.hStdOutput = 0;
1648             si.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1649
1650             GetSystemDirectoryW( cmdline, MAX_PATH );
1651             lstrcatW( cmdline, command_line );
1652             if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1653                                 NULL, NULL, &si, &pi ))
1654             {
1655                 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1656                 WaitForInputIdle( pi.hProcess, 10000 );
1657                 CloseHandle( pi.hThread );
1658                 CloseHandle( pi.hProcess );
1659             }
1660             else WARN( "failed to start explorer, err %d\n", GetLastError() );
1661         }
1662         else TRACE( "not starting explorer since winstation is not visible\n" );
1663
1664         SERVER_START_REQ( get_desktop_window )
1665         {
1666             req->force = 1;
1667             if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1668         }
1669         SERVER_END_REQ;
1670     }
1671
1672     if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1673         ERR( "failed to create desktop window\n" );
1674
1675     return thread_info->desktop;
1676 }
1677
1678
1679 /*******************************************************************
1680  *              EnableWindow (USER32.@)
1681  */
1682 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1683 {
1684     BOOL retvalue;
1685     HWND full_handle;
1686
1687     if (is_broadcast(hwnd))
1688     {
1689         SetLastError( ERROR_INVALID_PARAMETER );
1690         return FALSE;
1691     }
1692
1693     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1694         return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1695
1696     hwnd = full_handle;
1697
1698     TRACE("( %p, %d )\n", hwnd, enable);
1699
1700     retvalue = !IsWindowEnabled( hwnd );
1701
1702     if (enable && retvalue)
1703     {
1704         WIN_SetStyle( hwnd, 0, WS_DISABLED );
1705         SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1706     }
1707     else if (!enable && !retvalue)
1708     {
1709         HWND capture_wnd;
1710
1711         SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1712
1713         WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1714
1715         if (hwnd == GetFocus())
1716             SetFocus( 0 );  /* A disabled window can't have the focus */
1717
1718         capture_wnd = GetCapture();
1719         if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1720             ReleaseCapture();  /* A disabled window can't capture the mouse */
1721
1722         SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1723     }
1724     return retvalue;
1725 }
1726
1727
1728 /***********************************************************************
1729  *              IsWindowEnabled (USER32.@)
1730  */
1731 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1732 {
1733     return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1734 }
1735
1736
1737 /***********************************************************************
1738  *              IsWindowUnicode (USER32.@)
1739  */
1740 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1741 {
1742     WND * wndPtr;
1743     BOOL retvalue = FALSE;
1744
1745     if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1746
1747     if (wndPtr == WND_DESKTOP) return TRUE;
1748
1749     if (wndPtr != WND_OTHER_PROCESS)
1750     {
1751         retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1752         WIN_ReleasePtr( wndPtr );
1753     }
1754     else
1755     {
1756         SERVER_START_REQ( get_window_info )
1757         {
1758             req->handle = hwnd;
1759             if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1760         }
1761         SERVER_END_REQ;
1762     }
1763     return retvalue;
1764 }
1765
1766
1767 /**********************************************************************
1768  *           WIN_GetWindowLong
1769  *
1770  * Helper function for GetWindowLong().
1771  */
1772 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1773 {
1774     LONG_PTR retvalue = 0;
1775     WND *wndPtr;
1776
1777     if (offset == GWLP_HWNDPARENT)
1778     {
1779         HWND parent = GetAncestor( hwnd, GA_PARENT );
1780         if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1781         return (ULONG_PTR)parent;
1782     }
1783
1784     if (!(wndPtr = WIN_GetPtr( hwnd )))
1785     {
1786         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1787         return 0;
1788     }
1789
1790     if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1791     {
1792         if (offset == GWLP_WNDPROC)
1793         {
1794             SetLastError( ERROR_ACCESS_DENIED );
1795             return 0;
1796         }
1797         SERVER_START_REQ( set_window_info )
1798         {
1799             req->handle = hwnd;
1800             req->flags  = 0;  /* don't set anything, just retrieve */
1801             req->extra_offset = (offset >= 0) ? offset : -1;
1802             req->extra_size = (offset >= 0) ? size : 0;
1803             if (!wine_server_call_err( req ))
1804             {
1805                 switch(offset)
1806                 {
1807                 case GWL_STYLE:      retvalue = reply->old_style; break;
1808                 case GWL_EXSTYLE:    retvalue = reply->old_ex_style; break;
1809                 case GWLP_ID:        retvalue = reply->old_id; break;
1810                 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1811                 case GWLP_USERDATA:  retvalue = reply->old_user_data; break;
1812                 default:
1813                     if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1814                     else SetLastError( ERROR_INVALID_INDEX );
1815                     break;
1816                 }
1817             }
1818         }
1819         SERVER_END_REQ;
1820         return retvalue;
1821     }
1822
1823     /* now we have a valid wndPtr */
1824
1825     if (offset >= 0)
1826     {
1827         if (offset > (int)(wndPtr->cbWndExtra - size))
1828         {
1829             WARN("Invalid offset %d\n", offset );
1830             WIN_ReleasePtr( wndPtr );
1831             SetLastError( ERROR_INVALID_INDEX );
1832             return 0;
1833         }
1834         retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1835
1836         /* Special case for dialog window procedure */
1837         if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1838             retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1839         WIN_ReleasePtr( wndPtr );
1840         return retvalue;
1841     }
1842
1843     switch(offset)
1844     {
1845     case GWLP_USERDATA:  retvalue = wndPtr->userdata; break;
1846     case GWL_STYLE:      retvalue = wndPtr->dwStyle; break;
1847     case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle; break;
1848     case GWLP_ID:        retvalue = wndPtr->wIDmenu; break;
1849     case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1850     case GWLP_WNDPROC:
1851         /* This looks like a hack only for the edit control (see tests). This makes these controls
1852          * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1853          * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1854          */
1855         if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1856             retvalue = (ULONG_PTR)wndPtr->winproc;
1857         else
1858             retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1859         break;
1860     default:
1861         WARN("Unknown offset %d\n", offset );
1862         SetLastError( ERROR_INVALID_INDEX );
1863         break;
1864     }
1865     WIN_ReleasePtr(wndPtr);
1866     return retvalue;
1867 }
1868
1869
1870 /**********************************************************************
1871  *           WIN_SetWindowLong
1872  *
1873  * Helper function for SetWindowLong().
1874  *
1875  * 0 is the failure code. However, in the case of failure SetLastError
1876  * must be set to distinguish between a 0 return value and a failure.
1877  */
1878 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1879 {
1880     STYLESTRUCT style;
1881     BOOL ok;
1882     LONG_PTR retval = 0;
1883     WND *wndPtr;
1884
1885     TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1886
1887     if (is_broadcast(hwnd))
1888     {
1889         SetLastError( ERROR_INVALID_PARAMETER );
1890         return FALSE;
1891     }
1892
1893     if (!(wndPtr = WIN_GetPtr( hwnd )))
1894     {
1895         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1896         return 0;
1897     }
1898     if (wndPtr == WND_DESKTOP)
1899     {
1900         /* can't change anything on the desktop window */
1901         SetLastError( ERROR_ACCESS_DENIED );
1902         return 0;
1903     }
1904     if (wndPtr == WND_OTHER_PROCESS)
1905     {
1906         if (offset == GWLP_WNDPROC)
1907         {
1908             SetLastError( ERROR_ACCESS_DENIED );
1909             return 0;
1910         }
1911         if (offset > 32767 || offset < -32767)
1912         {
1913             SetLastError( ERROR_INVALID_INDEX );
1914             return 0;
1915         }
1916         return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1917     }
1918
1919     /* first some special cases */
1920     switch( offset )
1921     {
1922     case GWL_STYLE:
1923     case GWL_EXSTYLE:
1924         style.styleOld =
1925             offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1926         style.styleNew = newval;
1927         WIN_ReleasePtr( wndPtr );
1928         SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1929         if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1930         newval = style.styleNew;
1931         break;
1932     case GWLP_HWNDPARENT:
1933         if (wndPtr->parent == GetDesktopWindow())
1934         {
1935             WIN_ReleasePtr( wndPtr );
1936             return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1937         }
1938         else
1939         {
1940             WIN_ReleasePtr( wndPtr );
1941             return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1942         }
1943     case GWLP_WNDPROC:
1944     {
1945         WNDPROC proc;
1946         UINT old_flags = wndPtr->flags;
1947         retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1948         if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1949         else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1950         if (proc) wndPtr->winproc = proc;
1951         if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1952         else wndPtr->flags &= ~WIN_ISUNICODE;
1953         if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1954         {
1955             WIN_ReleasePtr( wndPtr );
1956             return retval;
1957         }
1958         /* update is_unicode flag on the server side */
1959         break;
1960     }
1961     case GWLP_ID:
1962     case GWLP_HINSTANCE:
1963     case GWLP_USERDATA:
1964         break;
1965     case DWLP_DLGPROC:
1966         if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1967             (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1968         {
1969             WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1970             retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1971             if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1972             else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1973             WIN_ReleasePtr( wndPtr );
1974             return retval;
1975         }
1976         /* fall through */
1977     default:
1978         if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1979         {
1980             WARN("Invalid offset %d\n", offset );
1981             WIN_ReleasePtr( wndPtr );
1982             SetLastError( ERROR_INVALID_INDEX );
1983             return 0;
1984         }
1985         else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1986         {
1987             /* already set to the same value */
1988             WIN_ReleasePtr( wndPtr );
1989             return newval;
1990         }
1991         break;
1992     }
1993
1994     SERVER_START_REQ( set_window_info )
1995     {
1996         req->handle = hwnd;
1997         req->extra_offset = -1;
1998         switch(offset)
1999         {
2000         case GWL_STYLE:
2001             req->flags = SET_WIN_STYLE;
2002             req->style = newval;
2003             break;
2004         case GWL_EXSTYLE:
2005             req->flags = SET_WIN_EXSTYLE;
2006             /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2007             newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2008             req->ex_style = newval;
2009             break;
2010         case GWLP_ID:
2011             req->flags = SET_WIN_ID;
2012             req->id = newval;
2013             break;
2014         case GWLP_HINSTANCE:
2015             req->flags = SET_WIN_INSTANCE;
2016             req->instance = (void *)newval;
2017             break;
2018         case GWLP_WNDPROC:
2019             req->flags = SET_WIN_UNICODE;
2020             req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2021             break;
2022         case GWLP_USERDATA:
2023             req->flags = SET_WIN_USERDATA;
2024             req->user_data = newval;
2025             break;
2026         default:
2027             req->flags = SET_WIN_EXTRA;
2028             req->extra_offset = offset;
2029             req->extra_size = size;
2030             set_win_data( &req->extra_value, newval, size );
2031         }
2032         if ((ok = !wine_server_call_err( req )))
2033         {
2034             switch(offset)
2035             {
2036             case GWL_STYLE:
2037                 wndPtr->dwStyle = newval;
2038                 retval = reply->old_style;
2039                 break;
2040             case GWL_EXSTYLE:
2041                 wndPtr->dwExStyle = newval;
2042                 retval = reply->old_ex_style;
2043                 break;
2044             case GWLP_ID:
2045                 wndPtr->wIDmenu = newval;
2046                 retval = reply->old_id;
2047                 break;
2048             case GWLP_HINSTANCE:
2049                 wndPtr->hInstance = (HINSTANCE)newval;
2050                 retval = (ULONG_PTR)reply->old_instance;
2051                 break;
2052             case GWLP_WNDPROC:
2053                 break;
2054             case GWLP_USERDATA:
2055                 wndPtr->userdata = newval;
2056                 retval = reply->old_user_data;
2057                 break;
2058             default:
2059                 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2060                 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2061                 break;
2062             }
2063         }
2064     }
2065     SERVER_END_REQ;
2066     WIN_ReleasePtr( wndPtr );
2067
2068     if (!ok) return 0;
2069
2070     if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2071
2072     if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2073         SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2074
2075     return retval;
2076 }
2077
2078
2079 /**********************************************************************
2080  *              GetWindowLong (USER.135)
2081  */
2082 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2083 {
2084     WND *wndPtr;
2085     LONG_PTR retvalue;
2086     BOOL is_winproc = (offset == GWLP_WNDPROC);
2087
2088     if (offset >= 0)
2089     {
2090         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2091         {
2092             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2093             return 0;
2094         }
2095         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2096         {
2097             if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2098             {
2099                 /*
2100                  * Some programs try to access last element from 16 bit
2101                  * code using illegal offset value. Hopefully this is
2102                  * what those programs really expect.
2103                  */
2104                 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2105                 {
2106                     INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2107                     ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2108                     offset = offset2;
2109                 }
2110                 else
2111                 {
2112                     WARN("Invalid offset %d\n", offset );
2113                     WIN_ReleasePtr( wndPtr );
2114                     SetLastError( ERROR_INVALID_INDEX );
2115                     return 0;
2116                 }
2117             }
2118             is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2119             WIN_ReleasePtr( wndPtr );
2120         }
2121     }
2122     retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2123     if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2124     return retvalue;
2125 }
2126
2127
2128 /**********************************************************************
2129  *              GetWindowWord (USER32.@)
2130  */
2131 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2132 {
2133     switch(offset)
2134     {
2135     case GWLP_ID:
2136     case GWLP_HINSTANCE:
2137     case GWLP_HWNDPARENT:
2138         break;
2139     default:
2140         if (offset < 0)
2141         {
2142             WARN("Invalid offset %d\n", offset );
2143             SetLastError( ERROR_INVALID_INDEX );
2144             return 0;
2145         }
2146         break;
2147     }
2148     return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2149 }
2150
2151
2152 /**********************************************************************
2153  *              GetWindowLongA (USER32.@)
2154  */
2155 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 {
2157     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2158 }
2159
2160
2161 /**********************************************************************
2162  *              GetWindowLongW (USER32.@)
2163  */
2164 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 {
2166     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2167 }
2168
2169
2170 /**********************************************************************
2171  *              SetWindowLong (USER.136)
2172  */
2173 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 {
2175     WND *wndPtr;
2176     BOOL is_winproc = (offset == GWLP_WNDPROC);
2177
2178     if (offset == DWLP_DLGPROC)
2179     {
2180         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2181         {
2182             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2183             return 0;
2184         }
2185         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2186         {
2187             is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2188                           (wndPtr->flags & WIN_ISDIALOG));
2189             WIN_ReleasePtr( wndPtr );
2190         }
2191     }
2192
2193     if (is_winproc)
2194     {
2195         WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2196         WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2197         return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2198     }
2199     else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2200 }
2201
2202
2203 /**********************************************************************
2204  *              SetWindowWord (USER32.@)
2205  */
2206 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2207 {
2208     switch(offset)
2209     {
2210     case GWLP_ID:
2211     case GWLP_HINSTANCE:
2212     case GWLP_HWNDPARENT:
2213         break;
2214     default:
2215         if (offset < 0)
2216         {
2217             WARN("Invalid offset %d\n", offset );
2218             SetLastError( ERROR_INVALID_INDEX );
2219             return 0;
2220         }
2221         break;
2222     }
2223     return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2224 }
2225
2226
2227 /**********************************************************************
2228  *              SetWindowLongA (USER32.@)
2229  *
2230  * See SetWindowLongW.
2231  */
2232 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2233 {
2234     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2235 }
2236
2237
2238 /**********************************************************************
2239  *              SetWindowLongW (USER32.@) Set window attribute
2240  *
2241  * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2242  * value in a window's extra memory.
2243  *
2244  * The _hwnd_ parameter specifies the window.  is the handle to a
2245  * window that has extra memory. The _newval_ parameter contains the
2246  * new attribute or extra memory value.  If positive, the _offset_
2247  * parameter is the byte-addressed location in the window's extra
2248  * memory to set.  If negative, _offset_ specifies the window
2249  * attribute to set, and should be one of the following values:
2250  *
2251  * GWL_EXSTYLE      The window's extended window style
2252  *
2253  * GWL_STYLE        The window's window style.
2254  *
2255  * GWLP_WNDPROC     Pointer to the window's window procedure.
2256  *
2257  * GWLP_HINSTANCE   The window's pplication instance handle.
2258  *
2259  * GWLP_ID          The window's identifier.
2260  *
2261  * GWLP_USERDATA    The window's user-specified data.
2262  *
2263  * If the window is a dialog box, the _offset_ parameter can be one of
2264  * the following values:
2265  *
2266  * DWLP_DLGPROC     The address of the window's dialog box procedure.
2267  *
2268  * DWLP_MSGRESULT   The return value of a message
2269  *                  that the dialog box procedure processed.
2270  *
2271  * DWLP_USER        Application specific information.
2272  *
2273  * RETURNS
2274  *
2275  * If successful, returns the previous value located at _offset_. Otherwise,
2276  * returns 0.
2277  *
2278  * NOTES
2279  *
2280  * Extra memory for a window class is specified by a nonzero cbWndExtra
2281  * parameter of the WNDCLASS structure passed to RegisterClass() at the
2282  * time of class creation.
2283  *
2284  * Using GWL_WNDPROC to set a new window procedure effectively creates
2285  * a window subclass. Use CallWindowProc() in the new windows procedure
2286  * to pass messages to the superclass's window procedure.
2287  *
2288  * The user data is reserved for use by the application which created
2289  * the window.
2290  *
2291  * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2292  * instead, call the EnableWindow() function to change the window's
2293  * disabled state.
2294  *
2295  * Do not use GWL_HWNDPARENT to reset the window's parent, use
2296  * SetParent() instead.
2297  *
2298  * Win95:
2299  * When offset is GWL_STYLE and the calling app's ver is 4.0,
2300  * it sends WM_STYLECHANGING before changing the settings
2301  * and WM_STYLECHANGED afterwards.
2302  * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2303  */
2304 LONG WINAPI SetWindowLongW(
2305     HWND hwnd,  /* [in] window to alter */
2306     INT offset, /* [in] offset, in bytes, of location to alter */
2307     LONG newval /* [in] new value of location */
2308 ) {
2309     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2310 }
2311
2312
2313 /*******************************************************************
2314  *              GetWindowTextA (USER32.@)
2315  */
2316 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2317 {
2318     WCHAR *buffer;
2319
2320     if (!lpString) return 0;
2321
2322     if (WIN_IsCurrentProcess( hwnd ))
2323         return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2324
2325     /* when window belongs to other process, don't send a message */
2326     if (nMaxCount <= 0) return 0;
2327     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2328     get_server_window_text( hwnd, buffer, nMaxCount );
2329     if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2330         lpString[nMaxCount-1] = 0;
2331     HeapFree( GetProcessHeap(), 0, buffer );
2332     return strlen(lpString);
2333 }
2334
2335
2336 /*******************************************************************
2337  *              InternalGetWindowText (USER32.@)
2338  */
2339 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2340 {
2341     WND *win;
2342
2343     if (nMaxCount <= 0) return 0;
2344     if (!(win = WIN_GetPtr( hwnd ))) return 0;
2345     if (win == WND_DESKTOP) lpString[0] = 0;
2346     else if (win != WND_OTHER_PROCESS)
2347     {
2348         if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2349         else lpString[0] = 0;
2350         WIN_ReleasePtr( win );
2351     }
2352     else
2353     {
2354         get_server_window_text( hwnd, lpString, nMaxCount );
2355     }
2356     return strlenW(lpString);
2357 }
2358
2359
2360 /*******************************************************************
2361  *              GetWindowTextW (USER32.@)
2362  */
2363 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2364 {
2365     if (!lpString) return 0;
2366
2367     if (WIN_IsCurrentProcess( hwnd ))
2368         return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2369
2370     /* when window belongs to other process, don't send a message */
2371     if (nMaxCount <= 0) return 0;
2372     get_server_window_text( hwnd, lpString, nMaxCount );
2373     return strlenW(lpString);
2374 }
2375
2376
2377 /*******************************************************************
2378  *              SetWindowTextA (USER32.@)
2379  *              SetWindowText  (USER32.@)
2380  */
2381 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2382 {
2383     if (is_broadcast(hwnd))
2384     {
2385         SetLastError( ERROR_INVALID_PARAMETER );
2386         return FALSE;
2387     }
2388     if (!WIN_IsCurrentProcess( hwnd ))
2389         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2390                debugstr_a(lpString), hwnd );
2391     return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2392 }
2393
2394
2395 /*******************************************************************
2396  *              SetWindowTextW (USER32.@)
2397  */
2398 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2399 {
2400     if (is_broadcast(hwnd))
2401     {
2402         SetLastError( ERROR_INVALID_PARAMETER );
2403         return FALSE;
2404     }
2405     if (!WIN_IsCurrentProcess( hwnd ))
2406         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2407                debugstr_w(lpString), hwnd );
2408     return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2409 }
2410
2411
2412 /*******************************************************************
2413  *              GetWindowTextLengthA (USER32.@)
2414  */
2415 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2416 {
2417     return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2418 }
2419
2420 /*******************************************************************
2421  *              GetWindowTextLengthW (USER32.@)
2422  */
2423 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2424 {
2425     return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2426 }
2427
2428
2429 /*******************************************************************
2430  *              IsWindow (USER32.@)
2431  */
2432 BOOL WINAPI IsWindow( HWND hwnd )
2433 {
2434     WND *ptr;
2435     BOOL ret;
2436
2437     if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2438     if (ptr == WND_DESKTOP) return TRUE;
2439
2440     if (ptr != WND_OTHER_PROCESS)
2441     {
2442         WIN_ReleasePtr( ptr );
2443         return TRUE;
2444     }
2445
2446     /* check other processes */
2447     SERVER_START_REQ( get_window_info )
2448     {
2449         req->handle = hwnd;
2450         ret = !wine_server_call_err( req );
2451     }
2452     SERVER_END_REQ;
2453     return ret;
2454 }
2455
2456
2457 /***********************************************************************
2458  *              GetWindowThreadProcessId (USER32.@)
2459  */
2460 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2461 {
2462     WND *ptr;
2463     DWORD tid = 0;
2464
2465     if (!(ptr = WIN_GetPtr( hwnd )))
2466     {
2467         SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2468         return 0;
2469     }
2470
2471     if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2472     {
2473         /* got a valid window */
2474         tid = ptr->tid;
2475         if (process) *process = GetCurrentProcessId();
2476         WIN_ReleasePtr( ptr );
2477         return tid;
2478     }
2479
2480     /* check other processes */
2481     SERVER_START_REQ( get_window_info )
2482     {
2483         req->handle = hwnd;
2484         if (!wine_server_call_err( req ))
2485         {
2486             tid = (DWORD)reply->tid;
2487             if (process) *process = (DWORD)reply->pid;
2488         }
2489     }
2490     SERVER_END_REQ;
2491     return tid;
2492 }
2493
2494
2495 /*****************************************************************
2496  *              GetParent (USER32.@)
2497  */
2498 HWND WINAPI GetParent( HWND hwnd )
2499 {
2500     WND *wndPtr;
2501     HWND retvalue = 0;
2502
2503     if (!(wndPtr = WIN_GetPtr( hwnd )))
2504     {
2505         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2506         return 0;
2507     }
2508     if (wndPtr == WND_DESKTOP) return 0;
2509     if (wndPtr == WND_OTHER_PROCESS)
2510     {
2511         LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2512         if (style & (WS_POPUP | WS_CHILD))
2513         {
2514             SERVER_START_REQ( get_window_tree )
2515             {
2516                 req->handle = hwnd;
2517                 if (!wine_server_call_err( req ))
2518                 {
2519                     if (style & WS_POPUP) retvalue = reply->owner;
2520                     else if (style & WS_CHILD) retvalue = reply->parent;
2521                 }
2522             }
2523             SERVER_END_REQ;
2524         }
2525     }
2526     else
2527     {
2528         if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2529         else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2530         WIN_ReleasePtr( wndPtr );
2531     }
2532     return retvalue;
2533 }
2534
2535
2536 /*****************************************************************
2537  *              GetAncestor (USER32.@)
2538  */
2539 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2540 {
2541     WND *win;
2542     HWND *list, ret = 0;
2543
2544     switch(type)
2545     {
2546     case GA_PARENT:
2547         if (!(win = WIN_GetPtr( hwnd )))
2548         {
2549             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2550             return 0;
2551         }
2552         if (win == WND_DESKTOP) return 0;
2553         if (win != WND_OTHER_PROCESS)
2554         {
2555             ret = win->parent;
2556             WIN_ReleasePtr( win );
2557         }
2558         else /* need to query the server */
2559         {
2560             SERVER_START_REQ( get_window_tree )
2561             {
2562                 req->handle = hwnd;
2563                 if (!wine_server_call_err( req )) ret = reply->parent;
2564             }
2565             SERVER_END_REQ;
2566         }
2567         break;
2568
2569     case GA_ROOT:
2570         if (!(list = list_window_parents( hwnd ))) return 0;
2571
2572         if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd );  /* top-level window */
2573         else
2574         {
2575             int count = 2;
2576             while (list[count]) count++;
2577             ret = list[count - 2];  /* get the one before the desktop */
2578         }
2579         HeapFree( GetProcessHeap(), 0, list );
2580         break;
2581
2582     case GA_ROOTOWNER:
2583         if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2584         for (;;)
2585         {
2586             HWND parent = GetParent( ret );
2587             if (!parent) break;
2588             ret = parent;
2589         }
2590         break;
2591     }
2592     return ret;
2593 }
2594
2595
2596 /*****************************************************************
2597  *              SetParent (USER32.@)
2598  */
2599 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2600 {
2601     HWND full_handle;
2602     HWND old_parent = 0;
2603     BOOL was_visible;
2604     WND *wndPtr;
2605     BOOL ret;
2606
2607     if (is_broadcast(hwnd) || is_broadcast(parent))
2608     {
2609         SetLastError(ERROR_INVALID_PARAMETER);
2610         return 0;
2611     }
2612
2613     if (!parent) parent = GetDesktopWindow();
2614     else parent = WIN_GetFullHandle( parent );
2615
2616     if (!IsWindow( parent ))
2617     {
2618         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2619         return 0;
2620     }
2621
2622     /* Some applications try to set a child as a parent */
2623     if (IsChild(hwnd, parent))
2624     {
2625         SetLastError( ERROR_INVALID_PARAMETER );
2626         return 0;
2627     }
2628
2629     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2630         return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2631
2632     /* Windows hides the window first, then shows it again
2633      * including the WM_SHOWWINDOW messages and all */
2634     was_visible = ShowWindow( hwnd, SW_HIDE );
2635
2636     wndPtr = WIN_GetPtr( hwnd );
2637     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2638
2639     SERVER_START_REQ( set_parent )
2640     {
2641         req->handle = hwnd;
2642         req->parent = parent;
2643         if ((ret = !wine_server_call( req )))
2644         {
2645             old_parent = reply->old_parent;
2646             wndPtr->parent = parent = reply->full_parent;
2647         }
2648
2649     }
2650     SERVER_END_REQ;
2651     WIN_ReleasePtr( wndPtr );
2652     if (!ret) return 0;
2653
2654     USER_Driver->pSetParent( full_handle, parent, old_parent );
2655
2656     /* SetParent additionally needs to make hwnd the topmost window
2657        in the x-order and send the expected WM_WINDOWPOSCHANGING and
2658        WM_WINDOWPOSCHANGED notification messages.
2659     */
2660     SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2661                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2662     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2663      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2664
2665     return old_parent;
2666 }
2667
2668
2669 /*******************************************************************
2670  *              IsChild (USER32.@)
2671  */
2672 BOOL WINAPI IsChild( HWND parent, HWND child )
2673 {
2674     HWND *list = list_window_parents( child );
2675     int i;
2676     BOOL ret;
2677
2678     if (!list) return FALSE;
2679     parent = WIN_GetFullHandle( parent );
2680     for (i = 0; list[i]; i++) if (list[i] == parent) break;
2681     ret = list[i] && list[i+1];
2682     HeapFree( GetProcessHeap(), 0, list );
2683     return ret;
2684 }
2685
2686
2687 /***********************************************************************
2688  *              IsWindowVisible (USER32.@)
2689  */
2690 BOOL WINAPI IsWindowVisible( HWND hwnd )
2691 {
2692     HWND *list;
2693     BOOL retval = TRUE;
2694     int i;
2695
2696     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2697     if (!(list = list_window_parents( hwnd ))) return TRUE;
2698     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2699     {
2700         for (i = 0; list[i+1]; i++)
2701             if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2702         retval = !list[i+1];
2703     }
2704     HeapFree( GetProcessHeap(), 0, list );
2705     return retval;
2706 }
2707
2708
2709 /***********************************************************************
2710  *           WIN_IsWindowDrawable
2711  *
2712  * hwnd is drawable when it is visible, all parents are not
2713  * minimized, and it is itself not minimized unless we are
2714  * trying to draw its default class icon.
2715  */
2716 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2717 {
2718     HWND *list;
2719     BOOL retval = TRUE;
2720     int i;
2721     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2722
2723     if (!(style & WS_VISIBLE)) return FALSE;
2724     if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON ))  return FALSE;
2725
2726     if (!(list = list_window_parents( hwnd ))) return TRUE;
2727     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2728     {
2729         for (i = 0; list[i+1]; i++)
2730             if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2731                 break;
2732         retval = !list[i+1];
2733     }
2734     HeapFree( GetProcessHeap(), 0, list );
2735     return retval;
2736 }
2737
2738
2739 /*******************************************************************
2740  *              GetTopWindow (USER32.@)
2741  */
2742 HWND WINAPI GetTopWindow( HWND hwnd )
2743 {
2744     if (!hwnd) hwnd = GetDesktopWindow();
2745     return GetWindow( hwnd, GW_CHILD );
2746 }
2747
2748
2749 /*******************************************************************
2750  *              GetWindow (USER32.@)
2751  */
2752 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2753 {
2754     HWND retval = 0;
2755
2756     if (rel == GW_OWNER)  /* this one may be available locally */
2757     {
2758         WND *wndPtr = WIN_GetPtr( hwnd );
2759         if (!wndPtr)
2760         {
2761             SetLastError( ERROR_INVALID_HANDLE );
2762             return 0;
2763         }
2764         if (wndPtr == WND_DESKTOP) return 0;
2765         if (wndPtr != WND_OTHER_PROCESS)
2766         {
2767             retval = wndPtr->owner;
2768             WIN_ReleasePtr( wndPtr );
2769             return retval;
2770         }
2771         /* else fall through to server call */
2772     }
2773
2774     SERVER_START_REQ( get_window_tree )
2775     {
2776         req->handle = hwnd;
2777         if (!wine_server_call_err( req ))
2778         {
2779             switch(rel)
2780             {
2781             case GW_HWNDFIRST:
2782                 retval = reply->first_sibling;
2783                 break;
2784             case GW_HWNDLAST:
2785                 retval = reply->last_sibling;
2786                 break;
2787             case GW_HWNDNEXT:
2788                 retval = reply->next_sibling;
2789                 break;
2790             case GW_HWNDPREV:
2791                 retval = reply->prev_sibling;
2792                 break;
2793             case GW_OWNER:
2794                 retval = reply->owner;
2795                 break;
2796             case GW_CHILD:
2797                 retval = reply->first_child;
2798                 break;
2799             }
2800         }
2801     }
2802     SERVER_END_REQ;
2803     return retval;
2804 }
2805
2806
2807 /*******************************************************************
2808  *              ShowOwnedPopups (USER32.@)
2809  */
2810 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2811 {
2812     int count = 0;
2813     WND *pWnd;
2814     HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2815
2816     if (!win_array) return TRUE;
2817
2818     while (win_array[count]) count++;
2819     while (--count >= 0)
2820     {
2821         if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2822         if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2823         if (pWnd == WND_OTHER_PROCESS) continue;
2824         if (fShow)
2825         {
2826             if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2827             {
2828                 WIN_ReleasePtr( pWnd );
2829                 /* In Windows, ShowOwnedPopups(TRUE) generates
2830                  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2831                  * regardless of the state of the owner
2832                  */
2833                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2834                 continue;
2835             }
2836         }
2837         else
2838         {
2839             if (pWnd->dwStyle & WS_VISIBLE)
2840             {
2841                 WIN_ReleasePtr( pWnd );
2842                 /* In Windows, ShowOwnedPopups(FALSE) generates
2843                  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2844                  * regardless of the state of the owner
2845                  */
2846                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2847                 continue;
2848             }
2849         }
2850         WIN_ReleasePtr( pWnd );
2851     }
2852     HeapFree( GetProcessHeap(), 0, win_array );
2853     return TRUE;
2854 }
2855
2856
2857 /*******************************************************************
2858  *              GetLastActivePopup (USER32.@)
2859  */
2860 HWND WINAPI GetLastActivePopup( HWND hwnd )
2861 {
2862     HWND retval = hwnd;
2863
2864     SERVER_START_REQ( get_window_info )
2865     {
2866         req->handle = hwnd;
2867         if (!wine_server_call_err( req )) retval = reply->last_active;
2868     }
2869     SERVER_END_REQ;
2870     return retval;
2871 }
2872
2873
2874 /*******************************************************************
2875  *           WIN_ListChildren
2876  *
2877  * Build an array of the children of a given window. The array must be
2878  * freed with HeapFree. Returns NULL when no windows are found.
2879  */
2880 HWND *WIN_ListChildren( HWND hwnd )
2881 {
2882     return list_window_children( 0, hwnd, NULL, 0 );
2883 }
2884
2885
2886 /*******************************************************************
2887  *              EnumWindows (USER32.@)
2888  */
2889 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2890 {
2891     HWND *list;
2892     BOOL ret = TRUE;
2893     int i;
2894
2895     USER_CheckNotLock();
2896
2897     /* We have to build a list of all windows first, to avoid */
2898     /* unpleasant side-effects, for instance if the callback */
2899     /* function changes the Z-order of the windows.          */
2900
2901     if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2902
2903     /* Now call the callback function for every window */
2904
2905     for (i = 0; list[i]; i++)
2906     {
2907         /* Make sure that the window still exists */
2908         if (!IsWindow( list[i] )) continue;
2909         if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2910     }
2911     HeapFree( GetProcessHeap(), 0, list );
2912     return ret;
2913 }
2914
2915
2916 /**********************************************************************
2917  *              EnumThreadWindows (USER32.@)
2918  */
2919 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2920 {
2921     HWND *list;
2922     int i;
2923
2924     USER_CheckNotLock();
2925
2926     if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2927
2928     /* Now call the callback function for every window */
2929
2930     for (i = 0; list[i]; i++)
2931         if (!func( list[i], lParam )) break;
2932     HeapFree( GetProcessHeap(), 0, list );
2933     return TRUE;
2934 }
2935
2936
2937 /***********************************************************************
2938  *              EnumDesktopWindows   (USER32.@)
2939  */
2940 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2941 {
2942     HWND *list;
2943     int i;
2944
2945     USER_CheckNotLock();
2946
2947     if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2948
2949     for (i = 0; list[i]; i++)
2950         if (!func( list[i], lparam )) break;
2951     HeapFree( GetProcessHeap(), 0, list );
2952     return TRUE;
2953 }
2954
2955
2956 /**********************************************************************
2957  *           WIN_EnumChildWindows
2958  *
2959  * Helper function for EnumChildWindows().
2960  */
2961 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2962 {
2963     HWND *childList;
2964     BOOL ret = FALSE;
2965
2966     for ( ; *list; list++)
2967     {
2968         /* Make sure that the window still exists */
2969         if (!IsWindow( *list )) continue;
2970         /* Build children list first */
2971         childList = WIN_ListChildren( *list );
2972
2973         ret = func( *list, lParam );
2974
2975         if (childList)
2976         {
2977             if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2978             HeapFree( GetProcessHeap(), 0, childList );
2979         }
2980         if (!ret) return FALSE;
2981     }
2982     return TRUE;
2983 }
2984
2985
2986 /**********************************************************************
2987  *              EnumChildWindows (USER32.@)
2988  */
2989 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2990 {
2991     HWND *list;
2992     BOOL ret;
2993
2994     USER_CheckNotLock();
2995
2996     if (!(list = WIN_ListChildren( parent ))) return FALSE;
2997     ret = WIN_EnumChildWindows( list, func, lParam );
2998     HeapFree( GetProcessHeap(), 0, list );
2999     return ret;
3000 }
3001
3002
3003 /*******************************************************************
3004  *              AnyPopup (USER.52)
3005  */
3006 BOOL16 WINAPI AnyPopup16(void)
3007 {
3008     return AnyPopup();
3009 }
3010
3011
3012 /*******************************************************************
3013  *              AnyPopup (USER32.@)
3014  */
3015 BOOL WINAPI AnyPopup(void)
3016 {
3017     int i;
3018     BOOL retvalue;
3019     HWND *list = WIN_ListChildren( GetDesktopWindow() );
3020
3021     if (!list) return FALSE;
3022     for (i = 0; list[i]; i++)
3023     {
3024         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3025     }
3026     retvalue = (list[i] != 0);
3027     HeapFree( GetProcessHeap(), 0, list );
3028     return retvalue;
3029 }
3030
3031
3032 /*******************************************************************
3033  *              FlashWindow (USER32.@)
3034  */
3035 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3036 {
3037     WND *wndPtr;
3038
3039     TRACE("%p\n", hWnd);
3040
3041     if (IsIconic( hWnd ))
3042     {
3043         RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3044
3045         wndPtr = WIN_GetPtr(hWnd);
3046         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3047         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3048         {
3049             wndPtr->flags |= WIN_NCACTIVATED;
3050         }
3051         else
3052         {
3053             wndPtr->flags &= ~WIN_NCACTIVATED;
3054         }
3055         WIN_ReleasePtr( wndPtr );
3056         return TRUE;
3057     }
3058     else
3059     {
3060         WPARAM wparam;
3061
3062         wndPtr = WIN_GetPtr(hWnd);
3063         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3064         hWnd = wndPtr->hwndSelf;  /* make it a full handle */
3065
3066         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3067         else wparam = (hWnd == GetForegroundWindow());
3068
3069         WIN_ReleasePtr( wndPtr );
3070         SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3071         return wparam;
3072     }
3073 }
3074
3075 /*******************************************************************
3076  *              FlashWindowEx (USER32.@)
3077  */
3078 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3079 {
3080     FIXME("%p\n", pfwi);
3081     return TRUE;
3082 }
3083
3084 /*******************************************************************
3085  *              GetWindowContextHelpId (USER32.@)
3086  */
3087 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3088 {
3089     DWORD retval;
3090     WND *wnd = WIN_GetPtr( hwnd );
3091     if (!wnd || wnd == WND_DESKTOP) return 0;
3092     if (wnd == WND_OTHER_PROCESS)
3093     {
3094         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3095         return 0;
3096     }
3097     retval = wnd->helpContext;
3098     WIN_ReleasePtr( wnd );
3099     return retval;
3100 }
3101
3102
3103 /*******************************************************************
3104  *              SetWindowContextHelpId (USER32.@)
3105  */
3106 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3107 {
3108     WND *wnd = WIN_GetPtr( hwnd );
3109     if (!wnd || wnd == WND_DESKTOP) return FALSE;
3110     if (wnd == WND_OTHER_PROCESS)
3111     {
3112         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3113         return 0;
3114     }
3115     wnd->helpContext = id;
3116     WIN_ReleasePtr( wnd );
3117     return TRUE;
3118 }
3119
3120
3121 /*******************************************************************
3122  *              DragDetect (USER32.@)
3123  */
3124 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3125 {
3126     MSG msg;
3127     RECT rect;
3128     WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3129     WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3130
3131     rect.left = pt.x - wDragWidth;
3132     rect.right = pt.x + wDragWidth;
3133
3134     rect.top = pt.y - wDragHeight;
3135     rect.bottom = pt.y + wDragHeight;
3136
3137     SetCapture(hWnd);
3138
3139     while(1)
3140     {
3141         while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3142         {
3143             if( msg.message == WM_LBUTTONUP )
3144             {
3145                 ReleaseCapture();
3146                 return 0;
3147             }
3148             if( msg.message == WM_MOUSEMOVE )
3149             {
3150                 POINT tmp;
3151                 tmp.x = (short)LOWORD(msg.lParam);
3152                 tmp.y = (short)HIWORD(msg.lParam);
3153                 if( !PtInRect( &rect, tmp ))
3154                 {
3155                     ReleaseCapture();
3156                     return 1;
3157                 }
3158             }
3159         }
3160         WaitMessage();
3161     }
3162     return 0;
3163 }
3164
3165 /******************************************************************************
3166  *              GetWindowModuleFileNameA (USER32.@)
3167  */
3168 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3169 {
3170     WND *win;
3171     HINSTANCE hinst;
3172
3173     TRACE( "%p, %p, %u\n", hwnd, module, size );
3174
3175     win = WIN_GetPtr( hwnd );
3176     if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3177     {
3178         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3179         return 0;
3180     }
3181     hinst = win->hInstance;
3182     WIN_ReleasePtr( win );
3183
3184     return GetModuleFileNameA( hinst, module, size );
3185 }
3186
3187 /******************************************************************************
3188  *              GetWindowModuleFileNameW (USER32.@)
3189  */
3190 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3191 {
3192     WND *win;
3193     HINSTANCE hinst;
3194
3195     TRACE( "%p, %p, %u\n", hwnd, module, size );
3196
3197     win = WIN_GetPtr( hwnd );
3198     if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3199     {
3200         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3201         return 0;
3202     }
3203     hinst = win->hInstance;
3204     WIN_ReleasePtr( win );
3205
3206     return GetModuleFileNameW( hinst, module, size );
3207 }
3208
3209 /******************************************************************************
3210  *              GetWindowInfo (USER32.@)
3211  *
3212  * Note: tests show that Windows doesn't check cbSize of the structure.
3213  */
3214 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3215 {
3216     if (!pwi) return FALSE;
3217     if (!IsWindow(hwnd)) return FALSE;
3218
3219     GetWindowRect(hwnd, &pwi->rcWindow);
3220     GetClientRect(hwnd, &pwi->rcClient);
3221     /* translate to screen coordinates */
3222     MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3223
3224     pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3225     pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3226     pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3227
3228     pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3229     pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3230
3231     pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3232     pwi->wCreatorVersion = 0x0400;
3233
3234     return TRUE;
3235 }
3236
3237 /******************************************************************************
3238  *              SwitchDesktop (USER32.@)
3239  *
3240  * NOTES: Sets the current input or interactive desktop.
3241  */
3242 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3243 {
3244     FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3245     return TRUE;
3246 }
3247
3248 /*****************************************************************************
3249  *              SetLayeredWindowAttributes (USER32.@)
3250  */
3251 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey, 
3252                                         BYTE bAlpha, DWORD dwFlags )
3253 {
3254     FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3255     return TRUE;
3256 }
3257
3258 /*****************************************************************************
3259  *              GetLayeredWindowAttributes (USER32.@)
3260  */
3261 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3262                                         BYTE *pbAlpha, DWORD *pdwFlags )
3263 {
3264     FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3265     return FALSE;
3266 }
3267
3268 /*****************************************************************************
3269  *              UpdateLayeredWindow (USER32.@)
3270  */
3271 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3272                                  HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3273                                  DWORD dwFlags)
3274 {
3275     static int once;
3276     if (!once)
3277     {
3278         once = 1;
3279         FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3280               hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3281     }
3282     return 0;
3283 }
3284
3285 /* 64bit versions */
3286
3287 #ifdef GetWindowLongPtrW
3288 #undef GetWindowLongPtrW
3289 #endif
3290
3291 #ifdef GetWindowLongPtrA
3292 #undef GetWindowLongPtrA
3293 #endif
3294
3295 #ifdef SetWindowLongPtrW
3296 #undef SetWindowLongPtrW
3297 #endif
3298
3299 #ifdef SetWindowLongPtrA
3300 #undef SetWindowLongPtrA
3301 #endif
3302
3303 /*****************************************************************************
3304  *              GetWindowLongPtrW (USER32.@)
3305  */
3306 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3307 {
3308     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3309 }
3310
3311 /*****************************************************************************
3312  *              GetWindowLongPtrA (USER32.@)
3313  */
3314 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3315 {
3316     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3317 }
3318
3319 /*****************************************************************************
3320  *              SetWindowLongPtrW (USER32.@)
3321  */
3322 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3323 {
3324     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3325 }
3326
3327 /*****************************************************************************
3328  *              SetWindowLongPtrA (USER32.@)
3329  */
3330 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3331 {
3332     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );
3333 }