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