-Fixed MESSAGE functions that were thunking down to 16 bits implementation.
[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( wndPtr );
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     TRACE(win,"EnableWindow32: ( %x, %d )\n", hwnd, enable);
1326    
1327     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1328     if (enable && (wndPtr->dwStyle & WS_DISABLED))
1329     {
1330           /* Enable window */
1331         wndPtr->dwStyle &= ~WS_DISABLED;
1332         SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1333         return TRUE;
1334     }
1335     else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1336     {
1337           /* Disable window */
1338         wndPtr->dwStyle |= WS_DISABLED;
1339         if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1340         {
1341             SetFocus32( 0 );  /* A disabled window can't have the focus */
1342         }
1343         if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1344         {
1345             ReleaseCapture();  /* A disabled window can't capture the mouse */
1346         }
1347         SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1348         return FALSE;
1349     }
1350     return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1351 }
1352
1353
1354 /***********************************************************************
1355  *           IsWindowEnabled16   (USER.35)
1356  */ 
1357 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1358 {
1359     return IsWindowEnabled32(hWnd);
1360 }
1361
1362
1363 /***********************************************************************
1364  *           IsWindowEnabled32   (USER32.349)
1365  */ 
1366 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1367 {
1368     WND * wndPtr; 
1369
1370     if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1371     return !(wndPtr->dwStyle & WS_DISABLED);
1372 }
1373
1374
1375 /***********************************************************************
1376  *           IsWindowUnicode   (USER32.350)
1377  */
1378 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1379 {
1380     WND * wndPtr; 
1381
1382     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1383     return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1384 }
1385
1386
1387 /**********************************************************************
1388  *           GetWindowWord16    (USER.133)
1389  */
1390 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1391 {
1392     return GetWindowWord32( hwnd, offset );
1393 }
1394
1395
1396 /**********************************************************************
1397  *           GetWindowWord32    (USER32.314)
1398  */
1399 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1400 {
1401     WND * wndPtr = WIN_FindWndPtr( hwnd );
1402     if (!wndPtr) return 0;
1403     if (offset >= 0)
1404     {
1405         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1406         {
1407             WARN( win, "Invalid offset %d\n", offset );
1408             return 0;
1409         }
1410         return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1411     }
1412     switch(offset)
1413     {
1414     case GWW_ID:         
1415         if (HIWORD(wndPtr->wIDmenu))
1416                 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1417                     wndPtr->wIDmenu);
1418         return (WORD)wndPtr->wIDmenu;
1419     case GWW_HWNDPARENT: 
1420         return wndPtr->parent ?
1421                 wndPtr->parent->hwndSelf : (
1422                         wndPtr->owner ?
1423                          wndPtr->owner->hwndSelf : 
1424                          0);
1425     case GWW_HINSTANCE:  
1426         if (HIWORD(wndPtr->hInstance))
1427                 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1428                     wndPtr->hInstance);
1429         return (WORD)wndPtr->hInstance;
1430     default:
1431         WARN( win, "Invalid offset %d\n", offset );
1432         return 0;
1433     }
1434 }
1435
1436
1437 /**********************************************************************
1438  *           WIN_GetWindowInstance
1439  */
1440 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1441 {
1442     WND * wndPtr = WIN_FindWndPtr( hwnd );
1443     if (!wndPtr) return (HINSTANCE32)0;
1444     return wndPtr->hInstance;
1445 }
1446
1447
1448 /**********************************************************************
1449  *           SetWindowWord16    (USER.134)
1450  */
1451 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1452 {
1453     return SetWindowWord32( hwnd, offset, newval );
1454 }
1455
1456
1457 /**********************************************************************
1458  *           SetWindowWord32    (USER32.524)
1459  */
1460 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1461 {
1462     WORD *ptr, retval;
1463     WND * wndPtr = WIN_FindWndPtr( hwnd );
1464     if (!wndPtr) return 0;
1465     if (offset >= 0)
1466     {
1467         if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1468         {
1469             WARN( win, "Invalid offset %d\n", offset );
1470             return 0;
1471         }
1472         ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1473     }
1474     else switch(offset)
1475     {
1476         case GWW_ID:        ptr = (WORD *)&wndPtr->wIDmenu; break;
1477         case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1478         case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1479         default:
1480             WARN( win, "Invalid offset %d\n", offset );
1481             return 0;
1482     }
1483     retval = *ptr;
1484     *ptr = newval;
1485     return retval;
1486 }
1487
1488
1489 /**********************************************************************
1490  *           WIN_GetWindowLong
1491  *
1492  * Helper function for GetWindowLong().
1493  */
1494 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1495 {
1496     LONG retval;
1497     WND * wndPtr = WIN_FindWndPtr( hwnd );
1498     if (!wndPtr) return 0;
1499     if (offset >= 0)
1500     {
1501         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1502         {
1503             WARN( win, "Invalid offset %d\n", offset );
1504             return 0;
1505         }
1506         retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1507         /* Special case for dialog window procedure */
1508         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1509             return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1510         return retval;
1511     }
1512     switch(offset)
1513     {
1514         case GWL_USERDATA:   return wndPtr->userdata;
1515         case GWL_STYLE:      return wndPtr->dwStyle;
1516         case GWL_EXSTYLE:    return wndPtr->dwExStyle;
1517         case GWL_ID:         return (LONG)wndPtr->wIDmenu;
1518         case GWL_WNDPROC:    return (LONG)WINPROC_GetProc( wndPtr->winproc,
1519                                                            type );
1520         case GWL_HWNDPARENT: return wndPtr->parent ?
1521                                         (HWND32)wndPtr->parent->hwndSelf : 0;
1522         case GWL_HINSTANCE:  return wndPtr->hInstance;
1523         default:
1524             WARN( win, "Unknown offset %d\n", offset );
1525     }
1526     return 0;
1527 }
1528
1529
1530 /**********************************************************************
1531  *           WIN_SetWindowLong
1532  *
1533  * Helper function for SetWindowLong().
1534  *
1535  * 0 is the failure code. However, in the case of failure SetLastError
1536  * must be set to distinguish between a 0 return value and a failure.
1537  *
1538  * FIXME: The error values for SetLastError may not be right. Can
1539  *        someone check with the real thing?
1540  */
1541 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1542                                WINDOWPROCTYPE type )
1543 {
1544     LONG *ptr, retval;
1545     WND * wndPtr = WIN_FindWndPtr( hwnd );
1546     STYLESTRUCT style;
1547     
1548     TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1549
1550     if (!wndPtr)
1551     {
1552        /* Is this the right error? */
1553        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1554        return 0;
1555     }
1556
1557     if (offset >= 0)
1558     {
1559         if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1560         {
1561             WARN( win, "Invalid offset %d\n", offset );
1562
1563             /* Is this the right error? */
1564             SetLastError( ERROR_OUTOFMEMORY );
1565
1566             return 0;
1567         }
1568         ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1569         /* Special case for dialog window procedure */
1570         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1571         {
1572             retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1573             WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, 
1574                              type, WIN_PROC_WINDOW );
1575             return retval;
1576         }
1577     }
1578     else switch(offset)
1579     {
1580         case GWL_ID:
1581                 ptr = (DWORD*)&wndPtr->wIDmenu;
1582                 break;
1583         case GWL_HINSTANCE:
1584                 return SetWindowWord32( hwnd, offset, newval );
1585         case GWL_WNDPROC:
1586                                         retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1587                 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, 
1588                                                 type, WIN_PROC_WINDOW );
1589                 return retval;
1590         case GWL_STYLE:
1591                 style.styleOld = wndPtr->dwStyle;
1592                 newval &= ~(WS_VISIBLE | WS_CHILD);     /* Some bits can't be changed this way */
1593                 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1594
1595                 if (wndPtr->flags & WIN_ISWIN32)
1596                         SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1597                 wndPtr->dwStyle = style.styleNew;
1598                 if (wndPtr->flags & WIN_ISWIN32)
1599                         SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1600                 return style.styleOld;
1601                     
1602         case GWL_USERDATA: 
1603                 ptr = &wndPtr->userdata; 
1604                 break;
1605         case GWL_EXSTYLE:  
1606                 style.styleOld = wndPtr->dwExStyle;
1607                 style.styleNew = newval;
1608                 if (wndPtr->flags & WIN_ISWIN32)
1609                         SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1610                 wndPtr->dwExStyle = newval;
1611                 if (wndPtr->flags & WIN_ISWIN32)
1612                         SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1613                 return style.styleOld;
1614
1615         default:
1616             WARN( win, "Invalid offset %d\n", offset );
1617
1618             /* Don't think this is right error but it should do */
1619             SetLastError( ERROR_OUTOFMEMORY );
1620
1621             return 0;
1622     }
1623     retval = *ptr;
1624     *ptr = newval;
1625     return retval;
1626 }
1627
1628
1629 /**********************************************************************
1630  *           GetWindowLong16    (USER.135)
1631  */
1632 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1633 {
1634     return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1635 }
1636
1637
1638 /**********************************************************************
1639  *           GetWindowLong32A    (USER32.305)
1640  */
1641 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1642 {
1643     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1644 }
1645
1646
1647 /**********************************************************************
1648  *           GetWindowLong32W    (USER32.306)
1649  */
1650 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1651 {
1652     return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1653 }
1654
1655
1656 /**********************************************************************
1657  *           SetWindowLong16    (USER.136)
1658  */
1659 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1660 {
1661     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1662 }
1663
1664
1665 /**********************************************************************
1666  *           SetWindowLong32A    (USER32.517)
1667  */
1668 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1669 {
1670     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1671 }
1672
1673
1674 /**********************************************************************
1675  *           SetWindowLong32W    (USER32.518) Set window attribute
1676  *
1677  * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1678  * value in a window's extra memory. 
1679  *
1680  * The _hwnd_ parameter specifies the window.  is the handle to a
1681  * window that has extra memory. The _newval_ parameter contains the
1682  * new attribute or extra memory value.  If positive, the _offset_
1683  * parameter is the byte-addressed location in the window's extra
1684  * memory to set.  If negative, _offset_ specifies the window
1685  * attribute to set, and should be one of the following values:
1686  *
1687  * GWL_EXSTYLE      The window's extended window style
1688  *
1689  * GWL_STYLE        The window's window style. 
1690  *
1691  * GWL_WNDPROC      Pointer to the window's window procedure. 
1692  *
1693  * GWL_HINSTANCE    The window's pplication instance handle.
1694  *
1695  * GWL_ID           The window's identifier.
1696  *
1697  * GWL_USERDATA     The window's user-specified data. 
1698  *
1699  * If the window is a dialog box, the _offset_ parameter can be one of 
1700  * the following values:
1701  *
1702  * DWL_DLGPROC      The address of the window's dialog box procedure.
1703  *
1704  * DWL_MSGRESULT    The return value of a message 
1705  *                  that the dialog box procedure processed.
1706  *
1707  * DWL_USER         Application specific information.
1708  *
1709  * RETURNS
1710  *
1711  * If successful, returns the previous value located at _offset_. Otherwise,
1712  * returns 0.
1713  *
1714  * NOTES
1715  *
1716  * Extra memory for a window class is specified by a nonzero cbWndExtra 
1717  * parameter of the WNDCLASS structure passed to RegisterClass() at the
1718  * time of class creation.
1719  *  
1720  * Using GWL_WNDPROC to set a new window procedure effectively creates
1721  * a window subclass. Use CallWindowProc() in the new windows procedure
1722  * to pass messages to the superclass's window procedure.
1723  *
1724  * The user data is reserved for use by the application which created
1725  * the window.
1726  *
1727  * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1728  * instead, call the EnableWindow() function to change the window's
1729  * disabled state.
1730  *
1731  * Do not use GWL_HWNDPARENT to reset the window's parent, use
1732  * SetParent() instead.
1733  *
1734  * Win95:
1735  * When offset is GWL_STYLE and the calling app's ver is 4.0,
1736  * it sends WM_STYLECHANGING before changing the settings
1737  * and WM_STYLECHANGED afterwards.
1738  * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1739  *
1740  * BUGS
1741  *
1742  * GWL_STYLE does not dispatch WM_STYLE... messages.
1743  *
1744  * CONFORMANCE
1745  *
1746  * ECMA-234, Win32 
1747  *
1748  */
1749 LONG WINAPI SetWindowLong32W( 
1750     HWND32 hwnd, /* window to alter */
1751     INT32 offset, /* offset, in bytes, of location to alter */
1752     LONG newval  /* new value of location */
1753 ) {
1754     return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1755 }
1756
1757
1758 /*******************************************************************
1759  *           GetWindowText16    (USER.36)
1760  */
1761 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1762 {
1763     return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1764 }
1765
1766
1767 /*******************************************************************
1768  *           GetWindowText32A    (USER32.309)
1769  */
1770 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1771 {
1772     return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1773                                   (LPARAM)lpString );
1774 }
1775
1776 /*******************************************************************
1777  *           InternalGetWindowText    (USER32.326)
1778  */
1779 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1780 {
1781     FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1782     return GetWindowText32W(hwnd,lpString,nMaxCount);
1783 }
1784
1785
1786 /*******************************************************************
1787  *           GetWindowText32W    (USER32.312)
1788  */
1789 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1790 {
1791     return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1792                                   (LPARAM)lpString );
1793 }
1794
1795
1796 /*******************************************************************
1797  *           SetWindowText16    (USER.37)
1798  */
1799 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1800 {
1801     return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1802 }
1803
1804
1805 /*******************************************************************
1806  *           SetWindowText32A    (USER32.521)
1807  */
1808 BOOL32 WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1809 {
1810     return (BOOL32)SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1811 }
1812
1813
1814 /*******************************************************************
1815  *           SetWindowText32W    (USER32.523)
1816  */
1817 BOOL32 WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1818 {
1819     return (BOOL32)SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1820 }
1821
1822
1823 /*******************************************************************
1824  *         GetWindowTextLength16    (USER.38)
1825  */
1826 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1827 {
1828     return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1829 }
1830
1831
1832 /*******************************************************************
1833  *         GetWindowTextLength32A   (USER32.310)
1834  */
1835 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1836 {
1837     return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1838 }
1839
1840 /*******************************************************************
1841  *         GetWindowTextLength32W   (USER32.311)
1842  */
1843 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1844 {
1845     return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1846 }
1847
1848
1849 /*******************************************************************
1850  *         IsWindow16   (USER.47)
1851  */
1852 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1853 {
1854     return IsWindow32( hwnd );
1855 }
1856
1857 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1858 {
1859     WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1860     HWND16 hwnd = (HWND16)stack[2];
1861
1862     AX_reg(context) = IsWindow32( hwnd );
1863     ES_reg(context) = USER_HeapSel;
1864 }
1865
1866
1867 /*******************************************************************
1868  *         IsWindow32   (USER32.348)
1869  */
1870 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1871 {
1872     WND * wndPtr = WIN_FindWndPtr( hwnd );
1873     return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1874 }
1875
1876
1877 /*****************************************************************
1878  *         GetParent16   (USER.46)
1879  */
1880 HWND16 WINAPI GetParent16( HWND16 hwnd )
1881 {
1882     return (HWND16)GetParent32( hwnd );
1883 }
1884
1885
1886 /*****************************************************************
1887  *         GetParent32   (USER32.278)
1888  */
1889 HWND32 WINAPI GetParent32( HWND32 hwnd )
1890 {
1891     WND *wndPtr = WIN_FindWndPtr(hwnd);
1892     if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1893     wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1894     return wndPtr ? wndPtr->hwndSelf : 0;
1895 }
1896
1897 /*****************************************************************
1898  *         WIN_GetTopParent
1899  *
1900  * Get the top-level parent for a child window.
1901  */
1902 WND* WIN_GetTopParentPtr( WND* pWnd )
1903 {
1904     while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1905     return pWnd;
1906 }
1907
1908 /*****************************************************************
1909  *         WIN_GetTopParent
1910  *
1911  * Get the top-level parent for a child window.
1912  */
1913 HWND32 WIN_GetTopParent( HWND32 hwnd )
1914 {
1915     WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1916     return wndPtr ? wndPtr->hwndSelf : 0;
1917 }
1918
1919
1920 /*****************************************************************
1921  *         SetParent16   (USER.233)
1922  */
1923 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1924 {
1925     return SetParent32( hwndChild, hwndNewParent );
1926 }
1927
1928
1929 /*****************************************************************
1930  *         SetParent32   (USER32.495)
1931  */
1932 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1933 {
1934   WND *wndPtr = WIN_FindWndPtr( hwndChild );
1935   WND *pWndNewParent = 
1936     (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent ) : pWndDesktop;
1937   WND *pWndOldParent =
1938     (wndPtr)?(*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent):NULL;
1939
1940   /* SetParent32 additionally needs to make hwndChild the topmost window
1941      in the x-order and send the expected WM_WINDOWPOSCHANGING and
1942      WM_WINDOWPOSCHANGED notification messages. 
1943   */
1944   SetWindowPos32( hwndChild, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1945                               
1946   return pWndOldParent?pWndOldParent->hwndSelf:0;
1947 }
1948
1949 /*******************************************************************
1950  *         IsChild16    (USER.48)
1951  */
1952 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1953 {
1954     return IsChild32(parent,child);
1955 }
1956
1957
1958 /*******************************************************************
1959  *         IsChild32    (USER32.339)
1960  */
1961 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
1962 {
1963     WND * wndPtr = WIN_FindWndPtr( child );
1964     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1965     {
1966         wndPtr = wndPtr->parent;
1967         if (wndPtr->hwndSelf == parent) return TRUE;
1968     }
1969     return FALSE;
1970 }
1971
1972
1973 /***********************************************************************
1974  *           IsWindowVisible16   (USER.49)
1975  */
1976 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
1977 {
1978     return IsWindowVisible32(hwnd);
1979 }
1980
1981
1982 /***********************************************************************
1983  *           IsWindowVisible32   (USER32.351)
1984  */
1985 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
1986 {
1987     WND *wndPtr = WIN_FindWndPtr( hwnd );
1988     while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1989     {
1990         if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1991         wndPtr = wndPtr->parent;
1992     }
1993     return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1994 }
1995
1996
1997 /***********************************************************************
1998  *           WIN_IsWindowDrawable
1999  *
2000  * hwnd is drawable when it is visible, all parents are not
2001  * minimized, and it is itself not minimized unless we are
2002  * trying to draw its default class icon.
2003  */
2004 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2005 {
2006   if( (wnd->dwStyle & WS_MINIMIZE &&
2007        icon && wnd->class->hIcon) ||
2008      !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2009   for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2010     if( wnd->dwStyle & WS_MINIMIZE ||
2011       !(wnd->dwStyle & WS_VISIBLE) ) break;
2012   return (wnd == NULL);
2013 }
2014
2015
2016 /*******************************************************************
2017  *         GetTopWindow16    (USER.229)
2018  */
2019 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2020 {
2021     return GetTopWindow32(hwnd);
2022 }
2023
2024
2025 /*******************************************************************
2026  *         GetTopWindow32    (USER.229)
2027  */
2028 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2029 {
2030     WND * wndPtr = WIN_FindWndPtr( hwnd );
2031     if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2032     else return 0;
2033 }
2034
2035
2036 /*******************************************************************
2037  *         GetWindow16    (USER.262)
2038  */
2039 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2040 {
2041     return GetWindow32( hwnd,rel );
2042 }
2043
2044
2045 /*******************************************************************
2046  *         GetWindow32    (USER32.302)
2047  */
2048 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2049 {
2050     WND * wndPtr = WIN_FindWndPtr( hwnd );
2051     if (!wndPtr) return 0;
2052     switch(rel)
2053     {
2054     case GW_HWNDFIRST:
2055         if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2056         else return 0;
2057         
2058     case GW_HWNDLAST:
2059         if (!wndPtr->parent) return 0;  /* Desktop window */
2060         while (wndPtr->next) wndPtr = wndPtr->next;
2061         return wndPtr->hwndSelf;
2062         
2063     case GW_HWNDNEXT:
2064         if (!wndPtr->next) return 0;
2065         return wndPtr->next->hwndSelf;
2066         
2067     case GW_HWNDPREV:
2068         if (!wndPtr->parent) return 0;  /* Desktop window */
2069         wndPtr = wndPtr->parent->child;  /* First sibling */
2070         if (wndPtr->hwndSelf == hwnd) return 0;  /* First in list */
2071         while (wndPtr->next)
2072         {
2073             if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2074             wndPtr = wndPtr->next;
2075         }
2076         return 0;
2077         
2078     case GW_OWNER:
2079         return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2080
2081     case GW_CHILD:
2082         return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2083     }
2084     return 0;
2085 }
2086
2087
2088 /*******************************************************************
2089  *         GetNextWindow16    (USER.230)
2090  */
2091 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2092 {
2093     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2094     return GetWindow16( hwnd, flag );
2095 }
2096
2097 /*******************************************************************
2098  *         ShowOwnedPopups16  (USER.265)
2099  */
2100 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2101 {
2102     ShowOwnedPopups32( owner, fShow );
2103 }
2104
2105
2106 /*******************************************************************
2107  *         ShowOwnedPopups32  (USER32.531)
2108  */
2109 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2110 {
2111     WND *pWnd = pWndDesktop->child;
2112     while (pWnd)
2113     {
2114         if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2115             (pWnd->dwStyle & WS_POPUP))
2116             ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2117         pWnd = pWnd->next;
2118     }
2119     return TRUE;
2120 }
2121
2122
2123 /*******************************************************************
2124  *         GetLastActivePopup16   (USER.287)
2125  */
2126 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2127 {
2128     return GetLastActivePopup32( hwnd );
2129 }
2130
2131 /*******************************************************************
2132  *         GetLastActivePopup32   (USER32.256)
2133  */
2134 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2135 {
2136     WND *wndPtr;
2137     wndPtr = WIN_FindWndPtr(hwnd);
2138     if (wndPtr == NULL) return hwnd;
2139     return wndPtr->hwndLastActive;
2140 }
2141
2142
2143 /*******************************************************************
2144  *           WIN_BuildWinArray
2145  *
2146  * Build an array of pointers to the children of a given window.
2147  * The array must be freed with HeapFree(SystemHeap). Return NULL
2148  * when no windows are found.
2149  */
2150 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2151 {
2152     WND **list, **ppWnd;
2153     WND *pWnd;
2154     UINT32 count, skipOwned, skipHidden;
2155     DWORD skipFlags;
2156
2157     skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2158     skipOwned = bwaFlags & BWA_SKIPOWNED;
2159     skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2160     if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2161
2162     /* First count the windows */
2163
2164     if (!wndPtr) wndPtr = pWndDesktop;
2165     for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) 
2166     {
2167         if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2168         if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2169     }
2170
2171     if( count )
2172     {
2173         /* Now build the list of all windows */
2174
2175         if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2176         {
2177             for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2178             {
2179                 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2180                 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2181                 {
2182                    *ppWnd++ = pWnd;
2183                     count++;
2184                 }
2185             }
2186            *ppWnd = NULL;
2187         }
2188         else count = 0;
2189     } else list = NULL;
2190
2191     if( pTotal ) *pTotal = count;
2192     return list;
2193 }
2194
2195
2196 /*******************************************************************
2197  *           EnumWindows16   (USER.54)
2198  */
2199 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2200 {
2201     WND **list, **ppWnd;
2202
2203     /* We have to build a list of all windows first, to avoid */
2204     /* unpleasant side-effects, for instance if the callback  */
2205     /* function changes the Z-order of the windows.           */
2206
2207     if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2208
2209     /* Now call the callback function for every window */
2210
2211     for (ppWnd = list; *ppWnd; ppWnd++)
2212     {
2213         /* Make sure that the window still exists */
2214         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2215         if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2216     }
2217     HeapFree( SystemHeap, 0, list );
2218     return TRUE;
2219 }
2220
2221
2222 /*******************************************************************
2223  *           EnumWindows32   (USER32.193)
2224  */
2225 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2226 {
2227     return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2228 }
2229
2230
2231 /**********************************************************************
2232  *           EnumTaskWindows16   (USER.225)
2233  */
2234 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2235                                  LPARAM lParam )
2236 {
2237     WND **list, **ppWnd;
2238
2239     /* This function is the same as EnumWindows(),    */
2240     /* except for an added check on the window's task. */
2241
2242     if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2243
2244     /* Now call the callback function for every window */
2245
2246     for (ppWnd = list; *ppWnd; ppWnd++)
2247     {
2248         /* Make sure that the window still exists */
2249         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2250         if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2251         if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2252     }
2253     HeapFree( SystemHeap, 0, list );
2254     return TRUE;
2255 }
2256
2257
2258 /**********************************************************************
2259  *           EnumThreadWindows   (USER32.190)
2260  */
2261 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2262 {
2263     THDB        *tdb = THREAD_ID_TO_THDB(id);
2264
2265     return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2266 }
2267
2268
2269 /**********************************************************************
2270  *           WIN_EnumChildWindows
2271  *
2272  * Helper function for EnumChildWindows().
2273  */
2274 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2275                                     LPARAM lParam )
2276 {
2277     WND **childList;
2278     BOOL16 ret = FALSE;
2279
2280     for ( ; *ppWnd; ppWnd++)
2281     {
2282         /* Make sure that the window still exists */
2283         if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2284         /* Build children list first */
2285         childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2286         ret = func( (*ppWnd)->hwndSelf, lParam );
2287         if (childList)
2288         {
2289             if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2290             HeapFree( SystemHeap, 0, childList );
2291         }
2292         if (!ret) return FALSE;
2293     }
2294     return TRUE;
2295 }
2296
2297
2298 /**********************************************************************
2299  *           EnumChildWindows16   (USER.55)
2300  */
2301 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2302                                   LPARAM lParam )
2303 {
2304     WND **list, *pParent;
2305
2306     if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2307     if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2308     WIN_EnumChildWindows( list, func, lParam );
2309     HeapFree( SystemHeap, 0, list );
2310     return TRUE;
2311 }
2312
2313
2314 /**********************************************************************
2315  *           EnumChildWindows32   (USER32.178)
2316  */
2317 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2318                                   LPARAM lParam )
2319 {
2320     return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2321                                        lParam );
2322 }
2323
2324
2325 /*******************************************************************
2326  *           AnyPopup16   (USER.52)
2327  */
2328 BOOL16 WINAPI AnyPopup16(void)
2329 {
2330     return AnyPopup32();
2331 }
2332
2333
2334 /*******************************************************************
2335  *           AnyPopup32   (USER32.4)
2336  */
2337 BOOL32 WINAPI AnyPopup32(void)
2338 {
2339     WND *wndPtr;
2340     for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2341         if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2342     return FALSE;
2343 }
2344
2345
2346 /*******************************************************************
2347  *            FlashWindow16   (USER.105)
2348  */
2349 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2350 {
2351     return FlashWindow32( hWnd, bInvert );
2352 }
2353
2354
2355 /*******************************************************************
2356  *            FlashWindow32   (USER32.202)
2357  */
2358 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2359 {
2360     WND *wndPtr = WIN_FindWndPtr(hWnd);
2361
2362     TRACE(win,"%04x\n", hWnd);
2363
2364     if (!wndPtr) return FALSE;
2365
2366     if (wndPtr->dwStyle & WS_MINIMIZE)
2367     {
2368         if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2369         {
2370             HDC32 hDC = GetDC32(hWnd);
2371             
2372             if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2373                 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2374             
2375             ReleaseDC32( hWnd, hDC );
2376             wndPtr->flags |= WIN_NCACTIVATED;
2377         }
2378         else
2379         {
2380             PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2381                                           RDW_UPDATENOW | RDW_FRAME, 0 );
2382             wndPtr->flags &= ~WIN_NCACTIVATED;
2383         }
2384         return TRUE;
2385     }
2386     else
2387     {
2388         WPARAM16 wparam;
2389         if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2390         else wparam = (hWnd == GetActiveWindow32());
2391
2392         SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2393         return wparam;
2394     }
2395 }
2396
2397
2398 /*******************************************************************
2399  *           SetSysModalWindow16   (USER.188)
2400  */
2401 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2402 {
2403     HWND32 hWndOldModal = hwndSysModal;
2404     hwndSysModal = hWnd;
2405     FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2406     return hWndOldModal;
2407 }
2408
2409
2410 /*******************************************************************
2411  *           GetSysModalWindow16   (USER.52)
2412  */
2413 HWND16 WINAPI GetSysModalWindow16(void)
2414 {
2415     return hwndSysModal;
2416 }
2417
2418
2419 /*******************************************************************
2420  *           GetWindowContextHelpId   (USER32.303)
2421  */
2422 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2423 {
2424     WND *wnd = WIN_FindWndPtr( hwnd );
2425     if (!wnd) return 0;
2426     return wnd->helpContext;
2427 }
2428
2429
2430 /*******************************************************************
2431  *           SetWindowContextHelpId   (USER32.515)
2432  */
2433 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2434 {
2435     WND *wnd = WIN_FindWndPtr( hwnd );
2436     if (!wnd) return FALSE;
2437     wnd->helpContext = id;
2438     return TRUE;
2439 }
2440
2441
2442 /*******************************************************************
2443  *                      DRAG_QueryUpdate
2444  *
2445  * recursively find a child that contains spDragInfo->pt point 
2446  * and send WM_QUERYDROPOBJECT
2447  */
2448 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2449 {
2450  BOOL16         wParam,bResult = 0;
2451  POINT32        pt;
2452  LPDRAGINFO     ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2453  WND           *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2454  RECT32         tempRect;
2455
2456  if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2457
2458  CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2459
2460  GetWindowRect32(hQueryWnd,&tempRect); 
2461
2462  if( !PtInRect32(&tempRect,pt) ||
2463      (ptrQueryWnd->dwStyle & WS_DISABLED) )
2464         return 0;
2465
2466  if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) ) 
2467    {
2468      tempRect = ptrQueryWnd->rectClient;
2469      if(ptrQueryWnd->dwStyle & WS_CHILD)
2470         MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2471                            (LPPOINT32)&tempRect, 2 );
2472
2473      if (PtInRect32( &tempRect, pt))
2474         {
2475          wParam = 0;
2476          
2477          for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2478              if( ptrWnd->dwStyle & WS_VISIBLE )
2479              {
2480                  GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2481                  if (PtInRect32( &tempRect, pt )) break;
2482              }
2483
2484          if(ptrWnd)
2485          {
2486             TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2487                         ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2488                         ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2489             if( !(ptrWnd->dwStyle & WS_DISABLED) )
2490                 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2491          }
2492
2493          if(bResult) return bResult;
2494         }
2495      else wParam = 1;
2496    }
2497  else wParam = 1;
2498
2499  ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2500
2501  ptrDragInfo->hScope = hQueryWnd;
2502
2503  bResult = ( bNoSend ) 
2504            ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2505            : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2506                           (WPARAM16)wParam ,(LPARAM) spDragInfo );
2507  if( !bResult ) 
2508      CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2509
2510  return bResult;
2511 }
2512
2513
2514 /*******************************************************************
2515  *             DragDetect   (USER.465)
2516  */
2517 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2518 {
2519     POINT32 pt32;
2520     CONV_POINT16TO32( &pt, &pt32 );
2521     return DragDetect32( hWnd, pt32 );
2522 }
2523
2524 /*******************************************************************
2525  *             DragDetect32   (USER32.151)
2526  */
2527 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2528 {
2529     MSG16 msg;
2530     RECT16  rect;
2531
2532     rect.left = pt.x - wDragWidth;
2533     rect.right = pt.x + wDragWidth;
2534
2535     rect.top = pt.y - wDragHeight;
2536     rect.bottom = pt.y + wDragHeight;
2537
2538     SetCapture32(hWnd);
2539
2540     while(1)
2541     {
2542         while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2543         {
2544             if( msg.message == WM_LBUTTONUP )
2545             {
2546                 ReleaseCapture();
2547                 return 0;
2548             }
2549             if( msg.message == WM_MOUSEMOVE )
2550             {
2551                 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2552                 {
2553                     ReleaseCapture();
2554                     return 1;
2555                 }
2556             }
2557         }
2558         WaitMessage();
2559     }
2560     return 0;
2561 }
2562
2563 /******************************************************************************
2564  *             DragObject16   (USER.464)
2565  */
2566 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2567                            HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2568 {
2569     MSG16       msg;
2570     LPDRAGINFO  lpDragInfo;
2571     SEGPTR      spDragInfo;
2572     HCURSOR16   hDragCursor=0, hOldCursor=0, hBummer=0;
2573     HGLOBAL16   hDragInfo  = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2574     WND        *wndPtr = WIN_FindWndPtr(hWnd);
2575     HCURSOR16   hCurrentCursor = 0;
2576     HWND16      hCurrentWnd = 0;
2577
2578     lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2579     spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2580
2581     if( !lpDragInfo || !spDragInfo ) return 0L;
2582
2583     hBummer = LoadCursor16(0, IDC_BUMMER16);
2584
2585     if( !hBummer || !wndPtr )
2586     {
2587         GlobalFree16(hDragInfo);
2588         return 0L;
2589     }
2590
2591     if(hCursor)
2592     {
2593         if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2594         {
2595             GlobalFree16(hDragInfo);
2596             return 0L;
2597         }
2598
2599         if( hDragCursor == hCursor ) hDragCursor = 0;
2600         else hCursor = hDragCursor;
2601
2602         hOldCursor = SetCursor32(hDragCursor);
2603     }
2604
2605     lpDragInfo->hWnd   = hWnd;
2606     lpDragInfo->hScope = 0;
2607     lpDragInfo->wFlags = wObj;
2608     lpDragInfo->hList  = szList; /* near pointer! */
2609     lpDragInfo->hOfStruct = hOfStruct;
2610     lpDragInfo->l = 0L; 
2611
2612     SetCapture32(hWnd);
2613     ShowCursor32( TRUE );
2614
2615     do
2616     {
2617         do{  WaitMessage(); }
2618         while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2619
2620        *(lpDragInfo+1) = *lpDragInfo;
2621
2622         lpDragInfo->pt = msg.pt;
2623
2624         /* update DRAGINFO struct */
2625         TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2626
2627         if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2628             hCurrentCursor = hCursor;
2629         else
2630         {
2631             hCurrentCursor = hBummer;
2632             lpDragInfo->hScope = 0;
2633         }
2634         if( hCurrentCursor )
2635             SetCursor32(hCurrentCursor);
2636
2637         /* send WM_DRAGLOOP */
2638         SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer), 
2639                                           (LPARAM) spDragInfo );
2640         /* send WM_DRAGSELECT or WM_DRAGMOVE */
2641         if( hCurrentWnd != lpDragInfo->hScope )
2642         {
2643             if( hCurrentWnd )
2644                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0, 
2645                        (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2646                                         HIWORD(spDragInfo)) );
2647             hCurrentWnd = lpDragInfo->hScope;
2648             if( hCurrentWnd )
2649                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo); 
2650         }
2651         else
2652             if( hCurrentWnd )
2653                 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2654
2655     } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2656
2657     ReleaseCapture();
2658     ShowCursor32( FALSE );
2659
2660     if( hCursor )
2661     {
2662         SetCursor32( hOldCursor );
2663         if (hDragCursor) DestroyCursor32( hDragCursor );
2664     }
2665
2666     if( hCurrentCursor != hBummer ) 
2667         msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT, 
2668                                    (WPARAM16)hWnd, (LPARAM)spDragInfo );
2669     else
2670         msg.lParam = 0;
2671     GlobalFree16(hDragInfo);
2672
2673     return (DWORD)(msg.lParam);
2674 }