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