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