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