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