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