Abey George (of Macadamian/Corel)
[wine.git] / windows / win.c
blobfb656bc3d5c1a36ddf0b9cbd9e324d57f387fab6
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "monitor.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "process.h"
32 #include "winerror.h"
33 #include "mdi.h"
34 #include "local.h"
35 #include "syslevel.h"
36 #include "stackframe.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(win)
40 DECLARE_DEBUG_CHANNEL(msg)
42 /**********************************************************************/
44 WND_DRIVER *WND_Driver = NULL;
46 /* Desktop window */
47 static WND *pWndDesktop = NULL;
49 static HWND hwndSysModal = 0;
51 static WORD wDragWidth = 4;
52 static WORD wDragHeight= 3;
54 /* thread safeness */
55 static SYSLEVEL WIN_SysLevel;
57 /***********************************************************************
58 * WIN_Init
59 */
60 void WIN_Init( void )
62 /* Initialisation of the critical section for thread safeness */
63 _CreateSysLevel( &WIN_SysLevel, 2 );
66 /***********************************************************************
67 * WIN_LockWnds
69 * Locks access to all WND structures for thread safeness
71 void WIN_LockWnds( void )
73 _EnterSysLevel( &WIN_SysLevel );
76 /***********************************************************************
77 * WIN_UnlockWnds
79 * Unlocks access to all WND structures
81 void WIN_UnlockWnds( void )
83 _LeaveSysLevel( &WIN_SysLevel );
86 /***********************************************************************
87 * WIN_SuspendWndsLock
89 * Suspend the lock on WND structures.
90 * Returns the number of locks suspended
92 int WIN_SuspendWndsLock( void )
94 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
95 int count = isuspendedLocks;
97 while ( count-- > 0 )
98 _LeaveSysLevel( &WIN_SysLevel );
100 return isuspendedLocks;
103 /***********************************************************************
104 * WIN_RestoreWndsLock
106 * Restore the suspended locks on WND structures
108 void WIN_RestoreWndsLock( int ipreviousLocks )
110 while ( ipreviousLocks-- > 0 )
111 _EnterSysLevel( &WIN_SysLevel );
114 /***********************************************************************
115 * WIN_FindWndPtr
117 * Return a pointer to the WND structure corresponding to a HWND.
119 WND * WIN_FindWndPtr( HWND hwnd )
121 WND * ptr;
123 if (!hwnd || HIWORD(hwnd)) goto error2;
124 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
125 /* Lock all WND structures for thread safeness*/
126 WIN_LockWnds();
127 /*and increment destruction monitoring*/
128 ptr->irefCount++;
130 if (ptr->dwMagic != WND_MAGIC) goto error;
131 if (ptr->hwndSelf != hwnd)
133 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
134 goto error;
136 /* returns a locked pointer */
137 return ptr;
138 error:
139 /* Unlock all WND structures for thread safeness*/
140 WIN_UnlockWnds();
141 /* and decrement destruction monitoring value */
142 ptr->irefCount--;
144 error2:
145 if ( hwnd!=0 )
146 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
147 return NULL;
150 /***********************************************************************
151 * WIN_LockWndPtr
153 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
154 * but by initWndPtr;
155 * Returns the locked initialisation pointer
157 WND *WIN_LockWndPtr(WND *initWndPtr)
159 if(!initWndPtr) return 0;
161 /* Lock all WND structures for thread safeness*/
162 WIN_LockWnds();
163 /*and increment destruction monitoring*/
164 initWndPtr->irefCount++;
166 return initWndPtr;
170 /***********************************************************************
171 * WIN_ReleaseWndPtr
173 * Release the pointer to the WND structure.
175 void WIN_ReleaseWndPtr(WND *wndPtr)
177 if(!wndPtr) return;
179 /*Decrement destruction monitoring value*/
180 wndPtr->irefCount--;
181 /* Check if it's time to release the memory*/
182 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
184 /* Release memory */
185 USER_HEAP_FREE( wndPtr->hwndSelf);
186 wndPtr->hwndSelf = 0;
188 else if(wndPtr->irefCount < 0)
190 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
191 ERR("forgot a Lock on %p somewhere\n",wndPtr);
193 /*unlock all WND structures for thread safeness*/
194 WIN_UnlockWnds();
197 /***********************************************************************
198 * WIN_UpdateWndPtr
200 * Updates the value of oldPtr to newPtr.
202 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
204 WND *tmpWnd = NULL;
206 tmpWnd = WIN_LockWndPtr(newPtr);
207 WIN_ReleaseWndPtr(*oldPtr);
208 *oldPtr = tmpWnd;
212 /***********************************************************************
213 * WIN_DumpWindow
215 * Dump the content of a window structure to stderr.
217 void WIN_DumpWindow( HWND hwnd )
219 WND *ptr;
220 char className[80];
221 int i;
223 if (!(ptr = WIN_FindWndPtr( hwnd )))
225 WARN("%04x is not a window handle\n", hwnd );
226 return;
229 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
230 strcpy( className, "#NULL#" );
232 TRACE("Window %04x (%p):\n", hwnd, ptr );
233 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
234 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
235 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
236 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
237 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
238 ptr->next, ptr->child, ptr->parent, ptr->owner,
239 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
240 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
241 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
242 ptr->text ? ptr->text : "",
243 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
244 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
245 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
246 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
248 if (ptr->class->cbWndExtra)
250 DPRINTF( "extra bytes:" );
251 for (i = 0; i < ptr->class->cbWndExtra; i++)
252 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
253 DPRINTF( "\n" );
255 DPRINTF( "\n" );
256 WIN_ReleaseWndPtr(ptr);
260 /***********************************************************************
261 * WIN_WalkWindows
263 * Walk the windows tree and print each window on stderr.
265 void WIN_WalkWindows( HWND hwnd, int indent )
267 WND *ptr;
268 char className[80];
270 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
272 if (!ptr)
274 WARN("Invalid window handle %04x\n", hwnd );
275 return;
278 if (!indent) /* first time around */
279 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
280 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
281 " Text");
283 while (ptr)
285 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
287 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
289 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
290 (DWORD)ptr, ptr->hmemTaskQ, className,
291 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
292 ptr->text?ptr->text:"<null>");
294 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
295 WIN_UpdateWndPtr(&ptr,ptr->next);
301 /***********************************************************************
302 * WIN_UnlinkWindow
304 * Remove a window from the siblings linked list.
306 BOOL WIN_UnlinkWindow( HWND hwnd )
308 WND *wndPtr, **ppWnd;
309 BOOL ret = FALSE;
311 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
312 else if(!wndPtr->parent)
314 WIN_ReleaseWndPtr(wndPtr);
315 return FALSE;
318 ppWnd = &wndPtr->parent->child;
319 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
320 if (*ppWnd)
322 *ppWnd = wndPtr->next;
323 ret = TRUE;
325 WIN_ReleaseWndPtr(wndPtr);
326 return ret;
330 /***********************************************************************
331 * WIN_LinkWindow
333 * Insert a window into the siblings linked list.
334 * The window is inserted after the specified window, which can also
335 * be specified as HWND_TOP or HWND_BOTTOM.
337 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
339 WND *wndPtr, **ppWnd;
341 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
342 else if(!wndPtr->parent)
344 WIN_ReleaseWndPtr(wndPtr);
345 return FALSE;
347 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
349 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
350 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
351 while (*ppWnd) ppWnd = &(*ppWnd)->next;
353 else /* Normal case */
355 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
356 if (!afterPtr)
358 WIN_ReleaseWndPtr(wndPtr);
359 return FALSE;
361 ppWnd = &afterPtr->next;
362 WIN_ReleaseWndPtr(afterPtr);
364 wndPtr->next = *ppWnd;
365 *ppWnd = wndPtr;
366 WIN_ReleaseWndPtr(wndPtr);
367 return TRUE;
371 /***********************************************************************
372 * WIN_FindWinToRepaint
374 * Find a window that needs repaint.
376 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
378 HWND hwndRet;
379 WND *pWnd;
381 /* Note: the desktop window never gets WM_PAINT messages
382 * The real reason why is because Windows DesktopWndProc
383 * does ValidateRgn inside WM_ERASEBKGND handler.
386 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
388 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
390 if (!(pWnd->dwStyle & WS_VISIBLE))
392 TRACE("skipping window %04x\n",
393 pWnd->hwndSelf );
395 else if ((pWnd->hmemTaskQ == hQueue) &&
396 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
397 break;
399 else if (pWnd->child )
400 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
402 WIN_ReleaseWndPtr(pWnd);
403 return hwndRet;
408 if(!pWnd)
410 return 0;
413 hwndRet = pWnd->hwndSelf;
415 /* look among siblings if we got a transparent window */
416 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
417 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
419 WIN_UpdateWndPtr(&pWnd,pWnd->next);
421 if (pWnd)
423 hwndRet = pWnd->hwndSelf;
424 WIN_ReleaseWndPtr(pWnd);
426 TRACE("found %04x\n",hwndRet);
427 return hwndRet;
431 /***********************************************************************
432 * WIN_DestroyWindow
434 * Destroy storage associated to a window. "Internals" p.358
435 * returns a locked wndPtr->next
437 static WND* WIN_DestroyWindow( WND* wndPtr )
439 HWND hwnd = wndPtr->hwndSelf;
440 WND *pWnd;
442 TRACE("%04x\n", wndPtr->hwndSelf );
444 /* free child windows */
445 WIN_LockWndPtr(wndPtr->child);
446 while ((pWnd = wndPtr->child))
448 wndPtr->child = WIN_DestroyWindow( pWnd );
449 WIN_ReleaseWndPtr(pWnd);
453 * Clear the update region to make sure no WM_PAINT messages will be
454 * generated for this window while processing the WM_NCDESTROY.
456 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
458 if (wndPtr->hrgnUpdate > 1)
459 DeleteObject( wndPtr->hrgnUpdate );
461 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
463 wndPtr->hrgnUpdate = 0;
467 * Send the WM_NCDESTROY to the window being destroyed.
469 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
471 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
473 WINPOS_CheckInternalPos( wndPtr );
474 if( hwnd == GetCapture()) ReleaseCapture();
476 /* free resources associated with the window */
478 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
479 PROPERTY_RemoveWindowProps( wndPtr );
481 wndPtr->dwMagic = 0; /* Mark it as invalid */
483 /* toss stale messages from the queue */
485 if( wndPtr->hmemTaskQ )
487 BOOL bPostQuit = FALSE;
488 WPARAM wQuitParam = 0;
489 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
490 QMSG *qmsg;
492 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
494 if( qmsg->msg.message == WM_QUIT )
496 bPostQuit = TRUE;
497 wQuitParam = qmsg->msg.wParam;
499 QUEUE_RemoveMsg(msgQ, qmsg);
502 QUEUE_Unlock(msgQ);
504 /* repost WM_QUIT to make sure this app exits its message loop */
505 if( bPostQuit ) PostQuitMessage(wQuitParam);
506 wndPtr->hmemTaskQ = 0;
509 if (!(wndPtr->dwStyle & WS_CHILD))
510 if (wndPtr->wIDmenu)
512 DestroyMenu( wndPtr->wIDmenu );
513 wndPtr->wIDmenu = 0;
515 if (wndPtr->hSysMenu)
517 DestroyMenu( wndPtr->hSysMenu );
518 wndPtr->hSysMenu = 0;
520 wndPtr->pDriver->pDestroyWindow( wndPtr );
521 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
522 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
523 wndPtr->class->cWindows--;
524 wndPtr->class = NULL;
526 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
528 wndPtr->pDriver->pFinalize(wndPtr);
530 return pWnd;
533 /***********************************************************************
534 * WIN_ResetQueueWindows
536 * Reset the queue of all the children of a given window.
537 * Return TRUE if something was done.
539 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
541 BOOL ret = FALSE;
543 if (hNew) /* Set a new queue */
545 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
547 if (wnd->hmemTaskQ == hQueue)
549 wnd->hmemTaskQ = hNew;
550 ret = TRUE;
552 if (wnd->child)
554 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
558 else /* Queue is being destroyed */
560 while (wnd->child)
562 WND *tmp = WIN_LockWndPtr(wnd->child);
563 WND *tmp2;
564 ret = FALSE;
565 while (tmp)
567 if (tmp->hmemTaskQ == hQueue)
569 DestroyWindow( tmp->hwndSelf );
570 ret = TRUE;
571 break;
573 tmp2 = WIN_LockWndPtr(tmp->child);
574 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
575 ret = TRUE;
576 else
578 WIN_UpdateWndPtr(&tmp,tmp->next);
580 WIN_ReleaseWndPtr(tmp2);
582 WIN_ReleaseWndPtr(tmp);
583 if (!ret) break;
586 return ret;
589 /***********************************************************************
590 * WIN_CreateDesktopWindow
592 * Create the desktop window.
594 BOOL WIN_CreateDesktopWindow(void)
596 CLASS *class;
597 HWND hwndDesktop;
599 TRACE("Creating desktop window\n");
602 if (!ICONTITLE_Init() ||
603 !WINPOS_CreateInternalPosAtom() ||
604 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
605 return FALSE;
607 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
608 if (!hwndDesktop) return FALSE;
609 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
611 pWndDesktop->pDriver = WND_Driver;
612 pWndDesktop->pDriver->pInitialize(pWndDesktop);
614 pWndDesktop->next = NULL;
615 pWndDesktop->child = NULL;
616 pWndDesktop->parent = NULL;
617 pWndDesktop->owner = NULL;
618 pWndDesktop->class = class;
619 pWndDesktop->dwMagic = WND_MAGIC;
620 pWndDesktop->hwndSelf = hwndDesktop;
621 pWndDesktop->hInstance = 0;
622 pWndDesktop->rectWindow.left = 0;
623 pWndDesktop->rectWindow.top = 0;
624 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
625 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
626 pWndDesktop->rectClient = pWndDesktop->rectWindow;
627 pWndDesktop->text = NULL;
628 pWndDesktop->hmemTaskQ = GetFastQueue16();
629 pWndDesktop->hrgnUpdate = 0;
630 pWndDesktop->hwndLastActive = hwndDesktop;
631 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
632 WS_CLIPSIBLINGS;
633 pWndDesktop->dwExStyle = 0;
634 pWndDesktop->dce = NULL;
635 pWndDesktop->pVScroll = NULL;
636 pWndDesktop->pHScroll = NULL;
637 pWndDesktop->pProp = NULL;
638 pWndDesktop->wIDmenu = 0;
639 pWndDesktop->helpContext = 0;
640 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
641 pWndDesktop->hSysMenu = 0;
642 pWndDesktop->userdata = 0;
643 pWndDesktop->winproc = (WNDPROC16)class->winproc;
644 pWndDesktop->irefCount = 0;
646 /* FIXME: How do we know if it should be Unicode or not */
647 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
648 return FALSE;
650 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
651 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
652 return TRUE;
656 /***********************************************************************
657 * WIN_CreateWindowEx
659 * Implementation of CreateWindowEx().
661 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
662 BOOL win32, BOOL unicode )
664 INT sw = SW_SHOW;
665 CLASS *classPtr;
666 WND *wndPtr;
667 HWND retvalue;
668 HWND16 hwnd, hwndLinkAfter;
669 POINT maxSize, maxPos, minTrack, maxTrack;
670 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
672 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
673 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
674 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
675 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
676 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
678 /* Find the parent window */
680 if (cs->hwndParent)
682 /* Make sure parent is valid */
683 if (!IsWindow( cs->hwndParent ))
685 WARN("Bad parent %04x\n", cs->hwndParent );
686 return 0;
688 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
689 WARN("No parent for child window\n" );
690 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
693 /* Find the window class */
694 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
696 WARN("Bad class '%s'\n", cs->lpszClass );
697 return 0;
700 /* Fix the coordinates */
702 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
704 PDB *pdb = PROCESS_Current();
706 /* Never believe Microsoft's documentation... CreateWindowEx doc says
707 * that if an overlapped window is created with WS_VISIBLE style bit
708 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
709 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
710 * reveals that
712 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
713 * 2) it does not ignore the y parameter as the docs claim; instead, it
714 * uses it as second parameter to ShowWindow() unless y is either
715 * CW_USEDEFAULT or CW_USEDEFAULT16.
717 * The fact that we didn't do 2) caused bogus windows pop up when wine
718 * was running apps that were using this obscure feature. Example -
719 * calc.exe that comes with Win98 (only Win98, it's different from
720 * the one that comes with Win95 and NT)
722 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
724 /* We have saved cs->y, now we can trash it */
725 if ( !(cs->style & (WS_CHILD | WS_POPUP))
726 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
728 cs->x = pdb->env_db->startup_info->dwX;
729 cs->y = pdb->env_db->startup_info->dwY;
731 else
733 cs->x = 0;
734 cs->y = 0;
737 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
739 PDB *pdb = PROCESS_Current();
740 if ( !(cs->style & (WS_CHILD | WS_POPUP))
741 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
743 cs->cx = pdb->env_db->startup_info->dwXSize;
744 cs->cy = pdb->env_db->startup_info->dwYSize;
746 else
748 cs->cx = 600; /* FIXME */
749 cs->cy = 400;
753 /* Create the window structure */
755 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
756 - sizeof(wndPtr->wExtra) )))
758 TRACE("out of memory\n" );
759 return 0;
762 /* Fill the window structure */
764 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
765 wndPtr->next = NULL;
766 wndPtr->child = NULL;
768 if ((cs->style & WS_CHILD) && cs->hwndParent)
770 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
771 wndPtr->owner = NULL;
772 WIN_ReleaseWndPtr(wndPtr->parent);
774 else
776 wndPtr->parent = pWndDesktop;
777 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
778 wndPtr->owner = NULL;
779 else
781 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
782 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
783 WIN_ReleaseWndPtr(wndPtr->owner);
784 WIN_ReleaseWndPtr(tmpWnd);
789 wndPtr->pDriver = wndPtr->parent->pDriver;
790 wndPtr->pDriver->pInitialize(wndPtr);
792 wndPtr->class = classPtr;
793 wndPtr->winproc = classPtr->winproc;
794 wndPtr->dwMagic = WND_MAGIC;
795 wndPtr->hwndSelf = hwnd;
796 wndPtr->hInstance = cs->hInstance;
797 wndPtr->text = NULL;
798 wndPtr->hmemTaskQ = GetFastQueue16();
799 wndPtr->hrgnUpdate = 0;
800 wndPtr->hwndLastActive = hwnd;
801 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
802 wndPtr->dwExStyle = cs->dwExStyle;
803 wndPtr->wIDmenu = 0;
804 wndPtr->helpContext = 0;
805 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
806 wndPtr->pVScroll = NULL;
807 wndPtr->pHScroll = NULL;
808 wndPtr->pProp = NULL;
809 wndPtr->userdata = 0;
810 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
811 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
812 wndPtr->irefCount = 1;
814 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
816 /* Call the WH_CBT hook */
818 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
819 ? HWND_BOTTOM : HWND_TOP;
821 if (HOOK_IsHooked( WH_CBT ))
823 CBT_CREATEWNDA cbtc;
824 LRESULT ret;
826 cbtc.lpcs = cs;
827 cbtc.hwndInsertAfter = hwndLinkAfter;
828 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
829 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
830 if (ret)
832 TRACE("CBT-hook returned 0\n");
833 wndPtr->pDriver->pFinalize(wndPtr);
834 USER_HEAP_FREE( hwnd );
835 retvalue = 0;
836 goto end;
840 /* Increment class window counter */
842 classPtr->cWindows++;
844 /* Correct the window style */
846 if (!(cs->style & WS_CHILD))
848 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
849 if (!(cs->style & WS_POPUP))
851 wndPtr->dwStyle |= WS_CAPTION;
852 wndPtr->flags |= WIN_NEED_SIZE;
856 /* Get class or window DC if needed */
858 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
859 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
860 else wndPtr->dce = NULL;
862 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
864 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
866 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
867 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
868 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
869 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
870 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
873 if(cs->style & WS_CHILD)
875 if(cs->cx < 0) cs->cx = 0;
876 if(cs->cy < 0) cs->cy = 0;
878 else
880 if (cs->cx <= 0) cs->cx = 1;
881 if (cs->cy <= 0) cs->cy = 1;
884 wndPtr->rectWindow.left = cs->x;
885 wndPtr->rectWindow.top = cs->y;
886 wndPtr->rectWindow.right = cs->x + cs->cx;
887 wndPtr->rectWindow.bottom = cs->y + cs->cy;
888 wndPtr->rectClient = wndPtr->rectWindow;
890 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
892 retvalue = FALSE;
893 goto end;
896 /* Set the window menu */
898 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
900 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
901 else
903 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
904 if (classPtr->menuNameA)
905 cs->hMenu = HIWORD(classPtr->menuNameA) ?
906 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
907 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
908 #else
909 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
910 if (menuName)
912 if (HIWORD(cs->hInstance))
913 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
914 else
915 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
917 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
919 #endif
922 else wndPtr->wIDmenu = (UINT)cs->hMenu;
924 /* Send the WM_CREATE message
925 * Perhaps we shouldn't allow width/height changes as well.
926 * See p327 in "Internals".
929 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
931 localSend32 = unicode ? SendMessageW : SendMessageA;
932 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
934 /* Insert the window in the linked list */
936 WIN_LinkWindow( hwnd, hwndLinkAfter );
938 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
939 NULL, NULL, 0, &wndPtr->rectClient );
940 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
941 maxPos.y - wndPtr->rectWindow.top);
942 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
944 /* Send the size messages */
946 if (!(wndPtr->flags & WIN_NEED_SIZE))
948 /* send it anyway */
949 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
950 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
951 WARN("sending bogus WM_SIZE message 0x%08lx\n",
952 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
953 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
954 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
955 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
956 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
957 SendMessageA( hwnd, WM_MOVE, 0,
958 MAKELONG( wndPtr->rectClient.left,
959 wndPtr->rectClient.top ) );
962 /* Show the window, maximizing or minimizing if needed */
964 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
966 RECT16 newPos;
967 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
968 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
969 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
970 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
971 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
972 : SWP_NOZORDER | SWP_FRAMECHANGED;
973 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
974 newPos.right, newPos.bottom, swFlag );
977 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
979 /* Notify the parent window only */
981 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
982 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
983 if( !IsWindow(hwnd) )
985 retvalue = 0;
986 goto end;
990 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
992 /* Call WH_SHELL hook */
994 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
995 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
997 TRACE("created window %04x\n", hwnd);
998 retvalue = hwnd;
999 goto end;
1001 WIN_UnlinkWindow( hwnd );
1004 /* Abort window creation */
1006 WARN("aborted by WM_xxCREATE!\n");
1007 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1008 retvalue = 0;
1009 end:
1010 WIN_ReleaseWndPtr(wndPtr);
1012 return retvalue;
1016 /***********************************************************************
1017 * CreateWindow16 (USER.41)
1019 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1020 DWORD style, INT16 x, INT16 y, INT16 width,
1021 INT16 height, HWND16 parent, HMENU16 menu,
1022 HINSTANCE16 instance, LPVOID data )
1024 return CreateWindowEx16( 0, className, windowName, style,
1025 x, y, width, height, parent, menu, instance, data );
1029 /***********************************************************************
1030 * CreateWindowEx16 (USER.452)
1032 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1033 LPCSTR windowName, DWORD style, INT16 x,
1034 INT16 y, INT16 width, INT16 height,
1035 HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 ATOM classAtom;
1039 CREATESTRUCTA cs;
1040 char buffer[256];
1042 /* Find the class atom */
1044 if (HIWORD(className))
1046 if (!(classAtom = GlobalFindAtomA( className )))
1048 ERR( "bad class name %s\n", debugres_a(className) );
1049 return 0;
1052 else
1054 classAtom = LOWORD(className);
1055 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1057 ERR( "bad atom %x\n", classAtom);
1058 return 0;
1060 className = buffer;
1063 /* Fix the coordinates */
1065 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1066 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1067 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1068 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1070 /* Create the window */
1072 cs.lpCreateParams = data;
1073 cs.hInstance = (HINSTANCE)instance;
1074 cs.hMenu = (HMENU)menu;
1075 cs.hwndParent = (HWND)parent;
1076 cs.style = style;
1077 cs.lpszName = windowName;
1078 cs.lpszClass = className;
1079 cs.dwExStyle = exStyle;
1081 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1085 /***********************************************************************
1086 * CreateWindowExA (USER32.83)
1088 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1089 LPCSTR windowName, DWORD style, INT x,
1090 INT y, INT width, INT height,
1091 HWND parent, HMENU menu,
1092 HINSTANCE instance, LPVOID data )
1094 ATOM classAtom;
1095 CREATESTRUCTA cs;
1096 char buffer[256];
1098 if(!instance)
1099 instance=GetModuleHandleA(NULL);
1101 if(exStyle & WS_EX_MDICHILD)
1102 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1104 /* Find the class atom */
1106 if (HIWORD(className))
1108 if (!(classAtom = GlobalFindAtomA( className )))
1110 ERR( "bad class name %s\n", debugres_a(className) );
1111 return 0;
1114 else
1116 classAtom = LOWORD(className);
1117 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1119 ERR( "bad atom %x\n", classAtom);
1120 return 0;
1122 className = buffer;
1125 /* Create the window */
1127 cs.lpCreateParams = data;
1128 cs.hInstance = instance;
1129 cs.hMenu = menu;
1130 cs.hwndParent = parent;
1131 cs.x = x;
1132 cs.y = y;
1133 cs.cx = width;
1134 cs.cy = height;
1135 cs.style = style;
1136 cs.lpszName = windowName;
1137 cs.lpszClass = className;
1138 cs.dwExStyle = exStyle;
1140 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1144 /***********************************************************************
1145 * CreateWindowExW (USER32.84)
1147 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1148 LPCWSTR windowName, DWORD style, INT x,
1149 INT y, INT width, INT height,
1150 HWND parent, HMENU menu,
1151 HINSTANCE instance, LPVOID data )
1153 ATOM classAtom;
1154 CREATESTRUCTW cs;
1155 WCHAR buffer[256];
1157 if(!instance)
1158 instance=GetModuleHandleA(NULL);
1160 if(exStyle & WS_EX_MDICHILD)
1161 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1163 /* Find the class atom */
1165 if (HIWORD(className))
1167 if (!(classAtom = GlobalFindAtomW( className )))
1169 ERR( "bad class name %s\n", debugres_w(className) );
1170 return 0;
1173 else
1175 classAtom = LOWORD(className);
1176 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1178 ERR( "bad atom %x\n", classAtom);
1179 return 0;
1181 className = buffer;
1184 /* Create the window */
1186 cs.lpCreateParams = data;
1187 cs.hInstance = instance;
1188 cs.hMenu = menu;
1189 cs.hwndParent = parent;
1190 cs.x = x;
1191 cs.y = y;
1192 cs.cx = width;
1193 cs.cy = height;
1194 cs.style = style;
1195 cs.lpszName = windowName;
1196 cs.lpszClass = className;
1197 cs.dwExStyle = exStyle;
1199 /* Note: we rely on the fact that CREATESTRUCTA and */
1200 /* CREATESTRUCTW have the same layout. */
1201 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1205 /***********************************************************************
1206 * WIN_CheckFocus
1208 static void WIN_CheckFocus( WND* pWnd )
1210 if( GetFocus16() == pWnd->hwndSelf )
1211 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1214 /***********************************************************************
1215 * WIN_SendDestroyMsg
1217 static void WIN_SendDestroyMsg( WND* pWnd )
1219 WIN_CheckFocus(pWnd);
1221 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1222 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1225 * Send the WM_DESTROY to the window.
1227 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1230 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1231 * make sure that the window still exists when we come back.
1233 if (IsWindow(pWnd->hwndSelf))
1235 HWND* pWndArray = NULL;
1236 WND* pChild = NULL;
1237 int nKidCount = 0;
1240 * Now, if the window has kids, we have to send WM_DESTROY messages
1241 * recursively to it's kids. It seems that those calls can also
1242 * trigger re-entrant calls to DestroyWindow for the kids so we must
1243 * protect against corruption of the list of siblings. We first build
1244 * a list of HWNDs representing all the kids.
1246 pChild = WIN_LockWndPtr(pWnd->child);
1247 while( pChild )
1249 nKidCount++;
1250 WIN_UpdateWndPtr(&pChild,pChild->next);
1254 * If there are no kids, we're done.
1256 if (nKidCount==0)
1257 return;
1259 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1262 * Sanity check
1264 if (pWndArray==NULL)
1265 return;
1268 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1269 * call, our linked list of siblings should be safe.
1271 nKidCount = 0;
1272 pChild = WIN_LockWndPtr(pWnd->child);
1273 while( pChild )
1275 pWndArray[nKidCount] = pChild->hwndSelf;
1276 nKidCount++;
1277 WIN_UpdateWndPtr(&pChild,pChild->next);
1281 * Now that we have a list, go through that list again and send the destroy
1282 * message to those windows. We are using the HWND to retrieve the
1283 * WND pointer so we are effectively checking that all the kid windows are
1284 * still valid before sending the message.
1286 while (nKidCount>0)
1288 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1290 if (pChild!=NULL)
1292 WIN_SendDestroyMsg( pChild );
1293 WIN_ReleaseWndPtr(pChild);
1298 * Cleanup
1300 HeapFree(GetProcessHeap(), 0, pWndArray);
1301 WIN_CheckFocus(pWnd);
1303 else
1304 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1308 /***********************************************************************
1309 * DestroyWindow16 (USER.53)
1311 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1313 return DestroyWindow(hwnd);
1317 /***********************************************************************
1318 * DestroyWindow (USER32.135)
1320 BOOL WINAPI DestroyWindow( HWND hwnd )
1322 WND * wndPtr;
1323 BOOL retvalue;
1325 TRACE("(%04x)\n", hwnd);
1327 /* Initialization */
1329 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1330 if (wndPtr == pWndDesktop)
1332 retvalue = FALSE; /* Can't destroy desktop */
1333 goto end;
1336 /* Call hooks */
1338 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1340 retvalue = FALSE;
1341 goto end;
1344 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1346 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1347 /* FIXME: clean up palette - see "Internals" p.352 */
1350 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1351 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1353 /* Notify the parent window only */
1354 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1355 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1356 if( !IsWindow(hwnd) )
1358 retvalue = TRUE;
1359 goto end;
1363 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1365 /* Hide the window */
1367 if (wndPtr->dwStyle & WS_VISIBLE)
1369 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1370 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1371 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1372 if (!IsWindow(hwnd))
1374 retvalue = TRUE;
1375 goto end;
1379 /* Recursively destroy owned windows */
1381 if( !(wndPtr->dwStyle & WS_CHILD) )
1383 /* make sure top menu popup doesn't get destroyed */
1384 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1386 for (;;)
1388 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1389 while (siblingPtr)
1391 if (siblingPtr->owner == wndPtr)
1393 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1394 break;
1395 else
1396 siblingPtr->owner = NULL;
1398 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1400 if (siblingPtr)
1402 DestroyWindow( siblingPtr->hwndSelf );
1403 WIN_ReleaseWndPtr(siblingPtr);
1405 else break;
1408 if( !Options.managed || EVENT_CheckFocus() )
1409 WINPOS_ActivateOtherWindow(wndPtr);
1411 if( wndPtr->owner &&
1412 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1413 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1416 /* Send destroy messages */
1418 WIN_SendDestroyMsg( wndPtr );
1419 if (!IsWindow(hwnd))
1421 retvalue = TRUE;
1422 goto end;
1425 /* Unlink now so we won't bother with the children later on */
1427 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1429 /* Destroy the window storage */
1431 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1432 retvalue = TRUE;
1433 end:
1434 WIN_ReleaseWndPtr(wndPtr);
1435 return retvalue;
1439 /***********************************************************************
1440 * CloseWindow16 (USER.43)
1442 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1444 return CloseWindow( hwnd );
1448 /***********************************************************************
1449 * CloseWindow (USER32.56)
1451 BOOL WINAPI CloseWindow( HWND hwnd )
1453 WND * wndPtr = WIN_FindWndPtr( hwnd );
1454 BOOL retvalue;
1456 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1458 retvalue = FALSE;
1459 goto end;
1461 ShowWindow( hwnd, SW_MINIMIZE );
1462 retvalue = TRUE;
1463 end:
1464 WIN_ReleaseWndPtr(wndPtr);
1465 return retvalue;
1470 /***********************************************************************
1471 * OpenIcon16 (USER.44)
1473 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1475 return OpenIcon( hwnd );
1479 /***********************************************************************
1480 * OpenIcon (USER32.410)
1482 BOOL WINAPI OpenIcon( HWND hwnd )
1484 if (!IsIconic( hwnd )) return FALSE;
1485 ShowWindow( hwnd, SW_SHOWNORMAL );
1486 return TRUE;
1490 /***********************************************************************
1491 * WIN_FindWindow
1493 * Implementation of FindWindow() and FindWindowEx().
1495 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1496 LPCSTR title )
1498 WND *pWnd;
1499 HWND retvalue;
1501 if (child)
1503 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1504 if (parent)
1506 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1508 retvalue = 0;
1509 goto end;
1512 else if (pWnd->parent != pWndDesktop)
1514 retvalue = 0;
1515 goto end;
1517 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1519 else
1521 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1523 retvalue = 0;
1524 goto end;
1526 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1528 if (!pWnd)
1530 retvalue = 0;
1531 goto end;
1534 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1536 if (className && (pWnd->class->atomName != className))
1537 continue; /* Not the right class */
1539 /* Now check the title */
1541 if (!title)
1543 retvalue = pWnd->hwndSelf;
1544 goto end;
1546 if (pWnd->text && !strcmp( pWnd->text, title ))
1548 retvalue = pWnd->hwndSelf;
1549 goto end;
1552 retvalue = 0;
1553 end:
1554 WIN_ReleaseWndPtr(pWnd);
1555 return retvalue;
1560 /***********************************************************************
1561 * FindWindow16 (USER.50)
1563 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1565 return FindWindowA( className, title );
1569 /***********************************************************************
1570 * FindWindowEx16 (USER.427)
1572 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1574 return FindWindowExA( parent, child, className, title );
1578 /***********************************************************************
1579 * FindWindowA (USER32.198)
1581 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1583 HWND ret = FindWindowExA( 0, 0, className, title );
1584 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1585 return ret;
1589 /***********************************************************************
1590 * FindWindowExA (USER32.199)
1592 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1593 LPCSTR className, LPCSTR title )
1595 ATOM atom = 0;
1597 if (className)
1599 /* If the atom doesn't exist, then no class */
1600 /* with this name exists either. */
1601 if (!(atom = GlobalFindAtomA( className )))
1603 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1604 return 0;
1607 return WIN_FindWindow( parent, child, atom, title );
1611 /***********************************************************************
1612 * FindWindowExW (USER32.200)
1614 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1615 LPCWSTR className, LPCWSTR title )
1617 ATOM atom = 0;
1618 char *buffer;
1619 HWND hwnd;
1621 if (className)
1623 /* If the atom doesn't exist, then no class */
1624 /* with this name exists either. */
1625 if (!(atom = GlobalFindAtomW( className )))
1627 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1628 return 0;
1631 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1632 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1633 HeapFree( GetProcessHeap(), 0, buffer );
1634 return hwnd;
1638 /***********************************************************************
1639 * FindWindowW (USER32.201)
1641 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1643 return FindWindowExW( 0, 0, className, title );
1647 /**********************************************************************
1648 * WIN_GetDesktop
1649 * returns a locked pointer
1651 WND *WIN_GetDesktop(void)
1653 return WIN_LockWndPtr(pWndDesktop);
1655 /**********************************************************************
1656 * WIN_ReleaseDesktop
1657 * unlock the desktop pointer
1659 void WIN_ReleaseDesktop(void)
1661 WIN_ReleaseWndPtr(pWndDesktop);
1665 /**********************************************************************
1666 * GetDesktopWindow16 (USER.286)
1668 HWND16 WINAPI GetDesktopWindow16(void)
1670 return (HWND16)pWndDesktop->hwndSelf;
1674 /**********************************************************************
1675 * GetDesktopWindow (USER32.232)
1677 HWND WINAPI GetDesktopWindow(void)
1679 if (pWndDesktop) return pWndDesktop->hwndSelf;
1680 ERR( "You need the -desktop option when running with native USER\n" );
1681 ExitProcess(1);
1682 return 0;
1686 /**********************************************************************
1687 * GetDesktopHwnd (USER.278)
1689 * Exactly the same thing as GetDesktopWindow(), but not documented.
1690 * Don't ask me why...
1692 HWND16 WINAPI GetDesktopHwnd16(void)
1694 return (HWND16)pWndDesktop->hwndSelf;
1698 /*******************************************************************
1699 * EnableWindow16 (USER.34)
1701 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1703 return EnableWindow( hwnd, enable );
1707 /*******************************************************************
1708 * EnableWindow (USER32.172)
1710 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1712 WND *wndPtr;
1713 BOOL retvalue;
1715 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1717 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1718 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1720 /* Enable window */
1721 wndPtr->dwStyle &= ~WS_DISABLED;
1723 if( wndPtr->flags & WIN_NATIVE )
1724 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1726 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1727 retvalue = TRUE;
1728 goto end;
1730 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1732 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1734 /* Disable window */
1735 wndPtr->dwStyle |= WS_DISABLED;
1737 if( wndPtr->flags & WIN_NATIVE )
1738 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1740 if (hwnd == GetFocus())
1742 SetFocus( 0 ); /* A disabled window can't have the focus */
1744 if (hwnd == GetCapture())
1746 ReleaseCapture(); /* A disabled window can't capture the mouse */
1748 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1749 retvalue = FALSE;
1750 goto end;
1752 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1753 end:
1754 WIN_ReleaseWndPtr(wndPtr);
1755 return retvalue;
1759 /***********************************************************************
1760 * IsWindowEnabled16 (USER.35)
1762 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1764 return IsWindowEnabled(hWnd);
1768 /***********************************************************************
1769 * IsWindowEnabled (USER32.349)
1771 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1773 WND * wndPtr;
1774 BOOL retvalue;
1776 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1777 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1778 WIN_ReleaseWndPtr(wndPtr);
1779 return retvalue;
1784 /***********************************************************************
1785 * IsWindowUnicode (USER32.350)
1787 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1789 WND * wndPtr;
1790 BOOL retvalue;
1792 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1793 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1794 WIN_ReleaseWndPtr(wndPtr);
1795 return retvalue;
1799 /**********************************************************************
1800 * GetWindowWord16 (USER.133)
1802 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1804 return GetWindowWord( hwnd, offset );
1808 /**********************************************************************
1809 * GetWindowWord (USER32.314)
1811 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1813 WORD retvalue;
1814 WND * wndPtr = WIN_FindWndPtr( hwnd );
1815 if (!wndPtr) return 0;
1816 if (offset >= 0)
1818 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1820 WARN("Invalid offset %d\n", offset );
1821 retvalue = 0;
1822 goto end;
1824 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1825 goto end;
1827 switch(offset)
1829 case GWW_ID:
1830 if (HIWORD(wndPtr->wIDmenu))
1831 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1832 wndPtr->wIDmenu);
1833 retvalue = (WORD)wndPtr->wIDmenu;
1834 goto end;
1835 case GWW_HWNDPARENT:
1836 retvalue = GetParent(hwnd);
1837 goto end;
1838 case GWW_HINSTANCE:
1839 if (HIWORD(wndPtr->hInstance))
1840 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1841 wndPtr->hInstance);
1842 retvalue = (WORD)wndPtr->hInstance;
1843 goto end;
1844 default:
1845 WARN("Invalid offset %d\n", offset );
1846 retvalue = 0;
1847 goto end;
1849 end:
1850 WIN_ReleaseWndPtr(wndPtr);
1851 return retvalue;
1854 /**********************************************************************
1855 * SetWindowWord16 (USER.134)
1857 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1859 return SetWindowWord( hwnd, offset, newval );
1863 /**********************************************************************
1864 * SetWindowWord (USER32.524)
1866 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1868 WORD *ptr, retval;
1869 WND * wndPtr = WIN_FindWndPtr( hwnd );
1870 if (!wndPtr) return 0;
1871 if (offset >= 0)
1873 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1875 WARN("Invalid offset %d\n", offset );
1876 retval = 0;
1877 goto end;
1879 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1881 else switch(offset)
1883 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1884 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1885 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1886 goto end;
1887 default:
1888 WARN("Invalid offset %d\n", offset );
1889 retval = 0;
1890 goto end;
1892 retval = *ptr;
1893 *ptr = newval;
1894 end:
1895 WIN_ReleaseWndPtr(wndPtr);
1896 return retval;
1900 /**********************************************************************
1901 * WIN_GetWindowLong
1903 * Helper function for GetWindowLong().
1905 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1907 LONG retvalue;
1908 WND * wndPtr = WIN_FindWndPtr( hwnd );
1909 if (!wndPtr) return 0;
1910 if (offset >= 0)
1912 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1914 WARN("Invalid offset %d\n", offset );
1915 retvalue = 0;
1916 goto end;
1918 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1919 /* Special case for dialog window procedure */
1920 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1922 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1923 goto end;
1925 goto end;
1927 switch(offset)
1929 case GWL_USERDATA: retvalue = wndPtr->userdata;
1930 goto end;
1931 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1932 goto end;
1933 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1934 goto end;
1935 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1936 goto end;
1937 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1938 type );
1939 goto end;
1940 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1941 goto end;
1942 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1943 goto end;
1944 default:
1945 WARN("Unknown offset %d\n", offset );
1947 retvalue = 0;
1948 end:
1949 WIN_ReleaseWndPtr(wndPtr);
1950 return retvalue;
1954 /**********************************************************************
1955 * WIN_SetWindowLong
1957 * Helper function for SetWindowLong().
1959 * 0 is the failure code. However, in the case of failure SetLastError
1960 * must be set to distinguish between a 0 return value and a failure.
1962 * FIXME: The error values for SetLastError may not be right. Can
1963 * someone check with the real thing?
1965 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1966 WINDOWPROCTYPE type )
1968 LONG *ptr, retval;
1969 WND * wndPtr = WIN_FindWndPtr( hwnd );
1970 STYLESTRUCT style;
1972 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1974 if (!wndPtr)
1976 /* Is this the right error? */
1977 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1978 return 0;
1981 if (offset >= 0)
1983 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1985 WARN("Invalid offset %d\n", offset );
1987 /* Is this the right error? */
1988 SetLastError( ERROR_OUTOFMEMORY );
1990 retval = 0;
1991 goto end;
1993 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1994 /* Special case for dialog window procedure */
1995 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1997 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1998 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1999 type, WIN_PROC_WINDOW );
2000 goto end;
2003 else switch(offset)
2005 case GWL_ID:
2006 ptr = (DWORD*)&wndPtr->wIDmenu;
2007 break;
2008 case GWL_HINSTANCE:
2009 retval = SetWindowWord( hwnd, offset, newval );
2010 goto end;
2011 case GWL_WNDPROC:
2012 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2013 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2014 type, WIN_PROC_WINDOW );
2015 goto end;
2016 case GWL_STYLE:
2017 style.styleOld = wndPtr->dwStyle;
2018 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2019 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2021 if (wndPtr->flags & WIN_ISWIN32)
2022 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2023 wndPtr->dwStyle = style.styleNew;
2024 if (wndPtr->flags & WIN_ISWIN32)
2025 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2026 retval = style.styleOld;
2027 goto end;
2029 case GWL_USERDATA:
2030 ptr = &wndPtr->userdata;
2031 break;
2032 case GWL_EXSTYLE:
2033 style.styleOld = wndPtr->dwExStyle;
2034 style.styleNew = newval;
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2037 wndPtr->dwExStyle = newval;
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2040 retval = style.styleOld;
2041 goto end;
2043 default:
2044 WARN("Invalid offset %d\n", offset );
2046 /* Don't think this is right error but it should do */
2047 SetLastError( ERROR_OUTOFMEMORY );
2049 retval = 0;
2050 goto end;
2052 retval = *ptr;
2053 *ptr = newval;
2054 end:
2055 WIN_ReleaseWndPtr(wndPtr);
2056 return retval;
2060 /**********************************************************************
2061 * GetWindowLong16 (USER.135)
2063 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2065 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2069 /**********************************************************************
2070 * GetWindowLongA (USER32.305)
2072 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2074 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2078 /**********************************************************************
2079 * GetWindowLongW (USER32.306)
2081 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2083 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2087 /**********************************************************************
2088 * SetWindowLong16 (USER.136)
2090 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2092 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2096 /**********************************************************************
2097 * SetWindowLongA (USER32.517)
2099 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2101 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2105 /**********************************************************************
2106 * SetWindowLongW (USER32.518) Set window attribute
2108 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2109 * value in a window's extra memory.
2111 * The _hwnd_ parameter specifies the window. is the handle to a
2112 * window that has extra memory. The _newval_ parameter contains the
2113 * new attribute or extra memory value. If positive, the _offset_
2114 * parameter is the byte-addressed location in the window's extra
2115 * memory to set. If negative, _offset_ specifies the window
2116 * attribute to set, and should be one of the following values:
2118 * GWL_EXSTYLE The window's extended window style
2120 * GWL_STYLE The window's window style.
2122 * GWL_WNDPROC Pointer to the window's window procedure.
2124 * GWL_HINSTANCE The window's pplication instance handle.
2126 * GWL_ID The window's identifier.
2128 * GWL_USERDATA The window's user-specified data.
2130 * If the window is a dialog box, the _offset_ parameter can be one of
2131 * the following values:
2133 * DWL_DLGPROC The address of the window's dialog box procedure.
2135 * DWL_MSGRESULT The return value of a message
2136 * that the dialog box procedure processed.
2138 * DWL_USER Application specific information.
2140 * RETURNS
2142 * If successful, returns the previous value located at _offset_. Otherwise,
2143 * returns 0.
2145 * NOTES
2147 * Extra memory for a window class is specified by a nonzero cbWndExtra
2148 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2149 * time of class creation.
2151 * Using GWL_WNDPROC to set a new window procedure effectively creates
2152 * a window subclass. Use CallWindowProc() in the new windows procedure
2153 * to pass messages to the superclass's window procedure.
2155 * The user data is reserved for use by the application which created
2156 * the window.
2158 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2159 * instead, call the EnableWindow() function to change the window's
2160 * disabled state.
2162 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2163 * SetParent() instead.
2165 * Win95:
2166 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2167 * it sends WM_STYLECHANGING before changing the settings
2168 * and WM_STYLECHANGED afterwards.
2169 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2171 * BUGS
2173 * GWL_STYLE does not dispatch WM_STYLE... messages.
2175 * CONFORMANCE
2177 * ECMA-234, Win32
2180 LONG WINAPI SetWindowLongW(
2181 HWND hwnd, /* window to alter */
2182 INT offset, /* offset, in bytes, of location to alter */
2183 LONG newval /* new value of location */
2185 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2189 /*******************************************************************
2190 * GetWindowText16 (USER.36)
2192 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2194 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2198 /*******************************************************************
2199 * GetWindowTextA (USER32.309)
2201 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2203 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2204 (LPARAM)lpString );
2207 /*******************************************************************
2208 * InternalGetWindowText (USER32.326)
2210 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2212 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2213 return GetWindowTextW(hwnd,lpString,nMaxCount);
2217 /*******************************************************************
2218 * GetWindowTextW (USER32.312)
2220 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2222 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2223 (LPARAM)lpString );
2227 /*******************************************************************
2228 * SetWindowText16 (USER.37)
2230 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2232 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2236 /*******************************************************************
2237 * SetWindowTextA (USER32.521)
2239 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2241 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2245 /*******************************************************************
2246 * SetWindowTextW (USER32.523)
2248 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2250 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2254 /*******************************************************************
2255 * GetWindowTextLength16 (USER.38)
2257 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2259 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2263 /*******************************************************************
2264 * GetWindowTextLengthA (USER32.310)
2266 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2268 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2271 /*******************************************************************
2272 * GetWindowTextLengthW (USER32.311)
2274 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2276 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2280 /*******************************************************************
2281 * IsWindow16 (USER.47)
2283 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2285 CURRENT_STACK16->es = USER_HeapSel;
2286 return IsWindow( hwnd );
2290 /*******************************************************************
2291 * IsWindow (USER32.348)
2293 BOOL WINAPI IsWindow( HWND hwnd )
2295 WND * wndPtr;
2296 BOOL retvalue;
2298 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2299 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2300 WIN_ReleaseWndPtr(wndPtr);
2301 return retvalue;
2306 /*****************************************************************
2307 * GetParent16 (USER.46)
2309 HWND16 WINAPI GetParent16( HWND16 hwnd )
2311 return (HWND16)GetParent( hwnd );
2315 /*****************************************************************
2316 * GetParent (USER32.278)
2318 HWND WINAPI GetParent( HWND hwnd )
2320 WND *wndPtr;
2321 HWND retvalue = 0;
2323 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2324 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2325 goto end;
2327 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2328 if (wndPtr)
2329 retvalue = wndPtr->hwndSelf;
2331 end:
2332 WIN_ReleaseWndPtr(wndPtr);
2333 return retvalue;
2337 /*****************************************************************
2338 * WIN_GetTopParent
2340 * Get the top-level parent for a child window.
2341 * returns a locked pointer
2343 WND* WIN_GetTopParentPtr( WND* pWnd )
2345 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2347 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2349 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2351 return tmpWnd;
2354 /*****************************************************************
2355 * WIN_GetTopParent
2357 * Get the top-level parent for a child window.
2359 HWND WIN_GetTopParent( HWND hwnd )
2361 HWND retvalue;
2362 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2363 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2365 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2366 WIN_ReleaseWndPtr(tmpPtr);
2367 WIN_ReleaseWndPtr(wndPtr);
2368 return retvalue;
2372 /*****************************************************************
2373 * SetParent16 (USER.233)
2375 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2377 return SetParent( hwndChild, hwndNewParent );
2381 /*****************************************************************
2382 * SetParent (USER32.495)
2384 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2386 WND *wndPtr;
2387 DWORD dwStyle;
2388 WND *pWndNewParent;
2389 WND *pWndOldParent;
2390 HWND retvalue;
2393 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2395 dwStyle = wndPtr->dwStyle;
2397 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2398 : WIN_LockWndPtr(pWndDesktop);
2400 /* Windows hides the window first, then shows it again
2401 * including the WM_SHOWWINDOW messages and all */
2402 if (dwStyle & WS_VISIBLE)
2403 ShowWindow( hwndChild, SW_HIDE );
2405 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2407 /* SetParent additionally needs to make hwndChild the topmost window
2408 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2409 WM_WINDOWPOSCHANGED notification messages.
2411 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2412 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2413 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2414 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2416 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2418 WIN_ReleaseWndPtr(pWndOldParent);
2419 WIN_ReleaseWndPtr(pWndNewParent);
2420 WIN_ReleaseWndPtr(wndPtr);
2422 return retvalue;
2426 /*******************************************************************
2427 * IsChild16 (USER.48)
2429 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2431 return IsChild(parent,child);
2435 /*******************************************************************
2436 * IsChild (USER32.339)
2438 BOOL WINAPI IsChild( HWND parent, HWND child )
2440 WND * wndPtr = WIN_FindWndPtr( child );
2441 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2443 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2444 if (wndPtr->hwndSelf == parent)
2446 WIN_ReleaseWndPtr(wndPtr);
2447 return TRUE;
2450 WIN_ReleaseWndPtr(wndPtr);
2451 return FALSE;
2455 /***********************************************************************
2456 * IsWindowVisible16 (USER.49)
2458 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2460 return IsWindowVisible(hwnd);
2464 /***********************************************************************
2465 * IsWindowVisible (USER32.351)
2467 BOOL WINAPI IsWindowVisible( HWND hwnd )
2469 BOOL retval;
2470 WND *wndPtr = WIN_FindWndPtr( hwnd );
2471 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2473 if (!(wndPtr->dwStyle & WS_VISIBLE))
2475 WIN_ReleaseWndPtr(wndPtr);
2476 return FALSE;
2478 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2480 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2481 WIN_ReleaseWndPtr(wndPtr);
2482 return retval;
2487 /***********************************************************************
2488 * WIN_IsWindowDrawable
2490 * hwnd is drawable when it is visible, all parents are not
2491 * minimized, and it is itself not minimized unless we are
2492 * trying to draw its default class icon.
2494 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2496 if( (wnd->dwStyle & WS_MINIMIZE &&
2497 icon && wnd->class->hIcon) ||
2498 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2499 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2500 if( wnd->dwStyle & WS_MINIMIZE ||
2501 !(wnd->dwStyle & WS_VISIBLE) ) break;
2502 return (wnd == NULL);
2506 /*******************************************************************
2507 * GetTopWindow16 (USER.229)
2509 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2511 return GetTopWindow(hwnd);
2515 /*******************************************************************
2516 * GetTopWindow (USER.229)
2518 HWND WINAPI GetTopWindow( HWND hwnd )
2520 HWND retval = 0;
2521 WND * wndPtr = (hwnd) ?
2522 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2524 if (wndPtr && wndPtr->child)
2525 retval = wndPtr->child->hwndSelf;
2527 WIN_ReleaseWndPtr(wndPtr);
2528 return retval;
2532 /*******************************************************************
2533 * GetWindow16 (USER.262)
2535 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2537 return GetWindow( hwnd,rel );
2541 /*******************************************************************
2542 * GetWindow (USER32.302)
2544 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2546 HWND retval;
2548 WND * wndPtr = WIN_FindWndPtr( hwnd );
2549 if (!wndPtr) return 0;
2550 switch(rel)
2552 case GW_HWNDFIRST:
2553 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2554 goto end;
2556 case GW_HWNDLAST:
2557 if (!wndPtr->parent)
2559 retval = 0; /* Desktop window */
2560 goto end;
2562 while (wndPtr->next)
2564 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2566 retval = wndPtr->hwndSelf;
2567 goto end;
2569 case GW_HWNDNEXT:
2570 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2571 goto end;
2573 case GW_HWNDPREV:
2574 if (!wndPtr->parent)
2576 retval = 0; /* Desktop window */
2577 goto end;
2579 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2580 if (wndPtr->hwndSelf == hwnd)
2582 retval = 0; /* First in list */
2583 goto end;
2585 while (wndPtr->next)
2587 if (wndPtr->next->hwndSelf == hwnd)
2589 retval = wndPtr->hwndSelf;
2590 goto end;
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2594 retval = 0;
2595 goto end;
2597 case GW_OWNER:
2598 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2599 goto end;
2601 case GW_CHILD:
2602 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2603 goto end;
2605 retval = 0;
2606 end:
2607 WIN_ReleaseWndPtr(wndPtr);
2608 return retval;
2612 /*******************************************************************
2613 * GetNextWindow16 (USER.230)
2615 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2617 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2618 return GetWindow16( hwnd, flag );
2621 /*******************************************************************
2622 * ShowOwnedPopups16 (USER.265)
2624 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2626 ShowOwnedPopups( owner, fShow );
2630 /*******************************************************************
2631 * ShowOwnedPopups (USER32.531)
2633 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2635 UINT totalChild=0, count=0;
2637 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2639 if (!pWnd) return TRUE;
2641 for (; count < totalChild; count++)
2643 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2645 if (fShow)
2647 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2649 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2650 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2653 else
2655 if (IsWindowVisible(pWnd[count]->hwndSelf))
2657 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2658 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2664 WIN_ReleaseDesktop();
2665 WIN_ReleaseWinArray(pWnd);
2666 return TRUE;
2670 /*******************************************************************
2671 * GetLastActivePopup16 (USER.287)
2673 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2675 return GetLastActivePopup( hwnd );
2678 /*******************************************************************
2679 * GetLastActivePopup (USER32.256)
2681 HWND WINAPI GetLastActivePopup( HWND hwnd )
2683 HWND retval;
2684 WND *wndPtr =WIN_FindWndPtr(hwnd);
2685 if (!wndPtr) return hwnd;
2686 retval = wndPtr->hwndLastActive;
2687 WIN_ReleaseWndPtr(wndPtr);
2688 return retval;
2692 /*******************************************************************
2693 * WIN_BuildWinArray
2695 * Build an array of pointers to the children of a given window.
2696 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2697 * when no windows are found.
2699 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2701 /* Future: this function will lock all windows associated with this array */
2703 WND **list, **ppWnd;
2704 WND *pWnd;
2705 UINT count = 0, skipOwned, skipHidden;
2706 DWORD skipFlags;
2708 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2709 skipOwned = bwaFlags & BWA_SKIPOWNED;
2710 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2711 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2713 /* First count the windows */
2715 if (!wndPtr)
2716 wndPtr = WIN_GetDesktop();
2718 pWnd = WIN_LockWndPtr(wndPtr->child);
2719 while (pWnd)
2721 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2722 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2723 count++;
2724 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2727 if( count )
2729 /* Now build the list of all windows */
2731 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2733 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2735 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2736 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2738 *ppWnd++ = pWnd;
2739 count++;
2742 WIN_ReleaseWndPtr(pWnd);
2743 *ppWnd = NULL;
2745 else count = 0;
2746 } else list = NULL;
2748 if( pTotal ) *pTotal = count;
2749 return list;
2751 /*******************************************************************
2752 * WIN_ReleaseWinArray
2754 void WIN_ReleaseWinArray(WND **wndArray)
2756 /* Future: this function will also unlock all windows associated with wndArray */
2757 HeapFree( GetProcessHeap(), 0, wndArray );
2761 /*******************************************************************
2762 * EnumWindows (USER32.193)
2764 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2766 WND **list, **ppWnd;
2768 /* We have to build a list of all windows first, to avoid */
2769 /* unpleasant side-effects, for instance if the callback */
2770 /* function changes the Z-order of the windows. */
2772 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2774 WIN_ReleaseDesktop();
2775 return FALSE;
2778 /* Now call the callback function for every window */
2780 for (ppWnd = list; *ppWnd; ppWnd++)
2782 LRESULT lpEnumFuncRetval;
2783 int iWndsLocks = 0;
2784 /* Make sure that the window still exists */
2785 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2787 /* To avoid any deadlocks, all the locks on the windows
2788 structures must be suspended before the control
2789 is passed to the application */
2790 iWndsLocks = WIN_SuspendWndsLock();
2791 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2792 WIN_RestoreWndsLock(iWndsLocks);
2794 if (!lpEnumFuncRetval) break;
2796 WIN_ReleaseWinArray(list);
2797 WIN_ReleaseDesktop();
2798 return TRUE;
2802 /**********************************************************************
2803 * EnumTaskWindows16 (USER.225)
2805 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2806 LPARAM lParam )
2808 WND **list, **ppWnd;
2810 /* This function is the same as EnumWindows(), */
2811 /* except for an added check on the window's task. */
2813 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2815 WIN_ReleaseDesktop();
2816 return FALSE;
2819 /* Now call the callback function for every window */
2821 for (ppWnd = list; *ppWnd; ppWnd++)
2823 LRESULT funcRetval;
2824 int iWndsLocks = 0;
2825 /* Make sure that the window still exists */
2826 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2827 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2829 /* To avoid any deadlocks, all the locks on the windows
2830 structures must be suspended before the control
2831 is passed to the application */
2832 iWndsLocks = WIN_SuspendWndsLock();
2833 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2834 WIN_RestoreWndsLock(iWndsLocks);
2836 if (!funcRetval) break;
2838 WIN_ReleaseWinArray(list);
2839 WIN_ReleaseDesktop();
2840 return TRUE;
2844 /**********************************************************************
2845 * EnumThreadWindows (USER32.190)
2847 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2849 TEB *teb = THREAD_IdToTEB(id);
2851 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2855 /**********************************************************************
2856 * WIN_EnumChildWindows
2858 * Helper function for EnumChildWindows().
2860 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2862 WND **childList;
2863 BOOL16 ret = FALSE;
2865 for ( ; *ppWnd; ppWnd++)
2867 int iWndsLocks = 0;
2869 /* Make sure that the window still exists */
2870 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2871 /* Build children list first */
2872 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2874 /* To avoid any deadlocks, all the locks on the windows
2875 structures must be suspended before the control
2876 is passed to the application */
2877 iWndsLocks = WIN_SuspendWndsLock();
2878 ret = func( (*ppWnd)->hwndSelf, lParam );
2879 WIN_RestoreWndsLock(iWndsLocks);
2881 if (childList)
2883 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2884 WIN_ReleaseWinArray(childList);
2886 if (!ret) return FALSE;
2888 return TRUE;
2892 /**********************************************************************
2893 * EnumChildWindows (USER32.178)
2895 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2896 LPARAM lParam )
2898 WND **list, *pParent;
2900 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2901 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2903 WIN_ReleaseWndPtr(pParent);
2904 return FALSE;
2906 WIN_EnumChildWindows( list, func, lParam );
2907 WIN_ReleaseWinArray(list);
2908 WIN_ReleaseWndPtr(pParent);
2909 return TRUE;
2913 /*******************************************************************
2914 * AnyPopup16 (USER.52)
2916 BOOL16 WINAPI AnyPopup16(void)
2918 return AnyPopup();
2922 /*******************************************************************
2923 * AnyPopup (USER32.4)
2925 BOOL WINAPI AnyPopup(void)
2927 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2928 BOOL retvalue;
2930 while (wndPtr)
2932 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2934 retvalue = TRUE;
2935 goto end;
2937 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2939 retvalue = FALSE;
2940 end:
2941 WIN_ReleaseWndPtr(wndPtr);
2942 return retvalue;
2946 /*******************************************************************
2947 * FlashWindow16 (USER.105)
2949 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2951 return FlashWindow( hWnd, bInvert );
2955 /*******************************************************************
2956 * FlashWindow (USER32.202)
2958 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2960 WND *wndPtr = WIN_FindWndPtr(hWnd);
2962 TRACE("%04x\n", hWnd);
2964 if (!wndPtr) return FALSE;
2966 if (wndPtr->dwStyle & WS_MINIMIZE)
2968 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2970 HDC hDC = GetDC(hWnd);
2972 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2973 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2975 ReleaseDC( hWnd, hDC );
2976 wndPtr->flags |= WIN_NCACTIVATED;
2978 else
2980 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2981 RDW_UPDATENOW | RDW_FRAME, 0 );
2982 wndPtr->flags &= ~WIN_NCACTIVATED;
2984 WIN_ReleaseWndPtr(wndPtr);
2985 return TRUE;
2987 else
2989 WPARAM16 wparam;
2990 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2991 else wparam = (hWnd == GetActiveWindow());
2993 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2994 WIN_ReleaseWndPtr(wndPtr);
2995 return wparam;
3000 /*******************************************************************
3001 * SetSysModalWindow16 (USER.188)
3003 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3005 HWND hWndOldModal = hwndSysModal;
3006 hwndSysModal = hWnd;
3007 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3008 return hWndOldModal;
3012 /*******************************************************************
3013 * GetSysModalWindow16 (USER.52)
3015 HWND16 WINAPI GetSysModalWindow16(void)
3017 return hwndSysModal;
3021 /*******************************************************************
3022 * GetWindowContextHelpId (USER32.303)
3024 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3026 DWORD retval;
3027 WND *wnd = WIN_FindWndPtr( hwnd );
3028 if (!wnd) return 0;
3029 retval = wnd->helpContext;
3030 WIN_ReleaseWndPtr(wnd);
3031 return retval;
3035 /*******************************************************************
3036 * SetWindowContextHelpId (USER32.515)
3038 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3040 WND *wnd = WIN_FindWndPtr( hwnd );
3041 if (!wnd) return FALSE;
3042 wnd->helpContext = id;
3043 WIN_ReleaseWndPtr(wnd);
3044 return TRUE;
3048 /*******************************************************************
3049 * DRAG_QueryUpdate
3051 * recursively find a child that contains spDragInfo->pt point
3052 * and send WM_QUERYDROPOBJECT
3054 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3056 BOOL16 wParam, bResult = 0;
3057 POINT pt;
3058 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3059 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3060 RECT tempRect;
3062 if( !ptrQueryWnd || !ptrDragInfo )
3063 goto end;
3065 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3067 GetWindowRect(hQueryWnd,&tempRect);
3069 if( !PtInRect(&tempRect,pt) ||
3070 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3071 goto end;
3073 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3075 tempRect = ptrQueryWnd->rectClient;
3076 if(ptrQueryWnd->dwStyle & WS_CHILD)
3077 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3078 (LPPOINT)&tempRect, 2 );
3080 if (PtInRect( &tempRect, pt))
3082 wParam = 0;
3084 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3086 if( ptrWnd->dwStyle & WS_VISIBLE )
3088 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3089 if (PtInRect( &tempRect, pt )) break;
3093 if(ptrWnd)
3095 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3096 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3097 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3098 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3099 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3101 WIN_ReleaseWndPtr(ptrWnd);
3104 if(bResult)
3105 goto end;
3107 else wParam = 1;
3109 else wParam = 1;
3111 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3113 ptrDragInfo->hScope = hQueryWnd;
3115 bResult = ( bNoSend )
3116 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3117 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3118 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3119 if( !bResult )
3120 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3122 end:
3123 WIN_ReleaseWndPtr(ptrQueryWnd);
3124 return bResult;
3128 /*******************************************************************
3129 * DragDetect (USER.465)
3131 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3133 POINT pt32;
3134 CONV_POINT16TO32( &pt, &pt32 );
3135 return DragDetect( hWnd, pt32 );
3138 /*******************************************************************
3139 * DragDetect (USER32.151)
3141 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3143 MSG16 msg;
3144 RECT16 rect;
3146 rect.left = pt.x - wDragWidth;
3147 rect.right = pt.x + wDragWidth;
3149 rect.top = pt.y - wDragHeight;
3150 rect.bottom = pt.y + wDragHeight;
3152 SetCapture(hWnd);
3154 while(1)
3156 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3158 if( msg.message == WM_LBUTTONUP )
3160 ReleaseCapture();
3161 return 0;
3163 if( msg.message == WM_MOUSEMOVE )
3165 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3167 ReleaseCapture();
3168 return 1;
3172 WaitMessage();
3174 return 0;
3177 /******************************************************************************
3178 * DragObject16 (USER.464)
3180 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3181 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3183 MSG16 msg;
3184 LPDRAGINFO lpDragInfo;
3185 SEGPTR spDragInfo;
3186 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3187 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3188 WND *wndPtr = WIN_FindWndPtr(hWnd);
3189 HCURSOR16 hCurrentCursor = 0;
3190 HWND16 hCurrentWnd = 0;
3192 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3193 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3195 if( !lpDragInfo || !spDragInfo )
3197 WIN_ReleaseWndPtr(wndPtr);
3198 return 0L;
3201 hBummer = LoadCursor16(0, IDC_BUMMER16);
3203 if( !hBummer || !wndPtr )
3205 GlobalFree16(hDragInfo);
3206 WIN_ReleaseWndPtr(wndPtr);
3207 return 0L;
3210 if(hCursor)
3212 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3214 GlobalFree16(hDragInfo);
3215 WIN_ReleaseWndPtr(wndPtr);
3216 return 0L;
3219 if( hDragCursor == hCursor ) hDragCursor = 0;
3220 else hCursor = hDragCursor;
3222 hOldCursor = SetCursor(hDragCursor);
3225 lpDragInfo->hWnd = hWnd;
3226 lpDragInfo->hScope = 0;
3227 lpDragInfo->wFlags = wObj;
3228 lpDragInfo->hList = szList; /* near pointer! */
3229 lpDragInfo->hOfStruct = hOfStruct;
3230 lpDragInfo->l = 0L;
3232 SetCapture(hWnd);
3233 ShowCursor( TRUE );
3237 do{ WaitMessage(); }
3238 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3240 *(lpDragInfo+1) = *lpDragInfo;
3242 lpDragInfo->pt = msg.pt;
3244 /* update DRAGINFO struct */
3245 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3247 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3248 hCurrentCursor = hCursor;
3249 else
3251 hCurrentCursor = hBummer;
3252 lpDragInfo->hScope = 0;
3254 if( hCurrentCursor )
3255 SetCursor(hCurrentCursor);
3257 /* send WM_DRAGLOOP */
3258 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3259 (LPARAM) spDragInfo );
3260 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3261 if( hCurrentWnd != lpDragInfo->hScope )
3263 if( hCurrentWnd )
3264 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3265 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3266 HIWORD(spDragInfo)) );
3267 hCurrentWnd = lpDragInfo->hScope;
3268 if( hCurrentWnd )
3269 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3271 else
3272 if( hCurrentWnd )
3273 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3275 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3277 ReleaseCapture();
3278 ShowCursor( FALSE );
3280 if( hCursor )
3282 SetCursor( hOldCursor );
3283 if (hDragCursor) DestroyCursor( hDragCursor );
3286 if( hCurrentCursor != hBummer )
3287 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3288 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3289 else
3290 msg.lParam = 0;
3291 GlobalFree16(hDragInfo);
3292 WIN_ReleaseWndPtr(wndPtr);
3294 return (DWORD)(msg.lParam);