Serge Ivanov
[wine.git] / windows / win.c
blobbdc8197dfa40d542575b9f06670bec432bf96134
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 "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "syslevel.h"
35 #include "stackframe.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(win);
39 DECLARE_DEBUG_CHANNEL(msg);
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static SYSLEVEL WIN_SysLevel;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 _CreateSysLevel( &WIN_SysLevel, 2 );
65 /***********************************************************************
66 * WIN_LockWnds
68 * Locks access to all WND structures for thread safeness
70 void WIN_LockWnds( void )
72 _EnterSysLevel( &WIN_SysLevel );
75 /***********************************************************************
76 * WIN_UnlockWnds
78 * Unlocks access to all WND structures
80 void WIN_UnlockWnds( void )
82 _LeaveSysLevel( &WIN_SysLevel );
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock( void )
93 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
94 int count = isuspendedLocks;
96 while ( count-- > 0 )
97 _LeaveSysLevel( &WIN_SysLevel );
99 return isuspendedLocks;
102 /***********************************************************************
103 * WIN_RestoreWndsLock
105 * Restore the suspended locks on WND structures
107 void WIN_RestoreWndsLock( int ipreviousLocks )
109 while ( ipreviousLocks-- > 0 )
110 _EnterSysLevel( &WIN_SysLevel );
113 /***********************************************************************
114 * WIN_FindWndPtr
116 * Return a pointer to the WND structure corresponding to a HWND.
118 WND * WIN_FindWndPtr( HWND hwnd )
120 WND * ptr;
122 if (!hwnd || HIWORD(hwnd)) goto error2;
123 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
124 /* Lock all WND structures for thread safeness*/
125 WIN_LockWnds();
126 /*and increment destruction monitoring*/
127 ptr->irefCount++;
129 if (ptr->dwMagic != WND_MAGIC) goto error;
130 if (ptr->hwndSelf != hwnd)
132 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
133 goto error;
135 /* returns a locked pointer */
136 return ptr;
137 error:
138 /* Unlock all WND structures for thread safeness*/
139 WIN_UnlockWnds();
140 /* and decrement destruction monitoring value */
141 ptr->irefCount--;
143 error2:
144 if ( hwnd!=0 )
145 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
146 return NULL;
149 /***********************************************************************
150 * WIN_LockWndPtr
152 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
153 * but by initWndPtr;
154 * Returns the locked initialisation pointer
156 WND *WIN_LockWndPtr(WND *initWndPtr)
158 if(!initWndPtr) return 0;
160 /* Lock all WND structures for thread safeness*/
161 WIN_LockWnds();
162 /*and increment destruction monitoring*/
163 initWndPtr->irefCount++;
165 return initWndPtr;
169 /***********************************************************************
170 * WIN_ReleaseWndPtr
172 * Release the pointer to the WND structure.
174 void WIN_ReleaseWndPtr(WND *wndPtr)
176 if(!wndPtr) return;
178 /*Decrement destruction monitoring value*/
179 wndPtr->irefCount--;
180 /* Check if it's time to release the memory*/
181 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
183 /* Release memory */
184 USER_HEAP_FREE( wndPtr->hwndSelf);
185 wndPtr->hwndSelf = 0;
187 else if(wndPtr->irefCount < 0)
189 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
190 ERR("forgot a Lock on %p somewhere\n",wndPtr);
192 /*unlock all WND structures for thread safeness*/
193 WIN_UnlockWnds();
196 /***********************************************************************
197 * WIN_UpdateWndPtr
199 * Updates the value of oldPtr to newPtr.
201 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
203 WND *tmpWnd = NULL;
205 tmpWnd = WIN_LockWndPtr(newPtr);
206 WIN_ReleaseWndPtr(*oldPtr);
207 *oldPtr = tmpWnd;
211 /***********************************************************************
212 * WIN_DumpWindow
214 * Dump the content of a window structure to stderr.
216 void WIN_DumpWindow( HWND hwnd )
218 WND *ptr;
219 char className[80];
220 int i;
222 if (!(ptr = WIN_FindWndPtr( hwnd )))
224 WARN("%04x is not a window handle\n", hwnd );
225 return;
228 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
229 strcpy( className, "#NULL#" );
231 TRACE("Window %04x (%p):\n", hwnd, ptr );
232 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
233 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
234 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
235 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
236 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
237 ptr->next, ptr->child, ptr->parent, ptr->owner,
238 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
239 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
240 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
241 ptr->text ? ptr->text : "",
242 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
243 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
244 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
245 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
247 if (ptr->class->cbWndExtra)
249 DPRINTF( "extra bytes:" );
250 for (i = 0; i < ptr->class->cbWndExtra; i++)
251 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
252 DPRINTF( "\n" );
254 DPRINTF( "\n" );
255 WIN_ReleaseWndPtr(ptr);
259 /***********************************************************************
260 * WIN_WalkWindows
262 * Walk the windows tree and print each window on stderr.
264 void WIN_WalkWindows( HWND hwnd, int indent )
266 WND *ptr;
267 char className[80];
269 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
271 if (!ptr)
273 WARN("Invalid window handle %04x\n", hwnd );
274 return;
277 if (!indent) /* first time around */
278 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
279 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
280 " Text");
282 while (ptr)
284 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
286 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
288 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
289 (DWORD)ptr, ptr->hmemTaskQ, className,
290 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
291 ptr->text?ptr->text:"<null>");
293 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
294 WIN_UpdateWndPtr(&ptr,ptr->next);
300 /***********************************************************************
301 * WIN_UnlinkWindow
303 * Remove a window from the siblings linked list.
305 BOOL WIN_UnlinkWindow( HWND hwnd )
307 WND *wndPtr, **ppWnd;
308 BOOL ret = FALSE;
310 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
311 else if(!wndPtr->parent)
313 WIN_ReleaseWndPtr(wndPtr);
314 return FALSE;
317 ppWnd = &wndPtr->parent->child;
318 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
319 if (*ppWnd)
321 *ppWnd = wndPtr->next;
322 ret = TRUE;
324 WIN_ReleaseWndPtr(wndPtr);
325 return ret;
329 /***********************************************************************
330 * WIN_LinkWindow
332 * Insert a window into the siblings linked list.
333 * The window is inserted after the specified window, which can also
334 * be specified as HWND_TOP or HWND_BOTTOM.
336 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
338 WND *wndPtr, **ppWnd;
340 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
341 else if(!wndPtr->parent)
343 WIN_ReleaseWndPtr(wndPtr);
344 return FALSE;
346 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
348 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
349 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
350 while (*ppWnd) ppWnd = &(*ppWnd)->next;
352 else /* Normal case */
354 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
355 if (!afterPtr)
357 WIN_ReleaseWndPtr(wndPtr);
358 return FALSE;
360 ppWnd = &afterPtr->next;
361 WIN_ReleaseWndPtr(afterPtr);
363 wndPtr->next = *ppWnd;
364 *ppWnd = wndPtr;
365 WIN_ReleaseWndPtr(wndPtr);
366 return TRUE;
370 /***********************************************************************
371 * WIN_FindWinToRepaint
373 * Find a window that needs repaint.
375 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
377 HWND hwndRet;
378 WND *pWnd;
380 /* Note: the desktop window never gets WM_PAINT messages
381 * The real reason why is because Windows DesktopWndProc
382 * does ValidateRgn inside WM_ERASEBKGND handler.
385 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
387 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
389 if (!(pWnd->dwStyle & WS_VISIBLE))
391 TRACE("skipping window %04x\n",
392 pWnd->hwndSelf );
394 else if ((pWnd->hmemTaskQ == hQueue) &&
395 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
396 break;
398 else if (pWnd->child )
399 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
401 WIN_ReleaseWndPtr(pWnd);
402 return hwndRet;
407 if(!pWnd)
409 return 0;
412 hwndRet = pWnd->hwndSelf;
414 /* look among siblings if we got a transparent window */
415 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
416 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
418 WIN_UpdateWndPtr(&pWnd,pWnd->next);
420 if (pWnd)
422 hwndRet = pWnd->hwndSelf;
423 WIN_ReleaseWndPtr(pWnd);
425 TRACE("found %04x\n",hwndRet);
426 return hwndRet;
430 /***********************************************************************
431 * WIN_DestroyWindow
433 * Destroy storage associated to a window. "Internals" p.358
434 * returns a locked wndPtr->next
436 static WND* WIN_DestroyWindow( WND* wndPtr )
438 HWND hwnd = wndPtr->hwndSelf;
439 WND *pWnd;
441 TRACE("%04x\n", wndPtr->hwndSelf );
443 /* free child windows */
444 WIN_LockWndPtr(wndPtr->child);
445 while ((pWnd = wndPtr->child))
447 wndPtr->child = WIN_DestroyWindow( pWnd );
448 WIN_ReleaseWndPtr(pWnd);
452 * Clear the update region to make sure no WM_PAINT messages will be
453 * generated for this window while processing the WM_NCDESTROY.
455 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
457 if (wndPtr->hrgnUpdate > 1)
458 DeleteObject( wndPtr->hrgnUpdate );
460 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
462 wndPtr->hrgnUpdate = 0;
466 * Send the WM_NCDESTROY to the window being destroyed.
468 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
470 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
472 WINPOS_CheckInternalPos( wndPtr );
473 if( hwnd == GetCapture()) ReleaseCapture();
475 /* free resources associated with the window */
477 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
478 PROPERTY_RemoveWindowProps( wndPtr );
480 wndPtr->dwMagic = 0; /* Mark it as invalid */
482 /* toss stale messages from the queue */
484 if( wndPtr->hmemTaskQ )
486 BOOL bPostQuit = FALSE;
487 WPARAM wQuitParam = 0;
488 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
489 QMSG *qmsg;
491 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
493 if( qmsg->msg.message == WM_QUIT )
495 bPostQuit = TRUE;
496 wQuitParam = qmsg->msg.wParam;
498 QUEUE_RemoveMsg(msgQ, qmsg);
501 QUEUE_Unlock(msgQ);
503 /* repost WM_QUIT to make sure this app exits its message loop */
504 if( bPostQuit ) PostQuitMessage(wQuitParam);
505 wndPtr->hmemTaskQ = 0;
508 if (!(wndPtr->dwStyle & WS_CHILD))
509 if (wndPtr->wIDmenu)
511 DestroyMenu( wndPtr->wIDmenu );
512 wndPtr->wIDmenu = 0;
514 if (wndPtr->hSysMenu)
516 DestroyMenu( wndPtr->hSysMenu );
517 wndPtr->hSysMenu = 0;
519 wndPtr->pDriver->pDestroyWindow( wndPtr );
520 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
521 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
522 wndPtr->class->cWindows--;
523 wndPtr->class = NULL;
525 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
527 wndPtr->pDriver->pFinalize(wndPtr);
529 return pWnd;
532 /***********************************************************************
533 * WIN_ResetQueueWindows
535 * Reset the queue of all the children of a given window.
536 * Return TRUE if something was done.
538 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
540 BOOL ret = FALSE;
542 if (hNew) /* Set a new queue */
544 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
546 if (wnd->hmemTaskQ == hQueue)
548 wnd->hmemTaskQ = hNew;
549 ret = TRUE;
551 if (wnd->child)
553 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
557 else /* Queue is being destroyed */
559 while (wnd->child)
561 WND *tmp = WIN_LockWndPtr(wnd->child);
562 WND *tmp2;
563 ret = FALSE;
564 while (tmp)
566 if (tmp->hmemTaskQ == hQueue)
568 DestroyWindow( tmp->hwndSelf );
569 ret = TRUE;
570 break;
572 tmp2 = WIN_LockWndPtr(tmp->child);
573 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
574 ret = TRUE;
575 else
577 WIN_UpdateWndPtr(&tmp,tmp->next);
579 WIN_ReleaseWndPtr(tmp2);
581 WIN_ReleaseWndPtr(tmp);
582 if (!ret) break;
585 return ret;
588 /***********************************************************************
589 * WIN_CreateDesktopWindow
591 * Create the desktop window.
593 BOOL WIN_CreateDesktopWindow(void)
595 CLASS *class;
596 HWND hwndDesktop;
598 TRACE("Creating desktop window\n");
601 if (!ICONTITLE_Init() ||
602 !WINPOS_CreateInternalPosAtom() ||
603 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
604 return FALSE;
606 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
607 if (!hwndDesktop) return FALSE;
608 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
610 pWndDesktop->pDriver = WND_Driver;
611 pWndDesktop->pDriver->pInitialize(pWndDesktop);
613 pWndDesktop->next = NULL;
614 pWndDesktop->child = NULL;
615 pWndDesktop->parent = NULL;
616 pWndDesktop->owner = NULL;
617 pWndDesktop->class = class;
618 pWndDesktop->dwMagic = WND_MAGIC;
619 pWndDesktop->hwndSelf = hwndDesktop;
620 pWndDesktop->hInstance = 0;
621 pWndDesktop->rectWindow.left = 0;
622 pWndDesktop->rectWindow.top = 0;
623 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
624 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
625 pWndDesktop->rectClient = pWndDesktop->rectWindow;
626 pWndDesktop->text = NULL;
627 pWndDesktop->hmemTaskQ = GetFastQueue16();
628 pWndDesktop->hrgnUpdate = 0;
629 pWndDesktop->hwndLastActive = hwndDesktop;
630 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
631 WS_CLIPSIBLINGS;
632 pWndDesktop->dwExStyle = 0;
633 pWndDesktop->dce = NULL;
634 pWndDesktop->pVScroll = NULL;
635 pWndDesktop->pHScroll = NULL;
636 pWndDesktop->pProp = NULL;
637 pWndDesktop->wIDmenu = 0;
638 pWndDesktop->helpContext = 0;
639 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
640 pWndDesktop->hSysMenu = 0;
641 pWndDesktop->userdata = 0;
642 pWndDesktop->winproc = (WNDPROC16)class->winproc;
643 pWndDesktop->irefCount = 0;
645 /* FIXME: How do we know if it should be Unicode or not */
646 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
647 return FALSE;
649 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
650 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
651 return TRUE;
655 /***********************************************************************
656 * WIN_CreateWindowEx
658 * Implementation of CreateWindowEx().
660 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
661 BOOL win32, BOOL unicode )
663 INT sw = SW_SHOW;
664 CLASS *classPtr;
665 WND *wndPtr;
666 HWND retvalue;
667 HWND16 hwnd, hwndLinkAfter;
668 POINT maxSize, maxPos, minTrack, maxTrack;
669 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
671 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
672 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
673 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
674 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
675 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
677 /* Find the parent window */
679 if (cs->hwndParent)
681 /* Make sure parent is valid */
682 if (!IsWindow( cs->hwndParent ))
684 WARN("Bad parent %04x\n", cs->hwndParent );
685 return 0;
687 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
688 WARN("No parent for child window\n" );
689 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
692 /* Find the window class */
693 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
695 WARN("Bad class '%s'\n", cs->lpszClass );
696 return 0;
699 /* Fix the coordinates */
701 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
702 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
704 STARTUPINFOA info;
705 info.dwFlags = 0;
706 if (!(cs->style & (WS_CHILD | WS_POPUP))) GetStartupInfoA( &info );
708 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
710 /* Never believe Microsoft's documentation... CreateWindowEx doc says
711 * that if an overlapped window is created with WS_VISIBLE style bit
712 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
713 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
714 * reveals that
716 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
717 * 2) it does not ignore the y parameter as the docs claim; instead, it
718 * uses it as second parameter to ShowWindow() unless y is either
719 * CW_USEDEFAULT or CW_USEDEFAULT16.
721 * The fact that we didn't do 2) caused bogus windows pop up when wine
722 * was running apps that were using this obscure feature. Example -
723 * calc.exe that comes with Win98 (only Win98, it's different from
724 * the one that comes with Win95 and NT)
726 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
727 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
728 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
730 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
732 cs->cx = (info.dwFlags & STARTF_USESIZE) ? info.dwXSize : 0;
733 cs->cy = (info.dwFlags & STARTF_USESIZE) ? info.dwYSize : 0;
737 /* Create the window structure */
739 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
740 - sizeof(wndPtr->wExtra) )))
742 TRACE("out of memory\n" );
743 return 0;
746 /* Fill the window structure */
748 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
749 wndPtr->next = NULL;
750 wndPtr->child = NULL;
752 if ((cs->style & WS_CHILD) && cs->hwndParent)
754 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
755 wndPtr->owner = NULL;
756 WIN_ReleaseWndPtr(wndPtr->parent);
758 else
760 wndPtr->parent = pWndDesktop;
761 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
762 wndPtr->owner = NULL;
763 else
765 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
766 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
767 WIN_ReleaseWndPtr(wndPtr->owner);
768 WIN_ReleaseWndPtr(tmpWnd);
773 wndPtr->pDriver = wndPtr->parent->pDriver;
774 wndPtr->pDriver->pInitialize(wndPtr);
776 wndPtr->class = classPtr;
777 wndPtr->winproc = classPtr->winproc;
778 wndPtr->dwMagic = WND_MAGIC;
779 wndPtr->hwndSelf = hwnd;
780 wndPtr->hInstance = cs->hInstance;
781 wndPtr->text = NULL;
782 wndPtr->hmemTaskQ = GetFastQueue16();
783 wndPtr->hrgnUpdate = 0;
784 wndPtr->hwndLastActive = hwnd;
785 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
786 wndPtr->dwExStyle = cs->dwExStyle;
787 wndPtr->wIDmenu = 0;
788 wndPtr->helpContext = 0;
789 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
790 wndPtr->pVScroll = NULL;
791 wndPtr->pHScroll = NULL;
792 wndPtr->pProp = NULL;
793 wndPtr->userdata = 0;
794 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
795 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
796 wndPtr->irefCount = 1;
798 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
800 /* Call the WH_CBT hook */
802 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
803 ? HWND_BOTTOM : HWND_TOP;
805 if (HOOK_IsHooked( WH_CBT ))
807 CBT_CREATEWNDA cbtc;
808 LRESULT ret;
810 cbtc.lpcs = cs;
811 cbtc.hwndInsertAfter = hwndLinkAfter;
812 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
813 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
814 if (ret)
816 TRACE("CBT-hook returned 0\n");
817 wndPtr->pDriver->pFinalize(wndPtr);
818 USER_HEAP_FREE( hwnd );
819 retvalue = 0;
820 goto end;
824 /* Increment class window counter */
826 classPtr->cWindows++;
828 /* Correct the window style */
830 if (!(cs->style & WS_CHILD))
832 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
833 if (!(cs->style & WS_POPUP))
835 wndPtr->dwStyle |= WS_CAPTION;
836 wndPtr->flags |= WIN_NEED_SIZE;
840 /* Get class or window DC if needed */
842 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
843 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
844 else wndPtr->dce = NULL;
846 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
848 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
850 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
851 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
852 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
853 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
854 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
857 if(cs->style & WS_CHILD)
859 if(cs->cx < 0) cs->cx = 0;
860 if(cs->cy < 0) cs->cy = 0;
862 else
864 if (cs->cx <= 0) cs->cx = 1;
865 if (cs->cy <= 0) cs->cy = 1;
868 wndPtr->rectWindow.left = cs->x;
869 wndPtr->rectWindow.top = cs->y;
870 wndPtr->rectWindow.right = cs->x + cs->cx;
871 wndPtr->rectWindow.bottom = cs->y + cs->cy;
872 wndPtr->rectClient = wndPtr->rectWindow;
874 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
876 retvalue = FALSE;
877 goto end;
880 /* Set the window menu */
882 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
884 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
885 else
887 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
888 if (classPtr->menuNameA)
889 cs->hMenu = HIWORD(classPtr->menuNameA) ?
890 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
891 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
892 #else
893 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
894 if (menuName)
896 if (HIWORD(cs->hInstance))
897 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
898 else
899 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
901 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
903 #endif
906 else wndPtr->wIDmenu = (UINT)cs->hMenu;
908 /* Send the WM_CREATE message
909 * Perhaps we shouldn't allow width/height changes as well.
910 * See p327 in "Internals".
913 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
915 localSend32 = unicode ? SendMessageW : SendMessageA;
916 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
918 /* Insert the window in the linked list */
920 WIN_LinkWindow( hwnd, hwndLinkAfter );
922 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
923 NULL, NULL, 0, &wndPtr->rectClient );
924 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
925 maxPos.y - wndPtr->rectWindow.top);
926 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
928 /* Send the size messages */
930 if (!(wndPtr->flags & WIN_NEED_SIZE))
932 /* send it anyway */
933 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
934 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
935 WARN("sending bogus WM_SIZE message 0x%08lx\n",
936 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
937 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
938 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
939 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
940 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
941 SendMessageA( hwnd, WM_MOVE, 0,
942 MAKELONG( wndPtr->rectClient.left,
943 wndPtr->rectClient.top ) );
946 /* Show the window, maximizing or minimizing if needed */
948 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
950 RECT16 newPos;
951 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
952 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
953 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
954 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
955 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
956 : SWP_NOZORDER | SWP_FRAMECHANGED;
957 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
958 newPos.right, newPos.bottom, swFlag );
961 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
963 /* Notify the parent window only */
965 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
966 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
967 if( !IsWindow(hwnd) )
969 retvalue = 0;
970 goto end;
974 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
976 /* Call WH_SHELL hook */
978 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
979 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
981 TRACE("created window %04x\n", hwnd);
982 retvalue = hwnd;
983 goto end;
985 WIN_UnlinkWindow( hwnd );
988 /* Abort window creation */
990 WARN("aborted by WM_xxCREATE!\n");
991 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
992 retvalue = 0;
993 end:
994 WIN_ReleaseWndPtr(wndPtr);
996 return retvalue;
1000 /***********************************************************************
1001 * CreateWindow16 (USER.41)
1003 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1004 DWORD style, INT16 x, INT16 y, INT16 width,
1005 INT16 height, HWND16 parent, HMENU16 menu,
1006 HINSTANCE16 instance, LPVOID data )
1008 return CreateWindowEx16( 0, className, windowName, style,
1009 x, y, width, height, parent, menu, instance, data );
1013 /***********************************************************************
1014 * CreateWindowEx16 (USER.452)
1016 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1017 LPCSTR windowName, DWORD style, INT16 x,
1018 INT16 y, INT16 width, INT16 height,
1019 HWND16 parent, HMENU16 menu,
1020 HINSTANCE16 instance, LPVOID data )
1022 ATOM classAtom;
1023 CREATESTRUCTA cs;
1024 char buffer[256];
1026 /* Find the class atom */
1028 if (HIWORD(className))
1030 if (!(classAtom = GlobalFindAtomA( className )))
1032 ERR( "bad class name %s\n", debugres_a(className) );
1033 return 0;
1036 else
1038 classAtom = LOWORD(className);
1039 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1041 ERR( "bad atom %x\n", classAtom);
1042 return 0;
1044 className = buffer;
1047 /* Fix the coordinates */
1049 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1050 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1051 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1052 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1054 /* Create the window */
1056 cs.lpCreateParams = data;
1057 cs.hInstance = (HINSTANCE)instance;
1058 cs.hMenu = (HMENU)menu;
1059 cs.hwndParent = (HWND)parent;
1060 cs.style = style;
1061 cs.lpszName = windowName;
1062 cs.lpszClass = className;
1063 cs.dwExStyle = exStyle;
1065 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1069 /***********************************************************************
1070 * CreateWindowExA (USER32.83)
1072 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1073 LPCSTR windowName, DWORD style, INT x,
1074 INT y, INT width, INT height,
1075 HWND parent, HMENU menu,
1076 HINSTANCE instance, LPVOID data )
1078 ATOM classAtom;
1079 CREATESTRUCTA cs;
1080 char buffer[256];
1082 if(!instance)
1083 instance=GetModuleHandleA(NULL);
1085 if(exStyle & WS_EX_MDICHILD)
1086 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1088 /* Find the class atom */
1090 if (HIWORD(className))
1092 if (!(classAtom = GlobalFindAtomA( className )))
1094 ERR( "bad class name %s\n", debugres_a(className) );
1095 return 0;
1098 else
1100 classAtom = LOWORD(className);
1101 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1103 ERR( "bad atom %x\n", classAtom);
1104 return 0;
1106 className = buffer;
1109 /* Create the window */
1111 cs.lpCreateParams = data;
1112 cs.hInstance = instance;
1113 cs.hMenu = menu;
1114 cs.hwndParent = parent;
1115 cs.x = x;
1116 cs.y = y;
1117 cs.cx = width;
1118 cs.cy = height;
1119 cs.style = style;
1120 cs.lpszName = windowName;
1121 cs.lpszClass = className;
1122 cs.dwExStyle = exStyle;
1124 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1128 /***********************************************************************
1129 * CreateWindowExW (USER32.84)
1131 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1132 LPCWSTR windowName, DWORD style, INT x,
1133 INT y, INT width, INT height,
1134 HWND parent, HMENU menu,
1135 HINSTANCE instance, LPVOID data )
1137 ATOM classAtom;
1138 CREATESTRUCTW cs;
1139 WCHAR buffer[256];
1141 if(!instance)
1142 instance=GetModuleHandleA(NULL);
1144 if(exStyle & WS_EX_MDICHILD)
1145 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1147 /* Find the class atom */
1149 if (HIWORD(className))
1151 if (!(classAtom = GlobalFindAtomW( className )))
1153 ERR( "bad class name %s\n", debugres_w(className) );
1154 return 0;
1157 else
1159 classAtom = LOWORD(className);
1160 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1162 ERR( "bad atom %x\n", classAtom);
1163 return 0;
1165 className = buffer;
1168 /* Create the window */
1170 cs.lpCreateParams = data;
1171 cs.hInstance = instance;
1172 cs.hMenu = menu;
1173 cs.hwndParent = parent;
1174 cs.x = x;
1175 cs.y = y;
1176 cs.cx = width;
1177 cs.cy = height;
1178 cs.style = style;
1179 cs.lpszName = windowName;
1180 cs.lpszClass = className;
1181 cs.dwExStyle = exStyle;
1183 /* Note: we rely on the fact that CREATESTRUCTA and */
1184 /* CREATESTRUCTW have the same layout. */
1185 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1189 /***********************************************************************
1190 * WIN_CheckFocus
1192 static void WIN_CheckFocus( WND* pWnd )
1194 if( GetFocus16() == pWnd->hwndSelf )
1195 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1198 /***********************************************************************
1199 * WIN_SendDestroyMsg
1201 static void WIN_SendDestroyMsg( WND* pWnd )
1203 WIN_CheckFocus(pWnd);
1205 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1206 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1209 * Send the WM_DESTROY to the window.
1211 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1214 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1215 * make sure that the window still exists when we come back.
1217 if (IsWindow(pWnd->hwndSelf))
1219 HWND* pWndArray = NULL;
1220 WND* pChild = NULL;
1221 int nKidCount = 0;
1224 * Now, if the window has kids, we have to send WM_DESTROY messages
1225 * recursively to it's kids. It seems that those calls can also
1226 * trigger re-entrant calls to DestroyWindow for the kids so we must
1227 * protect against corruption of the list of siblings. We first build
1228 * a list of HWNDs representing all the kids.
1230 pChild = WIN_LockWndPtr(pWnd->child);
1231 while( pChild )
1233 nKidCount++;
1234 WIN_UpdateWndPtr(&pChild,pChild->next);
1238 * If there are no kids, we're done.
1240 if (nKidCount==0)
1241 return;
1243 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1246 * Sanity check
1248 if (pWndArray==NULL)
1249 return;
1252 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1253 * call, our linked list of siblings should be safe.
1255 nKidCount = 0;
1256 pChild = WIN_LockWndPtr(pWnd->child);
1257 while( pChild )
1259 pWndArray[nKidCount] = pChild->hwndSelf;
1260 nKidCount++;
1261 WIN_UpdateWndPtr(&pChild,pChild->next);
1265 * Now that we have a list, go through that list again and send the destroy
1266 * message to those windows. We are using the HWND to retrieve the
1267 * WND pointer so we are effectively checking that all the kid windows are
1268 * still valid before sending the message.
1270 while (nKidCount>0)
1272 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1274 if (pChild!=NULL)
1276 WIN_SendDestroyMsg( pChild );
1277 WIN_ReleaseWndPtr(pChild);
1282 * Cleanup
1284 HeapFree(GetProcessHeap(), 0, pWndArray);
1285 WIN_CheckFocus(pWnd);
1287 else
1288 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1292 /***********************************************************************
1293 * DestroyWindow16 (USER.53)
1295 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1297 return DestroyWindow(hwnd);
1301 /***********************************************************************
1302 * DestroyWindow (USER32.135)
1304 BOOL WINAPI DestroyWindow( HWND hwnd )
1306 WND * wndPtr;
1307 BOOL retvalue;
1309 TRACE("(%04x)\n", hwnd);
1311 /* Initialization */
1313 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1314 if (wndPtr == pWndDesktop)
1316 retvalue = FALSE; /* Can't destroy desktop */
1317 goto end;
1320 /* Call hooks */
1322 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1324 retvalue = FALSE;
1325 goto end;
1328 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1330 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1331 /* FIXME: clean up palette - see "Internals" p.352 */
1334 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1335 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1337 /* Notify the parent window only */
1338 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1339 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1340 if( !IsWindow(hwnd) )
1342 retvalue = TRUE;
1343 goto end;
1347 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1349 /* Hide the window */
1351 if (wndPtr->dwStyle & WS_VISIBLE)
1353 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1354 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1355 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1356 if (!IsWindow(hwnd))
1358 retvalue = TRUE;
1359 goto end;
1363 /* Recursively destroy owned windows */
1365 if( !(wndPtr->dwStyle & WS_CHILD) )
1367 /* make sure top menu popup doesn't get destroyed */
1368 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1370 for (;;)
1372 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1373 while (siblingPtr)
1375 if (siblingPtr->owner == wndPtr)
1377 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1378 break;
1379 else
1380 siblingPtr->owner = NULL;
1382 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1384 if (siblingPtr)
1386 DestroyWindow( siblingPtr->hwndSelf );
1387 WIN_ReleaseWndPtr(siblingPtr);
1389 else break;
1392 if( !Options.managed || EVENT_CheckFocus() )
1393 WINPOS_ActivateOtherWindow(wndPtr);
1395 if( wndPtr->owner &&
1396 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1397 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1400 /* Send destroy messages */
1402 WIN_SendDestroyMsg( wndPtr );
1403 if (!IsWindow(hwnd))
1405 retvalue = TRUE;
1406 goto end;
1409 /* Unlink now so we won't bother with the children later on */
1411 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1413 /* Destroy the window storage */
1415 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1416 retvalue = TRUE;
1417 end:
1418 WIN_ReleaseWndPtr(wndPtr);
1419 return retvalue;
1423 /***********************************************************************
1424 * CloseWindow16 (USER.43)
1426 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1428 return CloseWindow( hwnd );
1432 /***********************************************************************
1433 * CloseWindow (USER32.56)
1435 BOOL WINAPI CloseWindow( HWND hwnd )
1437 WND * wndPtr = WIN_FindWndPtr( hwnd );
1438 BOOL retvalue;
1440 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1442 retvalue = FALSE;
1443 goto end;
1445 ShowWindow( hwnd, SW_MINIMIZE );
1446 retvalue = TRUE;
1447 end:
1448 WIN_ReleaseWndPtr(wndPtr);
1449 return retvalue;
1454 /***********************************************************************
1455 * OpenIcon16 (USER.44)
1457 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1459 return OpenIcon( hwnd );
1463 /***********************************************************************
1464 * OpenIcon (USER32.410)
1466 BOOL WINAPI OpenIcon( HWND hwnd )
1468 if (!IsIconic( hwnd )) return FALSE;
1469 ShowWindow( hwnd, SW_SHOWNORMAL );
1470 return TRUE;
1474 /***********************************************************************
1475 * WIN_FindWindow
1477 * Implementation of FindWindow() and FindWindowEx().
1479 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1480 LPCSTR title )
1482 WND *pWnd;
1483 HWND retvalue;
1485 if (child)
1487 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1488 if (parent)
1490 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1492 retvalue = 0;
1493 goto end;
1496 else if (pWnd->parent != pWndDesktop)
1498 retvalue = 0;
1499 goto end;
1501 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1503 else
1505 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1507 retvalue = 0;
1508 goto end;
1510 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1512 if (!pWnd)
1514 retvalue = 0;
1515 goto end;
1518 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1520 if (className && (pWnd->class->atomName != className))
1521 continue; /* Not the right class */
1523 /* Now check the title */
1525 if (!title)
1527 retvalue = pWnd->hwndSelf;
1528 goto end;
1530 if (pWnd->text && !strcmp( pWnd->text, title ))
1532 retvalue = pWnd->hwndSelf;
1533 goto end;
1536 retvalue = 0;
1537 end:
1538 WIN_ReleaseWndPtr(pWnd);
1539 return retvalue;
1544 /***********************************************************************
1545 * FindWindow16 (USER.50)
1547 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1549 return FindWindowA( className, title );
1553 /***********************************************************************
1554 * FindWindowEx16 (USER.427)
1556 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1558 return FindWindowExA( parent, child, className, title );
1562 /***********************************************************************
1563 * FindWindowA (USER32.198)
1565 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1567 HWND ret = FindWindowExA( 0, 0, className, title );
1568 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1569 return ret;
1573 /***********************************************************************
1574 * FindWindowExA (USER32.199)
1576 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1577 LPCSTR className, LPCSTR title )
1579 ATOM atom = 0;
1581 if (className)
1583 /* If the atom doesn't exist, then no class */
1584 /* with this name exists either. */
1585 if (!(atom = GlobalFindAtomA( className )))
1587 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1588 return 0;
1591 return WIN_FindWindow( parent, child, atom, title );
1595 /***********************************************************************
1596 * FindWindowExW (USER32.200)
1598 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1599 LPCWSTR className, LPCWSTR title )
1601 ATOM atom = 0;
1602 char *buffer;
1603 HWND hwnd;
1605 if (className)
1607 /* If the atom doesn't exist, then no class */
1608 /* with this name exists either. */
1609 if (!(atom = GlobalFindAtomW( className )))
1611 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1612 return 0;
1615 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1616 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1617 HeapFree( GetProcessHeap(), 0, buffer );
1618 return hwnd;
1622 /***********************************************************************
1623 * FindWindowW (USER32.201)
1625 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1627 return FindWindowExW( 0, 0, className, title );
1631 /**********************************************************************
1632 * WIN_GetDesktop
1633 * returns a locked pointer
1635 WND *WIN_GetDesktop(void)
1637 return WIN_LockWndPtr(pWndDesktop);
1639 /**********************************************************************
1640 * WIN_ReleaseDesktop
1641 * unlock the desktop pointer
1643 void WIN_ReleaseDesktop(void)
1645 WIN_ReleaseWndPtr(pWndDesktop);
1649 /**********************************************************************
1650 * GetDesktopWindow16 (USER.286)
1652 HWND16 WINAPI GetDesktopWindow16(void)
1654 return (HWND16)pWndDesktop->hwndSelf;
1658 /**********************************************************************
1659 * GetDesktopWindow (USER32.232)
1661 HWND WINAPI GetDesktopWindow(void)
1663 if (pWndDesktop) return pWndDesktop->hwndSelf;
1664 ERR( "You need the -desktop option when running with native USER\n" );
1665 ExitProcess(1);
1666 return 0;
1670 /**********************************************************************
1671 * GetDesktopHwnd (USER.278)
1673 * Exactly the same thing as GetDesktopWindow(), but not documented.
1674 * Don't ask me why...
1676 HWND16 WINAPI GetDesktopHwnd16(void)
1678 return (HWND16)pWndDesktop->hwndSelf;
1682 /*******************************************************************
1683 * EnableWindow16 (USER.34)
1685 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1687 return EnableWindow( hwnd, enable );
1691 /*******************************************************************
1692 * EnableWindow (USER32.172)
1694 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1696 WND *wndPtr;
1697 BOOL retvalue;
1699 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1701 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1702 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1704 /* Enable window */
1705 wndPtr->dwStyle &= ~WS_DISABLED;
1707 if( wndPtr->flags & WIN_NATIVE )
1708 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1710 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1711 retvalue = TRUE;
1712 goto end;
1714 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1716 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1718 /* Disable window */
1719 wndPtr->dwStyle |= WS_DISABLED;
1721 if( wndPtr->flags & WIN_NATIVE )
1722 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1724 if (hwnd == GetFocus())
1726 SetFocus( 0 ); /* A disabled window can't have the focus */
1728 if (hwnd == GetCapture())
1730 ReleaseCapture(); /* A disabled window can't capture the mouse */
1732 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1733 retvalue = FALSE;
1734 goto end;
1736 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1737 end:
1738 WIN_ReleaseWndPtr(wndPtr);
1739 return retvalue;
1743 /***********************************************************************
1744 * IsWindowEnabled16 (USER.35)
1746 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1748 return IsWindowEnabled(hWnd);
1752 /***********************************************************************
1753 * IsWindowEnabled (USER32.349)
1755 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1757 WND * wndPtr;
1758 BOOL retvalue;
1760 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1761 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1762 WIN_ReleaseWndPtr(wndPtr);
1763 return retvalue;
1768 /***********************************************************************
1769 * IsWindowUnicode (USER32.350)
1771 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1773 WND * wndPtr;
1774 BOOL retvalue;
1776 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1777 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1778 WIN_ReleaseWndPtr(wndPtr);
1779 return retvalue;
1783 /**********************************************************************
1784 * GetWindowWord16 (USER.133)
1786 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1788 return GetWindowWord( hwnd, offset );
1792 /**********************************************************************
1793 * GetWindowWord (USER32.314)
1795 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1797 WORD retvalue;
1798 WND * wndPtr = WIN_FindWndPtr( hwnd );
1799 if (!wndPtr) return 0;
1800 if (offset >= 0)
1802 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1804 WARN("Invalid offset %d\n", offset );
1805 retvalue = 0;
1806 goto end;
1808 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1809 goto end;
1811 switch(offset)
1813 case GWW_ID:
1814 if (HIWORD(wndPtr->wIDmenu))
1815 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1816 wndPtr->wIDmenu);
1817 retvalue = (WORD)wndPtr->wIDmenu;
1818 goto end;
1819 case GWW_HWNDPARENT:
1820 retvalue = GetParent(hwnd);
1821 goto end;
1822 case GWW_HINSTANCE:
1823 if (HIWORD(wndPtr->hInstance))
1824 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1825 wndPtr->hInstance);
1826 retvalue = (WORD)wndPtr->hInstance;
1827 goto end;
1828 default:
1829 WARN("Invalid offset %d\n", offset );
1830 retvalue = 0;
1831 goto end;
1833 end:
1834 WIN_ReleaseWndPtr(wndPtr);
1835 return retvalue;
1838 /**********************************************************************
1839 * SetWindowWord16 (USER.134)
1841 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1843 return SetWindowWord( hwnd, offset, newval );
1847 /**********************************************************************
1848 * SetWindowWord (USER32.524)
1850 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1852 WORD *ptr, retval;
1853 WND * wndPtr = WIN_FindWndPtr( hwnd );
1854 if (!wndPtr) return 0;
1855 if (offset >= 0)
1857 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1859 WARN("Invalid offset %d\n", offset );
1860 retval = 0;
1861 goto end;
1863 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1865 else switch(offset)
1867 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1868 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1869 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1870 goto end;
1871 default:
1872 WARN("Invalid offset %d\n", offset );
1873 retval = 0;
1874 goto end;
1876 retval = *ptr;
1877 *ptr = newval;
1878 end:
1879 WIN_ReleaseWndPtr(wndPtr);
1880 return retval;
1884 /**********************************************************************
1885 * WIN_GetWindowLong
1887 * Helper function for GetWindowLong().
1889 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1891 LONG retvalue;
1892 WND * wndPtr = WIN_FindWndPtr( hwnd );
1893 if (!wndPtr) return 0;
1894 if (offset >= 0)
1896 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1898 WARN("Invalid offset %d\n", offset );
1899 retvalue = 0;
1900 goto end;
1902 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1903 /* Special case for dialog window procedure */
1904 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1906 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1907 goto end;
1909 goto end;
1911 switch(offset)
1913 case GWL_USERDATA: retvalue = wndPtr->userdata;
1914 goto end;
1915 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1916 goto end;
1917 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1918 goto end;
1919 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1920 goto end;
1921 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1922 type );
1923 goto end;
1924 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1925 goto end;
1926 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1927 goto end;
1928 default:
1929 WARN("Unknown offset %d\n", offset );
1931 retvalue = 0;
1932 end:
1933 WIN_ReleaseWndPtr(wndPtr);
1934 return retvalue;
1938 /**********************************************************************
1939 * WIN_SetWindowLong
1941 * Helper function for SetWindowLong().
1943 * 0 is the failure code. However, in the case of failure SetLastError
1944 * must be set to distinguish between a 0 return value and a failure.
1946 * FIXME: The error values for SetLastError may not be right. Can
1947 * someone check with the real thing?
1949 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1950 WINDOWPROCTYPE type )
1952 LONG *ptr, retval;
1953 WND * wndPtr = WIN_FindWndPtr( hwnd );
1954 STYLESTRUCT style;
1956 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1958 if (!wndPtr)
1960 /* Is this the right error? */
1961 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1962 return 0;
1965 if (offset >= 0)
1967 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1969 WARN("Invalid offset %d\n", offset );
1971 /* Is this the right error? */
1972 SetLastError( ERROR_OUTOFMEMORY );
1974 retval = 0;
1975 goto end;
1977 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1978 /* Special case for dialog window procedure */
1979 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1981 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1982 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1983 type, WIN_PROC_WINDOW );
1984 goto end;
1987 else switch(offset)
1989 case GWL_ID:
1990 ptr = (DWORD*)&wndPtr->wIDmenu;
1991 break;
1992 case GWL_HINSTANCE:
1993 retval = SetWindowWord( hwnd, offset, newval );
1994 goto end;
1995 case GWL_WNDPROC:
1996 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1997 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1998 type, WIN_PROC_WINDOW );
1999 goto end;
2000 case GWL_STYLE:
2001 style.styleOld = wndPtr->dwStyle;
2002 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2003 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2005 if (wndPtr->flags & WIN_ISWIN32)
2006 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2007 wndPtr->dwStyle = style.styleNew;
2008 if (wndPtr->flags & WIN_ISWIN32)
2009 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2010 retval = style.styleOld;
2011 goto end;
2013 case GWL_USERDATA:
2014 ptr = &wndPtr->userdata;
2015 break;
2016 case GWL_EXSTYLE:
2017 style.styleOld = wndPtr->dwExStyle;
2018 style.styleNew = newval;
2019 if (wndPtr->flags & WIN_ISWIN32)
2020 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2021 wndPtr->dwExStyle = newval;
2022 if (wndPtr->flags & WIN_ISWIN32)
2023 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2024 retval = style.styleOld;
2025 goto end;
2027 default:
2028 WARN("Invalid offset %d\n", offset );
2030 /* Don't think this is right error but it should do */
2031 SetLastError( ERROR_OUTOFMEMORY );
2033 retval = 0;
2034 goto end;
2036 retval = *ptr;
2037 *ptr = newval;
2038 end:
2039 WIN_ReleaseWndPtr(wndPtr);
2040 return retval;
2044 /**********************************************************************
2045 * GetWindowLong16 (USER.135)
2047 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2049 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2053 /**********************************************************************
2054 * GetWindowLongA (USER32.305)
2056 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2058 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2062 /**********************************************************************
2063 * GetWindowLongW (USER32.306)
2065 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2067 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2071 /**********************************************************************
2072 * SetWindowLong16 (USER.136)
2074 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2076 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2080 /**********************************************************************
2081 * SetWindowLongA (USER32.517)
2083 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2085 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2089 /**********************************************************************
2090 * SetWindowLongW (USER32.518) Set window attribute
2092 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2093 * value in a window's extra memory.
2095 * The _hwnd_ parameter specifies the window. is the handle to a
2096 * window that has extra memory. The _newval_ parameter contains the
2097 * new attribute or extra memory value. If positive, the _offset_
2098 * parameter is the byte-addressed location in the window's extra
2099 * memory to set. If negative, _offset_ specifies the window
2100 * attribute to set, and should be one of the following values:
2102 * GWL_EXSTYLE The window's extended window style
2104 * GWL_STYLE The window's window style.
2106 * GWL_WNDPROC Pointer to the window's window procedure.
2108 * GWL_HINSTANCE The window's pplication instance handle.
2110 * GWL_ID The window's identifier.
2112 * GWL_USERDATA The window's user-specified data.
2114 * If the window is a dialog box, the _offset_ parameter can be one of
2115 * the following values:
2117 * DWL_DLGPROC The address of the window's dialog box procedure.
2119 * DWL_MSGRESULT The return value of a message
2120 * that the dialog box procedure processed.
2122 * DWL_USER Application specific information.
2124 * RETURNS
2126 * If successful, returns the previous value located at _offset_. Otherwise,
2127 * returns 0.
2129 * NOTES
2131 * Extra memory for a window class is specified by a nonzero cbWndExtra
2132 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2133 * time of class creation.
2135 * Using GWL_WNDPROC to set a new window procedure effectively creates
2136 * a window subclass. Use CallWindowProc() in the new windows procedure
2137 * to pass messages to the superclass's window procedure.
2139 * The user data is reserved for use by the application which created
2140 * the window.
2142 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2143 * instead, call the EnableWindow() function to change the window's
2144 * disabled state.
2146 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2147 * SetParent() instead.
2149 * Win95:
2150 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2151 * it sends WM_STYLECHANGING before changing the settings
2152 * and WM_STYLECHANGED afterwards.
2153 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2155 * BUGS
2157 * GWL_STYLE does not dispatch WM_STYLE... messages.
2159 * CONFORMANCE
2161 * ECMA-234, Win32
2164 LONG WINAPI SetWindowLongW(
2165 HWND hwnd, /* window to alter */
2166 INT offset, /* offset, in bytes, of location to alter */
2167 LONG newval /* new value of location */
2169 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2173 /*******************************************************************
2174 * GetWindowText16 (USER.36)
2176 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2178 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2182 /*******************************************************************
2183 * GetWindowTextA (USER32.309)
2185 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2187 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2188 (LPARAM)lpString );
2191 /*******************************************************************
2192 * InternalGetWindowText (USER32.326)
2194 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2196 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2197 return GetWindowTextW(hwnd,lpString,nMaxCount);
2201 /*******************************************************************
2202 * GetWindowTextW (USER32.312)
2204 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2206 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2207 (LPARAM)lpString );
2211 /*******************************************************************
2212 * SetWindowText16 (USER.37)
2214 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2216 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2220 /*******************************************************************
2221 * SetWindowTextA (USER32.521)
2223 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2225 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2229 /*******************************************************************
2230 * SetWindowTextW (USER32.523)
2232 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2234 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2238 /*******************************************************************
2239 * GetWindowTextLength16 (USER.38)
2241 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2243 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2247 /*******************************************************************
2248 * GetWindowTextLengthA (USER32.310)
2250 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2252 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2255 /*******************************************************************
2256 * GetWindowTextLengthW (USER32.311)
2258 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2260 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2264 /*******************************************************************
2265 * IsWindow16 (USER.47)
2267 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2269 CURRENT_STACK16->es = USER_HeapSel;
2270 return IsWindow( hwnd );
2274 /*******************************************************************
2275 * IsWindow (USER32.348)
2277 BOOL WINAPI IsWindow( HWND hwnd )
2279 WND * wndPtr;
2280 BOOL retvalue;
2282 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2283 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2284 WIN_ReleaseWndPtr(wndPtr);
2285 return retvalue;
2290 /*****************************************************************
2291 * GetParent16 (USER.46)
2293 HWND16 WINAPI GetParent16( HWND16 hwnd )
2295 return (HWND16)GetParent( hwnd );
2299 /*****************************************************************
2300 * GetParent (USER32.278)
2302 HWND WINAPI GetParent( HWND hwnd )
2304 WND *wndPtr;
2305 HWND retvalue = 0;
2307 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2308 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2309 goto end;
2311 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2312 if (wndPtr)
2313 retvalue = wndPtr->hwndSelf;
2315 end:
2316 WIN_ReleaseWndPtr(wndPtr);
2317 return retvalue;
2321 /*****************************************************************
2322 * WIN_GetTopParent
2324 * Get the top-level parent for a child window.
2325 * returns a locked pointer
2327 WND* WIN_GetTopParentPtr( WND* pWnd )
2329 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2331 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2333 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2335 return tmpWnd;
2338 /*****************************************************************
2339 * WIN_GetTopParent
2341 * Get the top-level parent for a child window.
2343 HWND WIN_GetTopParent( HWND hwnd )
2345 HWND retvalue;
2346 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2347 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2349 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2350 WIN_ReleaseWndPtr(tmpPtr);
2351 WIN_ReleaseWndPtr(wndPtr);
2352 return retvalue;
2356 /*****************************************************************
2357 * SetParent16 (USER.233)
2359 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2361 return SetParent( hwndChild, hwndNewParent );
2365 /*****************************************************************
2366 * SetParent (USER32.495)
2368 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2370 WND *wndPtr;
2371 DWORD dwStyle;
2372 WND *pWndNewParent;
2373 WND *pWndOldParent;
2374 HWND retvalue;
2377 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2379 dwStyle = wndPtr->dwStyle;
2381 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2382 : WIN_LockWndPtr(pWndDesktop);
2384 /* Windows hides the window first, then shows it again
2385 * including the WM_SHOWWINDOW messages and all */
2386 if (dwStyle & WS_VISIBLE)
2387 ShowWindow( hwndChild, SW_HIDE );
2389 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2391 /* SetParent additionally needs to make hwndChild the topmost window
2392 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2393 WM_WINDOWPOSCHANGED notification messages.
2395 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2396 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2397 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2398 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2400 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2402 WIN_ReleaseWndPtr(pWndOldParent);
2403 WIN_ReleaseWndPtr(pWndNewParent);
2404 WIN_ReleaseWndPtr(wndPtr);
2406 return retvalue;
2410 /*******************************************************************
2411 * IsChild16 (USER.48)
2413 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2415 return IsChild(parent,child);
2419 /*******************************************************************
2420 * IsChild (USER32.339)
2422 BOOL WINAPI IsChild( HWND parent, HWND child )
2424 WND * wndPtr = WIN_FindWndPtr( child );
2425 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2427 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2428 if (wndPtr->hwndSelf == parent)
2430 WIN_ReleaseWndPtr(wndPtr);
2431 return TRUE;
2434 WIN_ReleaseWndPtr(wndPtr);
2435 return FALSE;
2439 /***********************************************************************
2440 * IsWindowVisible16 (USER.49)
2442 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2444 return IsWindowVisible(hwnd);
2448 /***********************************************************************
2449 * IsWindowVisible (USER32.351)
2451 BOOL WINAPI IsWindowVisible( HWND hwnd )
2453 BOOL retval;
2454 WND *wndPtr = WIN_FindWndPtr( hwnd );
2455 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2457 if (!(wndPtr->dwStyle & WS_VISIBLE))
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return FALSE;
2462 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2464 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2465 WIN_ReleaseWndPtr(wndPtr);
2466 return retval;
2471 /***********************************************************************
2472 * WIN_IsWindowDrawable
2474 * hwnd is drawable when it is visible, all parents are not
2475 * minimized, and it is itself not minimized unless we are
2476 * trying to draw its default class icon.
2478 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2480 if( (wnd->dwStyle & WS_MINIMIZE &&
2481 icon && wnd->class->hIcon) ||
2482 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2483 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2484 if( wnd->dwStyle & WS_MINIMIZE ||
2485 !(wnd->dwStyle & WS_VISIBLE) ) break;
2486 return (wnd == NULL);
2490 /*******************************************************************
2491 * GetTopWindow16 (USER.229)
2493 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2495 return GetTopWindow(hwnd);
2499 /*******************************************************************
2500 * GetTopWindow (USER.229)
2502 HWND WINAPI GetTopWindow( HWND hwnd )
2504 HWND retval = 0;
2505 WND * wndPtr = (hwnd) ?
2506 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2508 if (wndPtr && wndPtr->child)
2509 retval = wndPtr->child->hwndSelf;
2511 WIN_ReleaseWndPtr(wndPtr);
2512 return retval;
2516 /*******************************************************************
2517 * GetWindow16 (USER.262)
2519 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2521 return GetWindow( hwnd,rel );
2525 /*******************************************************************
2526 * GetWindow (USER32.302)
2528 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2530 HWND retval;
2532 WND * wndPtr = WIN_FindWndPtr( hwnd );
2533 if (!wndPtr) return 0;
2534 switch(rel)
2536 case GW_HWNDFIRST:
2537 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2538 goto end;
2540 case GW_HWNDLAST:
2541 if (!wndPtr->parent)
2543 retval = 0; /* Desktop window */
2544 goto end;
2546 while (wndPtr->next)
2548 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2550 retval = wndPtr->hwndSelf;
2551 goto end;
2553 case GW_HWNDNEXT:
2554 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2555 goto end;
2557 case GW_HWNDPREV:
2558 if (!wndPtr->parent)
2560 retval = 0; /* Desktop window */
2561 goto end;
2563 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2564 if (wndPtr->hwndSelf == hwnd)
2566 retval = 0; /* First in list */
2567 goto end;
2569 while (wndPtr->next)
2571 if (wndPtr->next->hwndSelf == hwnd)
2573 retval = wndPtr->hwndSelf;
2574 goto end;
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2578 retval = 0;
2579 goto end;
2581 case GW_OWNER:
2582 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2583 goto end;
2585 case GW_CHILD:
2586 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2587 goto end;
2589 retval = 0;
2590 end:
2591 WIN_ReleaseWndPtr(wndPtr);
2592 return retval;
2596 /*******************************************************************
2597 * GetNextWindow16 (USER.230)
2599 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2601 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2602 return GetWindow16( hwnd, flag );
2605 /*******************************************************************
2606 * ShowOwnedPopups16 (USER.265)
2608 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2610 ShowOwnedPopups( owner, fShow );
2614 /*******************************************************************
2615 * ShowOwnedPopups (USER32.531)
2617 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2619 UINT totalChild=0, count=0;
2621 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2623 if (!pWnd) return TRUE;
2625 for (; count < totalChild; count++)
2627 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2629 if (fShow)
2631 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2633 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2634 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2637 else
2639 if (IsWindowVisible(pWnd[count]->hwndSelf))
2641 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2642 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2648 WIN_ReleaseDesktop();
2649 WIN_ReleaseWinArray(pWnd);
2650 return TRUE;
2654 /*******************************************************************
2655 * GetLastActivePopup16 (USER.287)
2657 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2659 return GetLastActivePopup( hwnd );
2662 /*******************************************************************
2663 * GetLastActivePopup (USER32.256)
2665 HWND WINAPI GetLastActivePopup( HWND hwnd )
2667 HWND retval;
2668 WND *wndPtr =WIN_FindWndPtr(hwnd);
2669 if (!wndPtr) return hwnd;
2670 retval = wndPtr->hwndLastActive;
2671 WIN_ReleaseWndPtr(wndPtr);
2672 return retval;
2676 /*******************************************************************
2677 * WIN_BuildWinArray
2679 * Build an array of pointers to the children of a given window.
2680 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2681 * when no windows are found.
2683 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2685 /* Future: this function will lock all windows associated with this array */
2687 WND **list, **ppWnd;
2688 WND *pWnd;
2689 UINT count = 0, skipOwned, skipHidden;
2690 DWORD skipFlags;
2692 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2693 skipOwned = bwaFlags & BWA_SKIPOWNED;
2694 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2695 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2697 /* First count the windows */
2699 if (!wndPtr)
2700 wndPtr = WIN_GetDesktop();
2702 pWnd = WIN_LockWndPtr(wndPtr->child);
2703 while (pWnd)
2705 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2706 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2707 count++;
2708 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2711 if( count )
2713 /* Now build the list of all windows */
2715 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2717 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2719 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2720 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2722 *ppWnd++ = pWnd;
2723 count++;
2726 WIN_ReleaseWndPtr(pWnd);
2727 *ppWnd = NULL;
2729 else count = 0;
2730 } else list = NULL;
2732 if( pTotal ) *pTotal = count;
2733 return list;
2735 /*******************************************************************
2736 * WIN_ReleaseWinArray
2738 void WIN_ReleaseWinArray(WND **wndArray)
2740 /* Future: this function will also unlock all windows associated with wndArray */
2741 HeapFree( GetProcessHeap(), 0, wndArray );
2745 /*******************************************************************
2746 * EnumWindows (USER32.193)
2748 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2750 WND **list, **ppWnd;
2752 /* We have to build a list of all windows first, to avoid */
2753 /* unpleasant side-effects, for instance if the callback */
2754 /* function changes the Z-order of the windows. */
2756 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2758 WIN_ReleaseDesktop();
2759 return FALSE;
2762 /* Now call the callback function for every window */
2764 for (ppWnd = list; *ppWnd; ppWnd++)
2766 LRESULT lpEnumFuncRetval;
2767 int iWndsLocks = 0;
2768 /* Make sure that the window still exists */
2769 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2771 /* To avoid any deadlocks, all the locks on the windows
2772 structures must be suspended before the control
2773 is passed to the application */
2774 iWndsLocks = WIN_SuspendWndsLock();
2775 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2776 WIN_RestoreWndsLock(iWndsLocks);
2778 if (!lpEnumFuncRetval) break;
2780 WIN_ReleaseWinArray(list);
2781 WIN_ReleaseDesktop();
2782 return TRUE;
2786 /**********************************************************************
2787 * EnumTaskWindows16 (USER.225)
2789 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2790 LPARAM lParam )
2792 WND **list, **ppWnd;
2794 /* This function is the same as EnumWindows(), */
2795 /* except for an added check on the window's task. */
2797 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2799 WIN_ReleaseDesktop();
2800 return FALSE;
2803 /* Now call the callback function for every window */
2805 for (ppWnd = list; *ppWnd; ppWnd++)
2807 LRESULT funcRetval;
2808 int iWndsLocks = 0;
2809 /* Make sure that the window still exists */
2810 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2811 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2813 /* To avoid any deadlocks, all the locks on the windows
2814 structures must be suspended before the control
2815 is passed to the application */
2816 iWndsLocks = WIN_SuspendWndsLock();
2817 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2818 WIN_RestoreWndsLock(iWndsLocks);
2820 if (!funcRetval) break;
2822 WIN_ReleaseWinArray(list);
2823 WIN_ReleaseDesktop();
2824 return TRUE;
2828 /**********************************************************************
2829 * EnumThreadWindows (USER32.190)
2831 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2833 TEB *teb = THREAD_IdToTEB(id);
2835 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2839 /**********************************************************************
2840 * WIN_EnumChildWindows
2842 * Helper function for EnumChildWindows().
2844 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2846 WND **childList;
2847 BOOL16 ret = FALSE;
2849 for ( ; *ppWnd; ppWnd++)
2851 int iWndsLocks = 0;
2853 /* Make sure that the window still exists */
2854 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2855 /* Build children list first */
2856 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2858 /* To avoid any deadlocks, all the locks on the windows
2859 structures must be suspended before the control
2860 is passed to the application */
2861 iWndsLocks = WIN_SuspendWndsLock();
2862 ret = func( (*ppWnd)->hwndSelf, lParam );
2863 WIN_RestoreWndsLock(iWndsLocks);
2865 if (childList)
2867 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2868 WIN_ReleaseWinArray(childList);
2870 if (!ret) return FALSE;
2872 return TRUE;
2876 /**********************************************************************
2877 * EnumChildWindows (USER32.178)
2879 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2880 LPARAM lParam )
2882 WND **list, *pParent;
2884 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2885 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2887 WIN_ReleaseWndPtr(pParent);
2888 return FALSE;
2890 WIN_EnumChildWindows( list, func, lParam );
2891 WIN_ReleaseWinArray(list);
2892 WIN_ReleaseWndPtr(pParent);
2893 return TRUE;
2897 /*******************************************************************
2898 * AnyPopup16 (USER.52)
2900 BOOL16 WINAPI AnyPopup16(void)
2902 return AnyPopup();
2906 /*******************************************************************
2907 * AnyPopup (USER32.4)
2909 BOOL WINAPI AnyPopup(void)
2911 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2912 BOOL retvalue;
2914 while (wndPtr)
2916 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2918 retvalue = TRUE;
2919 goto end;
2921 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2923 retvalue = FALSE;
2924 end:
2925 WIN_ReleaseWndPtr(wndPtr);
2926 return retvalue;
2930 /*******************************************************************
2931 * FlashWindow16 (USER.105)
2933 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2935 return FlashWindow( hWnd, bInvert );
2939 /*******************************************************************
2940 * FlashWindow (USER32.202)
2942 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2944 WND *wndPtr = WIN_FindWndPtr(hWnd);
2946 TRACE("%04x\n", hWnd);
2948 if (!wndPtr) return FALSE;
2950 if (wndPtr->dwStyle & WS_MINIMIZE)
2952 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2954 HDC hDC = GetDC(hWnd);
2956 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2957 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2959 ReleaseDC( hWnd, hDC );
2960 wndPtr->flags |= WIN_NCACTIVATED;
2962 else
2964 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2965 RDW_UPDATENOW | RDW_FRAME, 0 );
2966 wndPtr->flags &= ~WIN_NCACTIVATED;
2968 WIN_ReleaseWndPtr(wndPtr);
2969 return TRUE;
2971 else
2973 WPARAM16 wparam;
2974 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2975 else wparam = (hWnd == GetActiveWindow());
2977 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2978 WIN_ReleaseWndPtr(wndPtr);
2979 return wparam;
2984 /*******************************************************************
2985 * SetSysModalWindow16 (USER.188)
2987 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2989 HWND hWndOldModal = hwndSysModal;
2990 hwndSysModal = hWnd;
2991 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2992 return hWndOldModal;
2996 /*******************************************************************
2997 * GetSysModalWindow16 (USER.52)
2999 HWND16 WINAPI GetSysModalWindow16(void)
3001 return hwndSysModal;
3005 /*******************************************************************
3006 * GetWindowContextHelpId (USER32.303)
3008 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3010 DWORD retval;
3011 WND *wnd = WIN_FindWndPtr( hwnd );
3012 if (!wnd) return 0;
3013 retval = wnd->helpContext;
3014 WIN_ReleaseWndPtr(wnd);
3015 return retval;
3019 /*******************************************************************
3020 * SetWindowContextHelpId (USER32.515)
3022 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3024 WND *wnd = WIN_FindWndPtr( hwnd );
3025 if (!wnd) return FALSE;
3026 wnd->helpContext = id;
3027 WIN_ReleaseWndPtr(wnd);
3028 return TRUE;
3032 /*******************************************************************
3033 * DRAG_QueryUpdate
3035 * recursively find a child that contains spDragInfo->pt point
3036 * and send WM_QUERYDROPOBJECT
3038 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3040 BOOL16 wParam, bResult = 0;
3041 POINT pt;
3042 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3043 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3044 RECT tempRect;
3046 if( !ptrQueryWnd || !ptrDragInfo )
3047 goto end;
3049 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3051 GetWindowRect(hQueryWnd,&tempRect);
3053 if( !PtInRect(&tempRect,pt) ||
3054 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3055 goto end;
3057 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3059 tempRect = ptrQueryWnd->rectClient;
3060 if(ptrQueryWnd->dwStyle & WS_CHILD)
3061 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3062 (LPPOINT)&tempRect, 2 );
3064 if (PtInRect( &tempRect, pt))
3066 wParam = 0;
3068 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3070 if( ptrWnd->dwStyle & WS_VISIBLE )
3072 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3073 if (PtInRect( &tempRect, pt )) break;
3077 if(ptrWnd)
3079 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3080 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3081 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3082 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3083 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3085 WIN_ReleaseWndPtr(ptrWnd);
3088 if(bResult)
3089 goto end;
3091 else wParam = 1;
3093 else wParam = 1;
3095 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3097 ptrDragInfo->hScope = hQueryWnd;
3099 bResult = ( bNoSend )
3100 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3101 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3102 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3103 if( !bResult )
3104 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3106 end:
3107 WIN_ReleaseWndPtr(ptrQueryWnd);
3108 return bResult;
3112 /*******************************************************************
3113 * DragDetect (USER.465)
3115 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3117 POINT pt32;
3118 CONV_POINT16TO32( &pt, &pt32 );
3119 return DragDetect( hWnd, pt32 );
3122 /*******************************************************************
3123 * DragDetect (USER32.151)
3125 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3127 MSG16 msg;
3128 RECT16 rect;
3130 rect.left = pt.x - wDragWidth;
3131 rect.right = pt.x + wDragWidth;
3133 rect.top = pt.y - wDragHeight;
3134 rect.bottom = pt.y + wDragHeight;
3136 SetCapture(hWnd);
3138 while(1)
3140 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3142 if( msg.message == WM_LBUTTONUP )
3144 ReleaseCapture();
3145 return 0;
3147 if( msg.message == WM_MOUSEMOVE )
3149 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3151 ReleaseCapture();
3152 return 1;
3156 WaitMessage();
3158 return 0;
3161 /******************************************************************************
3162 * DragObject16 (USER.464)
3164 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3165 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3167 MSG16 msg;
3168 LPDRAGINFO lpDragInfo;
3169 SEGPTR spDragInfo;
3170 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3171 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3172 WND *wndPtr = WIN_FindWndPtr(hWnd);
3173 HCURSOR16 hCurrentCursor = 0;
3174 HWND16 hCurrentWnd = 0;
3176 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3177 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3179 if( !lpDragInfo || !spDragInfo )
3181 WIN_ReleaseWndPtr(wndPtr);
3182 return 0L;
3185 hBummer = LoadCursor16(0, IDC_BUMMER16);
3187 if( !hBummer || !wndPtr )
3189 GlobalFree16(hDragInfo);
3190 WIN_ReleaseWndPtr(wndPtr);
3191 return 0L;
3194 if(hCursor)
3196 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3198 GlobalFree16(hDragInfo);
3199 WIN_ReleaseWndPtr(wndPtr);
3200 return 0L;
3203 if( hDragCursor == hCursor ) hDragCursor = 0;
3204 else hCursor = hDragCursor;
3206 hOldCursor = SetCursor(hDragCursor);
3209 lpDragInfo->hWnd = hWnd;
3210 lpDragInfo->hScope = 0;
3211 lpDragInfo->wFlags = wObj;
3212 lpDragInfo->hList = szList; /* near pointer! */
3213 lpDragInfo->hOfStruct = hOfStruct;
3214 lpDragInfo->l = 0L;
3216 SetCapture(hWnd);
3217 ShowCursor( TRUE );
3221 do{ WaitMessage(); }
3222 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3224 *(lpDragInfo+1) = *lpDragInfo;
3226 lpDragInfo->pt = msg.pt;
3228 /* update DRAGINFO struct */
3229 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3231 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3232 hCurrentCursor = hCursor;
3233 else
3235 hCurrentCursor = hBummer;
3236 lpDragInfo->hScope = 0;
3238 if( hCurrentCursor )
3239 SetCursor(hCurrentCursor);
3241 /* send WM_DRAGLOOP */
3242 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3243 (LPARAM) spDragInfo );
3244 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3245 if( hCurrentWnd != lpDragInfo->hScope )
3247 if( hCurrentWnd )
3248 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3249 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3250 HIWORD(spDragInfo)) );
3251 hCurrentWnd = lpDragInfo->hScope;
3252 if( hCurrentWnd )
3253 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3255 else
3256 if( hCurrentWnd )
3257 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3259 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3261 ReleaseCapture();
3262 ShowCursor( FALSE );
3264 if( hCursor )
3266 SetCursor( hOldCursor );
3267 if (hDragCursor) DestroyCursor( hDragCursor );
3270 if( hCurrentCursor != hBummer )
3271 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3272 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3273 else
3274 msg.lParam = 0;
3275 GlobalFree16(hDragInfo);
3276 WIN_ReleaseWndPtr(wndPtr);
3278 return (DWORD)(msg.lParam);