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