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