winhelp.exe: Renamed to winhlp32.exe.
[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     if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1123
1124     /* send WM_NCCREATE */
1125
1126     TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1127     if (unicode)
1128         result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1129     else
1130         result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1131     if (!result)
1132     {
1133         WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1134         goto failed;
1135     }
1136
1137     /* send WM_NCCALCSIZE */
1138
1139     if ((wndPtr = WIN_GetPtr(hwnd)))
1140     {
1141         /* yes, even if the CBT hook was called with HWND_TOP */
1142         POINT pt;
1143         HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1144         RECT window_rect = wndPtr->rectWindow;
1145         RECT client_rect = window_rect;
1146         WIN_ReleasePtr( wndPtr );
1147
1148         /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1149         pt.x = pt.y = 0;
1150         MapWindowPoints( parent, 0, &pt, 1 );
1151         OffsetRect( &client_rect, pt.x, pt.y );
1152         SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1153         OffsetRect( &client_rect, -pt.x, -pt.y );
1154         set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1155     }
1156     else return 0;
1157
1158     /* send WM_CREATE */
1159
1160     if (unicode)
1161         result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1162     else
1163         result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1164     if (result == -1) goto failed;
1165
1166     /* call the driver */
1167
1168     if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1169
1170     NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1171
1172     /* send the size messages */
1173
1174     if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1175     if (!(wndPtr->flags & WIN_NEED_SIZE))
1176     {
1177         rect = wndPtr->rectClient;
1178         WIN_ReleasePtr( wndPtr );
1179         SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1180                       MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1181         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1182     }
1183     else WIN_ReleasePtr( wndPtr );
1184
1185     /* Show the window, maximizing or minimizing if needed */
1186
1187     style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1188     if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1189     {
1190         RECT newPos;
1191         UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1192
1193         swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1194         swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1195         if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1196         SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1197     }
1198
1199     /* Notify the parent window only */
1200
1201     send_parent_notify( hwnd, WM_CREATE );
1202     if (!IsWindow( hwnd )) return 0;
1203
1204     if (cs->style & WS_VISIBLE)
1205     {
1206         if (cs->style & WS_MAXIMIZE)
1207             sw = SW_SHOW;
1208         else if (cs->style & WS_MINIMIZE)
1209             sw = SW_SHOWMINIMIZED;
1210
1211         ShowWindow( hwnd, sw );
1212         if (cs->dwExStyle & WS_EX_MDICHILD)
1213         {
1214             SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1215             /* ShowWindow won't activate child windows */
1216             SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1217         }
1218     }
1219
1220     /* Call WH_SHELL hook */
1221
1222     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1223         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1224
1225     TRACE("created window %p\n", hwnd);
1226     return hwnd;
1227
1228 failed:
1229     WIN_DestroyWindow( hwnd );
1230     return 0;
1231 }
1232
1233
1234 /***********************************************************************
1235  *              CreateWindow (USER.41)
1236  */
1237 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1238                               DWORD style, INT16 x, INT16 y, INT16 width,
1239                               INT16 height, HWND16 parent, HMENU16 menu,
1240                               HINSTANCE16 instance, LPVOID data )
1241 {
1242     return CreateWindowEx16( 0, className, windowName, style,
1243                              x, y, width, height, parent, menu, instance, data );
1244 }
1245
1246
1247 /***********************************************************************
1248  *              CreateWindowEx (USER.452)
1249  */
1250 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1251                                 LPCSTR windowName, DWORD style, INT16 x,
1252                                 INT16 y, INT16 width, INT16 height,
1253                                 HWND16 parent, HMENU16 menu,
1254                                 HINSTANCE16 instance, LPVOID data )
1255 {
1256     CREATESTRUCTA cs;
1257     char buffer[256];
1258
1259     /* Fix the coordinates */
1260
1261     cs.x  = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1262     cs.y  = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1263     cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1264     cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1265
1266     /* Create the window */
1267
1268     cs.lpCreateParams = data;
1269     cs.hInstance      = HINSTANCE_32(instance);
1270     cs.hMenu          = HMENU_32(menu);
1271     cs.hwndParent     = WIN_Handle32( parent );
1272     cs.style          = style;
1273     cs.lpszName       = windowName;
1274     cs.lpszClass      = className;
1275     cs.dwExStyle      = exStyle;
1276
1277     if (!IS_INTRESOURCE(className))
1278     {
1279         WCHAR bufferW[256];
1280
1281         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1282             return 0;
1283         return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1284     }
1285     else
1286     {
1287         if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1288         {
1289             ERR( "bad atom %x\n", LOWORD(className));
1290             return 0;
1291         }
1292         cs.lpszClass = buffer;
1293         return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1294     }
1295 }
1296
1297
1298 /***********************************************************************
1299  *              CreateWindowExA (USER32.@)
1300  */
1301 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1302                                  LPCSTR windowName, DWORD style, INT x,
1303                                  INT y, INT width, INT height,
1304                                  HWND parent, HMENU menu,
1305                                  HINSTANCE instance, LPVOID data )
1306 {
1307     CREATESTRUCTA cs;
1308
1309     cs.lpCreateParams = data;
1310     cs.hInstance      = instance;
1311     cs.hMenu          = menu;
1312     cs.hwndParent     = parent;
1313     cs.x              = x;
1314     cs.y              = y;
1315     cs.cx             = width;
1316     cs.cy             = height;
1317     cs.style          = style;
1318     cs.lpszName       = windowName;
1319     cs.lpszClass      = className;
1320     cs.dwExStyle      = exStyle;
1321
1322     if (!IS_INTRESOURCE(className))
1323     {
1324         WCHAR bufferW[256];
1325         if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1326             return 0;
1327         return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1328     }
1329     return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1330 }
1331
1332
1333 /***********************************************************************
1334  *              CreateWindowExW (USER32.@)
1335  */
1336 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1337                                  LPCWSTR windowName, DWORD style, INT x,
1338                                  INT y, INT width, INT height,
1339                                  HWND parent, HMENU menu,
1340                                  HINSTANCE instance, LPVOID data )
1341 {
1342     CREATESTRUCTW cs;
1343
1344     cs.lpCreateParams = data;
1345     cs.hInstance      = instance;
1346     cs.hMenu          = menu;
1347     cs.hwndParent     = parent;
1348     cs.x              = x;
1349     cs.y              = y;
1350     cs.cx             = width;
1351     cs.cy             = height;
1352     cs.style          = style;
1353     cs.lpszName       = windowName;
1354     cs.lpszClass      = className;
1355     cs.dwExStyle      = exStyle;
1356
1357     /* Note: we rely on the fact that CREATESTRUCTA and */
1358     /* CREATESTRUCTW have the same layout. */
1359     return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1360 }
1361
1362
1363 /***********************************************************************
1364  *           WIN_SendDestroyMsg
1365  */
1366 static void WIN_SendDestroyMsg( HWND hwnd )
1367 {
1368     GUITHREADINFO info;
1369
1370     if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1371     {
1372         if (hwnd == info.hwndCaret) DestroyCaret();
1373         if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1374     }
1375
1376     /*
1377      * Send the WM_DESTROY to the window.
1378      */
1379     SendMessageW( hwnd, WM_DESTROY, 0, 0);
1380
1381     /*
1382      * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1383      * make sure that the window still exists when we come back.
1384      */
1385     if (IsWindow(hwnd))
1386     {
1387         HWND* pWndArray;
1388         int i;
1389
1390         if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1391
1392         for (i = 0; pWndArray[i]; i++)
1393         {
1394             if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1395         }
1396         HeapFree( GetProcessHeap(), 0, pWndArray );
1397     }
1398     else
1399       WARN("\tdestroyed itself while in WM_DESTROY!\n");
1400 }
1401
1402
1403 /***********************************************************************
1404  *              DestroyWindow (USER32.@)
1405  */
1406 BOOL WINAPI DestroyWindow( HWND hwnd )
1407 {
1408     BOOL is_child;
1409
1410     if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1411     {
1412         SetLastError( ERROR_ACCESS_DENIED );
1413         return FALSE;
1414     }
1415
1416     TRACE("(%p)\n", hwnd);
1417
1418       /* Call hooks */
1419
1420     if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1421
1422     if (MENU_IsMenuActive() == hwnd)
1423         EndMenu();
1424
1425     is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1426
1427     if (is_child)
1428     {
1429         if (!USER_IsExitingThread( GetCurrentThreadId() ))
1430             send_parent_notify( hwnd, WM_DESTROY );
1431     }
1432     else if (!GetWindow( hwnd, GW_OWNER ))
1433     {
1434         HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1435         /* FIXME: clean up palette - see "Internals" p.352 */
1436     }
1437
1438     if (!IsWindow(hwnd)) return TRUE;
1439
1440       /* Hide the window */
1441     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1442     {
1443         /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1444         if (is_child)
1445             ShowWindow( hwnd, SW_HIDE );
1446         else
1447             SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1448                           SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1449     }
1450
1451     if (!IsWindow(hwnd)) return TRUE;
1452
1453       /* Recursively destroy owned windows */
1454
1455     if (!is_child)
1456     {
1457         for (;;)
1458         {
1459             int i, got_one = 0;
1460             HWND *list = WIN_ListChildren( GetDesktopWindow() );
1461             if (list)
1462             {
1463                 for (i = 0; list[i]; i++)
1464                 {
1465                     if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1466                     if (WIN_IsCurrentThread( list[i] ))
1467                     {
1468                         DestroyWindow( list[i] );
1469                         got_one = 1;
1470                         continue;
1471                     }
1472                     WIN_SetOwner( list[i], 0 );
1473                 }
1474                 HeapFree( GetProcessHeap(), 0, list );
1475             }
1476             if (!got_one) break;
1477         }
1478     }
1479
1480       /* Send destroy messages */
1481
1482     WIN_SendDestroyMsg( hwnd );
1483     if (!IsWindow( hwnd )) return TRUE;
1484
1485     if (GetClipboardOwner() == hwnd)
1486         CLIPBOARD_ReleaseOwner();
1487
1488       /* Destroy the window storage */
1489
1490     WIN_DestroyWindow( hwnd );
1491     return TRUE;
1492 }
1493
1494
1495 /***********************************************************************
1496  *              CloseWindow (USER32.@)
1497  */
1498 BOOL WINAPI CloseWindow( HWND hwnd )
1499 {
1500     if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1501     ShowWindow( hwnd, SW_MINIMIZE );
1502     return TRUE;
1503 }
1504
1505
1506 /***********************************************************************
1507  *              OpenIcon (USER32.@)
1508  */
1509 BOOL WINAPI OpenIcon( HWND hwnd )
1510 {
1511     if (!IsIconic( hwnd )) return FALSE;
1512     ShowWindow( hwnd, SW_SHOWNORMAL );
1513     return TRUE;
1514 }
1515
1516
1517 /***********************************************************************
1518  *              FindWindowExW (USER32.@)
1519  */
1520 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1521 {
1522     HWND *list = NULL;
1523     HWND retvalue = 0;
1524     int i = 0, len = 0;
1525     WCHAR *buffer = NULL;
1526
1527     if (!parent) parent = GetDesktopWindow();
1528     if (title)
1529     {
1530         len = strlenW(title) + 1;  /* one extra char to check for chars beyond the end */
1531         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1532     }
1533
1534     if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1535
1536     if (child)
1537     {
1538         child = WIN_GetFullHandle( child );
1539         while (list[i] && list[i] != child) i++;
1540         if (!list[i]) goto done;
1541         i++;  /* start from next window */
1542     }
1543
1544     if (title)
1545     {
1546         while (list[i])
1547         {
1548             if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1549             i++;
1550         }
1551     }
1552     retvalue = list[i];
1553
1554  done:
1555     HeapFree( GetProcessHeap(), 0, list );
1556     HeapFree( GetProcessHeap(), 0, buffer );
1557     return retvalue;
1558 }
1559
1560
1561
1562 /***********************************************************************
1563  *              FindWindowA (USER32.@)
1564  */
1565 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1566 {
1567     HWND ret = FindWindowExA( 0, 0, className, title );
1568     if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569     return ret;
1570 }
1571
1572
1573 /***********************************************************************
1574  *              FindWindowExA (USER32.@)
1575  */
1576 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1577 {
1578     LPWSTR titleW = NULL;
1579     HWND hwnd = 0;
1580
1581     if (title)
1582     {
1583         DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1584         if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1585         MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1586     }
1587
1588     if (!IS_INTRESOURCE(className))
1589     {
1590         WCHAR classW[256];
1591         if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1592             hwnd = FindWindowExW( parent, child, classW, titleW );
1593     }
1594     else
1595     {
1596         hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1597     }
1598
1599     HeapFree( GetProcessHeap(), 0, titleW );
1600     return hwnd;
1601 }
1602
1603
1604 /***********************************************************************
1605  *              FindWindowW (USER32.@)
1606  */
1607 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1608 {
1609     return FindWindowExW( 0, 0, className, title );
1610 }
1611
1612
1613 /**********************************************************************
1614  *              GetDesktopWindow (USER32.@)
1615  */
1616 HWND WINAPI GetDesktopWindow(void)
1617 {
1618     struct user_thread_info *thread_info = get_user_thread_info();
1619
1620     if (thread_info->desktop) return thread_info->desktop;
1621
1622     SERVER_START_REQ( get_desktop_window )
1623     {
1624         req->force = 0;
1625         if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1626     }
1627     SERVER_END_REQ;
1628
1629     if (!thread_info->desktop)
1630     {
1631         USEROBJECTFLAGS flags;
1632         if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1633                                         sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1634         {
1635             static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1636             STARTUPINFOW si;
1637             PROCESS_INFORMATION pi;
1638             WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1639
1640             memset( &si, 0, sizeof(si) );
1641             si.cb = sizeof(si);
1642             si.dwFlags = STARTF_USESTDHANDLES;
1643             si.hStdInput  = 0;
1644             si.hStdOutput = 0;
1645             si.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1646
1647             GetSystemDirectoryW( cmdline, MAX_PATH );
1648             lstrcatW( cmdline, command_line );
1649             if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1650                                 NULL, NULL, &si, &pi ))
1651             {
1652                 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1653                 WaitForInputIdle( pi.hProcess, 10000 );
1654                 CloseHandle( pi.hThread );
1655                 CloseHandle( pi.hProcess );
1656             }
1657             else WARN( "failed to start explorer, err %d\n", GetLastError() );
1658         }
1659         else TRACE( "not starting explorer since winstation is not visible\n" );
1660
1661         SERVER_START_REQ( get_desktop_window )
1662         {
1663             req->force = 1;
1664             if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1665         }
1666         SERVER_END_REQ;
1667     }
1668
1669     if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1670         ERR( "failed to create desktop window\n" );
1671
1672     return thread_info->desktop;
1673 }
1674
1675
1676 /*******************************************************************
1677  *              EnableWindow (USER32.@)
1678  */
1679 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1680 {
1681     BOOL retvalue;
1682     HWND full_handle;
1683
1684     if (is_broadcast(hwnd))
1685     {
1686         SetLastError( ERROR_INVALID_PARAMETER );
1687         return FALSE;
1688     }
1689
1690     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1691         return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1692
1693     hwnd = full_handle;
1694
1695     TRACE("( %p, %d )\n", hwnd, enable);
1696
1697     retvalue = !IsWindowEnabled( hwnd );
1698
1699     if (enable && retvalue)
1700     {
1701         WIN_SetStyle( hwnd, 0, WS_DISABLED );
1702         SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1703     }
1704     else if (!enable && !retvalue)
1705     {
1706         HWND capture_wnd;
1707
1708         SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1709
1710         WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1711
1712         if (hwnd == GetFocus())
1713             SetFocus( 0 );  /* A disabled window can't have the focus */
1714
1715         capture_wnd = GetCapture();
1716         if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1717             ReleaseCapture();  /* A disabled window can't capture the mouse */
1718
1719         SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1720     }
1721     return retvalue;
1722 }
1723
1724
1725 /***********************************************************************
1726  *              IsWindowEnabled (USER32.@)
1727  */
1728 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1729 {
1730     return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1731 }
1732
1733
1734 /***********************************************************************
1735  *              IsWindowUnicode (USER32.@)
1736  */
1737 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1738 {
1739     WND * wndPtr;
1740     BOOL retvalue = FALSE;
1741
1742     if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1743
1744     if (wndPtr == WND_DESKTOP) return TRUE;
1745
1746     if (wndPtr != WND_OTHER_PROCESS)
1747     {
1748         retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1749         WIN_ReleasePtr( wndPtr );
1750     }
1751     else
1752     {
1753         SERVER_START_REQ( get_window_info )
1754         {
1755             req->handle = hwnd;
1756             if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1757         }
1758         SERVER_END_REQ;
1759     }
1760     return retvalue;
1761 }
1762
1763
1764 /**********************************************************************
1765  *           WIN_GetWindowLong
1766  *
1767  * Helper function for GetWindowLong().
1768  */
1769 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1770 {
1771     LONG_PTR retvalue = 0;
1772     WND *wndPtr;
1773
1774     if (offset == GWLP_HWNDPARENT)
1775     {
1776         HWND parent = GetAncestor( hwnd, GA_PARENT );
1777         if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1778         return (ULONG_PTR)parent;
1779     }
1780
1781     if (!(wndPtr = WIN_GetPtr( hwnd )))
1782     {
1783         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1784         return 0;
1785     }
1786
1787     if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1788     {
1789         if (offset == GWLP_WNDPROC)
1790         {
1791             SetLastError( ERROR_ACCESS_DENIED );
1792             return 0;
1793         }
1794         SERVER_START_REQ( set_window_info )
1795         {
1796             req->handle = hwnd;
1797             req->flags  = 0;  /* don't set anything, just retrieve */
1798             req->extra_offset = (offset >= 0) ? offset : -1;
1799             req->extra_size = (offset >= 0) ? size : 0;
1800             if (!wine_server_call_err( req ))
1801             {
1802                 switch(offset)
1803                 {
1804                 case GWL_STYLE:      retvalue = reply->old_style; break;
1805                 case GWL_EXSTYLE:    retvalue = reply->old_ex_style; break;
1806                 case GWLP_ID:        retvalue = reply->old_id; break;
1807                 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1808                 case GWLP_USERDATA:  retvalue = reply->old_user_data; break;
1809                 default:
1810                     if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1811                     else SetLastError( ERROR_INVALID_INDEX );
1812                     break;
1813                 }
1814             }
1815         }
1816         SERVER_END_REQ;
1817         return retvalue;
1818     }
1819
1820     /* now we have a valid wndPtr */
1821
1822     if (offset >= 0)
1823     {
1824         if (offset > (int)(wndPtr->cbWndExtra - size))
1825         {
1826             WARN("Invalid offset %d\n", offset );
1827             WIN_ReleasePtr( wndPtr );
1828             SetLastError( ERROR_INVALID_INDEX );
1829             return 0;
1830         }
1831         retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1832
1833         /* Special case for dialog window procedure */
1834         if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1835             retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1836         WIN_ReleasePtr( wndPtr );
1837         return retvalue;
1838     }
1839
1840     switch(offset)
1841     {
1842     case GWLP_USERDATA:  retvalue = wndPtr->userdata; break;
1843     case GWL_STYLE:      retvalue = wndPtr->dwStyle; break;
1844     case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle; break;
1845     case GWLP_ID:        retvalue = wndPtr->wIDmenu; break;
1846     case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1847     case GWLP_WNDPROC:
1848         /* This looks like a hack only for the edit control (see tests). This makes these controls
1849          * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1850          * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1851          */
1852         if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1853             retvalue = (ULONG_PTR)wndPtr->winproc;
1854         else
1855             retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1856         break;
1857     default:
1858         WARN("Unknown offset %d\n", offset );
1859         SetLastError( ERROR_INVALID_INDEX );
1860         break;
1861     }
1862     WIN_ReleasePtr(wndPtr);
1863     return retvalue;
1864 }
1865
1866
1867 /**********************************************************************
1868  *           WIN_SetWindowLong
1869  *
1870  * Helper function for SetWindowLong().
1871  *
1872  * 0 is the failure code. However, in the case of failure SetLastError
1873  * must be set to distinguish between a 0 return value and a failure.
1874  */
1875 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1876 {
1877     STYLESTRUCT style;
1878     BOOL ok;
1879     LONG_PTR retval = 0;
1880     WND *wndPtr;
1881
1882     TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1883
1884     if (is_broadcast(hwnd))
1885     {
1886         SetLastError( ERROR_INVALID_PARAMETER );
1887         return FALSE;
1888     }
1889
1890     if (!(wndPtr = WIN_GetPtr( hwnd )))
1891     {
1892         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1893         return 0;
1894     }
1895     if (wndPtr == WND_DESKTOP)
1896     {
1897         /* can't change anything on the desktop window */
1898         SetLastError( ERROR_ACCESS_DENIED );
1899         return 0;
1900     }
1901     if (wndPtr == WND_OTHER_PROCESS)
1902     {
1903         if (offset == GWLP_WNDPROC)
1904         {
1905             SetLastError( ERROR_ACCESS_DENIED );
1906             return 0;
1907         }
1908         if (offset > 32767 || offset < -32767)
1909         {
1910             SetLastError( ERROR_INVALID_INDEX );
1911             return 0;
1912         }
1913         return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1914     }
1915
1916     /* first some special cases */
1917     switch( offset )
1918     {
1919     case GWL_STYLE:
1920     case GWL_EXSTYLE:
1921         style.styleOld =
1922             offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1923         style.styleNew = newval;
1924         WIN_ReleasePtr( wndPtr );
1925         SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1926         if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1927         newval = style.styleNew;
1928         break;
1929     case GWLP_HWNDPARENT:
1930         if (wndPtr->parent == GetDesktopWindow())
1931         {
1932             WIN_ReleasePtr( wndPtr );
1933             return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1934         }
1935         else
1936         {
1937             WIN_ReleasePtr( wndPtr );
1938             return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1939         }
1940     case GWLP_WNDPROC:
1941     {
1942         WNDPROC proc;
1943         UINT old_flags = wndPtr->flags;
1944         retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1945         if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1946         else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1947         if (proc) wndPtr->winproc = proc;
1948         if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1949         else wndPtr->flags &= ~WIN_ISUNICODE;
1950         if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1951         {
1952             WIN_ReleasePtr( wndPtr );
1953             return retval;
1954         }
1955         /* update is_unicode flag on the server side */
1956         break;
1957     }
1958     case GWLP_ID:
1959     case GWLP_HINSTANCE:
1960     case GWLP_USERDATA:
1961         break;
1962     case DWLP_DLGPROC:
1963         if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1964             (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1965         {
1966             WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1967             retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1968             if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1969             else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1970             WIN_ReleasePtr( wndPtr );
1971             return retval;
1972         }
1973         /* fall through */
1974     default:
1975         if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1976         {
1977             WARN("Invalid offset %d\n", offset );
1978             WIN_ReleasePtr( wndPtr );
1979             SetLastError( ERROR_INVALID_INDEX );
1980             return 0;
1981         }
1982         else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1983         {
1984             /* already set to the same value */
1985             WIN_ReleasePtr( wndPtr );
1986             return newval;
1987         }
1988         break;
1989     }
1990
1991     SERVER_START_REQ( set_window_info )
1992     {
1993         req->handle = hwnd;
1994         req->extra_offset = -1;
1995         switch(offset)
1996         {
1997         case GWL_STYLE:
1998             req->flags = SET_WIN_STYLE;
1999             req->style = newval;
2000             break;
2001         case GWL_EXSTYLE:
2002             req->flags = SET_WIN_EXSTYLE;
2003             /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2004             newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2005             req->ex_style = newval;
2006             break;
2007         case GWLP_ID:
2008             req->flags = SET_WIN_ID;
2009             req->id = newval;
2010             break;
2011         case GWLP_HINSTANCE:
2012             req->flags = SET_WIN_INSTANCE;
2013             req->instance = (void *)newval;
2014             break;
2015         case GWLP_WNDPROC:
2016             req->flags = SET_WIN_UNICODE;
2017             req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2018             break;
2019         case GWLP_USERDATA:
2020             req->flags = SET_WIN_USERDATA;
2021             req->user_data = newval;
2022             break;
2023         default:
2024             req->flags = SET_WIN_EXTRA;
2025             req->extra_offset = offset;
2026             req->extra_size = size;
2027             set_win_data( &req->extra_value, newval, size );
2028         }
2029         if ((ok = !wine_server_call_err( req )))
2030         {
2031             switch(offset)
2032             {
2033             case GWL_STYLE:
2034                 wndPtr->dwStyle = newval;
2035                 retval = reply->old_style;
2036                 break;
2037             case GWL_EXSTYLE:
2038                 wndPtr->dwExStyle = newval;
2039                 retval = reply->old_ex_style;
2040                 break;
2041             case GWLP_ID:
2042                 wndPtr->wIDmenu = newval;
2043                 retval = reply->old_id;
2044                 break;
2045             case GWLP_HINSTANCE:
2046                 wndPtr->hInstance = (HINSTANCE)newval;
2047                 retval = (ULONG_PTR)reply->old_instance;
2048                 break;
2049             case GWLP_WNDPROC:
2050                 break;
2051             case GWLP_USERDATA:
2052                 wndPtr->userdata = newval;
2053                 retval = reply->old_user_data;
2054                 break;
2055             default:
2056                 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2057                 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2058                 break;
2059             }
2060         }
2061     }
2062     SERVER_END_REQ;
2063     WIN_ReleasePtr( wndPtr );
2064
2065     if (!ok) return 0;
2066
2067     if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2068
2069     if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2070         SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2071
2072     return retval;
2073 }
2074
2075
2076 /**********************************************************************
2077  *              GetWindowLong (USER.135)
2078  */
2079 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2080 {
2081     WND *wndPtr;
2082     LONG_PTR retvalue;
2083     BOOL is_winproc = (offset == GWLP_WNDPROC);
2084
2085     if (offset >= 0)
2086     {
2087         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2088         {
2089             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2090             return 0;
2091         }
2092         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2093         {
2094             if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2095             {
2096                 /*
2097                  * Some programs try to access last element from 16 bit
2098                  * code using illegal offset value. Hopefully this is
2099                  * what those programs really expect.
2100                  */
2101                 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2102                 {
2103                     INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2104                     ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2105                     offset = offset2;
2106                 }
2107                 else
2108                 {
2109                     WARN("Invalid offset %d\n", offset );
2110                     WIN_ReleasePtr( wndPtr );
2111                     SetLastError( ERROR_INVALID_INDEX );
2112                     return 0;
2113                 }
2114             }
2115             is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2116             WIN_ReleasePtr( wndPtr );
2117         }
2118     }
2119     retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2120     if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2121     return retvalue;
2122 }
2123
2124
2125 /**********************************************************************
2126  *              GetWindowWord (USER32.@)
2127  */
2128 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2129 {
2130     switch(offset)
2131     {
2132     case GWLP_ID:
2133     case GWLP_HINSTANCE:
2134     case GWLP_HWNDPARENT:
2135         break;
2136     default:
2137         if (offset < 0)
2138         {
2139             WARN("Invalid offset %d\n", offset );
2140             SetLastError( ERROR_INVALID_INDEX );
2141             return 0;
2142         }
2143         break;
2144     }
2145     return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2146 }
2147
2148
2149 /**********************************************************************
2150  *              GetWindowLongA (USER32.@)
2151  */
2152 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2153 {
2154     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2155 }
2156
2157
2158 /**********************************************************************
2159  *              GetWindowLongW (USER32.@)
2160  */
2161 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2162 {
2163     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2164 }
2165
2166
2167 /**********************************************************************
2168  *              SetWindowLong (USER.136)
2169  */
2170 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2171 {
2172     WND *wndPtr;
2173     BOOL is_winproc = (offset == GWLP_WNDPROC);
2174
2175     if (offset == DWLP_DLGPROC)
2176     {
2177         if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2178         {
2179             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2180             return 0;
2181         }
2182         if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2183         {
2184             is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2185                           (wndPtr->flags & WIN_ISDIALOG));
2186             WIN_ReleasePtr( wndPtr );
2187         }
2188     }
2189
2190     if (is_winproc)
2191     {
2192         WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2193         WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2194         return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2195     }
2196     else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2197 }
2198
2199
2200 /**********************************************************************
2201  *              SetWindowWord (USER32.@)
2202  */
2203 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2204 {
2205     switch(offset)
2206     {
2207     case GWLP_ID:
2208     case GWLP_HINSTANCE:
2209     case GWLP_HWNDPARENT:
2210         break;
2211     default:
2212         if (offset < 0)
2213         {
2214             WARN("Invalid offset %d\n", offset );
2215             SetLastError( ERROR_INVALID_INDEX );
2216             return 0;
2217         }
2218         break;
2219     }
2220     return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2221 }
2222
2223
2224 /**********************************************************************
2225  *              SetWindowLongA (USER32.@)
2226  *
2227  * See SetWindowLongW.
2228  */
2229 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2230 {
2231     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2232 }
2233
2234
2235 /**********************************************************************
2236  *              SetWindowLongW (USER32.@) Set window attribute
2237  *
2238  * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2239  * value in a window's extra memory.
2240  *
2241  * The _hwnd_ parameter specifies the window.  is the handle to a
2242  * window that has extra memory. The _newval_ parameter contains the
2243  * new attribute or extra memory value.  If positive, the _offset_
2244  * parameter is the byte-addressed location in the window's extra
2245  * memory to set.  If negative, _offset_ specifies the window
2246  * attribute to set, and should be one of the following values:
2247  *
2248  * GWL_EXSTYLE      The window's extended window style
2249  *
2250  * GWL_STYLE        The window's window style.
2251  *
2252  * GWLP_WNDPROC     Pointer to the window's window procedure.
2253  *
2254  * GWLP_HINSTANCE   The window's pplication instance handle.
2255  *
2256  * GWLP_ID          The window's identifier.
2257  *
2258  * GWLP_USERDATA    The window's user-specified data.
2259  *
2260  * If the window is a dialog box, the _offset_ parameter can be one of
2261  * the following values:
2262  *
2263  * DWLP_DLGPROC     The address of the window's dialog box procedure.
2264  *
2265  * DWLP_MSGRESULT   The return value of a message
2266  *                  that the dialog box procedure processed.
2267  *
2268  * DWLP_USER        Application specific information.
2269  *
2270  * RETURNS
2271  *
2272  * If successful, returns the previous value located at _offset_. Otherwise,
2273  * returns 0.
2274  *
2275  * NOTES
2276  *
2277  * Extra memory for a window class is specified by a nonzero cbWndExtra
2278  * parameter of the WNDCLASS structure passed to RegisterClass() at the
2279  * time of class creation.
2280  *
2281  * Using GWL_WNDPROC to set a new window procedure effectively creates
2282  * a window subclass. Use CallWindowProc() in the new windows procedure
2283  * to pass messages to the superclass's window procedure.
2284  *
2285  * The user data is reserved for use by the application which created
2286  * the window.
2287  *
2288  * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2289  * instead, call the EnableWindow() function to change the window's
2290  * disabled state.
2291  *
2292  * Do not use GWL_HWNDPARENT to reset the window's parent, use
2293  * SetParent() instead.
2294  *
2295  * Win95:
2296  * When offset is GWL_STYLE and the calling app's ver is 4.0,
2297  * it sends WM_STYLECHANGING before changing the settings
2298  * and WM_STYLECHANGED afterwards.
2299  * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2300  */
2301 LONG WINAPI SetWindowLongW(
2302     HWND hwnd,  /* [in] window to alter */
2303     INT offset, /* [in] offset, in bytes, of location to alter */
2304     LONG newval /* [in] new value of location */
2305 ) {
2306     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2307 }
2308
2309
2310 /*******************************************************************
2311  *              GetWindowTextA (USER32.@)
2312  */
2313 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2314 {
2315     WCHAR *buffer;
2316
2317     if (!lpString) return 0;
2318
2319     if (WIN_IsCurrentProcess( hwnd ))
2320         return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2321
2322     /* when window belongs to other process, don't send a message */
2323     if (nMaxCount <= 0) return 0;
2324     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2325     get_server_window_text( hwnd, buffer, nMaxCount );
2326     if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2327         lpString[nMaxCount-1] = 0;
2328     HeapFree( GetProcessHeap(), 0, buffer );
2329     return strlen(lpString);
2330 }
2331
2332
2333 /*******************************************************************
2334  *              InternalGetWindowText (USER32.@)
2335  */
2336 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2337 {
2338     WND *win;
2339
2340     if (nMaxCount <= 0) return 0;
2341     if (!(win = WIN_GetPtr( hwnd ))) return 0;
2342     if (win == WND_DESKTOP) lpString[0] = 0;
2343     else if (win != WND_OTHER_PROCESS)
2344     {
2345         if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2346         else lpString[0] = 0;
2347         WIN_ReleasePtr( win );
2348     }
2349     else
2350     {
2351         get_server_window_text( hwnd, lpString, nMaxCount );
2352     }
2353     return strlenW(lpString);
2354 }
2355
2356
2357 /*******************************************************************
2358  *              GetWindowTextW (USER32.@)
2359  */
2360 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2361 {
2362     if (!lpString) return 0;
2363
2364     if (WIN_IsCurrentProcess( hwnd ))
2365         return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2366
2367     /* when window belongs to other process, don't send a message */
2368     if (nMaxCount <= 0) return 0;
2369     get_server_window_text( hwnd, lpString, nMaxCount );
2370     return strlenW(lpString);
2371 }
2372
2373
2374 /*******************************************************************
2375  *              SetWindowTextA (USER32.@)
2376  *              SetWindowText  (USER32.@)
2377  */
2378 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2379 {
2380     if (is_broadcast(hwnd))
2381     {
2382         SetLastError( ERROR_INVALID_PARAMETER );
2383         return FALSE;
2384     }
2385     if (!WIN_IsCurrentProcess( hwnd ))
2386         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2387                debugstr_a(lpString), hwnd );
2388     return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2389 }
2390
2391
2392 /*******************************************************************
2393  *              SetWindowTextW (USER32.@)
2394  */
2395 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2396 {
2397     if (is_broadcast(hwnd))
2398     {
2399         SetLastError( ERROR_INVALID_PARAMETER );
2400         return FALSE;
2401     }
2402     if (!WIN_IsCurrentProcess( hwnd ))
2403         WARN( "setting text %s of other process window %p should not use SendMessage\n",
2404                debugstr_w(lpString), hwnd );
2405     return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2406 }
2407
2408
2409 /*******************************************************************
2410  *              GetWindowTextLengthA (USER32.@)
2411  */
2412 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2413 {
2414     return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2415 }
2416
2417 /*******************************************************************
2418  *              GetWindowTextLengthW (USER32.@)
2419  */
2420 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2421 {
2422     return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2423 }
2424
2425
2426 /*******************************************************************
2427  *              IsWindow (USER32.@)
2428  */
2429 BOOL WINAPI IsWindow( HWND hwnd )
2430 {
2431     WND *ptr;
2432     BOOL ret;
2433
2434     if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2435     if (ptr == WND_DESKTOP) return TRUE;
2436
2437     if (ptr != WND_OTHER_PROCESS)
2438     {
2439         WIN_ReleasePtr( ptr );
2440         return TRUE;
2441     }
2442
2443     /* check other processes */
2444     SERVER_START_REQ( get_window_info )
2445     {
2446         req->handle = hwnd;
2447         ret = !wine_server_call_err( req );
2448     }
2449     SERVER_END_REQ;
2450     return ret;
2451 }
2452
2453
2454 /***********************************************************************
2455  *              GetWindowThreadProcessId (USER32.@)
2456  */
2457 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2458 {
2459     WND *ptr;
2460     DWORD tid = 0;
2461
2462     if (!(ptr = WIN_GetPtr( hwnd )))
2463     {
2464         SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2465         return 0;
2466     }
2467
2468     if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2469     {
2470         /* got a valid window */
2471         tid = ptr->tid;
2472         if (process) *process = GetCurrentProcessId();
2473         WIN_ReleasePtr( ptr );
2474         return tid;
2475     }
2476
2477     /* check other processes */
2478     SERVER_START_REQ( get_window_info )
2479     {
2480         req->handle = hwnd;
2481         if (!wine_server_call_err( req ))
2482         {
2483             tid = (DWORD)reply->tid;
2484             if (process) *process = (DWORD)reply->pid;
2485         }
2486     }
2487     SERVER_END_REQ;
2488     return tid;
2489 }
2490
2491
2492 /*****************************************************************
2493  *              GetParent (USER32.@)
2494  */
2495 HWND WINAPI GetParent( HWND hwnd )
2496 {
2497     WND *wndPtr;
2498     HWND retvalue = 0;
2499
2500     if (!(wndPtr = WIN_GetPtr( hwnd )))
2501     {
2502         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2503         return 0;
2504     }
2505     if (wndPtr == WND_DESKTOP) return 0;
2506     if (wndPtr == WND_OTHER_PROCESS)
2507     {
2508         LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2509         if (style & (WS_POPUP | WS_CHILD))
2510         {
2511             SERVER_START_REQ( get_window_tree )
2512             {
2513                 req->handle = hwnd;
2514                 if (!wine_server_call_err( req ))
2515                 {
2516                     if (style & WS_POPUP) retvalue = reply->owner;
2517                     else if (style & WS_CHILD) retvalue = reply->parent;
2518                 }
2519             }
2520             SERVER_END_REQ;
2521         }
2522     }
2523     else
2524     {
2525         if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2526         else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2527         WIN_ReleasePtr( wndPtr );
2528     }
2529     return retvalue;
2530 }
2531
2532
2533 /*****************************************************************
2534  *              GetAncestor (USER32.@)
2535  */
2536 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2537 {
2538     WND *win;
2539     HWND *list, ret = 0;
2540
2541     switch(type)
2542     {
2543     case GA_PARENT:
2544         if (!(win = WIN_GetPtr( hwnd )))
2545         {
2546             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2547             return 0;
2548         }
2549         if (win == WND_DESKTOP) return 0;
2550         if (win != WND_OTHER_PROCESS)
2551         {
2552             ret = win->parent;
2553             WIN_ReleasePtr( win );
2554         }
2555         else /* need to query the server */
2556         {
2557             SERVER_START_REQ( get_window_tree )
2558             {
2559                 req->handle = hwnd;
2560                 if (!wine_server_call_err( req )) ret = reply->parent;
2561             }
2562             SERVER_END_REQ;
2563         }
2564         break;
2565
2566     case GA_ROOT:
2567         if (!(list = list_window_parents( hwnd ))) return 0;
2568
2569         if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd );  /* top-level window */
2570         else
2571         {
2572             int count = 2;
2573             while (list[count]) count++;
2574             ret = list[count - 2];  /* get the one before the desktop */
2575         }
2576         HeapFree( GetProcessHeap(), 0, list );
2577         break;
2578
2579     case GA_ROOTOWNER:
2580         if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2581         for (;;)
2582         {
2583             HWND parent = GetParent( ret );
2584             if (!parent) break;
2585             ret = parent;
2586         }
2587         break;
2588     }
2589     return ret;
2590 }
2591
2592
2593 /*****************************************************************
2594  *              SetParent (USER32.@)
2595  */
2596 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2597 {
2598     HWND full_handle;
2599     HWND old_parent = 0;
2600     BOOL was_visible;
2601     WND *wndPtr;
2602     BOOL ret;
2603
2604     if (is_broadcast(hwnd) || is_broadcast(parent))
2605     {
2606         SetLastError(ERROR_INVALID_PARAMETER);
2607         return 0;
2608     }
2609
2610     if (!parent) parent = GetDesktopWindow();
2611     else parent = WIN_GetFullHandle( parent );
2612
2613     if (!IsWindow( parent ))
2614     {
2615         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2616         return 0;
2617     }
2618
2619     /* Some applications try to set a child as a parent */
2620     if (IsChild(hwnd, parent))
2621     {
2622         SetLastError( ERROR_INVALID_PARAMETER );
2623         return 0;
2624     }
2625
2626     if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2627         return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2628
2629     /* Windows hides the window first, then shows it again
2630      * including the WM_SHOWWINDOW messages and all */
2631     was_visible = ShowWindow( hwnd, SW_HIDE );
2632
2633     wndPtr = WIN_GetPtr( hwnd );
2634     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2635
2636     SERVER_START_REQ( set_parent )
2637     {
2638         req->handle = hwnd;
2639         req->parent = parent;
2640         if ((ret = !wine_server_call( req )))
2641         {
2642             old_parent = reply->old_parent;
2643             wndPtr->parent = parent = reply->full_parent;
2644         }
2645
2646     }
2647     SERVER_END_REQ;
2648     WIN_ReleasePtr( wndPtr );
2649     if (!ret) return 0;
2650
2651     USER_Driver->pSetParent( full_handle, parent, old_parent );
2652
2653     /* SetParent additionally needs to make hwnd the topmost window
2654        in the x-order and send the expected WM_WINDOWPOSCHANGING and
2655        WM_WINDOWPOSCHANGED notification messages.
2656     */
2657     SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2658                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2659     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2660      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2661
2662     return old_parent;
2663 }
2664
2665
2666 /*******************************************************************
2667  *              IsChild (USER32.@)
2668  */
2669 BOOL WINAPI IsChild( HWND parent, HWND child )
2670 {
2671     HWND *list = list_window_parents( child );
2672     int i;
2673     BOOL ret;
2674
2675     if (!list) return FALSE;
2676     parent = WIN_GetFullHandle( parent );
2677     for (i = 0; list[i]; i++) if (list[i] == parent) break;
2678     ret = list[i] && list[i+1];
2679     HeapFree( GetProcessHeap(), 0, list );
2680     return ret;
2681 }
2682
2683
2684 /***********************************************************************
2685  *              IsWindowVisible (USER32.@)
2686  */
2687 BOOL WINAPI IsWindowVisible( HWND hwnd )
2688 {
2689     HWND *list;
2690     BOOL retval = TRUE;
2691     int i;
2692
2693     if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2694     if (!(list = list_window_parents( hwnd ))) return TRUE;
2695     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2696     {
2697         for (i = 0; list[i+1]; i++)
2698             if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2699         retval = !list[i+1];
2700     }
2701     HeapFree( GetProcessHeap(), 0, list );
2702     return retval;
2703 }
2704
2705
2706 /***********************************************************************
2707  *           WIN_IsWindowDrawable
2708  *
2709  * hwnd is drawable when it is visible, all parents are not
2710  * minimized, and it is itself not minimized unless we are
2711  * trying to draw its default class icon.
2712  */
2713 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2714 {
2715     HWND *list;
2716     BOOL retval = TRUE;
2717     int i;
2718     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2719
2720     if (!(style & WS_VISIBLE)) return FALSE;
2721     if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON ))  return FALSE;
2722
2723     if (!(list = list_window_parents( hwnd ))) return TRUE;
2724     if (list[0] && list[1])  /* desktop window is considered always visible so we don't check it */
2725     {
2726         for (i = 0; list[i+1]; i++)
2727             if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2728                 break;
2729         retval = !list[i+1];
2730     }
2731     HeapFree( GetProcessHeap(), 0, list );
2732     return retval;
2733 }
2734
2735
2736 /*******************************************************************
2737  *              GetTopWindow (USER32.@)
2738  */
2739 HWND WINAPI GetTopWindow( HWND hwnd )
2740 {
2741     if (!hwnd) hwnd = GetDesktopWindow();
2742     return GetWindow( hwnd, GW_CHILD );
2743 }
2744
2745
2746 /*******************************************************************
2747  *              GetWindow (USER32.@)
2748  */
2749 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2750 {
2751     HWND retval = 0;
2752
2753     if (rel == GW_OWNER)  /* this one may be available locally */
2754     {
2755         WND *wndPtr = WIN_GetPtr( hwnd );
2756         if (!wndPtr)
2757         {
2758             SetLastError( ERROR_INVALID_HANDLE );
2759             return 0;
2760         }
2761         if (wndPtr == WND_DESKTOP) return 0;
2762         if (wndPtr != WND_OTHER_PROCESS)
2763         {
2764             retval = wndPtr->owner;
2765             WIN_ReleasePtr( wndPtr );
2766             return retval;
2767         }
2768         /* else fall through to server call */
2769     }
2770
2771     SERVER_START_REQ( get_window_tree )
2772     {
2773         req->handle = hwnd;
2774         if (!wine_server_call_err( req ))
2775         {
2776             switch(rel)
2777             {
2778             case GW_HWNDFIRST:
2779                 retval = reply->first_sibling;
2780                 break;
2781             case GW_HWNDLAST:
2782                 retval = reply->last_sibling;
2783                 break;
2784             case GW_HWNDNEXT:
2785                 retval = reply->next_sibling;
2786                 break;
2787             case GW_HWNDPREV:
2788                 retval = reply->prev_sibling;
2789                 break;
2790             case GW_OWNER:
2791                 retval = reply->owner;
2792                 break;
2793             case GW_CHILD:
2794                 retval = reply->first_child;
2795                 break;
2796             }
2797         }
2798     }
2799     SERVER_END_REQ;
2800     return retval;
2801 }
2802
2803
2804 /*******************************************************************
2805  *              ShowOwnedPopups (USER32.@)
2806  */
2807 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2808 {
2809     int count = 0;
2810     WND *pWnd;
2811     HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2812
2813     if (!win_array) return TRUE;
2814
2815     while (win_array[count]) count++;
2816     while (--count >= 0)
2817     {
2818         if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2819         if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2820         if (pWnd == WND_OTHER_PROCESS) continue;
2821         if (fShow)
2822         {
2823             if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2824             {
2825                 WIN_ReleasePtr( pWnd );
2826                 /* In Windows, ShowOwnedPopups(TRUE) generates
2827                  * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2828                  * regardless of the state of the owner
2829                  */
2830                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2831                 continue;
2832             }
2833         }
2834         else
2835         {
2836             if (pWnd->dwStyle & WS_VISIBLE)
2837             {
2838                 WIN_ReleasePtr( pWnd );
2839                 /* In Windows, ShowOwnedPopups(FALSE) generates
2840                  * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2841                  * regardless of the state of the owner
2842                  */
2843                 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2844                 continue;
2845             }
2846         }
2847         WIN_ReleasePtr( pWnd );
2848     }
2849     HeapFree( GetProcessHeap(), 0, win_array );
2850     return TRUE;
2851 }
2852
2853
2854 /*******************************************************************
2855  *              GetLastActivePopup (USER32.@)
2856  */
2857 HWND WINAPI GetLastActivePopup( HWND hwnd )
2858 {
2859     HWND retval = hwnd;
2860
2861     SERVER_START_REQ( get_window_info )
2862     {
2863         req->handle = hwnd;
2864         if (!wine_server_call_err( req )) retval = reply->last_active;
2865     }
2866     SERVER_END_REQ;
2867     return retval;
2868 }
2869
2870
2871 /*******************************************************************
2872  *           WIN_ListChildren
2873  *
2874  * Build an array of the children of a given window. The array must be
2875  * freed with HeapFree. Returns NULL when no windows are found.
2876  */
2877 HWND *WIN_ListChildren( HWND hwnd )
2878 {
2879     return list_window_children( 0, hwnd, NULL, 0 );
2880 }
2881
2882
2883 /*******************************************************************
2884  *              EnumWindows (USER32.@)
2885  */
2886 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2887 {
2888     HWND *list;
2889     BOOL ret = TRUE;
2890     int i;
2891
2892     USER_CheckNotLock();
2893
2894     /* We have to build a list of all windows first, to avoid */
2895     /* unpleasant side-effects, for instance if the callback */
2896     /* function changes the Z-order of the windows.          */
2897
2898     if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2899
2900     /* Now call the callback function for every window */
2901
2902     for (i = 0; list[i]; i++)
2903     {
2904         /* Make sure that the window still exists */
2905         if (!IsWindow( list[i] )) continue;
2906         if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2907     }
2908     HeapFree( GetProcessHeap(), 0, list );
2909     return ret;
2910 }
2911
2912
2913 /**********************************************************************
2914  *              EnumThreadWindows (USER32.@)
2915  */
2916 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2917 {
2918     HWND *list;
2919     int i;
2920
2921     USER_CheckNotLock();
2922
2923     if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2924
2925     /* Now call the callback function for every window */
2926
2927     for (i = 0; list[i]; i++)
2928         if (!func( list[i], lParam )) break;
2929     HeapFree( GetProcessHeap(), 0, list );
2930     return TRUE;
2931 }
2932
2933
2934 /***********************************************************************
2935  *              EnumDesktopWindows   (USER32.@)
2936  */
2937 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2938 {
2939     HWND *list;
2940     int i;
2941
2942     USER_CheckNotLock();
2943
2944     if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2945
2946     for (i = 0; list[i]; i++)
2947         if (!func( list[i], lparam )) break;
2948     HeapFree( GetProcessHeap(), 0, list );
2949     return TRUE;
2950 }
2951
2952
2953 /**********************************************************************
2954  *           WIN_EnumChildWindows
2955  *
2956  * Helper function for EnumChildWindows().
2957  */
2958 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2959 {
2960     HWND *childList;
2961     BOOL ret = FALSE;
2962
2963     for ( ; *list; list++)
2964     {
2965         /* Make sure that the window still exists */
2966         if (!IsWindow( *list )) continue;
2967         /* Build children list first */
2968         childList = WIN_ListChildren( *list );
2969
2970         ret = func( *list, lParam );
2971
2972         if (childList)
2973         {
2974             if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2975             HeapFree( GetProcessHeap(), 0, childList );
2976         }
2977         if (!ret) return FALSE;
2978     }
2979     return TRUE;
2980 }
2981
2982
2983 /**********************************************************************
2984  *              EnumChildWindows (USER32.@)
2985  */
2986 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2987 {
2988     HWND *list;
2989     BOOL ret;
2990
2991     USER_CheckNotLock();
2992
2993     if (!(list = WIN_ListChildren( parent ))) return FALSE;
2994     ret = WIN_EnumChildWindows( list, func, lParam );
2995     HeapFree( GetProcessHeap(), 0, list );
2996     return ret;
2997 }
2998
2999
3000 /*******************************************************************
3001  *              AnyPopup (USER.52)
3002  */
3003 BOOL16 WINAPI AnyPopup16(void)
3004 {
3005     return AnyPopup();
3006 }
3007
3008
3009 /*******************************************************************
3010  *              AnyPopup (USER32.@)
3011  */
3012 BOOL WINAPI AnyPopup(void)
3013 {
3014     int i;
3015     BOOL retvalue;
3016     HWND *list = WIN_ListChildren( GetDesktopWindow() );
3017
3018     if (!list) return FALSE;
3019     for (i = 0; list[i]; i++)
3020     {
3021         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3022     }
3023     retvalue = (list[i] != 0);
3024     HeapFree( GetProcessHeap(), 0, list );
3025     return retvalue;
3026 }
3027
3028
3029 /*******************************************************************
3030  *              FlashWindow (USER32.@)
3031  */
3032 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3033 {
3034     WND *wndPtr;
3035
3036     TRACE("%p\n", hWnd);
3037
3038     if (IsIconic( hWnd ))
3039     {
3040         RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3041
3042         wndPtr = WIN_GetPtr(hWnd);
3043         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3044         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3045         {
3046             wndPtr->flags |= WIN_NCACTIVATED;
3047         }
3048         else
3049         {
3050             wndPtr->flags &= ~WIN_NCACTIVATED;
3051         }
3052         WIN_ReleasePtr( wndPtr );
3053         return TRUE;
3054     }
3055     else
3056     {
3057         WPARAM wparam;
3058
3059         wndPtr = WIN_GetPtr(hWnd);
3060         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3061         hWnd = wndPtr->hwndSelf;  /* make it a full handle */
3062
3063         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3064         else wparam = (hWnd == GetForegroundWindow());
3065
3066         WIN_ReleasePtr( wndPtr );
3067         SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3068         return wparam;
3069     }
3070 }
3071
3072 /*******************************************************************
3073  *              FlashWindowEx (USER32.@)
3074  */
3075 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3076 {
3077     FIXME("%p\n", pfwi);
3078     return TRUE;
3079 }
3080
3081 /*******************************************************************
3082  *              GetWindowContextHelpId (USER32.@)
3083  */
3084 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3085 {
3086     DWORD retval;
3087     WND *wnd = WIN_GetPtr( hwnd );
3088     if (!wnd || wnd == WND_DESKTOP) return 0;
3089     if (wnd == WND_OTHER_PROCESS)
3090     {
3091         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3092         return 0;
3093     }
3094     retval = wnd->helpContext;
3095     WIN_ReleasePtr( wnd );
3096     return retval;
3097 }
3098
3099
3100 /*******************************************************************
3101  *              SetWindowContextHelpId (USER32.@)
3102  */
3103 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3104 {
3105     WND *wnd = WIN_GetPtr( hwnd );
3106     if (!wnd || wnd == WND_DESKTOP) return FALSE;
3107     if (wnd == WND_OTHER_PROCESS)
3108     {
3109         if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3110         return 0;
3111     }
3112     wnd->helpContext = id;
3113     WIN_ReleasePtr( wnd );
3114     return TRUE;
3115 }
3116
3117
3118 /*******************************************************************
3119  *              DragDetect (USER32.@)
3120  */
3121 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3122 {
3123     MSG msg;
3124     RECT rect;
3125     WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3126     WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3127
3128     rect.left = pt.x - wDragWidth;
3129     rect.right = pt.x + wDragWidth;
3130
3131     rect.top = pt.y - wDragHeight;
3132     rect.bottom = pt.y + wDragHeight;
3133
3134     SetCapture(hWnd);
3135
3136     while(1)
3137     {
3138         while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3139         {
3140             if( msg.message == WM_LBUTTONUP )
3141             {
3142                 ReleaseCapture();
3143                 return 0;
3144             }
3145             if( msg.message == WM_MOUSEMOVE )
3146             {
3147                 POINT tmp;
3148                 tmp.x = (short)LOWORD(msg.lParam);
3149                 tmp.y = (short)HIWORD(msg.lParam);
3150                 if( !PtInRect( &rect, tmp ))
3151                 {
3152                     ReleaseCapture();
3153                     return 1;
3154                 }
3155             }
3156         }
3157         WaitMessage();
3158     }
3159     return 0;
3160 }
3161
3162 /******************************************************************************
3163  *              GetWindowModuleFileNameA (USER32.@)
3164  */
3165 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3166 {
3167     FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3168           hwnd, lpszFileName, cchFileNameMax);
3169     return 0;
3170 }
3171
3172 /******************************************************************************
3173  *              GetWindowModuleFileNameW (USER32.@)
3174  */
3175 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3176 {
3177     FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3178           hwnd, lpszFileName, cchFileNameMax);
3179     return 0;
3180 }
3181
3182 /******************************************************************************
3183  *              GetWindowInfo (USER32.@)
3184  *
3185  * Note: tests show that Windows doesn't check cbSize of the structure.
3186  */
3187 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3188 {
3189     if (!pwi) return FALSE;
3190     if (!IsWindow(hwnd)) return FALSE;
3191
3192     GetWindowRect(hwnd, &pwi->rcWindow);
3193     GetClientRect(hwnd, &pwi->rcClient);
3194     /* translate to screen coordinates */
3195     MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3196
3197     pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3198     pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3199     pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3200
3201     pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3202     pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3203
3204     pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3205     pwi->wCreatorVersion = 0x0400;
3206
3207     return TRUE;
3208 }
3209
3210 /******************************************************************************
3211  *              SwitchDesktop (USER32.@)
3212  *
3213  * NOTES: Sets the current input or interactive desktop.
3214  */
3215 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3216 {
3217     FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3218     return TRUE;
3219 }
3220
3221 /*****************************************************************************
3222  *              SetLayeredWindowAttributes (USER32.@)
3223  */
3224 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey, 
3225                                         BYTE bAlpha, DWORD dwFlags )
3226 {
3227     FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3228     return TRUE;
3229 }
3230
3231 /*****************************************************************************
3232  *              GetLayeredWindowAttributes (USER32.@)
3233  */
3234 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3235                                         BYTE *pbAlpha, DWORD *pdwFlags )
3236 {
3237     FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3238     return FALSE;
3239 }
3240
3241 /*****************************************************************************
3242  *              UpdateLayeredWindow (USER32.@)
3243  */
3244 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3245                                  HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3246                                  DWORD dwFlags)
3247 {
3248     static int once;
3249     if (!once)
3250     {
3251         once = 1;
3252         FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3253               hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3254     }
3255     return 0;
3256 }
3257
3258 /* 64bit versions */
3259
3260 #ifdef GetWindowLongPtrW
3261 #undef GetWindowLongPtrW
3262 #endif
3263
3264 #ifdef GetWindowLongPtrA
3265 #undef GetWindowLongPtrA
3266 #endif
3267
3268 #ifdef SetWindowLongPtrW
3269 #undef SetWindowLongPtrW
3270 #endif
3271
3272 #ifdef SetWindowLongPtrA
3273 #undef SetWindowLongPtrA
3274 #endif
3275
3276 /*****************************************************************************
3277  *              GetWindowLongPtrW (USER32.@)
3278  */
3279 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3280 {
3281     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3282 }
3283
3284 /*****************************************************************************
3285  *              GetWindowLongPtrA (USER32.@)
3286  */
3287 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3288 {
3289     return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3290 }
3291
3292 /*****************************************************************************
3293  *              SetWindowLongPtrW (USER32.@)
3294  */
3295 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3296 {
3297     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3298 }
3299
3300 /*****************************************************************************
3301  *              SetWindowLongPtrA (USER32.@)
3302  */
3303 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3304 {
3305     return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );
3306 }