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