Fix typo in ITypeLib::IsName.
[wine/dcerpc.git] / windows / win.c
blobdce2b1a037475d2a7fade6e639e266cfb04916bf
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 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 LPCSTR 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 && !strcmp( 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;
1610 if (className)
1612 /* If the atom doesn't exist, then no class */
1613 /* with this name exists either. */
1614 if (!(atom = GlobalFindAtomA( className )))
1616 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1617 return 0;
1620 return WIN_FindWindow( parent, child, atom, title );
1624 /***********************************************************************
1625 * FindWindowExW (USER32.200)
1627 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1628 LPCWSTR className, LPCWSTR title )
1630 ATOM atom = 0;
1631 char *buffer;
1632 HWND hwnd;
1634 if (className)
1636 /* If the atom doesn't exist, then no class */
1637 /* with this name exists either. */
1638 if (!(atom = GlobalFindAtomW( className )))
1640 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1641 return 0;
1644 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1645 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1646 HeapFree( GetProcessHeap(), 0, buffer );
1647 return hwnd;
1651 /***********************************************************************
1652 * FindWindowW (USER32.201)
1654 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1656 return FindWindowExW( 0, 0, className, title );
1660 /**********************************************************************
1661 * WIN_GetDesktop
1662 * returns a locked pointer
1664 WND *WIN_GetDesktop(void)
1666 return WIN_LockWndPtr(pWndDesktop);
1668 /**********************************************************************
1669 * WIN_ReleaseDesktop
1670 * unlock the desktop pointer
1672 void WIN_ReleaseDesktop(void)
1674 WIN_ReleaseWndPtr(pWndDesktop);
1678 /**********************************************************************
1679 * GetDesktopWindow16 (USER.286)
1681 HWND16 WINAPI GetDesktopWindow16(void)
1683 return (HWND16)pWndDesktop->hwndSelf;
1687 /**********************************************************************
1688 * GetDesktopWindow (USER32.232)
1690 HWND WINAPI GetDesktopWindow(void)
1692 if (pWndDesktop) return pWndDesktop->hwndSelf;
1693 ERR( "You need the -desktop option when running with native USER\n" );
1694 ExitProcess(1);
1695 return 0;
1699 /**********************************************************************
1700 * GetDesktopHwnd (USER.278)
1702 * Exactly the same thing as GetDesktopWindow(), but not documented.
1703 * Don't ask me why...
1705 HWND16 WINAPI GetDesktopHwnd16(void)
1707 return (HWND16)pWndDesktop->hwndSelf;
1711 /*******************************************************************
1712 * EnableWindow16 (USER.34)
1714 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1716 return EnableWindow( hwnd, enable );
1720 /*******************************************************************
1721 * EnableWindow (USER32.172)
1723 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1725 WND *wndPtr;
1726 BOOL retvalue;
1728 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1730 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1731 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1733 /* Enable window */
1734 wndPtr->dwStyle &= ~WS_DISABLED;
1736 if( wndPtr->flags & WIN_NATIVE )
1737 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1739 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1740 retvalue = TRUE;
1741 goto end;
1743 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1745 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1747 /* Disable window */
1748 wndPtr->dwStyle |= WS_DISABLED;
1750 if( wndPtr->flags & WIN_NATIVE )
1751 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1753 if (hwnd == GetFocus())
1755 SetFocus( 0 ); /* A disabled window can't have the focus */
1757 if (hwnd == GetCapture())
1759 ReleaseCapture(); /* A disabled window can't capture the mouse */
1761 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1762 retvalue = FALSE;
1763 goto end;
1765 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1766 end:
1767 WIN_ReleaseWndPtr(wndPtr);
1768 return retvalue;
1772 /***********************************************************************
1773 * IsWindowEnabled16 (USER.35)
1775 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1777 return IsWindowEnabled(hWnd);
1781 /***********************************************************************
1782 * IsWindowEnabled (USER32.349)
1784 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1786 WND * wndPtr;
1787 BOOL retvalue;
1789 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1790 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1791 WIN_ReleaseWndPtr(wndPtr);
1792 return retvalue;
1797 /***********************************************************************
1798 * IsWindowUnicode (USER32.350)
1800 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1802 WND * wndPtr;
1803 BOOL retvalue;
1805 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1806 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1807 WIN_ReleaseWndPtr(wndPtr);
1808 return retvalue;
1812 /**********************************************************************
1813 * GetWindowWord16 (USER.133)
1815 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1817 return GetWindowWord( hwnd, offset );
1821 /**********************************************************************
1822 * GetWindowWord (USER32.314)
1824 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1826 WORD retvalue;
1827 WND * wndPtr = WIN_FindWndPtr( hwnd );
1828 if (!wndPtr) return 0;
1829 if (offset >= 0)
1831 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1833 WARN("Invalid offset %d\n", offset );
1834 retvalue = 0;
1835 goto end;
1837 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1838 goto end;
1840 switch(offset)
1842 case GWW_ID:
1843 if (HIWORD(wndPtr->wIDmenu))
1844 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1845 wndPtr->wIDmenu);
1846 retvalue = (WORD)wndPtr->wIDmenu;
1847 goto end;
1848 case GWW_HWNDPARENT:
1849 retvalue = GetParent(hwnd);
1850 goto end;
1851 case GWW_HINSTANCE:
1852 if (HIWORD(wndPtr->hInstance))
1853 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1854 wndPtr->hInstance);
1855 retvalue = (WORD)wndPtr->hInstance;
1856 goto end;
1857 default:
1858 WARN("Invalid offset %d\n", offset );
1859 retvalue = 0;
1860 goto end;
1862 end:
1863 WIN_ReleaseWndPtr(wndPtr);
1864 return retvalue;
1867 /**********************************************************************
1868 * SetWindowWord16 (USER.134)
1870 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1872 return SetWindowWord( hwnd, offset, newval );
1876 /**********************************************************************
1877 * SetWindowWord (USER32.524)
1879 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1881 WORD *ptr, retval;
1882 WND * wndPtr = WIN_FindWndPtr( hwnd );
1883 if (!wndPtr) return 0;
1884 if (offset >= 0)
1886 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1888 WARN("Invalid offset %d\n", offset );
1889 retval = 0;
1890 goto end;
1892 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1894 else switch(offset)
1896 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1897 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1898 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1899 goto end;
1900 default:
1901 WARN("Invalid offset %d\n", offset );
1902 retval = 0;
1903 goto end;
1905 retval = *ptr;
1906 *ptr = newval;
1907 end:
1908 WIN_ReleaseWndPtr(wndPtr);
1909 return retval;
1913 /**********************************************************************
1914 * WIN_GetWindowLong
1916 * Helper function for GetWindowLong().
1918 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1920 LONG retvalue;
1921 WND * wndPtr = WIN_FindWndPtr( hwnd );
1922 if (!wndPtr) return 0;
1923 if (offset >= 0)
1925 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1927 WARN("Invalid offset %d\n", offset );
1928 retvalue = 0;
1929 goto end;
1931 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1932 /* Special case for dialog window procedure */
1933 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1935 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1936 goto end;
1938 goto end;
1940 switch(offset)
1942 case GWL_USERDATA: retvalue = wndPtr->userdata;
1943 goto end;
1944 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1945 goto end;
1946 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1947 goto end;
1948 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1949 goto end;
1950 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1951 type );
1952 goto end;
1953 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1954 goto end;
1955 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1956 goto end;
1957 default:
1958 WARN("Unknown offset %d\n", offset );
1960 retvalue = 0;
1961 end:
1962 WIN_ReleaseWndPtr(wndPtr);
1963 return retvalue;
1967 /**********************************************************************
1968 * WIN_SetWindowLong
1970 * Helper function for SetWindowLong().
1972 * 0 is the failure code. However, in the case of failure SetLastError
1973 * must be set to distinguish between a 0 return value and a failure.
1975 * FIXME: The error values for SetLastError may not be right. Can
1976 * someone check with the real thing?
1978 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1979 WINDOWPROCTYPE type )
1981 LONG *ptr, retval;
1982 WND * wndPtr = WIN_FindWndPtr( hwnd );
1983 STYLESTRUCT style;
1985 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1987 if (!wndPtr)
1989 /* Is this the right error? */
1990 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1991 return 0;
1994 if (offset >= 0)
1996 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1998 WARN("Invalid offset %d\n", offset );
2000 /* Is this the right error? */
2001 SetLastError( ERROR_OUTOFMEMORY );
2003 retval = 0;
2004 goto end;
2006 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2007 /* Special case for dialog window procedure */
2008 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2010 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2011 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2012 type, WIN_PROC_WINDOW );
2013 goto end;
2016 else switch(offset)
2018 case GWL_ID:
2019 ptr = (DWORD*)&wndPtr->wIDmenu;
2020 break;
2021 case GWL_HINSTANCE:
2022 retval = SetWindowWord( hwnd, offset, newval );
2023 goto end;
2024 case GWL_WNDPROC:
2025 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2026 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2027 type, WIN_PROC_WINDOW );
2028 goto end;
2029 case GWL_STYLE:
2030 style.styleOld = wndPtr->dwStyle;
2031 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2032 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2034 if (wndPtr->flags & WIN_ISWIN32)
2035 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2036 wndPtr->dwStyle = style.styleNew;
2037 if (wndPtr->flags & WIN_ISWIN32)
2038 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2039 retval = style.styleOld;
2040 goto end;
2042 case GWL_USERDATA:
2043 ptr = &wndPtr->userdata;
2044 break;
2045 case GWL_EXSTYLE:
2046 style.styleOld = wndPtr->dwExStyle;
2047 style.styleNew = newval;
2048 if (wndPtr->flags & WIN_ISWIN32)
2049 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2050 wndPtr->dwExStyle = newval;
2051 if (wndPtr->flags & WIN_ISWIN32)
2052 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2053 retval = style.styleOld;
2054 goto end;
2056 default:
2057 WARN("Invalid offset %d\n", offset );
2059 /* Don't think this is right error but it should do */
2060 SetLastError( ERROR_OUTOFMEMORY );
2062 retval = 0;
2063 goto end;
2065 retval = *ptr;
2066 *ptr = newval;
2067 end:
2068 WIN_ReleaseWndPtr(wndPtr);
2069 return retval;
2073 /**********************************************************************
2074 * GetWindowLong16 (USER.135)
2076 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2078 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2082 /**********************************************************************
2083 * GetWindowLongA (USER32.305)
2085 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2087 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2091 /**********************************************************************
2092 * GetWindowLongW (USER32.306)
2094 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2100 /**********************************************************************
2101 * SetWindowLong16 (USER.136)
2103 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2109 /**********************************************************************
2110 * SetWindowLongA (USER32.517)
2112 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2114 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2118 /**********************************************************************
2119 * SetWindowLongW (USER32.518) Set window attribute
2121 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2122 * value in a window's extra memory.
2124 * The _hwnd_ parameter specifies the window. is the handle to a
2125 * window that has extra memory. The _newval_ parameter contains the
2126 * new attribute or extra memory value. If positive, the _offset_
2127 * parameter is the byte-addressed location in the window's extra
2128 * memory to set. If negative, _offset_ specifies the window
2129 * attribute to set, and should be one of the following values:
2131 * GWL_EXSTYLE The window's extended window style
2133 * GWL_STYLE The window's window style.
2135 * GWL_WNDPROC Pointer to the window's window procedure.
2137 * GWL_HINSTANCE The window's pplication instance handle.
2139 * GWL_ID The window's identifier.
2141 * GWL_USERDATA The window's user-specified data.
2143 * If the window is a dialog box, the _offset_ parameter can be one of
2144 * the following values:
2146 * DWL_DLGPROC The address of the window's dialog box procedure.
2148 * DWL_MSGRESULT The return value of a message
2149 * that the dialog box procedure processed.
2151 * DWL_USER Application specific information.
2153 * RETURNS
2155 * If successful, returns the previous value located at _offset_. Otherwise,
2156 * returns 0.
2158 * NOTES
2160 * Extra memory for a window class is specified by a nonzero cbWndExtra
2161 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2162 * time of class creation.
2164 * Using GWL_WNDPROC to set a new window procedure effectively creates
2165 * a window subclass. Use CallWindowProc() in the new windows procedure
2166 * to pass messages to the superclass's window procedure.
2168 * The user data is reserved for use by the application which created
2169 * the window.
2171 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2172 * instead, call the EnableWindow() function to change the window's
2173 * disabled state.
2175 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2176 * SetParent() instead.
2178 * Win95:
2179 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2180 * it sends WM_STYLECHANGING before changing the settings
2181 * and WM_STYLECHANGED afterwards.
2182 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2184 * BUGS
2186 * GWL_STYLE does not dispatch WM_STYLE... messages.
2188 * CONFORMANCE
2190 * ECMA-234, Win32
2193 LONG WINAPI SetWindowLongW(
2194 HWND hwnd, /* window to alter */
2195 INT offset, /* offset, in bytes, of location to alter */
2196 LONG newval /* new value of location */
2198 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2202 /*******************************************************************
2203 * GetWindowText16 (USER.36)
2205 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2207 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2211 /*******************************************************************
2212 * GetWindowTextA (USER32.309)
2214 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2216 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2217 (LPARAM)lpString );
2220 /*******************************************************************
2221 * InternalGetWindowText (USER32.326)
2223 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2225 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2226 return GetWindowTextW(hwnd,lpString,nMaxCount);
2230 /*******************************************************************
2231 * GetWindowTextW (USER32.312)
2233 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2235 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2236 (LPARAM)lpString );
2240 /*******************************************************************
2241 * SetWindowText16 (USER.37)
2243 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2245 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2249 /*******************************************************************
2250 * SetWindowTextA (USER32.521)
2252 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2254 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2258 /*******************************************************************
2259 * SetWindowTextW (USER32.523)
2261 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2263 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2267 /*******************************************************************
2268 * GetWindowTextLength16 (USER.38)
2270 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2272 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2276 /*******************************************************************
2277 * GetWindowTextLengthA (USER32.310)
2279 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2281 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2284 /*******************************************************************
2285 * GetWindowTextLengthW (USER32.311)
2287 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2289 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2293 /*******************************************************************
2294 * IsWindow16 (USER.47)
2296 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2298 CURRENT_STACK16->es = USER_HeapSel;
2299 return IsWindow( hwnd );
2303 /*******************************************************************
2304 * IsWindow (USER32.348)
2306 BOOL WINAPI IsWindow( HWND hwnd )
2308 WND * wndPtr;
2309 BOOL retvalue;
2311 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2312 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2313 WIN_ReleaseWndPtr(wndPtr);
2314 return retvalue;
2319 /*****************************************************************
2320 * GetParent16 (USER.46)
2322 HWND16 WINAPI GetParent16( HWND16 hwnd )
2324 return (HWND16)GetParent( hwnd );
2328 /*****************************************************************
2329 * GetParent (USER32.278)
2331 HWND WINAPI GetParent( HWND hwnd )
2333 WND *wndPtr;
2334 HWND retvalue = 0;
2336 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2337 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2338 goto end;
2340 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2341 if (wndPtr)
2342 retvalue = wndPtr->hwndSelf;
2344 end:
2345 WIN_ReleaseWndPtr(wndPtr);
2346 return retvalue;
2350 /*****************************************************************
2351 * WIN_GetTopParent
2353 * Get the top-level parent for a child window.
2354 * returns a locked pointer
2356 WND* WIN_GetTopParentPtr( WND* pWnd )
2358 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2360 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2362 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2364 return tmpWnd;
2367 /*****************************************************************
2368 * WIN_GetTopParent
2370 * Get the top-level parent for a child window.
2372 HWND WIN_GetTopParent( HWND hwnd )
2374 HWND retvalue;
2375 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2376 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2378 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2379 WIN_ReleaseWndPtr(tmpPtr);
2380 WIN_ReleaseWndPtr(wndPtr);
2381 return retvalue;
2385 /*****************************************************************
2386 * SetParent16 (USER.233)
2388 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2390 return SetParent( hwndChild, hwndNewParent );
2394 /*****************************************************************
2395 * SetParent (USER32.495)
2397 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2399 WND *wndPtr;
2400 DWORD dwStyle;
2401 WND *pWndNewParent;
2402 WND *pWndOldParent;
2403 HWND retvalue;
2406 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2408 dwStyle = wndPtr->dwStyle;
2410 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2411 : WIN_LockWndPtr(pWndDesktop);
2413 /* Windows hides the window first, then shows it again
2414 * including the WM_SHOWWINDOW messages and all */
2415 if (dwStyle & WS_VISIBLE)
2416 ShowWindow( hwndChild, SW_HIDE );
2418 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2420 /* SetParent additionally needs to make hwndChild the topmost window
2421 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2422 WM_WINDOWPOSCHANGED notification messages.
2424 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2425 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2426 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2427 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2429 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2431 WIN_ReleaseWndPtr(pWndOldParent);
2432 WIN_ReleaseWndPtr(pWndNewParent);
2433 WIN_ReleaseWndPtr(wndPtr);
2435 return retvalue;
2439 /*******************************************************************
2440 * IsChild16 (USER.48)
2442 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2444 return IsChild(parent,child);
2448 /*******************************************************************
2449 * IsChild (USER32.339)
2451 BOOL WINAPI IsChild( HWND parent, HWND child )
2453 WND * wndPtr = WIN_FindWndPtr( child );
2454 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2456 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2457 if (wndPtr->hwndSelf == parent)
2459 WIN_ReleaseWndPtr(wndPtr);
2460 return TRUE;
2463 WIN_ReleaseWndPtr(wndPtr);
2464 return FALSE;
2468 /***********************************************************************
2469 * IsWindowVisible16 (USER.49)
2471 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2473 return IsWindowVisible(hwnd);
2477 /***********************************************************************
2478 * IsWindowVisible (USER32.351)
2480 BOOL WINAPI IsWindowVisible( HWND hwnd )
2482 BOOL retval;
2483 WND *wndPtr = WIN_FindWndPtr( hwnd );
2484 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2486 if (!(wndPtr->dwStyle & WS_VISIBLE))
2488 WIN_ReleaseWndPtr(wndPtr);
2489 return FALSE;
2491 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2493 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2494 WIN_ReleaseWndPtr(wndPtr);
2495 return retval;
2500 /***********************************************************************
2501 * WIN_IsWindowDrawable
2503 * hwnd is drawable when it is visible, all parents are not
2504 * minimized, and it is itself not minimized unless we are
2505 * trying to draw its default class icon.
2507 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2509 if( (wnd->dwStyle & WS_MINIMIZE &&
2510 icon && wnd->class->hIcon) ||
2511 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2512 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2513 if( wnd->dwStyle & WS_MINIMIZE ||
2514 !(wnd->dwStyle & WS_VISIBLE) ) break;
2515 return (wnd == NULL);
2519 /*******************************************************************
2520 * GetTopWindow16 (USER.229)
2522 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2524 return GetTopWindow(hwnd);
2528 /*******************************************************************
2529 * GetTopWindow (USER.229)
2531 HWND WINAPI GetTopWindow( HWND hwnd )
2533 HWND retval = 0;
2534 WND * wndPtr = (hwnd) ?
2535 WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
2537 if (wndPtr && wndPtr->child)
2538 retval = wndPtr->child->hwndSelf;
2540 WIN_ReleaseWndPtr(wndPtr);
2541 return retval;
2545 /*******************************************************************
2546 * GetWindow16 (USER.262)
2548 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2550 return GetWindow( hwnd,rel );
2554 /*******************************************************************
2555 * GetWindow (USER32.302)
2557 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2559 HWND retval;
2561 WND * wndPtr = WIN_FindWndPtr( hwnd );
2562 if (!wndPtr) return 0;
2563 switch(rel)
2565 case GW_HWNDFIRST:
2566 retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0;
2567 goto end;
2569 case GW_HWNDLAST:
2570 if (!wndPtr->parent)
2572 retval = 0; /* Desktop window */
2573 goto end;
2575 while (wndPtr->next)
2577 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2579 retval = wndPtr->hwndSelf;
2580 goto end;
2582 case GW_HWNDNEXT:
2583 retval = wndPtr->next ? wndPtr->next->hwndSelf : 0;
2584 goto end;
2586 case GW_HWNDPREV:
2587 if (!wndPtr->parent)
2589 retval = 0; /* Desktop window */
2590 goto end;
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2593 if (wndPtr->hwndSelf == hwnd)
2595 retval = 0; /* First in list */
2596 goto end;
2598 while (wndPtr->next)
2600 if (wndPtr->next->hwndSelf == hwnd)
2602 retval = wndPtr->hwndSelf;
2603 goto end;
2605 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2607 retval = 0;
2608 goto end;
2610 case GW_OWNER:
2611 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2612 goto end;
2614 case GW_CHILD:
2615 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2616 goto end;
2618 retval = 0;
2619 end:
2620 WIN_ReleaseWndPtr(wndPtr);
2621 return retval;
2625 /*******************************************************************
2626 * GetNextWindow16 (USER.230)
2628 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2630 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2631 return GetWindow16( hwnd, flag );
2634 /*******************************************************************
2635 * ShowOwnedPopups16 (USER.265)
2637 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2639 ShowOwnedPopups( owner, fShow );
2643 /*******************************************************************
2644 * ShowOwnedPopups (USER32.531)
2646 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2648 UINT totalChild=0, count=0;
2650 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2652 if (!pWnd) return TRUE;
2654 for (; count < totalChild; count++)
2656 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2658 if (fShow)
2660 if (pWnd[count]->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2662 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_SHOW, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2663 pWnd[count]->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2666 else
2668 if (IsWindowVisible(pWnd[count]->hwndSelf))
2670 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, SW_HIDE, IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2671 pWnd[count]->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2677 WIN_ReleaseDesktop();
2678 WIN_ReleaseWinArray(pWnd);
2679 return TRUE;
2683 /*******************************************************************
2684 * GetLastActivePopup16 (USER.287)
2686 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2688 return GetLastActivePopup( hwnd );
2691 /*******************************************************************
2692 * GetLastActivePopup (USER32.256)
2694 HWND WINAPI GetLastActivePopup( HWND hwnd )
2696 HWND retval;
2697 WND *wndPtr =WIN_FindWndPtr(hwnd);
2698 if (!wndPtr) return hwnd;
2699 retval = wndPtr->hwndLastActive;
2700 WIN_ReleaseWndPtr(wndPtr);
2701 return retval;
2705 /*******************************************************************
2706 * WIN_BuildWinArray
2708 * Build an array of pointers to the children of a given window.
2709 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2710 * when no windows are found.
2712 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2714 /* Future: this function will lock all windows associated with this array */
2716 WND **list, **ppWnd;
2717 WND *pWnd;
2718 UINT count = 0, skipOwned, skipHidden;
2719 DWORD skipFlags;
2721 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2722 skipOwned = bwaFlags & BWA_SKIPOWNED;
2723 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2724 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2726 /* First count the windows */
2728 if (!wndPtr)
2729 wndPtr = WIN_GetDesktop();
2731 pWnd = WIN_LockWndPtr(wndPtr->child);
2732 while (pWnd)
2734 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2735 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2736 count++;
2737 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2740 if( count )
2742 /* Now build the list of all windows */
2744 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2746 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2748 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2749 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2751 *ppWnd++ = pWnd;
2752 count++;
2755 WIN_ReleaseWndPtr(pWnd);
2756 *ppWnd = NULL;
2758 else count = 0;
2759 } else list = NULL;
2761 if( pTotal ) *pTotal = count;
2762 return list;
2764 /*******************************************************************
2765 * WIN_ReleaseWinArray
2767 void WIN_ReleaseWinArray(WND **wndArray)
2769 /* Future: this function will also unlock all windows associated with wndArray */
2770 HeapFree( GetProcessHeap(), 0, wndArray );
2774 /*******************************************************************
2775 * EnumWindows (USER32.193)
2777 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2779 WND **list, **ppWnd;
2781 /* We have to build a list of all windows first, to avoid */
2782 /* unpleasant side-effects, for instance if the callback */
2783 /* function changes the Z-order of the windows. */
2785 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2787 WIN_ReleaseDesktop();
2788 return FALSE;
2791 /* Now call the callback function for every window */
2793 for (ppWnd = list; *ppWnd; ppWnd++)
2795 LRESULT lpEnumFuncRetval;
2796 int iWndsLocks = 0;
2797 /* Make sure that the window still exists */
2798 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2800 /* To avoid any deadlocks, all the locks on the windows
2801 structures must be suspended before the control
2802 is passed to the application */
2803 iWndsLocks = WIN_SuspendWndsLock();
2804 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2805 WIN_RestoreWndsLock(iWndsLocks);
2807 if (!lpEnumFuncRetval) break;
2809 WIN_ReleaseWinArray(list);
2810 WIN_ReleaseDesktop();
2811 return TRUE;
2815 /**********************************************************************
2816 * EnumTaskWindows16 (USER.225)
2818 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2819 LPARAM lParam )
2821 WND **list, **ppWnd;
2823 /* This function is the same as EnumWindows(), */
2824 /* except for an added check on the window's task. */
2826 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2828 WIN_ReleaseDesktop();
2829 return FALSE;
2832 /* Now call the callback function for every window */
2834 for (ppWnd = list; *ppWnd; ppWnd++)
2836 LRESULT funcRetval;
2837 int iWndsLocks = 0;
2838 /* Make sure that the window still exists */
2839 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2840 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2842 /* To avoid any deadlocks, all the locks on the windows
2843 structures must be suspended before the control
2844 is passed to the application */
2845 iWndsLocks = WIN_SuspendWndsLock();
2846 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2847 WIN_RestoreWndsLock(iWndsLocks);
2849 if (!funcRetval) break;
2851 WIN_ReleaseWinArray(list);
2852 WIN_ReleaseDesktop();
2853 return TRUE;
2857 /**********************************************************************
2858 * EnumThreadWindows (USER32.190)
2860 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2862 TEB *teb = THREAD_IdToTEB(id);
2864 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2868 /**********************************************************************
2869 * WIN_EnumChildWindows
2871 * Helper function for EnumChildWindows().
2873 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC func, LPARAM lParam )
2875 WND **childList;
2876 BOOL16 ret = FALSE;
2878 for ( ; *ppWnd; ppWnd++)
2880 int iWndsLocks = 0;
2882 /* Make sure that the window still exists */
2883 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2884 /* Build children list first */
2885 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2887 /* To avoid any deadlocks, all the locks on the windows
2888 structures must be suspended before the control
2889 is passed to the application */
2890 iWndsLocks = WIN_SuspendWndsLock();
2891 ret = func( (*ppWnd)->hwndSelf, lParam );
2892 WIN_RestoreWndsLock(iWndsLocks);
2894 if (childList)
2896 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2897 WIN_ReleaseWinArray(childList);
2899 if (!ret) return FALSE;
2901 return TRUE;
2905 /**********************************************************************
2906 * EnumChildWindows (USER32.178)
2908 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2909 LPARAM lParam )
2911 WND **list, *pParent;
2913 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2914 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2916 WIN_ReleaseWndPtr(pParent);
2917 return FALSE;
2919 WIN_EnumChildWindows( list, func, lParam );
2920 WIN_ReleaseWinArray(list);
2921 WIN_ReleaseWndPtr(pParent);
2922 return TRUE;
2926 /*******************************************************************
2927 * AnyPopup16 (USER.52)
2929 BOOL16 WINAPI AnyPopup16(void)
2931 return AnyPopup();
2935 /*******************************************************************
2936 * AnyPopup (USER32.4)
2938 BOOL WINAPI AnyPopup(void)
2940 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2941 BOOL retvalue;
2943 while (wndPtr)
2945 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2947 retvalue = TRUE;
2948 goto end;
2950 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2952 retvalue = FALSE;
2953 end:
2954 WIN_ReleaseWndPtr(wndPtr);
2955 return retvalue;
2959 /*******************************************************************
2960 * FlashWindow16 (USER.105)
2962 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2964 return FlashWindow( hWnd, bInvert );
2968 /*******************************************************************
2969 * FlashWindow (USER32.202)
2971 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2973 WND *wndPtr = WIN_FindWndPtr(hWnd);
2975 TRACE("%04x\n", hWnd);
2977 if (!wndPtr) return FALSE;
2979 if (wndPtr->dwStyle & WS_MINIMIZE)
2981 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2983 HDC hDC = GetDC(hWnd);
2985 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2986 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2988 ReleaseDC( hWnd, hDC );
2989 wndPtr->flags |= WIN_NCACTIVATED;
2991 else
2993 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2994 RDW_UPDATENOW | RDW_FRAME, 0 );
2995 wndPtr->flags &= ~WIN_NCACTIVATED;
2997 WIN_ReleaseWndPtr(wndPtr);
2998 return TRUE;
3000 else
3002 WPARAM16 wparam;
3003 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3004 else wparam = (hWnd == GetActiveWindow());
3006 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3007 WIN_ReleaseWndPtr(wndPtr);
3008 return wparam;
3013 /*******************************************************************
3014 * SetSysModalWindow16 (USER.188)
3016 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3018 HWND hWndOldModal = hwndSysModal;
3019 hwndSysModal = hWnd;
3020 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3021 return hWndOldModal;
3025 /*******************************************************************
3026 * GetSysModalWindow16 (USER.52)
3028 HWND16 WINAPI GetSysModalWindow16(void)
3030 return hwndSysModal;
3034 /*******************************************************************
3035 * GetWindowContextHelpId (USER32.303)
3037 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3039 DWORD retval;
3040 WND *wnd = WIN_FindWndPtr( hwnd );
3041 if (!wnd) return 0;
3042 retval = wnd->helpContext;
3043 WIN_ReleaseWndPtr(wnd);
3044 return retval;
3048 /*******************************************************************
3049 * SetWindowContextHelpId (USER32.515)
3051 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3053 WND *wnd = WIN_FindWndPtr( hwnd );
3054 if (!wnd) return FALSE;
3055 wnd->helpContext = id;
3056 WIN_ReleaseWndPtr(wnd);
3057 return TRUE;
3061 /*******************************************************************
3062 * DRAG_QueryUpdate
3064 * recursively find a child that contains spDragInfo->pt point
3065 * and send WM_QUERYDROPOBJECT
3067 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3069 BOOL16 wParam, bResult = 0;
3070 POINT pt;
3071 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3072 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3073 RECT tempRect;
3075 if( !ptrQueryWnd || !ptrDragInfo )
3076 goto end;
3078 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3080 GetWindowRect(hQueryWnd,&tempRect);
3082 if( !PtInRect(&tempRect,pt) ||
3083 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3084 goto end;
3086 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3088 tempRect = ptrQueryWnd->rectClient;
3089 if(ptrQueryWnd->dwStyle & WS_CHILD)
3090 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3091 (LPPOINT)&tempRect, 2 );
3093 if (PtInRect( &tempRect, pt))
3095 wParam = 0;
3097 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3099 if( ptrWnd->dwStyle & WS_VISIBLE )
3101 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3102 if (PtInRect( &tempRect, pt )) break;
3106 if(ptrWnd)
3108 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3109 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3110 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3111 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3112 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3114 WIN_ReleaseWndPtr(ptrWnd);
3117 if(bResult)
3118 goto end;
3120 else wParam = 1;
3122 else wParam = 1;
3124 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3126 ptrDragInfo->hScope = hQueryWnd;
3128 bResult = ( bNoSend )
3129 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3130 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3131 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3132 if( !bResult )
3133 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3135 end:
3136 WIN_ReleaseWndPtr(ptrQueryWnd);
3137 return bResult;
3141 /*******************************************************************
3142 * DragDetect (USER.465)
3144 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3146 POINT pt32;
3147 CONV_POINT16TO32( &pt, &pt32 );
3148 return DragDetect( hWnd, pt32 );
3151 /*******************************************************************
3152 * DragDetect (USER32.151)
3154 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3156 MSG16 msg;
3157 RECT16 rect;
3159 rect.left = pt.x - wDragWidth;
3160 rect.right = pt.x + wDragWidth;
3162 rect.top = pt.y - wDragHeight;
3163 rect.bottom = pt.y + wDragHeight;
3165 SetCapture(hWnd);
3167 while(1)
3169 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3171 if( msg.message == WM_LBUTTONUP )
3173 ReleaseCapture();
3174 return 0;
3176 if( msg.message == WM_MOUSEMOVE )
3178 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3180 ReleaseCapture();
3181 return 1;
3185 WaitMessage();
3187 return 0;
3190 /******************************************************************************
3191 * DragObject16 (USER.464)
3193 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3194 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3196 MSG16 msg;
3197 LPDRAGINFO lpDragInfo;
3198 SEGPTR spDragInfo;
3199 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3200 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3201 WND *wndPtr = WIN_FindWndPtr(hWnd);
3202 HCURSOR16 hCurrentCursor = 0;
3203 HWND16 hCurrentWnd = 0;
3205 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3206 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3208 if( !lpDragInfo || !spDragInfo )
3210 WIN_ReleaseWndPtr(wndPtr);
3211 return 0L;
3214 hBummer = LoadCursor16(0, IDC_BUMMER16);
3216 if( !hBummer || !wndPtr )
3218 GlobalFree16(hDragInfo);
3219 WIN_ReleaseWndPtr(wndPtr);
3220 return 0L;
3223 if(hCursor)
3225 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3227 GlobalFree16(hDragInfo);
3228 WIN_ReleaseWndPtr(wndPtr);
3229 return 0L;
3232 if( hDragCursor == hCursor ) hDragCursor = 0;
3233 else hCursor = hDragCursor;
3235 hOldCursor = SetCursor(hDragCursor);
3238 lpDragInfo->hWnd = hWnd;
3239 lpDragInfo->hScope = 0;
3240 lpDragInfo->wFlags = wObj;
3241 lpDragInfo->hList = szList; /* near pointer! */
3242 lpDragInfo->hOfStruct = hOfStruct;
3243 lpDragInfo->l = 0L;
3245 SetCapture(hWnd);
3246 ShowCursor( TRUE );
3250 do{ WaitMessage(); }
3251 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3253 *(lpDragInfo+1) = *lpDragInfo;
3255 lpDragInfo->pt = msg.pt;
3257 /* update DRAGINFO struct */
3258 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3260 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3261 hCurrentCursor = hCursor;
3262 else
3264 hCurrentCursor = hBummer;
3265 lpDragInfo->hScope = 0;
3267 if( hCurrentCursor )
3268 SetCursor(hCurrentCursor);
3270 /* send WM_DRAGLOOP */
3271 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3272 (LPARAM) spDragInfo );
3273 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3274 if( hCurrentWnd != lpDragInfo->hScope )
3276 if( hCurrentWnd )
3277 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3278 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3279 HIWORD(spDragInfo)) );
3280 hCurrentWnd = lpDragInfo->hScope;
3281 if( hCurrentWnd )
3282 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3284 else
3285 if( hCurrentWnd )
3286 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3288 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3290 ReleaseCapture();
3291 ShowCursor( FALSE );
3293 if( hCursor )
3295 SetCursor( hOldCursor );
3296 if (hDragCursor) DestroyCursor( hDragCursor );
3299 if( hCurrentCursor != hBummer )
3300 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3301 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3302 else
3303 msg.lParam = 0;
3304 GlobalFree16(hDragInfo);
3305 WIN_ReleaseWndPtr(wndPtr);
3307 return (DWORD)(msg.lParam);