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