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