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