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