Get full path of argv[0] before we change directories.
[wine.git] / windows / win.c
blob68a1e44c0dfef7e774f584b19981b23fac556385
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 ? debugstr_w(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 ? debugstr_w(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 if (cs->style & (WS_CHILD | WS_POPUP))
669 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
670 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
672 else /* overlapped window */
674 STARTUPINFOA info;
676 GetStartupInfoA( &info );
678 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
680 /* Never believe Microsoft's documentation... CreateWindowEx doc says
681 * that if an overlapped window is created with WS_VISIBLE style bit
682 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
683 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
684 * reveals that
686 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
687 * 2) it does not ignore the y parameter as the docs claim; instead, it
688 * uses it as second parameter to ShowWindow() unless y is either
689 * CW_USEDEFAULT or CW_USEDEFAULT16.
691 * The fact that we didn't do 2) caused bogus windows pop up when wine
692 * was running apps that were using this obscure feature. Example -
693 * calc.exe that comes with Win98 (only Win98, it's different from
694 * the one that comes with Win95 and NT)
696 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
697 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
698 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
701 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
703 if (info.dwFlags & STARTF_USESIZE)
705 cs->cx = info.dwXSize;
706 cs->cy = info.dwYSize;
708 else /* if no other hint from the app, pick 3/4 of the screen real estate */
710 RECT r;
711 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
712 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
720 /***********************************************************************
721 * WIN_CreateWindowEx
723 * Implementation of CreateWindowEx().
725 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
726 BOOL win32, BOOL unicode )
728 INT sw = SW_SHOW;
729 CLASS *classPtr;
730 WND *wndPtr;
731 HWND retvalue;
732 HWND16 hwnd, hwndLinkAfter;
733 POINT maxSize, maxPos, minTrack, maxTrack;
734 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
736 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
737 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
738 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
739 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
740 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
742 /* Find the parent window */
744 if (cs->hwndParent)
746 /* Make sure parent is valid */
747 if (!IsWindow( cs->hwndParent ))
749 WARN("Bad parent %04x\n", cs->hwndParent );
750 return 0;
752 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
753 WARN("No parent for child window\n" );
754 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
757 /* Find the window class */
758 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
760 WARN("Bad class '%s'\n", cs->lpszClass );
761 return 0;
764 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
766 /* Create the window structure */
768 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
769 - sizeof(wndPtr->wExtra) )))
771 TRACE("out of memory\n" );
772 return 0;
775 /* Fill the window structure */
777 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
778 wndPtr->next = NULL;
779 wndPtr->child = NULL;
781 if ((cs->style & WS_CHILD) && cs->hwndParent)
783 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
784 wndPtr->owner = NULL;
785 WIN_ReleaseWndPtr(wndPtr->parent);
787 else
789 wndPtr->parent = pWndDesktop;
790 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
791 wndPtr->owner = NULL;
792 else
794 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
795 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
796 WIN_ReleaseWndPtr(wndPtr->owner);
797 WIN_ReleaseWndPtr(tmpWnd);
802 wndPtr->pDriver = wndPtr->parent->pDriver;
803 wndPtr->pDriver->pInitialize(wndPtr);
805 wndPtr->class = classPtr;
806 wndPtr->winproc = classPtr->winproc;
807 wndPtr->dwMagic = WND_MAGIC;
808 wndPtr->hwndSelf = hwnd;
809 wndPtr->hInstance = cs->hInstance;
810 wndPtr->text = NULL;
811 wndPtr->hmemTaskQ = GetFastQueue16();
812 wndPtr->hrgnUpdate = 0;
813 wndPtr->hwndLastActive = hwnd;
814 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
815 wndPtr->dwExStyle = cs->dwExStyle;
816 wndPtr->wIDmenu = 0;
817 wndPtr->helpContext = 0;
818 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
819 wndPtr->pVScroll = NULL;
820 wndPtr->pHScroll = NULL;
821 wndPtr->pProp = NULL;
822 wndPtr->userdata = 0;
823 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
824 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
825 wndPtr->irefCount = 1;
827 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
829 /* Call the WH_CBT hook */
831 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
832 ? HWND_BOTTOM : HWND_TOP;
834 if (HOOK_IsHooked( WH_CBT ))
836 CBT_CREATEWNDA cbtc;
837 LRESULT ret;
839 cbtc.lpcs = cs;
840 cbtc.hwndInsertAfter = hwndLinkAfter;
841 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
842 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
843 if (ret)
845 TRACE("CBT-hook returned 0\n");
846 wndPtr->pDriver->pFinalize(wndPtr);
847 USER_HEAP_FREE( hwnd );
848 retvalue = 0;
849 goto end;
853 /* Increment class window counter */
855 classPtr->cWindows++;
857 /* Correct the window style */
859 if (!(cs->style & WS_CHILD))
861 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
862 if (!(cs->style & WS_POPUP))
864 wndPtr->dwStyle |= WS_CAPTION;
865 wndPtr->flags |= WIN_NEED_SIZE;
869 /* Get class or window DC if needed */
871 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
872 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
873 else wndPtr->dce = NULL;
875 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
877 wndPtr->rectWindow.left = cs->x;
878 wndPtr->rectWindow.top = cs->y;
879 wndPtr->rectWindow.right = cs->x + cs->cx;
880 wndPtr->rectWindow.bottom = cs->y + cs->cy;
881 wndPtr->rectClient = wndPtr->rectWindow;
883 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
885 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
887 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
888 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
889 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
890 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
891 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
894 if (cs->cx < 0) cs->cx = 0;
895 if (cs->cy < 0) cs->cy = 0;
897 wndPtr->rectWindow.left = cs->x;
898 wndPtr->rectWindow.top = cs->y;
899 wndPtr->rectWindow.right = cs->x + cs->cx;
900 wndPtr->rectWindow.bottom = cs->y + cs->cy;
901 wndPtr->rectClient = wndPtr->rectWindow;
903 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
905 retvalue = FALSE;
906 goto end;
909 /* Set the window menu */
911 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
913 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
914 else
916 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
917 if (classPtr->menuNameA)
918 cs->hMenu = HIWORD(classPtr->menuNameA) ?
919 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
920 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
921 #else
922 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
923 if (menuName)
925 if (HIWORD(cs->hInstance))
926 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
927 else
928 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
930 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
932 #endif
935 else wndPtr->wIDmenu = (UINT)cs->hMenu;
937 /* Send the WM_CREATE message
938 * Perhaps we shouldn't allow width/height changes as well.
939 * See p327 in "Internals".
942 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
944 localSend32 = unicode ? SendMessageW : SendMessageA;
945 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
947 /* Insert the window in the linked list */
949 WIN_LinkWindow( hwnd, hwndLinkAfter );
951 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
952 NULL, NULL, 0, &wndPtr->rectClient );
953 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
954 maxPos.y - wndPtr->rectWindow.top);
955 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
957 /* Send the size messages */
959 if (!(wndPtr->flags & WIN_NEED_SIZE))
961 /* send it anyway */
962 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
963 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
964 WARN("sending bogus WM_SIZE message 0x%08lx\n",
965 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
966 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
967 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
968 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
969 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
970 SendMessageA( hwnd, WM_MOVE, 0,
971 MAKELONG( wndPtr->rectClient.left,
972 wndPtr->rectClient.top ) );
975 /* Show the window, maximizing or minimizing if needed */
977 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
979 RECT16 newPos;
980 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
981 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
982 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
983 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
984 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
985 : SWP_NOZORDER | SWP_FRAMECHANGED;
986 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
987 newPos.right, newPos.bottom, swFlag );
990 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
992 /* Notify the parent window only */
994 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
995 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
996 if( !IsWindow(hwnd) )
998 retvalue = 0;
999 goto end;
1003 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1005 /* Call WH_SHELL hook */
1007 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1008 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1010 TRACE("created window %04x\n", hwnd);
1011 retvalue = hwnd;
1012 goto end;
1014 WIN_UnlinkWindow( hwnd );
1017 /* Abort window creation */
1019 WARN("aborted by WM_xxCREATE!\n");
1020 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1021 retvalue = 0;
1022 end:
1023 WIN_ReleaseWndPtr(wndPtr);
1025 return retvalue;
1029 /***********************************************************************
1030 * CreateWindow16 (USER.41)
1032 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1033 DWORD style, INT16 x, INT16 y, INT16 width,
1034 INT16 height, HWND16 parent, HMENU16 menu,
1035 HINSTANCE16 instance, LPVOID data )
1037 return CreateWindowEx16( 0, className, windowName, style,
1038 x, y, width, height, parent, menu, instance, data );
1042 /***********************************************************************
1043 * CreateWindowEx16 (USER.452)
1045 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1046 LPCSTR windowName, DWORD style, INT16 x,
1047 INT16 y, INT16 width, INT16 height,
1048 HWND16 parent, HMENU16 menu,
1049 HINSTANCE16 instance, LPVOID data )
1051 ATOM classAtom;
1052 CREATESTRUCTA cs;
1053 char buffer[256];
1055 /* Find the class atom */
1057 if (HIWORD(className))
1059 if (!(classAtom = GlobalFindAtomA( className )))
1061 ERR( "bad class name %s\n", debugres_a(className) );
1062 return 0;
1065 else
1067 classAtom = LOWORD(className);
1068 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1070 ERR( "bad atom %x\n", classAtom);
1071 return 0;
1073 className = buffer;
1076 /* Fix the coordinates */
1078 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1079 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1080 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1081 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1083 /* Create the window */
1085 cs.lpCreateParams = data;
1086 cs.hInstance = (HINSTANCE)instance;
1087 cs.hMenu = (HMENU)menu;
1088 cs.hwndParent = (HWND)parent;
1089 cs.style = style;
1090 cs.lpszName = windowName;
1091 cs.lpszClass = className;
1092 cs.dwExStyle = exStyle;
1094 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1098 /***********************************************************************
1099 * CreateWindowExA (USER32.83)
1101 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1102 LPCSTR windowName, DWORD style, INT x,
1103 INT y, INT width, INT height,
1104 HWND parent, HMENU menu,
1105 HINSTANCE instance, LPVOID data )
1107 ATOM classAtom;
1108 CREATESTRUCTA cs;
1109 char buffer[256];
1111 if(!instance)
1112 instance=GetModuleHandleA(NULL);
1114 if(exStyle & WS_EX_MDICHILD)
1115 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1117 /* Find the class atom */
1119 if (HIWORD(className))
1121 if (!(classAtom = GlobalFindAtomA( className )))
1123 ERR( "bad class name %s\n", debugres_a(className) );
1124 return 0;
1127 else
1129 classAtom = LOWORD(className);
1130 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1132 ERR( "bad atom %x\n", classAtom);
1133 return 0;
1135 className = buffer;
1138 /* Create the window */
1140 cs.lpCreateParams = data;
1141 cs.hInstance = instance;
1142 cs.hMenu = menu;
1143 cs.hwndParent = parent;
1144 cs.x = x;
1145 cs.y = y;
1146 cs.cx = width;
1147 cs.cy = height;
1148 cs.style = style;
1149 cs.lpszName = windowName;
1150 cs.lpszClass = className;
1151 cs.dwExStyle = exStyle;
1153 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1157 /***********************************************************************
1158 * CreateWindowExW (USER32.84)
1160 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1161 LPCWSTR windowName, DWORD style, INT x,
1162 INT y, INT width, INT height,
1163 HWND parent, HMENU menu,
1164 HINSTANCE instance, LPVOID data )
1166 ATOM classAtom;
1167 CREATESTRUCTW cs;
1168 WCHAR buffer[256];
1170 if(!instance)
1171 instance=GetModuleHandleA(NULL);
1173 if(exStyle & WS_EX_MDICHILD)
1174 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomW( className )))
1182 ERR( "bad class name %s\n", debugres_w(className) );
1183 return 0;
1186 else
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1191 ERR( "bad atom %x\n", classAtom);
1192 return 0;
1194 className = buffer;
1197 /* Create the window */
1199 cs.lpCreateParams = data;
1200 cs.hInstance = instance;
1201 cs.hMenu = menu;
1202 cs.hwndParent = parent;
1203 cs.x = x;
1204 cs.y = y;
1205 cs.cx = width;
1206 cs.cy = height;
1207 cs.style = style;
1208 cs.lpszName = windowName;
1209 cs.lpszClass = className;
1210 cs.dwExStyle = exStyle;
1212 /* Note: we rely on the fact that CREATESTRUCTA and */
1213 /* CREATESTRUCTW have the same layout. */
1214 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1218 /***********************************************************************
1219 * WIN_CheckFocus
1221 static void WIN_CheckFocus( WND* pWnd )
1223 if( GetFocus16() == pWnd->hwndSelf )
1224 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1227 /***********************************************************************
1228 * WIN_SendDestroyMsg
1230 static void WIN_SendDestroyMsg( WND* pWnd )
1232 WIN_CheckFocus(pWnd);
1234 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1235 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1238 * Send the WM_DESTROY to the window.
1240 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1243 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1244 * make sure that the window still exists when we come back.
1246 if (IsWindow(pWnd->hwndSelf))
1248 HWND* pWndArray = NULL;
1249 WND* pChild = NULL;
1250 int nKidCount = 0;
1253 * Now, if the window has kids, we have to send WM_DESTROY messages
1254 * recursively to it's kids. It seems that those calls can also
1255 * trigger re-entrant calls to DestroyWindow for the kids so we must
1256 * protect against corruption of the list of siblings. We first build
1257 * a list of HWNDs representing all the kids.
1259 pChild = WIN_LockWndPtr(pWnd->child);
1260 while( pChild )
1262 nKidCount++;
1263 WIN_UpdateWndPtr(&pChild,pChild->next);
1267 * If there are no kids, we're done.
1269 if (nKidCount==0)
1270 return;
1272 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1275 * Sanity check
1277 if (pWndArray==NULL)
1278 return;
1281 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1282 * call, our linked list of siblings should be safe.
1284 nKidCount = 0;
1285 pChild = WIN_LockWndPtr(pWnd->child);
1286 while( pChild )
1288 pWndArray[nKidCount] = pChild->hwndSelf;
1289 nKidCount++;
1290 WIN_UpdateWndPtr(&pChild,pChild->next);
1294 * Now that we have a list, go through that list again and send the destroy
1295 * message to those windows. We are using the HWND to retrieve the
1296 * WND pointer so we are effectively checking that all the kid windows are
1297 * still valid before sending the message.
1299 while (nKidCount>0)
1301 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1303 if (pChild!=NULL)
1305 WIN_SendDestroyMsg( pChild );
1306 WIN_ReleaseWndPtr(pChild);
1311 * Cleanup
1313 HeapFree(GetProcessHeap(), 0, pWndArray);
1314 WIN_CheckFocus(pWnd);
1316 else
1317 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1321 /***********************************************************************
1322 * DestroyWindow16 (USER.53)
1324 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1326 return DestroyWindow(hwnd);
1330 /***********************************************************************
1331 * DestroyWindow (USER32.135)
1333 BOOL WINAPI DestroyWindow( HWND hwnd )
1335 WND * wndPtr;
1336 BOOL retvalue;
1338 TRACE("(%04x)\n", hwnd);
1340 /* Initialization */
1342 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1343 if (wndPtr == pWndDesktop)
1345 retvalue = FALSE; /* Can't destroy desktop */
1346 goto end;
1349 /* Call hooks */
1351 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1353 retvalue = FALSE;
1354 goto end;
1357 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1359 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1360 /* FIXME: clean up palette - see "Internals" p.352 */
1363 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1364 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1366 /* Notify the parent window only */
1367 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1368 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1369 if( !IsWindow(hwnd) )
1371 retvalue = TRUE;
1372 goto end;
1376 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1378 /* Hide the window */
1380 if (wndPtr->dwStyle & WS_VISIBLE)
1382 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1383 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1384 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1385 if (!IsWindow(hwnd))
1387 retvalue = TRUE;
1388 goto end;
1392 /* Recursively destroy owned windows */
1394 if( !(wndPtr->dwStyle & WS_CHILD) )
1396 /* make sure top menu popup doesn't get destroyed */
1397 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1399 for (;;)
1401 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1402 while (siblingPtr)
1404 if (siblingPtr->owner == wndPtr)
1406 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1407 break;
1408 else
1409 siblingPtr->owner = NULL;
1411 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1413 if (siblingPtr)
1415 DestroyWindow( siblingPtr->hwndSelf );
1416 WIN_ReleaseWndPtr(siblingPtr);
1418 else break;
1421 if( !Options.managed || EVENT_CheckFocus() )
1422 WINPOS_ActivateOtherWindow(wndPtr);
1424 if( wndPtr->owner &&
1425 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1426 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1429 /* Send destroy messages */
1431 WIN_SendDestroyMsg( wndPtr );
1432 if (!IsWindow(hwnd))
1434 retvalue = TRUE;
1435 goto end;
1438 /* Unlink now so we won't bother with the children later on */
1440 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1442 /* Destroy the window storage */
1444 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1445 retvalue = TRUE;
1446 end:
1447 WIN_ReleaseWndPtr(wndPtr);
1448 return retvalue;
1452 /***********************************************************************
1453 * CloseWindow16 (USER.43)
1455 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1457 return CloseWindow( hwnd );
1461 /***********************************************************************
1462 * CloseWindow (USER32.56)
1464 BOOL WINAPI CloseWindow( HWND hwnd )
1466 WND * wndPtr = WIN_FindWndPtr( hwnd );
1467 BOOL retvalue;
1469 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1471 retvalue = FALSE;
1472 goto end;
1474 ShowWindow( hwnd, SW_MINIMIZE );
1475 retvalue = TRUE;
1476 end:
1477 WIN_ReleaseWndPtr(wndPtr);
1478 return retvalue;
1483 /***********************************************************************
1484 * OpenIcon16 (USER.44)
1486 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1488 return OpenIcon( hwnd );
1492 /***********************************************************************
1493 * OpenIcon (USER32.410)
1495 BOOL WINAPI OpenIcon( HWND hwnd )
1497 if (!IsIconic( hwnd )) return FALSE;
1498 ShowWindow( hwnd, SW_SHOWNORMAL );
1499 return TRUE;
1503 /***********************************************************************
1504 * WIN_FindWindow
1506 * Implementation of FindWindow() and FindWindowEx().
1508 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1509 LPCWSTR title )
1511 WND *pWnd;
1512 HWND retvalue;
1514 if (child)
1516 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1517 if (parent)
1519 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1521 retvalue = 0;
1522 goto end;
1525 else if (pWnd->parent != pWndDesktop)
1527 retvalue = 0;
1528 goto end;
1530 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1532 else
1534 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1536 retvalue = 0;
1537 goto end;
1539 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1541 if (!pWnd)
1543 retvalue = 0;
1544 goto end;
1547 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1549 if (className && (pWnd->class->atomName != className))
1550 continue; /* Not the right class */
1552 /* Now check the title */
1554 if (!title)
1556 retvalue = pWnd->hwndSelf;
1557 goto end;
1559 if (pWnd->text && !lstrcmpW( pWnd->text, title ))
1561 retvalue = pWnd->hwndSelf;
1562 goto end;
1565 retvalue = 0;
1566 end:
1567 WIN_ReleaseWndPtr(pWnd);
1568 return retvalue;
1573 /***********************************************************************
1574 * FindWindow16 (USER.50)
1576 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1578 return FindWindowA( className, title );
1582 /***********************************************************************
1583 * FindWindowEx16 (USER.427)
1585 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1587 return FindWindowExA( parent, child, className, title );
1591 /***********************************************************************
1592 * FindWindowA (USER32.198)
1594 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1596 HWND ret = FindWindowExA( 0, 0, className, title );
1597 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1598 return ret;
1602 /***********************************************************************
1603 * FindWindowExA (USER32.199)
1605 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1606 LPCSTR className, LPCSTR title )
1608 ATOM atom = 0;
1609 LPWSTR buffer;
1610 HWND hwnd;
1612 if (className)
1614 /* If the atom doesn't exist, then no class */
1615 /* with this name exists either. */
1616 if (!(atom = GlobalFindAtomA( className )))
1618 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1619 return 0;
1623 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1624 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1625 HeapFree( GetProcessHeap(), 0, buffer );
1626 return hwnd;
1630 /***********************************************************************
1631 * FindWindowExW (USER32.200)
1633 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1634 LPCWSTR className, LPCWSTR title )
1636 ATOM atom = 0;
1638 if (className)
1640 /* If the atom doesn't exist, then no class */
1641 /* with this name exists either. */
1642 if (!(atom = GlobalFindAtomW( className )))
1644 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1645 return 0;
1648 return WIN_FindWindow( parent, child, atom, title );
1652 /***********************************************************************
1653 * FindWindowW (USER32.201)
1655 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1657 return FindWindowExW( 0, 0, className, title );
1661 /**********************************************************************
1662 * WIN_GetDesktop
1663 * returns a locked pointer
1665 WND *WIN_GetDesktop(void)
1667 return WIN_LockWndPtr(pWndDesktop);
1669 /**********************************************************************
1670 * WIN_ReleaseDesktop
1671 * unlock the desktop pointer
1673 void WIN_ReleaseDesktop(void)
1675 WIN_ReleaseWndPtr(pWndDesktop);
1679 /**********************************************************************
1680 * GetDesktopWindow16 (USER.286)
1682 HWND16 WINAPI GetDesktopWindow16(void)
1684 return (HWND16)pWndDesktop->hwndSelf;
1688 /**********************************************************************
1689 * GetDesktopWindow (USER32.232)
1691 HWND WINAPI GetDesktopWindow(void)
1693 if (pWndDesktop) return pWndDesktop->hwndSelf;
1694 ERR( "You need the -desktop option when running with native USER\n" );
1695 ExitProcess(1);
1696 return 0;
1700 /**********************************************************************
1701 * GetDesktopHwnd (USER.278)
1703 * Exactly the same thing as GetDesktopWindow(), but not documented.
1704 * Don't ask me why...
1706 HWND16 WINAPI GetDesktopHwnd16(void)
1708 return (HWND16)pWndDesktop->hwndSelf;
1712 /*******************************************************************
1713 * EnableWindow16 (USER.34)
1715 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1717 return EnableWindow( hwnd, enable );
1721 /*******************************************************************
1722 * EnableWindow (USER32.172)
1724 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1726 WND *wndPtr;
1727 BOOL retvalue;
1729 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1731 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1732 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1734 /* Enable window */
1735 wndPtr->dwStyle &= ~WS_DISABLED;
1737 if( wndPtr->flags & WIN_NATIVE )
1738 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1740 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1741 retvalue = TRUE;
1742 goto end;
1744 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1746 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1748 /* Disable window */
1749 wndPtr->dwStyle |= WS_DISABLED;
1751 if( wndPtr->flags & WIN_NATIVE )
1752 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1754 if (hwnd == GetFocus())
1756 SetFocus( 0 ); /* A disabled window can't have the focus */
1758 if (hwnd == GetCapture())
1760 ReleaseCapture(); /* A disabled window can't capture the mouse */
1762 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1763 retvalue = FALSE;
1764 goto end;
1766 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1767 end:
1768 WIN_ReleaseWndPtr(wndPtr);
1769 return retvalue;
1773 /***********************************************************************
1774 * IsWindowEnabled16 (USER.35)
1776 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1778 return IsWindowEnabled(hWnd);
1782 /***********************************************************************
1783 * IsWindowEnabled (USER32.349)
1785 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1787 WND * wndPtr;
1788 BOOL retvalue;
1790 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1791 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1792 WIN_ReleaseWndPtr(wndPtr);
1793 return retvalue;
1798 /***********************************************************************
1799 * IsWindowUnicode (USER32.350)
1801 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1803 WND * wndPtr;
1804 BOOL retvalue;
1806 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1807 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1808 WIN_ReleaseWndPtr(wndPtr);
1809 return retvalue;
1813 /**********************************************************************
1814 * GetWindowWord16 (USER.133)
1816 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1818 return GetWindowWord( hwnd, offset );
1822 /**********************************************************************
1823 * GetWindowWord (USER32.314)
1825 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1827 WORD retvalue;
1828 WND * wndPtr = WIN_FindWndPtr( hwnd );
1829 if (!wndPtr) return 0;
1830 if (offset >= 0)
1832 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1834 WARN("Invalid offset %d\n", offset );
1835 retvalue = 0;
1836 goto end;
1838 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1839 goto end;
1841 switch(offset)
1843 case GWW_ID:
1844 if (HIWORD(wndPtr->wIDmenu))
1845 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1846 wndPtr->wIDmenu);
1847 retvalue = (WORD)wndPtr->wIDmenu;
1848 goto end;
1849 case GWW_HWNDPARENT:
1850 retvalue = GetParent(hwnd);
1851 goto end;
1852 case GWW_HINSTANCE:
1853 if (HIWORD(wndPtr->hInstance))
1854 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1855 wndPtr->hInstance);
1856 retvalue = (WORD)wndPtr->hInstance;
1857 goto end;
1858 default:
1859 WARN("Invalid offset %d\n", offset );
1860 retvalue = 0;
1861 goto end;
1863 end:
1864 WIN_ReleaseWndPtr(wndPtr);
1865 return retvalue;
1868 /**********************************************************************
1869 * SetWindowWord16 (USER.134)
1871 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1873 return SetWindowWord( hwnd, offset, newval );
1877 /**********************************************************************
1878 * SetWindowWord (USER32.524)
1880 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1882 WORD *ptr, retval;
1883 WND * wndPtr = WIN_FindWndPtr( hwnd );
1884 if (!wndPtr) return 0;
1885 if (offset >= 0)
1887 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1889 WARN("Invalid offset %d\n", offset );
1890 retval = 0;
1891 goto end;
1893 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1895 else switch(offset)
1897 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1898 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1899 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1900 goto end;
1901 default:
1902 WARN("Invalid offset %d\n", offset );
1903 retval = 0;
1904 goto end;
1906 retval = *ptr;
1907 *ptr = newval;
1908 end:
1909 WIN_ReleaseWndPtr(wndPtr);
1910 return retval;
1914 /**********************************************************************
1915 * WIN_GetWindowLong
1917 * Helper function for GetWindowLong().
1919 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1921 LONG retvalue;
1922 WND * wndPtr = WIN_FindWndPtr( hwnd );
1923 if (!wndPtr) return 0;
1924 if (offset >= 0)
1926 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1928 WARN("Invalid offset %d\n", offset );
1929 retvalue = 0;
1930 goto end;
1932 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1933 /* Special case for dialog window procedure */
1934 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1936 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1937 goto end;
1939 goto end;
1941 switch(offset)
1943 case GWL_USERDATA: retvalue = wndPtr->userdata;
1944 goto end;
1945 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1946 goto end;
1947 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1948 goto end;
1949 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1950 goto end;
1951 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1952 type );
1953 goto end;
1954 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1955 goto end;
1956 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1957 goto end;
1958 default:
1959 WARN("Unknown offset %d\n", offset );
1961 retvalue = 0;
1962 end:
1963 WIN_ReleaseWndPtr(wndPtr);
1964 return retvalue;
1968 /**********************************************************************
1969 * WIN_SetWindowLong
1971 * Helper function for SetWindowLong().
1973 * 0 is the failure code. However, in the case of failure SetLastError
1974 * must be set to distinguish between a 0 return value and a failure.
1976 * FIXME: The error values for SetLastError may not be right. Can
1977 * someone check with the real thing?
1979 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1980 WINDOWPROCTYPE type )
1982 LONG *ptr, retval;
1983 WND * wndPtr = WIN_FindWndPtr( hwnd );
1984 STYLESTRUCT style;
1986 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1988 if (!wndPtr)
1990 /* Is this the right error? */
1991 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1992 return 0;
1995 if (offset >= 0)
1997 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1999 WARN("Invalid offset %d\n", offset );
2001 /* Is this the right error? */
2002 SetLastError( ERROR_OUTOFMEMORY );
2004 retval = 0;
2005 goto end;
2007 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2008 /* Special case for dialog window procedure */
2009 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2011 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2012 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2013 type, WIN_PROC_WINDOW );
2014 goto end;
2017 else switch(offset)
2019 case GWL_ID:
2020 ptr = (DWORD*)&wndPtr->wIDmenu;
2021 break;
2022 case GWL_HINSTANCE:
2023 retval = SetWindowWord( hwnd, offset, newval );
2024 goto end;
2025 case GWL_WNDPROC:
2026 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2027 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2028 type, WIN_PROC_WINDOW );
2029 goto end;
2030 case GWL_STYLE:
2031 style.styleOld = wndPtr->dwStyle;
2032 newval &= ~(WS_CHILD); /* this bit can't be changed this way */
2033 style.styleNew = newval | (style.styleOld & (WS_CHILD));
2035 if (wndPtr->flags & WIN_ISWIN32)
2036 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2037 wndPtr->dwStyle = style.styleNew;
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2040 retval = style.styleOld;
2041 goto end;
2043 case GWL_USERDATA:
2044 ptr = &wndPtr->userdata;
2045 break;
2046 case GWL_EXSTYLE:
2047 style.styleOld = wndPtr->dwExStyle;
2048 style.styleNew = newval;
2049 if (wndPtr->flags & WIN_ISWIN32)
2050 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2051 wndPtr->dwExStyle = newval;
2052 if (wndPtr->flags & WIN_ISWIN32)
2053 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2054 retval = style.styleOld;
2055 goto end;
2057 default:
2058 WARN("Invalid offset %d\n", offset );
2060 /* Don't think this is right error but it should do */
2061 SetLastError( ERROR_OUTOFMEMORY );
2063 retval = 0;
2064 goto end;
2066 retval = *ptr;
2067 *ptr = newval;
2068 end:
2069 WIN_ReleaseWndPtr(wndPtr);
2070 return retval;
2074 /**********************************************************************
2075 * GetWindowLong16 (USER.135)
2077 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2079 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2083 /**********************************************************************
2084 * GetWindowLongA (USER32.305)
2086 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2088 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2092 /**********************************************************************
2093 * GetWindowLongW (USER32.306)
2095 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2097 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2101 /**********************************************************************
2102 * SetWindowLong16 (USER.136)
2104 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2106 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2110 /**********************************************************************
2111 * SetWindowLongA (USER32.517)
2113 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2115 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2119 /**********************************************************************
2120 * SetWindowLongW (USER32.518) Set window attribute
2122 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2123 * value in a window's extra memory.
2125 * The _hwnd_ parameter specifies the window. is the handle to a
2126 * window that has extra memory. The _newval_ parameter contains the
2127 * new attribute or extra memory value. If positive, the _offset_
2128 * parameter is the byte-addressed location in the window's extra
2129 * memory to set. If negative, _offset_ specifies the window
2130 * attribute to set, and should be one of the following values:
2132 * GWL_EXSTYLE The window's extended window style
2134 * GWL_STYLE The window's window style.
2136 * GWL_WNDPROC Pointer to the window's window procedure.
2138 * GWL_HINSTANCE The window's pplication instance handle.
2140 * GWL_ID The window's identifier.
2142 * GWL_USERDATA The window's user-specified data.
2144 * If the window is a dialog box, the _offset_ parameter can be one of
2145 * the following values:
2147 * DWL_DLGPROC The address of the window's dialog box procedure.
2149 * DWL_MSGRESULT The return value of a message
2150 * that the dialog box procedure processed.
2152 * DWL_USER Application specific information.
2154 * RETURNS
2156 * If successful, returns the previous value located at _offset_. Otherwise,
2157 * returns 0.
2159 * NOTES
2161 * Extra memory for a window class is specified by a nonzero cbWndExtra
2162 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2163 * time of class creation.
2165 * Using GWL_WNDPROC to set a new window procedure effectively creates
2166 * a window subclass. Use CallWindowProc() in the new windows procedure
2167 * to pass messages to the superclass's window procedure.
2169 * The user data is reserved for use by the application which created
2170 * the window.
2172 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2173 * instead, call the EnableWindow() function to change the window's
2174 * disabled state.
2176 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2177 * SetParent() instead.
2179 * Win95:
2180 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2181 * it sends WM_STYLECHANGING before changing the settings
2182 * and WM_STYLECHANGED afterwards.
2183 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2185 * BUGS
2187 * GWL_STYLE does not dispatch WM_STYLE... messages.
2189 * CONFORMANCE
2191 * ECMA-234, Win32
2194 LONG WINAPI SetWindowLongW(
2195 HWND hwnd, /* window to alter */
2196 INT offset, /* offset, in bytes, of location to alter */
2197 LONG newval /* new value of location */
2199 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2203 /*******************************************************************
2204 * GetWindowText16 (USER.36)
2206 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2208 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2212 /*******************************************************************
2213 * GetWindowTextA (USER32.309)
2215 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2217 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2218 (LPARAM)lpString );
2221 /*******************************************************************
2222 * InternalGetWindowText (USER32.326)
2224 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2226 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2227 return GetWindowTextW(hwnd,lpString,nMaxCount);
2231 /*******************************************************************
2232 * GetWindowTextW (USER32.312)
2234 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2236 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2237 (LPARAM)lpString );
2241 /*******************************************************************
2242 * SetWindowText16 (USER.37)
2244 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2246 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2250 /*******************************************************************
2251 * SetWindowTextA (USER32.521)
2253 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2255 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2259 /*******************************************************************
2260 * SetWindowTextW (USER32.523)
2262 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2264 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2268 /*******************************************************************
2269 * GetWindowTextLength16 (USER.38)
2271 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2273 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2277 /*******************************************************************
2278 * GetWindowTextLengthA (USER32.310)
2280 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2282 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2285 /*******************************************************************
2286 * GetWindowTextLengthW (USER32.311)
2288 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2290 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2294 /*******************************************************************
2295 * IsWindow16 (USER.47)
2297 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2299 CURRENT_STACK16->es = USER_HeapSel;
2300 return IsWindow( hwnd );
2304 /*******************************************************************
2305 * IsWindow (USER32.348)
2307 BOOL WINAPI IsWindow( HWND hwnd )
2309 WND * wndPtr;
2310 BOOL retvalue;
2312 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2313 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2314 WIN_ReleaseWndPtr(wndPtr);
2315 return retvalue;
2320 /*****************************************************************
2321 * GetParent16 (USER.46)
2323 HWND16 WINAPI GetParent16( HWND16 hwnd )
2325 return (HWND16)GetParent( hwnd );
2329 /*****************************************************************
2330 * GetParent (USER32.278)
2332 HWND WINAPI GetParent( HWND hwnd )
2334 WND *wndPtr;
2335 HWND retvalue = 0;
2337 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2338 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2339 goto end;
2341 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2342 if (wndPtr)
2343 retvalue = wndPtr->hwndSelf;
2345 end:
2346 WIN_ReleaseWndPtr(wndPtr);
2347 return retvalue;
2351 /*****************************************************************
2352 * WIN_GetTopParent
2354 * Get the top-level parent for a child window.
2355 * returns a locked pointer
2357 WND* WIN_GetTopParentPtr( WND* pWnd )
2359 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2361 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2363 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2365 return tmpWnd;
2368 /*****************************************************************
2369 * WIN_GetTopParent
2371 * Get the top-level parent for a child window.
2373 HWND WIN_GetTopParent( HWND hwnd )
2375 HWND retvalue;
2376 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2377 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2379 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2380 WIN_ReleaseWndPtr(tmpPtr);
2381 WIN_ReleaseWndPtr(wndPtr);
2382 return retvalue;
2386 /*****************************************************************
2387 * SetParent16 (USER.233)
2389 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2391 return SetParent( hwndChild, hwndNewParent );
2395 /*****************************************************************
2396 * SetParent (USER32.495)
2398 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2400 WND *wndPtr;
2401 DWORD dwStyle;
2402 WND *pWndNewParent;
2403 WND *pWndOldParent;
2404 HWND retvalue;
2407 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2409 dwStyle = wndPtr->dwStyle;
2411 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2412 : WIN_LockWndPtr(pWndDesktop);
2414 /* Windows hides the window first, then shows it again
2415 * including the WM_SHOWWINDOW messages and all */
2416 if (dwStyle & WS_VISIBLE)
2417 ShowWindow( hwndChild, SW_HIDE );
2419 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2421 /* SetParent additionally needs to make hwndChild the topmost window
2422 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2423 WM_WINDOWPOSCHANGED notification messages.
2425 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2426 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2427 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2428 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2430 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2432 WIN_ReleaseWndPtr(pWndOldParent);
2433 WIN_ReleaseWndPtr(pWndNewParent);
2434 WIN_ReleaseWndPtr(wndPtr);
2436 return retvalue;
2440 /*******************************************************************
2441 * IsChild16 (USER.48)
2443 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2445 return IsChild(parent,child);
2449 /*******************************************************************
2450 * IsChild (USER32.339)
2452 BOOL WINAPI IsChild( HWND parent, HWND child )
2454 WND * wndPtr = WIN_FindWndPtr( child );
2455 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2457 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2458 if (wndPtr->hwndSelf == parent)
2460 WIN_ReleaseWndPtr(wndPtr);
2461 return TRUE;
2464 WIN_ReleaseWndPtr(wndPtr);
2465 return FALSE;
2469 /***********************************************************************
2470 * IsWindowVisible16 (USER.49)
2472 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2474 return IsWindowVisible(hwnd);
2478 /***********************************************************************
2479 * IsWindowVisible (USER32.351)
2481 BOOL WINAPI IsWindowVisible( HWND hwnd )
2483 BOOL retval;
2484 WND *wndPtr = WIN_FindWndPtr( hwnd );
2485 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2487 if (!(wndPtr->dwStyle & WS_VISIBLE))
2489 WIN_ReleaseWndPtr(wndPtr);
2490 return FALSE;
2492 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2494 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2495 WIN_ReleaseWndPtr(wndPtr);
2496 return retval;
2501 /***********************************************************************
2502 * WIN_IsWindowDrawable
2504 * hwnd is drawable when it is visible, all parents are not
2505 * minimized, and it is itself not minimized unless we are
2506 * trying to draw its default class icon.
2508 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2510 if( (wnd->dwStyle & WS_MINIMIZE &&
2511 icon && wnd->class->hIcon) ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2513 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2514 if( wnd->dwStyle & WS_MINIMIZE ||
2515 !(wnd->dwStyle & WS_VISIBLE) ) break;
2516 return (wnd == NULL);
2520 /*******************************************************************
2521 * GetTopWindow16 (USER.229)
2523 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2525 return GetTopWindow(hwnd);
2529 /*******************************************************************
2530 * GetTopWindow (USER.229)
2532 HWND WINAPI GetTopWindow( HWND hwnd )
2534 HWND retval = 0;
2535 WND * wndPtr = (hwnd) ?
2536 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2538 if (wndPtr && wndPtr->child)
2539 retval = wndPtr->child->hwndSelf;
2541 WIN_ReleaseWndPtr(wndPtr);
2542 return retval;
2546 /*******************************************************************
2547 * GetWindow16 (USER.262)
2549 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2551 return GetWindow( hwnd,rel );
2555 /*******************************************************************
2556 * GetWindow (USER32.302)
2558 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2560 HWND retval;
2562 WND * wndPtr = WIN_FindWndPtr( hwnd );
2563 if (!wndPtr) return 0;
2564 switch(rel)
2566 case GW_HWNDFIRST:
2567 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2568 goto end;
2570 case GW_HWNDLAST:
2571 if (!wndPtr->parent)
2573 retval = 0; /* Desktop window */
2574 goto end;
2576 while (wndPtr->next)
2578 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2580 retval = wndPtr->hwndSelf;
2581 goto end;
2583 case GW_HWNDNEXT:
2584 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2585 goto end;
2587 case GW_HWNDPREV:
2588 if (!wndPtr->parent)
2590 retval = 0; /* Desktop window */
2591 goto end;
2593 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2594 if (wndPtr->hwndSelf == hwnd)
2596 retval = 0; /* First in list */
2597 goto end;
2599 while (wndPtr->next)
2601 if (wndPtr->next->hwndSelf == hwnd)
2603 retval = wndPtr->hwndSelf;
2604 goto end;
2606 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2608 retval = 0;
2609 goto end;
2611 case GW_OWNER:
2612 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2613 goto end;
2615 case GW_CHILD:
2616 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2617 goto end;
2619 retval = 0;
2620 end:
2621 WIN_ReleaseWndPtr(wndPtr);
2622 return retval;
2626 /*******************************************************************
2627 * GetNextWindow16 (USER.230)
2629 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2631 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2632 return GetWindow16( hwnd, flag );
2635 /*******************************************************************
2636 * ShowOwnedPopups16 (USER.265)
2638 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2640 ShowOwnedPopups( owner, fShow );
2644 /*******************************************************************
2645 * ShowOwnedPopups (USER32.531)
2647 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2649 UINT totalChild=0, count=0;
2651 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2653 if (!pWnd) return TRUE;
2655 for (; count < totalChild; count++)
2657 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2659 if (fShow)
2661 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2663 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2664 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2667 else
2669 if (IsWindowVisible(pWnd[count]->hwndSelf))
2671 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2672 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2678 WIN_ReleaseDesktop();
2679 WIN_ReleaseWinArray(pWnd);
2680 return TRUE;
2684 /*******************************************************************
2685 * GetLastActivePopup16 (USER.287)
2687 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2689 return GetLastActivePopup( hwnd );
2692 /*******************************************************************
2693 * GetLastActivePopup (USER32.256)
2695 HWND WINAPI GetLastActivePopup( HWND hwnd )
2697 HWND retval;
2698 WND *wndPtr =WIN_FindWndPtr(hwnd);
2699 if (!wndPtr) return hwnd;
2700 retval = wndPtr->hwndLastActive;
2701 WIN_ReleaseWndPtr(wndPtr);
2702 return retval;
2706 /*******************************************************************
2707 * WIN_BuildWinArray
2709 * Build an array of pointers to the children of a given window.
2710 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2711 * when no windows are found.
2713 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2715 /* Future: this function will lock all windows associated with this array */
2717 WND **list, **ppWnd;
2718 WND *pWnd;
2719 UINT count = 0, skipOwned, skipHidden;
2720 DWORD skipFlags;
2722 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2723 skipOwned = bwaFlags & BWA_SKIPOWNED;
2724 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2725 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2727 /* First count the windows */
2729 if (!wndPtr)
2730 wndPtr = WIN_GetDesktop();
2732 pWnd = WIN_LockWndPtr(wndPtr->child);
2733 while (pWnd)
2735 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2736 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2737 count++;
2738 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2741 if( count )
2743 /* Now build the list of all windows */
2745 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2747 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2749 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2750 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2752 *ppWnd++ = pWnd;
2753 count++;
2756 WIN_ReleaseWndPtr(pWnd);
2757 *ppWnd = NULL;
2759 else count = 0;
2760 } else list = NULL;
2762 if( pTotal ) *pTotal = count;
2763 return list;
2765 /*******************************************************************
2766 * WIN_ReleaseWinArray
2768 void WIN_ReleaseWinArray(WND **wndArray)
2770 /* Future: this function will also unlock all windows associated with wndArray */
2771 HeapFree( GetProcessHeap(), 0, wndArray );
2775 /*******************************************************************
2776 * EnumWindows (USER32.193)
2778 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2780 WND **list, **ppWnd;
2782 /* We have to build a list of all windows first, to avoid */
2783 /* unpleasant side-effects, for instance if the callback */
2784 /* function changes the Z-order of the windows. */
2786 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2788 WIN_ReleaseDesktop();
2789 return FALSE;
2792 /* Now call the callback function for every window */
2794 for (ppWnd = list; *ppWnd; ppWnd++)
2796 LRESULT lpEnumFuncRetval;
2797 int iWndsLocks = 0;
2798 /* Make sure that the window still exists */
2799 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2801 /* To avoid any deadlocks, all the locks on the windows
2802 structures must be suspended before the control
2803 is passed to the application */
2804 iWndsLocks = WIN_SuspendWndsLock();
2805 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2806 WIN_RestoreWndsLock(iWndsLocks);
2808 if (!lpEnumFuncRetval) break;
2810 WIN_ReleaseWinArray(list);
2811 WIN_ReleaseDesktop();
2812 return TRUE;
2816 /**********************************************************************
2817 * EnumTaskWindows16 (USER.225)
2819 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2820 LPARAM lParam )
2822 WND **list, **ppWnd;
2824 /* This function is the same as EnumWindows(), */
2825 /* except for an added check on the window's task. */
2827 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2829 WIN_ReleaseDesktop();
2830 return FALSE;
2833 /* Now call the callback function for every window */
2835 for (ppWnd = list; *ppWnd; ppWnd++)
2837 LRESULT funcRetval;
2838 int iWndsLocks = 0;
2839 /* Make sure that the window still exists */
2840 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2841 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2843 /* To avoid any deadlocks, all the locks on the windows
2844 structures must be suspended before the control
2845 is passed to the application */
2846 iWndsLocks = WIN_SuspendWndsLock();
2847 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2848 WIN_RestoreWndsLock(iWndsLocks);
2850 if (!funcRetval) break;
2852 WIN_ReleaseWinArray(list);
2853 WIN_ReleaseDesktop();
2854 return TRUE;
2858 /**********************************************************************
2859 * EnumThreadWindows (USER32.190)
2861 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2863 TEB *teb = THREAD_IdToTEB(id);
2865 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2869 /**********************************************************************
2870 * WIN_EnumChildWindows
2872 * Helper function for EnumChildWindows().
2874 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2876 WND **childList;
2877 BOOL16 ret = FALSE;
2879 for ( ; *ppWnd; ppWnd++)
2881 int iWndsLocks = 0;
2883 /* Make sure that the window still exists */
2884 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2885 /* Build children list first */
2886 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2888 /* To avoid any deadlocks, all the locks on the windows
2889 structures must be suspended before the control
2890 is passed to the application */
2891 iWndsLocks = WIN_SuspendWndsLock();
2892 ret = func( (*ppWnd)->hwndSelf, lParam );
2893 WIN_RestoreWndsLock(iWndsLocks);
2895 if (childList)
2897 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2898 WIN_ReleaseWinArray(childList);
2900 if (!ret) return FALSE;
2902 return TRUE;
2906 /**********************************************************************
2907 * EnumChildWindows (USER32.178)
2909 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2910 LPARAM lParam )
2912 WND **list, *pParent;
2914 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2915 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2917 WIN_ReleaseWndPtr(pParent);
2918 return FALSE;
2920 WIN_EnumChildWindows( list, func, lParam );
2921 WIN_ReleaseWinArray(list);
2922 WIN_ReleaseWndPtr(pParent);
2923 return TRUE;
2927 /*******************************************************************
2928 * AnyPopup16 (USER.52)
2930 BOOL16 WINAPI AnyPopup16(void)
2932 return AnyPopup();
2936 /*******************************************************************
2937 * AnyPopup (USER32.4)
2939 BOOL WINAPI AnyPopup(void)
2941 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2942 BOOL retvalue;
2944 while (wndPtr)
2946 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2948 retvalue = TRUE;
2949 goto end;
2951 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2953 retvalue = FALSE;
2954 end:
2955 WIN_ReleaseWndPtr(wndPtr);
2956 return retvalue;
2960 /*******************************************************************
2961 * FlashWindow16 (USER.105)
2963 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2965 return FlashWindow( hWnd, bInvert );
2969 /*******************************************************************
2970 * FlashWindow (USER32.202)
2972 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2974 WND *wndPtr = WIN_FindWndPtr(hWnd);
2976 TRACE("%04x\n", hWnd);
2978 if (!wndPtr) return FALSE;
2980 if (wndPtr->dwStyle & WS_MINIMIZE)
2982 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2984 HDC hDC = GetDC(hWnd);
2986 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2987 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2989 ReleaseDC( hWnd, hDC );
2990 wndPtr->flags |= WIN_NCACTIVATED;
2992 else
2994 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2995 RDW_UPDATENOW | RDW_FRAME, 0 );
2996 wndPtr->flags &= ~WIN_NCACTIVATED;
2998 WIN_ReleaseWndPtr(wndPtr);
2999 return TRUE;
3001 else
3003 WPARAM16 wparam;
3004 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3005 else wparam = (hWnd == GetActiveWindow());
3007 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3008 WIN_ReleaseWndPtr(wndPtr);
3009 return wparam;
3014 /*******************************************************************
3015 * SetSysModalWindow16 (USER.188)
3017 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3019 HWND hWndOldModal = hwndSysModal;
3020 hwndSysModal = hWnd;
3021 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3022 return hWndOldModal;
3026 /*******************************************************************
3027 * GetSysModalWindow16 (USER.52)
3029 HWND16 WINAPI GetSysModalWindow16(void)
3031 return hwndSysModal;
3035 /*******************************************************************
3036 * GetWindowContextHelpId (USER32.303)
3038 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3040 DWORD retval;
3041 WND *wnd = WIN_FindWndPtr( hwnd );
3042 if (!wnd) return 0;
3043 retval = wnd->helpContext;
3044 WIN_ReleaseWndPtr(wnd);
3045 return retval;
3049 /*******************************************************************
3050 * SetWindowContextHelpId (USER32.515)
3052 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3054 WND *wnd = WIN_FindWndPtr( hwnd );
3055 if (!wnd) return FALSE;
3056 wnd->helpContext = id;
3057 WIN_ReleaseWndPtr(wnd);
3058 return TRUE;
3062 /*******************************************************************
3063 * DRAG_QueryUpdate
3065 * recursively find a child that contains spDragInfo->pt point
3066 * and send WM_QUERYDROPOBJECT
3068 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3070 BOOL16 wParam, bResult = 0;
3071 POINT pt;
3072 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3073 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3074 RECT tempRect;
3076 if( !ptrQueryWnd || !ptrDragInfo )
3077 goto end;
3079 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3081 GetWindowRect(hQueryWnd,&tempRect);
3083 if( !PtInRect(&tempRect,pt) ||
3084 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3085 goto end;
3087 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3089 tempRect = ptrQueryWnd->rectClient;
3090 if(ptrQueryWnd->dwStyle & WS_CHILD)
3091 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3092 (LPPOINT)&tempRect, 2 );
3094 if (PtInRect( &tempRect, pt))
3096 wParam = 0;
3098 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3100 if( ptrWnd->dwStyle & WS_VISIBLE )
3102 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3103 if (PtInRect( &tempRect, pt )) break;
3107 if(ptrWnd)
3109 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3110 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3111 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3112 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3113 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3115 WIN_ReleaseWndPtr(ptrWnd);
3118 if(bResult)
3119 goto end;
3121 else wParam = 1;
3123 else wParam = 1;
3125 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3127 ptrDragInfo->hScope = hQueryWnd;
3129 bResult = ( bNoSend )
3130 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3131 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3132 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3133 if( !bResult )
3134 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3136 end:
3137 WIN_ReleaseWndPtr(ptrQueryWnd);
3138 return bResult;
3142 /*******************************************************************
3143 * DragDetect (USER.465)
3145 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3147 POINT pt32;
3148 CONV_POINT16TO32( &pt, &pt32 );
3149 return DragDetect( hWnd, pt32 );
3152 /*******************************************************************
3153 * DragDetect (USER32.151)
3155 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3157 MSG16 msg;
3158 RECT16 rect;
3160 rect.left = pt.x - wDragWidth;
3161 rect.right = pt.x + wDragWidth;
3163 rect.top = pt.y - wDragHeight;
3164 rect.bottom = pt.y + wDragHeight;
3166 SetCapture(hWnd);
3168 while(1)
3170 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3172 if( msg.message == WM_LBUTTONUP )
3174 ReleaseCapture();
3175 return 0;
3177 if( msg.message == WM_MOUSEMOVE )
3179 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3181 ReleaseCapture();
3182 return 1;
3186 WaitMessage();
3188 return 0;
3191 /******************************************************************************
3192 * DragObject16 (USER.464)
3194 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3195 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3197 MSG16 msg;
3198 LPDRAGINFO lpDragInfo;
3199 SEGPTR spDragInfo;
3200 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3201 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3202 WND *wndPtr = WIN_FindWndPtr(hWnd);
3203 HCURSOR16 hCurrentCursor = 0;
3204 HWND16 hCurrentWnd = 0;
3206 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3207 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3209 if( !lpDragInfo || !spDragInfo )
3211 WIN_ReleaseWndPtr(wndPtr);
3212 return 0L;
3215 hBummer = LoadCursor16(0, IDC_BUMMER16);
3217 if( !hBummer || !wndPtr )
3219 GlobalFree16(hDragInfo);
3220 WIN_ReleaseWndPtr(wndPtr);
3221 return 0L;
3224 if(hCursor)
3226 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3228 GlobalFree16(hDragInfo);
3229 WIN_ReleaseWndPtr(wndPtr);
3230 return 0L;
3233 if( hDragCursor == hCursor ) hDragCursor = 0;
3234 else hCursor = hDragCursor;
3236 hOldCursor = SetCursor(hDragCursor);
3239 lpDragInfo->hWnd = hWnd;
3240 lpDragInfo->hScope = 0;
3241 lpDragInfo->wFlags = wObj;
3242 lpDragInfo->hList = szList; /* near pointer! */
3243 lpDragInfo->hOfStruct = hOfStruct;
3244 lpDragInfo->l = 0L;
3246 SetCapture(hWnd);
3247 ShowCursor( TRUE );
3251 do{ WaitMessage(); }
3252 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3254 *(lpDragInfo+1) = *lpDragInfo;
3256 lpDragInfo->pt = msg.pt;
3258 /* update DRAGINFO struct */
3259 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3261 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3262 hCurrentCursor = hCursor;
3263 else
3265 hCurrentCursor = hBummer;
3266 lpDragInfo->hScope = 0;
3268 if( hCurrentCursor )
3269 SetCursor(hCurrentCursor);
3271 /* send WM_DRAGLOOP */
3272 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3273 (LPARAM) spDragInfo );
3274 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3275 if( hCurrentWnd != lpDragInfo->hScope )
3277 if( hCurrentWnd )
3278 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3279 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3280 HIWORD(spDragInfo)) );
3281 hCurrentWnd = lpDragInfo->hScope;
3282 if( hCurrentWnd )
3283 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3285 else
3286 if( hCurrentWnd )
3287 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3289 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3291 ReleaseCapture();
3292 ShowCursor( FALSE );
3294 if( hCursor )
3296 SetCursor( hOldCursor );
3297 if (hDragCursor) DestroyCursor( hDragCursor );
3300 if( hCurrentCursor != hBummer )
3301 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3302 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3303 else
3304 msg.lParam = 0;
3305 GlobalFree16(hDragInfo);
3306 WIN_ReleaseWndPtr(wndPtr);
3308 return (DWORD)(msg.lParam);