Delay initialization of I/O permissions until they are first used.
[wine.git] / windows / win.c
blobaccc6294a06da2faf42ee179e2bb5786bbac4967
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 * Fix the coordinates - Helper for WIN_CreateWindowEx.
659 * returns default show mode in sw.
660 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
662 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
664 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
665 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
667 STARTUPINFOA info;
668 int defcx = 0, defcy = 0;
669 info.dwFlags = 0;
670 if (!(cs->style & (WS_CHILD | WS_POPUP))) GetStartupInfoA( &info );
672 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
674 /* Never believe Microsoft's documentation... CreateWindowEx doc says
675 * that if an overlapped window is created with WS_VISIBLE style bit
676 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
677 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
678 * reveals that
680 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
681 * 2) it does not ignore the y parameter as the docs claim; instead, it
682 * uses it as second parameter to ShowWindow() unless y is either
683 * CW_USEDEFAULT or CW_USEDEFAULT16.
685 * The fact that we didn't do 2) caused bogus windows pop up when wine
686 * was running apps that were using this obscure feature. Example -
687 * calc.exe that comes with Win98 (only Win98, it's different from
688 * the one that comes with Win95 and NT)
690 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
691 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
692 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
695 if (!(cs->style & (WS_CHILD | WS_POPUP)))
696 { /* if no other hint from the app, pick 3/4 of the screen real estate */
697 RECT r;
698 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
699 defcx = (((r.right - r.left) * 3) / 4) - cs->x;
700 defcy = (((r.bottom - r.top) * 3) / 4) - cs->y;
702 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
704 cs->cx = (info.dwFlags & STARTF_USESIZE) ? info.dwXSize : defcx;
705 cs->cy = (info.dwFlags & STARTF_USESIZE) ? info.dwYSize : defcy;
710 /***********************************************************************
711 * WIN_CreateWindowEx
713 * Implementation of CreateWindowEx().
715 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
716 BOOL win32, BOOL unicode )
718 INT sw = SW_SHOW;
719 CLASS *classPtr;
720 WND *wndPtr;
721 HWND retvalue;
722 HWND16 hwnd, hwndLinkAfter;
723 POINT maxSize, maxPos, minTrack, maxTrack;
724 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
726 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
727 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
728 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
729 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
730 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
732 /* Find the parent window */
734 if (cs->hwndParent)
736 /* Make sure parent is valid */
737 if (!IsWindow( cs->hwndParent ))
739 WARN("Bad parent %04x\n", cs->hwndParent );
740 return 0;
742 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
743 WARN("No parent for child window\n" );
744 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
747 /* Find the window class */
748 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
750 WARN("Bad class '%s'\n", cs->lpszClass );
751 return 0;
754 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
756 /* Create the window structure */
758 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
759 - sizeof(wndPtr->wExtra) )))
761 TRACE("out of memory\n" );
762 return 0;
765 /* Fill the window structure */
767 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
768 wndPtr->next = NULL;
769 wndPtr->child = NULL;
771 if ((cs->style & WS_CHILD) && cs->hwndParent)
773 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
774 wndPtr->owner = NULL;
775 WIN_ReleaseWndPtr(wndPtr->parent);
777 else
779 wndPtr->parent = pWndDesktop;
780 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
781 wndPtr->owner = NULL;
782 else
784 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
785 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
786 WIN_ReleaseWndPtr(wndPtr->owner);
787 WIN_ReleaseWndPtr(tmpWnd);
792 wndPtr->pDriver = wndPtr->parent->pDriver;
793 wndPtr->pDriver->pInitialize(wndPtr);
795 wndPtr->class = classPtr;
796 wndPtr->winproc = classPtr->winproc;
797 wndPtr->dwMagic = WND_MAGIC;
798 wndPtr->hwndSelf = hwnd;
799 wndPtr->hInstance = cs->hInstance;
800 wndPtr->text = NULL;
801 wndPtr->hmemTaskQ = GetFastQueue16();
802 wndPtr->hrgnUpdate = 0;
803 wndPtr->hwndLastActive = hwnd;
804 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
805 wndPtr->dwExStyle = cs->dwExStyle;
806 wndPtr->wIDmenu = 0;
807 wndPtr->helpContext = 0;
808 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
809 wndPtr->pVScroll = NULL;
810 wndPtr->pHScroll = NULL;
811 wndPtr->pProp = NULL;
812 wndPtr->userdata = 0;
813 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
814 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
815 wndPtr->irefCount = 1;
817 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
819 /* Call the WH_CBT hook */
821 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
822 ? HWND_BOTTOM : HWND_TOP;
824 if (HOOK_IsHooked( WH_CBT ))
826 CBT_CREATEWNDA cbtc;
827 LRESULT ret;
829 cbtc.lpcs = cs;
830 cbtc.hwndInsertAfter = hwndLinkAfter;
831 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
832 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
833 if (ret)
835 TRACE("CBT-hook returned 0\n");
836 wndPtr->pDriver->pFinalize(wndPtr);
837 USER_HEAP_FREE( hwnd );
838 retvalue = 0;
839 goto end;
843 /* Increment class window counter */
845 classPtr->cWindows++;
847 /* Correct the window style */
849 if (!(cs->style & WS_CHILD))
851 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
852 if (!(cs->style & WS_POPUP))
854 wndPtr->dwStyle |= WS_CAPTION;
855 wndPtr->flags |= WIN_NEED_SIZE;
859 /* Get class or window DC if needed */
861 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
862 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
863 else wndPtr->dce = NULL;
865 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
867 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
869 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
870 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
871 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
872 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
873 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
876 if(cs->style & WS_CHILD)
878 if(cs->cx < 0) cs->cx = 0;
879 if(cs->cy < 0) cs->cy = 0;
881 else
883 if (cs->cx <= 0) cs->cx = 1;
884 if (cs->cy <= 0) cs->cy = 1;
887 wndPtr->rectWindow.left = cs->x;
888 wndPtr->rectWindow.top = cs->y;
889 wndPtr->rectWindow.right = cs->x + cs->cx;
890 wndPtr->rectWindow.bottom = cs->y + cs->cy;
891 wndPtr->rectClient = wndPtr->rectWindow;
893 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
895 retvalue = FALSE;
896 goto end;
899 /* Set the window menu */
901 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
903 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
904 else
906 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
907 if (classPtr->menuNameA)
908 cs->hMenu = HIWORD(classPtr->menuNameA) ?
909 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
910 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
911 #else
912 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
913 if (menuName)
915 if (HIWORD(cs->hInstance))
916 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
917 else
918 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
920 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
922 #endif
925 else wndPtr->wIDmenu = (UINT)cs->hMenu;
927 /* Send the WM_CREATE message
928 * Perhaps we shouldn't allow width/height changes as well.
929 * See p327 in "Internals".
932 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
934 localSend32 = unicode ? SendMessageW : SendMessageA;
935 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
937 /* Insert the window in the linked list */
939 WIN_LinkWindow( hwnd, hwndLinkAfter );
941 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
942 NULL, NULL, 0, &wndPtr->rectClient );
943 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
944 maxPos.y - wndPtr->rectWindow.top);
945 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
947 /* Send the size messages */
949 if (!(wndPtr->flags & WIN_NEED_SIZE))
951 /* send it anyway */
952 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
953 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
954 WARN("sending bogus WM_SIZE message 0x%08lx\n",
955 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
956 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
957 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
958 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
959 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
960 SendMessageA( hwnd, WM_MOVE, 0,
961 MAKELONG( wndPtr->rectClient.left,
962 wndPtr->rectClient.top ) );
965 /* Show the window, maximizing or minimizing if needed */
967 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
969 RECT16 newPos;
970 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
971 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
972 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
973 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
974 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
975 : SWP_NOZORDER | SWP_FRAMECHANGED;
976 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
977 newPos.right, newPos.bottom, swFlag );
980 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
982 /* Notify the parent window only */
984 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
985 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
986 if( !IsWindow(hwnd) )
988 retvalue = 0;
989 goto end;
993 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
995 /* Call WH_SHELL hook */
997 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
998 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1000 TRACE("created window %04x\n", hwnd);
1001 retvalue = hwnd;
1002 goto end;
1004 WIN_UnlinkWindow( hwnd );
1007 /* Abort window creation */
1009 WARN("aborted by WM_xxCREATE!\n");
1010 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1011 retvalue = 0;
1012 end:
1013 WIN_ReleaseWndPtr(wndPtr);
1015 return retvalue;
1019 /***********************************************************************
1020 * CreateWindow16 (USER.41)
1022 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1023 DWORD style, INT16 x, INT16 y, INT16 width,
1024 INT16 height, HWND16 parent, HMENU16 menu,
1025 HINSTANCE16 instance, LPVOID data )
1027 return CreateWindowEx16( 0, className, windowName, style,
1028 x, y, width, height, parent, menu, instance, data );
1032 /***********************************************************************
1033 * CreateWindowEx16 (USER.452)
1035 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1036 LPCSTR windowName, DWORD style, INT16 x,
1037 INT16 y, INT16 width, INT16 height,
1038 HWND16 parent, HMENU16 menu,
1039 HINSTANCE16 instance, LPVOID data )
1041 ATOM classAtom;
1042 CREATESTRUCTA cs;
1043 char buffer[256];
1045 /* Find the class atom */
1047 if (HIWORD(className))
1049 if (!(classAtom = GlobalFindAtomA( className )))
1051 ERR( "bad class name %s\n", debugres_a(className) );
1052 return 0;
1055 else
1057 classAtom = LOWORD(className);
1058 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1060 ERR( "bad atom %x\n", classAtom);
1061 return 0;
1063 className = buffer;
1066 /* Fix the coordinates */
1068 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1069 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1070 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1071 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1073 /* Create the window */
1075 cs.lpCreateParams = data;
1076 cs.hInstance = (HINSTANCE)instance;
1077 cs.hMenu = (HMENU)menu;
1078 cs.hwndParent = (HWND)parent;
1079 cs.style = style;
1080 cs.lpszName = windowName;
1081 cs.lpszClass = className;
1082 cs.dwExStyle = exStyle;
1084 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1088 /***********************************************************************
1089 * CreateWindowExA (USER32.83)
1091 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1092 LPCSTR windowName, DWORD style, INT x,
1093 INT y, INT width, INT height,
1094 HWND parent, HMENU menu,
1095 HINSTANCE instance, LPVOID data )
1097 ATOM classAtom;
1098 CREATESTRUCTA cs;
1099 char buffer[256];
1101 if(!instance)
1102 instance=GetModuleHandleA(NULL);
1104 if(exStyle & WS_EX_MDICHILD)
1105 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1107 /* Find the class atom */
1109 if (HIWORD(className))
1111 if (!(classAtom = GlobalFindAtomA( className )))
1113 ERR( "bad class name %s\n", debugres_a(className) );
1114 return 0;
1117 else
1119 classAtom = LOWORD(className);
1120 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1122 ERR( "bad atom %x\n", classAtom);
1123 return 0;
1125 className = buffer;
1128 /* Create the window */
1130 cs.lpCreateParams = data;
1131 cs.hInstance = instance;
1132 cs.hMenu = menu;
1133 cs.hwndParent = parent;
1134 cs.x = x;
1135 cs.y = y;
1136 cs.cx = width;
1137 cs.cy = height;
1138 cs.style = style;
1139 cs.lpszName = windowName;
1140 cs.lpszClass = className;
1141 cs.dwExStyle = exStyle;
1143 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1147 /***********************************************************************
1148 * CreateWindowExW (USER32.84)
1150 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1151 LPCWSTR windowName, DWORD style, INT x,
1152 INT y, INT width, INT height,
1153 HWND parent, HMENU menu,
1154 HINSTANCE instance, LPVOID data )
1156 ATOM classAtom;
1157 CREATESTRUCTW cs;
1158 WCHAR buffer[256];
1160 if(!instance)
1161 instance=GetModuleHandleA(NULL);
1163 if(exStyle & WS_EX_MDICHILD)
1164 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1166 /* Find the class atom */
1168 if (HIWORD(className))
1170 if (!(classAtom = GlobalFindAtomW( className )))
1172 ERR( "bad class name %s\n", debugres_w(className) );
1173 return 0;
1176 else
1178 classAtom = LOWORD(className);
1179 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1181 ERR( "bad atom %x\n", classAtom);
1182 return 0;
1184 className = buffer;
1187 /* Create the window */
1189 cs.lpCreateParams = data;
1190 cs.hInstance = instance;
1191 cs.hMenu = menu;
1192 cs.hwndParent = parent;
1193 cs.x = x;
1194 cs.y = y;
1195 cs.cx = width;
1196 cs.cy = height;
1197 cs.style = style;
1198 cs.lpszName = windowName;
1199 cs.lpszClass = className;
1200 cs.dwExStyle = exStyle;
1202 /* Note: we rely on the fact that CREATESTRUCTA and */
1203 /* CREATESTRUCTW have the same layout. */
1204 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1208 /***********************************************************************
1209 * WIN_CheckFocus
1211 static void WIN_CheckFocus( WND* pWnd )
1213 if( GetFocus16() == pWnd->hwndSelf )
1214 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1217 /***********************************************************************
1218 * WIN_SendDestroyMsg
1220 static void WIN_SendDestroyMsg( WND* pWnd )
1222 WIN_CheckFocus(pWnd);
1224 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1225 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1228 * Send the WM_DESTROY to the window.
1230 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1233 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1234 * make sure that the window still exists when we come back.
1236 if (IsWindow(pWnd->hwndSelf))
1238 HWND* pWndArray = NULL;
1239 WND* pChild = NULL;
1240 int nKidCount = 0;
1243 * Now, if the window has kids, we have to send WM_DESTROY messages
1244 * recursively to it's kids. It seems that those calls can also
1245 * trigger re-entrant calls to DestroyWindow for the kids so we must
1246 * protect against corruption of the list of siblings. We first build
1247 * a list of HWNDs representing all the kids.
1249 pChild = WIN_LockWndPtr(pWnd->child);
1250 while( pChild )
1252 nKidCount++;
1253 WIN_UpdateWndPtr(&pChild,pChild->next);
1257 * If there are no kids, we're done.
1259 if (nKidCount==0)
1260 return;
1262 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1265 * Sanity check
1267 if (pWndArray==NULL)
1268 return;
1271 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1272 * call, our linked list of siblings should be safe.
1274 nKidCount = 0;
1275 pChild = WIN_LockWndPtr(pWnd->child);
1276 while( pChild )
1278 pWndArray[nKidCount] = pChild->hwndSelf;
1279 nKidCount++;
1280 WIN_UpdateWndPtr(&pChild,pChild->next);
1284 * Now that we have a list, go through that list again and send the destroy
1285 * message to those windows. We are using the HWND to retrieve the
1286 * WND pointer so we are effectively checking that all the kid windows are
1287 * still valid before sending the message.
1289 while (nKidCount>0)
1291 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1293 if (pChild!=NULL)
1295 WIN_SendDestroyMsg( pChild );
1296 WIN_ReleaseWndPtr(pChild);
1301 * Cleanup
1303 HeapFree(GetProcessHeap(), 0, pWndArray);
1304 WIN_CheckFocus(pWnd);
1306 else
1307 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1311 /***********************************************************************
1312 * DestroyWindow16 (USER.53)
1314 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1316 return DestroyWindow(hwnd);
1320 /***********************************************************************
1321 * DestroyWindow (USER32.135)
1323 BOOL WINAPI DestroyWindow( HWND hwnd )
1325 WND * wndPtr;
1326 BOOL retvalue;
1328 TRACE("(%04x)\n", hwnd);
1330 /* Initialization */
1332 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1333 if (wndPtr == pWndDesktop)
1335 retvalue = FALSE; /* Can't destroy desktop */
1336 goto end;
1339 /* Call hooks */
1341 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1343 retvalue = FALSE;
1344 goto end;
1347 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1349 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1350 /* FIXME: clean up palette - see "Internals" p.352 */
1353 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1354 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1356 /* Notify the parent window only */
1357 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1358 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1359 if( !IsWindow(hwnd) )
1361 retvalue = TRUE;
1362 goto end;
1366 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1368 /* Hide the window */
1370 if (wndPtr->dwStyle & WS_VISIBLE)
1372 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1373 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1374 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1375 if (!IsWindow(hwnd))
1377 retvalue = TRUE;
1378 goto end;
1382 /* Recursively destroy owned windows */
1384 if( !(wndPtr->dwStyle & WS_CHILD) )
1386 /* make sure top menu popup doesn't get destroyed */
1387 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1389 for (;;)
1391 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1392 while (siblingPtr)
1394 if (siblingPtr->owner == wndPtr)
1396 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1397 break;
1398 else
1399 siblingPtr->owner = NULL;
1401 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1403 if (siblingPtr)
1405 DestroyWindow( siblingPtr->hwndSelf );
1406 WIN_ReleaseWndPtr(siblingPtr);
1408 else break;
1411 if( !Options.managed || EVENT_CheckFocus() )
1412 WINPOS_ActivateOtherWindow(wndPtr);
1414 if( wndPtr->owner &&
1415 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1416 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1419 /* Send destroy messages */
1421 WIN_SendDestroyMsg( wndPtr );
1422 if (!IsWindow(hwnd))
1424 retvalue = TRUE;
1425 goto end;
1428 /* Unlink now so we won't bother with the children later on */
1430 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1432 /* Destroy the window storage */
1434 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1435 retvalue = TRUE;
1436 end:
1437 WIN_ReleaseWndPtr(wndPtr);
1438 return retvalue;
1442 /***********************************************************************
1443 * CloseWindow16 (USER.43)
1445 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1447 return CloseWindow( hwnd );
1451 /***********************************************************************
1452 * CloseWindow (USER32.56)
1454 BOOL WINAPI CloseWindow( HWND hwnd )
1456 WND * wndPtr = WIN_FindWndPtr( hwnd );
1457 BOOL retvalue;
1459 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1461 retvalue = FALSE;
1462 goto end;
1464 ShowWindow( hwnd, SW_MINIMIZE );
1465 retvalue = TRUE;
1466 end:
1467 WIN_ReleaseWndPtr(wndPtr);
1468 return retvalue;
1473 /***********************************************************************
1474 * OpenIcon16 (USER.44)
1476 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1478 return OpenIcon( hwnd );
1482 /***********************************************************************
1483 * OpenIcon (USER32.410)
1485 BOOL WINAPI OpenIcon( HWND hwnd )
1487 if (!IsIconic( hwnd )) return FALSE;
1488 ShowWindow( hwnd, SW_SHOWNORMAL );
1489 return TRUE;
1493 /***********************************************************************
1494 * WIN_FindWindow
1496 * Implementation of FindWindow() and FindWindowEx().
1498 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1499 LPCSTR title )
1501 WND *pWnd;
1502 HWND retvalue;
1504 if (child)
1506 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1507 if (parent)
1509 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1511 retvalue = 0;
1512 goto end;
1515 else if (pWnd->parent != pWndDesktop)
1517 retvalue = 0;
1518 goto end;
1520 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1522 else
1524 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1526 retvalue = 0;
1527 goto end;
1529 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1531 if (!pWnd)
1533 retvalue = 0;
1534 goto end;
1537 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1539 if (className && (pWnd->class->atomName != className))
1540 continue; /* Not the right class */
1542 /* Now check the title */
1544 if (!title)
1546 retvalue = pWnd->hwndSelf;
1547 goto end;
1549 if (pWnd->text && !strcmp( pWnd->text, title ))
1551 retvalue = pWnd->hwndSelf;
1552 goto end;
1555 retvalue = 0;
1556 end:
1557 WIN_ReleaseWndPtr(pWnd);
1558 return retvalue;
1563 /***********************************************************************
1564 * FindWindow16 (USER.50)
1566 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1568 return FindWindowA( className, title );
1572 /***********************************************************************
1573 * FindWindowEx16 (USER.427)
1575 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1577 return FindWindowExA( parent, child, className, title );
1581 /***********************************************************************
1582 * FindWindowA (USER32.198)
1584 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1586 HWND ret = FindWindowExA( 0, 0, className, title );
1587 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1588 return ret;
1592 /***********************************************************************
1593 * FindWindowExA (USER32.199)
1595 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1596 LPCSTR className, LPCSTR title )
1598 ATOM atom = 0;
1600 if (className)
1602 /* If the atom doesn't exist, then no class */
1603 /* with this name exists either. */
1604 if (!(atom = GlobalFindAtomA( className )))
1606 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1607 return 0;
1610 return WIN_FindWindow( parent, child, atom, title );
1614 /***********************************************************************
1615 * FindWindowExW (USER32.200)
1617 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1618 LPCWSTR className, LPCWSTR title )
1620 ATOM atom = 0;
1621 char *buffer;
1622 HWND hwnd;
1624 if (className)
1626 /* If the atom doesn't exist, then no class */
1627 /* with this name exists either. */
1628 if (!(atom = GlobalFindAtomW( className )))
1630 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1631 return 0;
1634 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1635 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1636 HeapFree( GetProcessHeap(), 0, buffer );
1637 return hwnd;
1641 /***********************************************************************
1642 * FindWindowW (USER32.201)
1644 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1646 return FindWindowExW( 0, 0, className, title );
1650 /**********************************************************************
1651 * WIN_GetDesktop
1652 * returns a locked pointer
1654 WND *WIN_GetDesktop(void)
1656 return WIN_LockWndPtr(pWndDesktop);
1658 /**********************************************************************
1659 * WIN_ReleaseDesktop
1660 * unlock the desktop pointer
1662 void WIN_ReleaseDesktop(void)
1664 WIN_ReleaseWndPtr(pWndDesktop);
1668 /**********************************************************************
1669 * GetDesktopWindow16 (USER.286)
1671 HWND16 WINAPI GetDesktopWindow16(void)
1673 return (HWND16)pWndDesktop->hwndSelf;
1677 /**********************************************************************
1678 * GetDesktopWindow (USER32.232)
1680 HWND WINAPI GetDesktopWindow(void)
1682 if (pWndDesktop) return pWndDesktop->hwndSelf;
1683 ERR( "You need the -desktop option when running with native USER\n" );
1684 ExitProcess(1);
1685 return 0;
1689 /**********************************************************************
1690 * GetDesktopHwnd (USER.278)
1692 * Exactly the same thing as GetDesktopWindow(), but not documented.
1693 * Don't ask me why...
1695 HWND16 WINAPI GetDesktopHwnd16(void)
1697 return (HWND16)pWndDesktop->hwndSelf;
1701 /*******************************************************************
1702 * EnableWindow16 (USER.34)
1704 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1706 return EnableWindow( hwnd, enable );
1710 /*******************************************************************
1711 * EnableWindow (USER32.172)
1713 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1715 WND *wndPtr;
1716 BOOL retvalue;
1718 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1720 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1721 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1723 /* Enable window */
1724 wndPtr->dwStyle &= ~WS_DISABLED;
1726 if( wndPtr->flags & WIN_NATIVE )
1727 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1729 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1730 retvalue = TRUE;
1731 goto end;
1733 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1735 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1737 /* Disable window */
1738 wndPtr->dwStyle |= WS_DISABLED;
1740 if( wndPtr->flags & WIN_NATIVE )
1741 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1743 if (hwnd == GetFocus())
1745 SetFocus( 0 ); /* A disabled window can't have the focus */
1747 if (hwnd == GetCapture())
1749 ReleaseCapture(); /* A disabled window can't capture the mouse */
1751 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1752 retvalue = FALSE;
1753 goto end;
1755 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1756 end:
1757 WIN_ReleaseWndPtr(wndPtr);
1758 return retvalue;
1762 /***********************************************************************
1763 * IsWindowEnabled16 (USER.35)
1765 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1767 return IsWindowEnabled(hWnd);
1771 /***********************************************************************
1772 * IsWindowEnabled (USER32.349)
1774 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1776 WND * wndPtr;
1777 BOOL retvalue;
1779 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1780 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1781 WIN_ReleaseWndPtr(wndPtr);
1782 return retvalue;
1787 /***********************************************************************
1788 * IsWindowUnicode (USER32.350)
1790 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1792 WND * wndPtr;
1793 BOOL retvalue;
1795 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1796 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1797 WIN_ReleaseWndPtr(wndPtr);
1798 return retvalue;
1802 /**********************************************************************
1803 * GetWindowWord16 (USER.133)
1805 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1807 return GetWindowWord( hwnd, offset );
1811 /**********************************************************************
1812 * GetWindowWord (USER32.314)
1814 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1816 WORD retvalue;
1817 WND * wndPtr = WIN_FindWndPtr( hwnd );
1818 if (!wndPtr) return 0;
1819 if (offset >= 0)
1821 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1823 WARN("Invalid offset %d\n", offset );
1824 retvalue = 0;
1825 goto end;
1827 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1828 goto end;
1830 switch(offset)
1832 case GWW_ID:
1833 if (HIWORD(wndPtr->wIDmenu))
1834 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1835 wndPtr->wIDmenu);
1836 retvalue = (WORD)wndPtr->wIDmenu;
1837 goto end;
1838 case GWW_HWNDPARENT:
1839 retvalue = GetParent(hwnd);
1840 goto end;
1841 case GWW_HINSTANCE:
1842 if (HIWORD(wndPtr->hInstance))
1843 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1844 wndPtr->hInstance);
1845 retvalue = (WORD)wndPtr->hInstance;
1846 goto end;
1847 default:
1848 WARN("Invalid offset %d\n", offset );
1849 retvalue = 0;
1850 goto end;
1852 end:
1853 WIN_ReleaseWndPtr(wndPtr);
1854 return retvalue;
1857 /**********************************************************************
1858 * SetWindowWord16 (USER.134)
1860 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1862 return SetWindowWord( hwnd, offset, newval );
1866 /**********************************************************************
1867 * SetWindowWord (USER32.524)
1869 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1871 WORD *ptr, retval;
1872 WND * wndPtr = WIN_FindWndPtr( hwnd );
1873 if (!wndPtr) return 0;
1874 if (offset >= 0)
1876 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1878 WARN("Invalid offset %d\n", offset );
1879 retval = 0;
1880 goto end;
1882 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1884 else switch(offset)
1886 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1887 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1888 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1889 goto end;
1890 default:
1891 WARN("Invalid offset %d\n", offset );
1892 retval = 0;
1893 goto end;
1895 retval = *ptr;
1896 *ptr = newval;
1897 end:
1898 WIN_ReleaseWndPtr(wndPtr);
1899 return retval;
1903 /**********************************************************************
1904 * WIN_GetWindowLong
1906 * Helper function for GetWindowLong().
1908 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1910 LONG retvalue;
1911 WND * wndPtr = WIN_FindWndPtr( hwnd );
1912 if (!wndPtr) return 0;
1913 if (offset >= 0)
1915 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1917 WARN("Invalid offset %d\n", offset );
1918 retvalue = 0;
1919 goto end;
1921 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1922 /* Special case for dialog window procedure */
1923 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1925 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1926 goto end;
1928 goto end;
1930 switch(offset)
1932 case GWL_USERDATA: retvalue = wndPtr->userdata;
1933 goto end;
1934 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1935 goto end;
1936 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1937 goto end;
1938 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1939 goto end;
1940 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1941 type );
1942 goto end;
1943 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1944 goto end;
1945 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1946 goto end;
1947 default:
1948 WARN("Unknown offset %d\n", offset );
1950 retvalue = 0;
1951 end:
1952 WIN_ReleaseWndPtr(wndPtr);
1953 return retvalue;
1957 /**********************************************************************
1958 * WIN_SetWindowLong
1960 * Helper function for SetWindowLong().
1962 * 0 is the failure code. However, in the case of failure SetLastError
1963 * must be set to distinguish between a 0 return value and a failure.
1965 * FIXME: The error values for SetLastError may not be right. Can
1966 * someone check with the real thing?
1968 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1969 WINDOWPROCTYPE type )
1971 LONG *ptr, retval;
1972 WND * wndPtr = WIN_FindWndPtr( hwnd );
1973 STYLESTRUCT style;
1975 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1977 if (!wndPtr)
1979 /* Is this the right error? */
1980 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1981 return 0;
1984 if (offset >= 0)
1986 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1988 WARN("Invalid offset %d\n", offset );
1990 /* Is this the right error? */
1991 SetLastError( ERROR_OUTOFMEMORY );
1993 retval = 0;
1994 goto end;
1996 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1997 /* Special case for dialog window procedure */
1998 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2000 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2001 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2002 type, WIN_PROC_WINDOW );
2003 goto end;
2006 else switch(offset)
2008 case GWL_ID:
2009 ptr = (DWORD*)&wndPtr->wIDmenu;
2010 break;
2011 case GWL_HINSTANCE:
2012 retval = SetWindowWord( hwnd, offset, newval );
2013 goto end;
2014 case GWL_WNDPROC:
2015 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2016 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2017 type, WIN_PROC_WINDOW );
2018 goto end;
2019 case GWL_STYLE:
2020 style.styleOld = wndPtr->dwStyle;
2021 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2022 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2024 if (wndPtr->flags & WIN_ISWIN32)
2025 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2026 wndPtr->dwStyle = style.styleNew;
2027 if (wndPtr->flags & WIN_ISWIN32)
2028 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2029 retval = style.styleOld;
2030 goto end;
2032 case GWL_USERDATA:
2033 ptr = &wndPtr->userdata;
2034 break;
2035 case GWL_EXSTYLE:
2036 style.styleOld = wndPtr->dwExStyle;
2037 style.styleNew = newval;
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2040 wndPtr->dwExStyle = newval;
2041 if (wndPtr->flags & WIN_ISWIN32)
2042 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2043 retval = style.styleOld;
2044 goto end;
2046 default:
2047 WARN("Invalid offset %d\n", offset );
2049 /* Don't think this is right error but it should do */
2050 SetLastError( ERROR_OUTOFMEMORY );
2052 retval = 0;
2053 goto end;
2055 retval = *ptr;
2056 *ptr = newval;
2057 end:
2058 WIN_ReleaseWndPtr(wndPtr);
2059 return retval;
2063 /**********************************************************************
2064 * GetWindowLong16 (USER.135)
2066 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2068 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2072 /**********************************************************************
2073 * GetWindowLongA (USER32.305)
2075 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2077 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2081 /**********************************************************************
2082 * GetWindowLongW (USER32.306)
2084 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2086 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2090 /**********************************************************************
2091 * SetWindowLong16 (USER.136)
2093 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2095 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2099 /**********************************************************************
2100 * SetWindowLongA (USER32.517)
2102 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2104 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2108 /**********************************************************************
2109 * SetWindowLongW (USER32.518) Set window attribute
2111 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2112 * value in a window's extra memory.
2114 * The _hwnd_ parameter specifies the window. is the handle to a
2115 * window that has extra memory. The _newval_ parameter contains the
2116 * new attribute or extra memory value. If positive, the _offset_
2117 * parameter is the byte-addressed location in the window's extra
2118 * memory to set. If negative, _offset_ specifies the window
2119 * attribute to set, and should be one of the following values:
2121 * GWL_EXSTYLE The window's extended window style
2123 * GWL_STYLE The window's window style.
2125 * GWL_WNDPROC Pointer to the window's window procedure.
2127 * GWL_HINSTANCE The window's pplication instance handle.
2129 * GWL_ID The window's identifier.
2131 * GWL_USERDATA The window's user-specified data.
2133 * If the window is a dialog box, the _offset_ parameter can be one of
2134 * the following values:
2136 * DWL_DLGPROC The address of the window's dialog box procedure.
2138 * DWL_MSGRESULT The return value of a message
2139 * that the dialog box procedure processed.
2141 * DWL_USER Application specific information.
2143 * RETURNS
2145 * If successful, returns the previous value located at _offset_. Otherwise,
2146 * returns 0.
2148 * NOTES
2150 * Extra memory for a window class is specified by a nonzero cbWndExtra
2151 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2152 * time of class creation.
2154 * Using GWL_WNDPROC to set a new window procedure effectively creates
2155 * a window subclass. Use CallWindowProc() in the new windows procedure
2156 * to pass messages to the superclass's window procedure.
2158 * The user data is reserved for use by the application which created
2159 * the window.
2161 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2162 * instead, call the EnableWindow() function to change the window's
2163 * disabled state.
2165 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2166 * SetParent() instead.
2168 * Win95:
2169 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2170 * it sends WM_STYLECHANGING before changing the settings
2171 * and WM_STYLECHANGED afterwards.
2172 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2174 * BUGS
2176 * GWL_STYLE does not dispatch WM_STYLE... messages.
2178 * CONFORMANCE
2180 * ECMA-234, Win32
2183 LONG WINAPI SetWindowLongW(
2184 HWND hwnd, /* window to alter */
2185 INT offset, /* offset, in bytes, of location to alter */
2186 LONG newval /* new value of location */
2188 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2192 /*******************************************************************
2193 * GetWindowText16 (USER.36)
2195 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2197 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2201 /*******************************************************************
2202 * GetWindowTextA (USER32.309)
2204 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2206 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2207 (LPARAM)lpString );
2210 /*******************************************************************
2211 * InternalGetWindowText (USER32.326)
2213 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2215 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2216 return GetWindowTextW(hwnd,lpString,nMaxCount);
2220 /*******************************************************************
2221 * GetWindowTextW (USER32.312)
2223 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2225 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2226 (LPARAM)lpString );
2230 /*******************************************************************
2231 * SetWindowText16 (USER.37)
2233 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2235 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2239 /*******************************************************************
2240 * SetWindowTextA (USER32.521)
2242 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2244 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2248 /*******************************************************************
2249 * SetWindowTextW (USER32.523)
2251 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2253 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2257 /*******************************************************************
2258 * GetWindowTextLength16 (USER.38)
2260 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2262 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2266 /*******************************************************************
2267 * GetWindowTextLengthA (USER32.310)
2269 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2271 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2274 /*******************************************************************
2275 * GetWindowTextLengthW (USER32.311)
2277 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2279 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2283 /*******************************************************************
2284 * IsWindow16 (USER.47)
2286 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2288 CURRENT_STACK16->es = USER_HeapSel;
2289 return IsWindow( hwnd );
2293 /*******************************************************************
2294 * IsWindow (USER32.348)
2296 BOOL WINAPI IsWindow( HWND hwnd )
2298 WND * wndPtr;
2299 BOOL retvalue;
2301 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2302 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2303 WIN_ReleaseWndPtr(wndPtr);
2304 return retvalue;
2309 /*****************************************************************
2310 * GetParent16 (USER.46)
2312 HWND16 WINAPI GetParent16( HWND16 hwnd )
2314 return (HWND16)GetParent( hwnd );
2318 /*****************************************************************
2319 * GetParent (USER32.278)
2321 HWND WINAPI GetParent( HWND hwnd )
2323 WND *wndPtr;
2324 HWND retvalue = 0;
2326 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2327 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2328 goto end;
2330 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2331 if (wndPtr)
2332 retvalue = wndPtr->hwndSelf;
2334 end:
2335 WIN_ReleaseWndPtr(wndPtr);
2336 return retvalue;
2340 /*****************************************************************
2341 * WIN_GetTopParent
2343 * Get the top-level parent for a child window.
2344 * returns a locked pointer
2346 WND* WIN_GetTopParentPtr( WND* pWnd )
2348 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2350 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2352 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2354 return tmpWnd;
2357 /*****************************************************************
2358 * WIN_GetTopParent
2360 * Get the top-level parent for a child window.
2362 HWND WIN_GetTopParent( HWND hwnd )
2364 HWND retvalue;
2365 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2366 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2368 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2369 WIN_ReleaseWndPtr(tmpPtr);
2370 WIN_ReleaseWndPtr(wndPtr);
2371 return retvalue;
2375 /*****************************************************************
2376 * SetParent16 (USER.233)
2378 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2380 return SetParent( hwndChild, hwndNewParent );
2384 /*****************************************************************
2385 * SetParent (USER32.495)
2387 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2389 WND *wndPtr;
2390 DWORD dwStyle;
2391 WND *pWndNewParent;
2392 WND *pWndOldParent;
2393 HWND retvalue;
2396 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2398 dwStyle = wndPtr->dwStyle;
2400 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2401 : WIN_LockWndPtr(pWndDesktop);
2403 /* Windows hides the window first, then shows it again
2404 * including the WM_SHOWWINDOW messages and all */
2405 if (dwStyle & WS_VISIBLE)
2406 ShowWindow( hwndChild, SW_HIDE );
2408 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2410 /* SetParent additionally needs to make hwndChild the topmost window
2411 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2412 WM_WINDOWPOSCHANGED notification messages.
2414 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2415 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2416 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2417 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2419 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2421 WIN_ReleaseWndPtr(pWndOldParent);
2422 WIN_ReleaseWndPtr(pWndNewParent);
2423 WIN_ReleaseWndPtr(wndPtr);
2425 return retvalue;
2429 /*******************************************************************
2430 * IsChild16 (USER.48)
2432 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2434 return IsChild(parent,child);
2438 /*******************************************************************
2439 * IsChild (USER32.339)
2441 BOOL WINAPI IsChild( HWND parent, HWND child )
2443 WND * wndPtr = WIN_FindWndPtr( child );
2444 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2446 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2447 if (wndPtr->hwndSelf == parent)
2449 WIN_ReleaseWndPtr(wndPtr);
2450 return TRUE;
2453 WIN_ReleaseWndPtr(wndPtr);
2454 return FALSE;
2458 /***********************************************************************
2459 * IsWindowVisible16 (USER.49)
2461 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2463 return IsWindowVisible(hwnd);
2467 /***********************************************************************
2468 * IsWindowVisible (USER32.351)
2470 BOOL WINAPI IsWindowVisible( HWND hwnd )
2472 BOOL retval;
2473 WND *wndPtr = WIN_FindWndPtr( hwnd );
2474 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2476 if (!(wndPtr->dwStyle & WS_VISIBLE))
2478 WIN_ReleaseWndPtr(wndPtr);
2479 return FALSE;
2481 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2483 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2484 WIN_ReleaseWndPtr(wndPtr);
2485 return retval;
2490 /***********************************************************************
2491 * WIN_IsWindowDrawable
2493 * hwnd is drawable when it is visible, all parents are not
2494 * minimized, and it is itself not minimized unless we are
2495 * trying to draw its default class icon.
2497 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2499 if( (wnd->dwStyle & WS_MINIMIZE &&
2500 icon && wnd->class->hIcon) ||
2501 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2502 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2503 if( wnd->dwStyle & WS_MINIMIZE ||
2504 !(wnd->dwStyle & WS_VISIBLE) ) break;
2505 return (wnd == NULL);
2509 /*******************************************************************
2510 * GetTopWindow16 (USER.229)
2512 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2514 return GetTopWindow(hwnd);
2518 /*******************************************************************
2519 * GetTopWindow (USER.229)
2521 HWND WINAPI GetTopWindow( HWND hwnd )
2523 HWND retval = 0;
2524 WND * wndPtr = (hwnd) ?
2525 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2527 if (wndPtr && wndPtr->child)
2528 retval = wndPtr->child->hwndSelf;
2530 WIN_ReleaseWndPtr(wndPtr);
2531 return retval;
2535 /*******************************************************************
2536 * GetWindow16 (USER.262)
2538 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2540 return GetWindow( hwnd,rel );
2544 /*******************************************************************
2545 * GetWindow (USER32.302)
2547 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2549 HWND retval;
2551 WND * wndPtr = WIN_FindWndPtr( hwnd );
2552 if (!wndPtr) return 0;
2553 switch(rel)
2555 case GW_HWNDFIRST:
2556 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2557 goto end;
2559 case GW_HWNDLAST:
2560 if (!wndPtr->parent)
2562 retval = 0; /* Desktop window */
2563 goto end;
2565 while (wndPtr->next)
2567 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2569 retval = wndPtr->hwndSelf;
2570 goto end;
2572 case GW_HWNDNEXT:
2573 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2574 goto end;
2576 case GW_HWNDPREV:
2577 if (!wndPtr->parent)
2579 retval = 0; /* Desktop window */
2580 goto end;
2582 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2583 if (wndPtr->hwndSelf == hwnd)
2585 retval = 0; /* First in list */
2586 goto end;
2588 while (wndPtr->next)
2590 if (wndPtr->next->hwndSelf == hwnd)
2592 retval = wndPtr->hwndSelf;
2593 goto end;
2595 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2597 retval = 0;
2598 goto end;
2600 case GW_OWNER:
2601 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2602 goto end;
2604 case GW_CHILD:
2605 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2606 goto end;
2608 retval = 0;
2609 end:
2610 WIN_ReleaseWndPtr(wndPtr);
2611 return retval;
2615 /*******************************************************************
2616 * GetNextWindow16 (USER.230)
2618 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2620 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2621 return GetWindow16( hwnd, flag );
2624 /*******************************************************************
2625 * ShowOwnedPopups16 (USER.265)
2627 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2629 ShowOwnedPopups( owner, fShow );
2633 /*******************************************************************
2634 * ShowOwnedPopups (USER32.531)
2636 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2638 UINT totalChild=0, count=0;
2640 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2642 if (!pWnd) return TRUE;
2644 for (; count < totalChild; count++)
2646 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2648 if (fShow)
2650 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2652 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2653 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2656 else
2658 if (IsWindowVisible(pWnd[count]->hwndSelf))
2660 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2661 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2667 WIN_ReleaseDesktop();
2668 WIN_ReleaseWinArray(pWnd);
2669 return TRUE;
2673 /*******************************************************************
2674 * GetLastActivePopup16 (USER.287)
2676 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2678 return GetLastActivePopup( hwnd );
2681 /*******************************************************************
2682 * GetLastActivePopup (USER32.256)
2684 HWND WINAPI GetLastActivePopup( HWND hwnd )
2686 HWND retval;
2687 WND *wndPtr =WIN_FindWndPtr(hwnd);
2688 if (!wndPtr) return hwnd;
2689 retval = wndPtr->hwndLastActive;
2690 WIN_ReleaseWndPtr(wndPtr);
2691 return retval;
2695 /*******************************************************************
2696 * WIN_BuildWinArray
2698 * Build an array of pointers to the children of a given window.
2699 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2700 * when no windows are found.
2702 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2704 /* Future: this function will lock all windows associated with this array */
2706 WND **list, **ppWnd;
2707 WND *pWnd;
2708 UINT count = 0, skipOwned, skipHidden;
2709 DWORD skipFlags;
2711 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2712 skipOwned = bwaFlags & BWA_SKIPOWNED;
2713 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2714 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2716 /* First count the windows */
2718 if (!wndPtr)
2719 wndPtr = WIN_GetDesktop();
2721 pWnd = WIN_LockWndPtr(wndPtr->child);
2722 while (pWnd)
2724 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2725 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2726 count++;
2727 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2730 if( count )
2732 /* Now build the list of all windows */
2734 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2736 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2738 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2739 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2741 *ppWnd++ = pWnd;
2742 count++;
2745 WIN_ReleaseWndPtr(pWnd);
2746 *ppWnd = NULL;
2748 else count = 0;
2749 } else list = NULL;
2751 if( pTotal ) *pTotal = count;
2752 return list;
2754 /*******************************************************************
2755 * WIN_ReleaseWinArray
2757 void WIN_ReleaseWinArray(WND **wndArray)
2759 /* Future: this function will also unlock all windows associated with wndArray */
2760 HeapFree( GetProcessHeap(), 0, wndArray );
2764 /*******************************************************************
2765 * EnumWindows (USER32.193)
2767 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2769 WND **list, **ppWnd;
2771 /* We have to build a list of all windows first, to avoid */
2772 /* unpleasant side-effects, for instance if the callback */
2773 /* function changes the Z-order of the windows. */
2775 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2777 WIN_ReleaseDesktop();
2778 return FALSE;
2781 /* Now call the callback function for every window */
2783 for (ppWnd = list; *ppWnd; ppWnd++)
2785 LRESULT lpEnumFuncRetval;
2786 int iWndsLocks = 0;
2787 /* Make sure that the window still exists */
2788 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2790 /* To avoid any deadlocks, all the locks on the windows
2791 structures must be suspended before the control
2792 is passed to the application */
2793 iWndsLocks = WIN_SuspendWndsLock();
2794 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2795 WIN_RestoreWndsLock(iWndsLocks);
2797 if (!lpEnumFuncRetval) break;
2799 WIN_ReleaseWinArray(list);
2800 WIN_ReleaseDesktop();
2801 return TRUE;
2805 /**********************************************************************
2806 * EnumTaskWindows16 (USER.225)
2808 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2809 LPARAM lParam )
2811 WND **list, **ppWnd;
2813 /* This function is the same as EnumWindows(), */
2814 /* except for an added check on the window's task. */
2816 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2818 WIN_ReleaseDesktop();
2819 return FALSE;
2822 /* Now call the callback function for every window */
2824 for (ppWnd = list; *ppWnd; ppWnd++)
2826 LRESULT funcRetval;
2827 int iWndsLocks = 0;
2828 /* Make sure that the window still exists */
2829 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2830 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2832 /* To avoid any deadlocks, all the locks on the windows
2833 structures must be suspended before the control
2834 is passed to the application */
2835 iWndsLocks = WIN_SuspendWndsLock();
2836 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2837 WIN_RestoreWndsLock(iWndsLocks);
2839 if (!funcRetval) break;
2841 WIN_ReleaseWinArray(list);
2842 WIN_ReleaseDesktop();
2843 return TRUE;
2847 /**********************************************************************
2848 * EnumThreadWindows (USER32.190)
2850 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2852 TEB *teb = THREAD_IdToTEB(id);
2854 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2858 /**********************************************************************
2859 * WIN_EnumChildWindows
2861 * Helper function for EnumChildWindows().
2863 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2865 WND **childList;
2866 BOOL16 ret = FALSE;
2868 for ( ; *ppWnd; ppWnd++)
2870 int iWndsLocks = 0;
2872 /* Make sure that the window still exists */
2873 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2874 /* Build children list first */
2875 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2877 /* To avoid any deadlocks, all the locks on the windows
2878 structures must be suspended before the control
2879 is passed to the application */
2880 iWndsLocks = WIN_SuspendWndsLock();
2881 ret = func( (*ppWnd)->hwndSelf, lParam );
2882 WIN_RestoreWndsLock(iWndsLocks);
2884 if (childList)
2886 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2887 WIN_ReleaseWinArray(childList);
2889 if (!ret) return FALSE;
2891 return TRUE;
2895 /**********************************************************************
2896 * EnumChildWindows (USER32.178)
2898 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2899 LPARAM lParam )
2901 WND **list, *pParent;
2903 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2904 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2906 WIN_ReleaseWndPtr(pParent);
2907 return FALSE;
2909 WIN_EnumChildWindows( list, func, lParam );
2910 WIN_ReleaseWinArray(list);
2911 WIN_ReleaseWndPtr(pParent);
2912 return TRUE;
2916 /*******************************************************************
2917 * AnyPopup16 (USER.52)
2919 BOOL16 WINAPI AnyPopup16(void)
2921 return AnyPopup();
2925 /*******************************************************************
2926 * AnyPopup (USER32.4)
2928 BOOL WINAPI AnyPopup(void)
2930 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2931 BOOL retvalue;
2933 while (wndPtr)
2935 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2937 retvalue = TRUE;
2938 goto end;
2940 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2942 retvalue = FALSE;
2943 end:
2944 WIN_ReleaseWndPtr(wndPtr);
2945 return retvalue;
2949 /*******************************************************************
2950 * FlashWindow16 (USER.105)
2952 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2954 return FlashWindow( hWnd, bInvert );
2958 /*******************************************************************
2959 * FlashWindow (USER32.202)
2961 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2963 WND *wndPtr = WIN_FindWndPtr(hWnd);
2965 TRACE("%04x\n", hWnd);
2967 if (!wndPtr) return FALSE;
2969 if (wndPtr->dwStyle & WS_MINIMIZE)
2971 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2973 HDC hDC = GetDC(hWnd);
2975 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2976 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2978 ReleaseDC( hWnd, hDC );
2979 wndPtr->flags |= WIN_NCACTIVATED;
2981 else
2983 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2984 RDW_UPDATENOW | RDW_FRAME, 0 );
2985 wndPtr->flags &= ~WIN_NCACTIVATED;
2987 WIN_ReleaseWndPtr(wndPtr);
2988 return TRUE;
2990 else
2992 WPARAM16 wparam;
2993 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2994 else wparam = (hWnd == GetActiveWindow());
2996 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2997 WIN_ReleaseWndPtr(wndPtr);
2998 return wparam;
3003 /*******************************************************************
3004 * SetSysModalWindow16 (USER.188)
3006 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3008 HWND hWndOldModal = hwndSysModal;
3009 hwndSysModal = hWnd;
3010 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3011 return hWndOldModal;
3015 /*******************************************************************
3016 * GetSysModalWindow16 (USER.52)
3018 HWND16 WINAPI GetSysModalWindow16(void)
3020 return hwndSysModal;
3024 /*******************************************************************
3025 * GetWindowContextHelpId (USER32.303)
3027 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3029 DWORD retval;
3030 WND *wnd = WIN_FindWndPtr( hwnd );
3031 if (!wnd) return 0;
3032 retval = wnd->helpContext;
3033 WIN_ReleaseWndPtr(wnd);
3034 return retval;
3038 /*******************************************************************
3039 * SetWindowContextHelpId (USER32.515)
3041 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3043 WND *wnd = WIN_FindWndPtr( hwnd );
3044 if (!wnd) return FALSE;
3045 wnd->helpContext = id;
3046 WIN_ReleaseWndPtr(wnd);
3047 return TRUE;
3051 /*******************************************************************
3052 * DRAG_QueryUpdate
3054 * recursively find a child that contains spDragInfo->pt point
3055 * and send WM_QUERYDROPOBJECT
3057 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3059 BOOL16 wParam, bResult = 0;
3060 POINT pt;
3061 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3062 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3063 RECT tempRect;
3065 if( !ptrQueryWnd || !ptrDragInfo )
3066 goto end;
3068 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3070 GetWindowRect(hQueryWnd,&tempRect);
3072 if( !PtInRect(&tempRect,pt) ||
3073 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3074 goto end;
3076 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3078 tempRect = ptrQueryWnd->rectClient;
3079 if(ptrQueryWnd->dwStyle & WS_CHILD)
3080 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3081 (LPPOINT)&tempRect, 2 );
3083 if (PtInRect( &tempRect, pt))
3085 wParam = 0;
3087 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3089 if( ptrWnd->dwStyle & WS_VISIBLE )
3091 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3092 if (PtInRect( &tempRect, pt )) break;
3096 if(ptrWnd)
3098 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3099 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3100 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3101 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3102 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3104 WIN_ReleaseWndPtr(ptrWnd);
3107 if(bResult)
3108 goto end;
3110 else wParam = 1;
3112 else wParam = 1;
3114 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3116 ptrDragInfo->hScope = hQueryWnd;
3118 bResult = ( bNoSend )
3119 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3120 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3121 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3122 if( !bResult )
3123 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3125 end:
3126 WIN_ReleaseWndPtr(ptrQueryWnd);
3127 return bResult;
3131 /*******************************************************************
3132 * DragDetect (USER.465)
3134 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3136 POINT pt32;
3137 CONV_POINT16TO32( &pt, &pt32 );
3138 return DragDetect( hWnd, pt32 );
3141 /*******************************************************************
3142 * DragDetect (USER32.151)
3144 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3146 MSG16 msg;
3147 RECT16 rect;
3149 rect.left = pt.x - wDragWidth;
3150 rect.right = pt.x + wDragWidth;
3152 rect.top = pt.y - wDragHeight;
3153 rect.bottom = pt.y + wDragHeight;
3155 SetCapture(hWnd);
3157 while(1)
3159 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3161 if( msg.message == WM_LBUTTONUP )
3163 ReleaseCapture();
3164 return 0;
3166 if( msg.message == WM_MOUSEMOVE )
3168 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3170 ReleaseCapture();
3171 return 1;
3175 WaitMessage();
3177 return 0;
3180 /******************************************************************************
3181 * DragObject16 (USER.464)
3183 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3184 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3186 MSG16 msg;
3187 LPDRAGINFO lpDragInfo;
3188 SEGPTR spDragInfo;
3189 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3190 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3191 WND *wndPtr = WIN_FindWndPtr(hWnd);
3192 HCURSOR16 hCurrentCursor = 0;
3193 HWND16 hCurrentWnd = 0;
3195 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3196 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3198 if( !lpDragInfo || !spDragInfo )
3200 WIN_ReleaseWndPtr(wndPtr);
3201 return 0L;
3204 hBummer = LoadCursor16(0, IDC_BUMMER16);
3206 if( !hBummer || !wndPtr )
3208 GlobalFree16(hDragInfo);
3209 WIN_ReleaseWndPtr(wndPtr);
3210 return 0L;
3213 if(hCursor)
3215 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3217 GlobalFree16(hDragInfo);
3218 WIN_ReleaseWndPtr(wndPtr);
3219 return 0L;
3222 if( hDragCursor == hCursor ) hDragCursor = 0;
3223 else hCursor = hDragCursor;
3225 hOldCursor = SetCursor(hDragCursor);
3228 lpDragInfo->hWnd = hWnd;
3229 lpDragInfo->hScope = 0;
3230 lpDragInfo->wFlags = wObj;
3231 lpDragInfo->hList = szList; /* near pointer! */
3232 lpDragInfo->hOfStruct = hOfStruct;
3233 lpDragInfo->l = 0L;
3235 SetCapture(hWnd);
3236 ShowCursor( TRUE );
3240 do{ WaitMessage(); }
3241 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3243 *(lpDragInfo+1) = *lpDragInfo;
3245 lpDragInfo->pt = msg.pt;
3247 /* update DRAGINFO struct */
3248 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3250 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3251 hCurrentCursor = hCursor;
3252 else
3254 hCurrentCursor = hBummer;
3255 lpDragInfo->hScope = 0;
3257 if( hCurrentCursor )
3258 SetCursor(hCurrentCursor);
3260 /* send WM_DRAGLOOP */
3261 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3262 (LPARAM) spDragInfo );
3263 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3264 if( hCurrentWnd != lpDragInfo->hScope )
3266 if( hCurrentWnd )
3267 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3268 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3269 HIWORD(spDragInfo)) );
3270 hCurrentWnd = lpDragInfo->hScope;
3271 if( hCurrentWnd )
3272 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3274 else
3275 if( hCurrentWnd )
3276 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3278 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3280 ReleaseCapture();
3281 ShowCursor( FALSE );
3283 if( hCursor )
3285 SetCursor( hOldCursor );
3286 if (hDragCursor) DestroyCursor( hDragCursor );
3289 if( hCurrentCursor != hBummer )
3290 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3291 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3292 else
3293 msg.lParam = 0;
3294 GlobalFree16(hDragInfo);
3295 WIN_ReleaseWndPtr(wndPtr);
3297 return (DWORD)(msg.lParam);