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