Make sure that all MDI children have the WS_EX_MDICHILD style set.
[wine/dcerpc.git] / windows / win.c
blob3e41d79e892163d3e0a0e51560ac3eb39aac7b3f
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "cursoricon.h"
18 #include "hook.h"
19 #include "menu.h"
20 #include "message.h"
21 #include "nonclient.h"
22 #include "queue.h"
23 #include "winpos.h"
24 #include "clipboard.h"
25 #include "winproc.h"
26 #include "task.h"
27 #include "thread.h"
28 #include "process.h"
29 #include "winerror.h"
30 #include "mdi.h"
31 #include "local.h"
32 #include "desktop.h"
33 #include "syslevel.h"
34 #include "stackframe.h"
35 #include "debugtools.h"
37 DECLARE_DEBUG_CHANNEL(msg)
38 DECLARE_DEBUG_CHANNEL(win)
40 /**********************************************************************/
42 WND_DRIVER *WND_Driver = NULL;
44 /* Desktop window */
45 static WND *pWndDesktop = NULL;
47 static HWND hwndSysModal = 0;
49 static WORD wDragWidth = 4;
50 static WORD wDragHeight= 3;
52 /* thread safeness */
53 static SYSLEVEL WIN_SysLevel;
55 /***********************************************************************
56 * WIN_Init
57 */
58 void WIN_Init( void )
60 /* Initialisation of the critical section for thread safeness */
61 _CreateSysLevel( &WIN_SysLevel, 2 );
64 /***********************************************************************
65 * WIN_LockWnds
67 * Locks access to all WND structures for thread safeness
69 void WIN_LockWnds( void )
71 _EnterSysLevel( &WIN_SysLevel );
74 /***********************************************************************
75 * WIN_UnlockWnds
77 * Unlocks access to all WND structures
79 void WIN_UnlockWnds( void )
81 _LeaveSysLevel( &WIN_SysLevel );
84 /***********************************************************************
85 * WIN_SuspendWndsLock
87 * Suspend the lock on WND structures.
88 * Returns the number of locks suspended
90 int WIN_SuspendWndsLock( void )
92 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
93 int count = isuspendedLocks;
95 while ( count-- > 0 )
96 _LeaveSysLevel( &WIN_SysLevel );
98 return isuspendedLocks;
101 /***********************************************************************
102 * WIN_RestoreWndsLock
104 * Restore the suspended locks on WND structures
106 void WIN_RestoreWndsLock( int ipreviousLocks )
108 while ( ipreviousLocks-- > 0 )
109 _EnterSysLevel( &WIN_SysLevel );
112 /***********************************************************************
113 * WIN_FindWndPtr
115 * Return a pointer to the WND structure corresponding to a HWND.
117 WND * WIN_FindWndPtr( HWND hwnd )
119 WND * ptr;
121 if (!hwnd || HIWORD(hwnd)) goto error2;
122 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
123 /* Lock all WND structures for thread safeness*/
124 WIN_LockWnds();
125 /*and increment destruction monitoring*/
126 ptr->irefCount++;
128 if (ptr->dwMagic != WND_MAGIC) goto error;
129 if (ptr->hwndSelf != hwnd)
131 ERR_(win)("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
132 goto error;
134 /* returns a locked pointer */
135 return ptr;
136 error:
137 /* Unlock all WND structures for thread safeness*/
138 WIN_UnlockWnds();
139 /* and decrement destruction monitoring value */
140 ptr->irefCount--;
142 error2:
143 if ( hwnd!=0 )
144 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
145 return NULL;
148 /***********************************************************************
149 * WIN_LockWndPtr
151 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
152 * but by initWndPtr;
153 * Returns the locked initialisation pointer
155 WND *WIN_LockWndPtr(WND *initWndPtr)
157 if(!initWndPtr) return 0;
159 /* Lock all WND structures for thread safeness*/
160 WIN_LockWnds();
161 /*and increment destruction monitoring*/
162 initWndPtr->irefCount++;
164 return initWndPtr;
168 /***********************************************************************
169 * WIN_ReleaseWndPtr
171 * Release the pointer to the WND structure.
173 void WIN_ReleaseWndPtr(WND *wndPtr)
175 if(!wndPtr) return;
177 /*Decrement destruction monitoring value*/
178 wndPtr->irefCount--;
179 /* Check if it's time to release the memory*/
180 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
182 /* Release memory */
183 USER_HEAP_FREE( wndPtr->hwndSelf);
184 wndPtr->hwndSelf = 0;
186 else if(wndPtr->irefCount < 0)
188 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
189 ERR_(win)("forgot a Lock on %p somewhere\n",wndPtr);
191 /*unlock all WND structures for thread safeness*/
192 WIN_UnlockWnds();
195 /***********************************************************************
196 * WIN_UpdateWndPtr
198 * Updates the value of oldPtr to newPtr.
200 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
202 WND *tmpWnd = NULL;
204 tmpWnd = WIN_LockWndPtr(newPtr);
205 WIN_ReleaseWndPtr(*oldPtr);
206 *oldPtr = tmpWnd;
210 /***********************************************************************
211 * WIN_DumpWindow
213 * Dump the content of a window structure to stderr.
215 void WIN_DumpWindow( HWND hwnd )
217 WND *ptr;
218 char className[80];
219 int i;
221 if (!(ptr = WIN_FindWndPtr( hwnd )))
223 WARN_(win)("%04x is not a window handle\n", hwnd );
224 return;
227 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
228 strcpy( className, "#NULL#" );
230 TRACE_(win)("Window %04x (%p):\n", hwnd, ptr );
231 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
232 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
233 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
234 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
235 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
236 ptr->next, ptr->child, ptr->parent, ptr->owner,
237 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
238 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
239 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
240 ptr->text ? ptr->text : "",
241 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
242 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
243 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
244 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
246 if (ptr->class->cbWndExtra)
248 DPRINTF( "extra bytes:" );
249 for (i = 0; i < ptr->class->cbWndExtra; i++)
250 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
251 DPRINTF( "\n" );
253 DPRINTF( "\n" );
254 WIN_ReleaseWndPtr(ptr);
258 /***********************************************************************
259 * WIN_WalkWindows
261 * Walk the windows tree and print each window on stderr.
263 void WIN_WalkWindows( HWND hwnd, int indent )
265 WND *ptr;
266 char className[80];
268 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
270 if (!ptr)
272 WARN_(win)("Invalid window handle %04x\n", hwnd );
273 return;
276 if (!indent) /* first time around */
277 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
278 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
279 " Text");
281 while (ptr)
283 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
285 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
287 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
288 (DWORD)ptr, ptr->hmemTaskQ, className,
289 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
290 ptr->text?ptr->text:"<null>");
292 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
293 WIN_UpdateWndPtr(&ptr,ptr->next);
299 /***********************************************************************
300 * WIN_UnlinkWindow
302 * Remove a window from the siblings linked list.
304 BOOL WIN_UnlinkWindow( HWND hwnd )
306 WND *wndPtr, **ppWnd;
307 BOOL ret = FALSE;
309 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
310 else if(!wndPtr->parent)
312 WIN_ReleaseWndPtr(wndPtr);
313 return FALSE;
316 ppWnd = &wndPtr->parent->child;
317 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
318 if (*ppWnd)
320 *ppWnd = wndPtr->next;
321 ret = TRUE;
323 WIN_ReleaseWndPtr(wndPtr);
324 return ret;
328 /***********************************************************************
329 * WIN_LinkWindow
331 * Insert a window into the siblings linked list.
332 * The window is inserted after the specified window, which can also
333 * be specified as HWND_TOP or HWND_BOTTOM.
335 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
337 WND *wndPtr, **ppWnd;
339 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
340 else if(!wndPtr->parent)
342 WIN_ReleaseWndPtr(wndPtr);
343 return FALSE;
345 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
347 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
348 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
349 while (*ppWnd) ppWnd = &(*ppWnd)->next;
351 else /* Normal case */
353 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
354 if (!afterPtr)
356 WIN_ReleaseWndPtr(wndPtr);
357 return FALSE;
359 ppWnd = &afterPtr->next;
360 WIN_ReleaseWndPtr(afterPtr);
362 wndPtr->next = *ppWnd;
363 *ppWnd = wndPtr;
364 WIN_ReleaseWndPtr(wndPtr);
365 return TRUE;
369 /***********************************************************************
370 * WIN_FindWinToRepaint
372 * Find a window that needs repaint.
374 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
376 HWND hwndRet;
377 WND *pWnd;
379 /* Note: the desktop window never gets WM_PAINT messages
380 * The real reason why is because Windows DesktopWndProc
381 * does ValidateRgn inside WM_ERASEBKGND handler.
384 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
386 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
388 if (!(pWnd->dwStyle & WS_VISIBLE))
390 TRACE_(win)("skipping window %04x\n",
391 pWnd->hwndSelf );
393 else if ((pWnd->hmemTaskQ == hQueue) &&
394 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
395 break;
397 else if (pWnd->child )
398 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
400 WIN_ReleaseWndPtr(pWnd);
401 return hwndRet;
406 if(!pWnd)
408 return 0;
411 hwndRet = pWnd->hwndSelf;
413 /* look among siblings if we got a transparent window */
414 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
415 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
417 WIN_UpdateWndPtr(&pWnd,pWnd->next);
419 if (pWnd)
421 hwndRet = pWnd->hwndSelf;
422 WIN_ReleaseWndPtr(pWnd);
424 TRACE_(win)("found %04x\n",hwndRet);
425 return hwndRet;
429 /***********************************************************************
430 * WIN_DestroyWindow
432 * Destroy storage associated to a window. "Internals" p.358
433 * returns a locked wndPtr->next
435 static WND* WIN_DestroyWindow( WND* wndPtr )
437 HWND hwnd = wndPtr->hwndSelf;
438 WND *pWnd;
440 TRACE_(win)("%04x\n", wndPtr->hwndSelf );
442 /* free child windows */
443 WIN_LockWndPtr(wndPtr->child);
444 while ((pWnd = wndPtr->child))
446 wndPtr->child = WIN_DestroyWindow( pWnd );
447 WIN_ReleaseWndPtr(pWnd);
451 * Clear the update region to make sure no WM_PAINT messages will be
452 * generated for this window while processing the WM_NCDESTROY.
454 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
456 if (wndPtr->hrgnUpdate > 1)
457 DeleteObject( wndPtr->hrgnUpdate );
459 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
461 wndPtr->hrgnUpdate = 0;
465 * Send the WM_NCDESTROY to the window being destroyed.
467 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
469 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
471 WINPOS_CheckInternalPos( wndPtr );
472 if( hwnd == GetCapture()) ReleaseCapture();
474 /* free resources associated with the window */
476 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
477 PROPERTY_RemoveWindowProps( wndPtr );
479 wndPtr->dwMagic = 0; /* Mark it as invalid */
481 /* toss stale messages from the queue */
483 if( wndPtr->hmemTaskQ )
485 BOOL bPostQuit = FALSE;
486 WPARAM wQuitParam = 0;
487 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
488 QMSG *qmsg;
490 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
492 if( qmsg->msg.message == WM_QUIT )
494 bPostQuit = TRUE;
495 wQuitParam = qmsg->msg.wParam;
497 QUEUE_RemoveMsg(msgQ, qmsg);
500 QUEUE_Unlock(msgQ);
502 /* repost WM_QUIT to make sure this app exits its message loop */
503 if( bPostQuit ) PostQuitMessage(wQuitParam);
504 wndPtr->hmemTaskQ = 0;
507 if (!(wndPtr->dwStyle & WS_CHILD))
508 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
509 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
510 wndPtr->pDriver->pDestroyWindow( wndPtr );
511 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
512 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
513 wndPtr->class->cWindows--;
514 wndPtr->class = NULL;
516 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
518 wndPtr->pDriver->pFinalize(wndPtr);
520 return pWnd;
523 /***********************************************************************
524 * WIN_ResetQueueWindows
526 * Reset the queue of all the children of a given window.
527 * Return TRUE if something was done.
529 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
531 BOOL ret = FALSE;
533 if (hNew) /* Set a new queue */
535 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
537 if (wnd->hmemTaskQ == hQueue)
539 wnd->hmemTaskQ = hNew;
540 ret = TRUE;
542 if (wnd->child)
544 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
548 else /* Queue is being destroyed */
550 while (wnd->child)
552 WND *tmp = WIN_LockWndPtr(wnd->child);
553 WND *tmp2;
554 ret = FALSE;
555 while (tmp)
557 if (tmp->hmemTaskQ == hQueue)
559 DestroyWindow( tmp->hwndSelf );
560 ret = TRUE;
561 break;
563 tmp2 = WIN_LockWndPtr(tmp->child);
564 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
565 ret = TRUE;
566 else
568 WIN_UpdateWndPtr(&tmp,tmp->next);
570 WIN_ReleaseWndPtr(tmp2);
572 WIN_ReleaseWndPtr(tmp);
573 if (!ret) break;
576 return ret;
579 /***********************************************************************
580 * WIN_CreateDesktopWindow
582 * Create the desktop window.
584 BOOL WIN_CreateDesktopWindow(void)
586 CLASS *class;
587 HWND hwndDesktop;
588 DESKTOP *pDesktop;
590 TRACE_(win)("Creating desktop window\n");
593 if (!ICONTITLE_Init() ||
594 !WINPOS_CreateInternalPosAtom() ||
595 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
596 return FALSE;
598 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
599 if (!hwndDesktop) return FALSE;
600 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
602 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
603 pDesktop->pDriver = DESKTOP_Driver;
604 pWndDesktop->pDriver = WND_Driver;
606 pDesktop->pDriver->pInitialize(pDesktop);
607 pWndDesktop->pDriver->pInitialize(pWndDesktop);
609 pWndDesktop->next = NULL;
610 pWndDesktop->child = NULL;
611 pWndDesktop->parent = NULL;
612 pWndDesktop->owner = NULL;
613 pWndDesktop->class = class;
614 pWndDesktop->dwMagic = WND_MAGIC;
615 pWndDesktop->hwndSelf = hwndDesktop;
616 pWndDesktop->hInstance = 0;
617 pWndDesktop->rectWindow.left = 0;
618 pWndDesktop->rectWindow.top = 0;
619 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
620 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
621 pWndDesktop->rectClient = pWndDesktop->rectWindow;
622 pWndDesktop->text = NULL;
623 pWndDesktop->hmemTaskQ = GetFastQueue16();
624 pWndDesktop->hrgnUpdate = 0;
625 pWndDesktop->hwndLastActive = hwndDesktop;
626 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
627 WS_CLIPSIBLINGS;
628 pWndDesktop->dwExStyle = 0;
629 pWndDesktop->dce = NULL;
630 pWndDesktop->pVScroll = NULL;
631 pWndDesktop->pHScroll = NULL;
632 pWndDesktop->pProp = NULL;
633 pWndDesktop->wIDmenu = 0;
634 pWndDesktop->helpContext = 0;
635 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
636 pWndDesktop->hSysMenu = 0;
637 pWndDesktop->userdata = 0;
638 pWndDesktop->winproc = (WNDPROC16)class->winproc;
639 pWndDesktop->irefCount = 0;
641 /* FIXME: How do we know if it should be Unicode or not */
642 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
643 return FALSE;
645 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
646 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
647 return TRUE;
651 /***********************************************************************
652 * WIN_CreateWindowEx
654 * Implementation of CreateWindowEx().
656 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
657 BOOL win32, BOOL unicode )
659 INT sw = SW_SHOW;
660 CLASS *classPtr;
661 WND *wndPtr;
662 HWND retvalue;
663 HWND16 hwnd, hwndLinkAfter;
664 POINT maxSize, maxPos, minTrack, maxTrack;
665 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
666 char buffer[256];
668 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
669 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
670 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
671 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
672 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
674 /* Find the parent window */
676 if (cs->hwndParent)
678 /* Make sure parent is valid */
679 if (!IsWindow( cs->hwndParent ))
681 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
682 return 0;
684 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
685 WARN_(win)("No parent for child window\n" );
686 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
689 /* Find the window class */
690 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
692 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
693 WARN_(win)("Bad class '%s'\n", buffer );
694 return 0;
697 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
698 * with an atom as the class name, put some programs expect to have a *REAL* string in
699 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
701 if ( !HIWORD(cs->lpszClass) ) {
702 if (unicode) {
703 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
704 } else {
705 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
707 cs->lpszClass = buffer;
710 /* Fix the coordinates */
712 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
714 PDB *pdb = PROCESS_Current();
716 /* Never believe Microsoft's documentation... CreateWindowEx doc says
717 * that if an overlapped window is created with WS_VISIBLE style bit
718 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
719 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
720 * reveals that
722 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
723 * 2) it does not ignore the y parameter as the docs claim; instead, it
724 * uses it as second parameter to ShowWindow() unless y is either
725 * CW_USEDEFAULT or CW_USEDEFAULT16.
727 * The fact that we didn't do 2) caused bogus windows pop up when wine
728 * was running apps that were using this obscure feature. Example -
729 * calc.exe that comes with Win98 (only Win98, it's different from
730 * the one that comes with Win95 and NT)
732 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
734 /* We have saved cs->y, now we can trash it */
735 if ( !(cs->style & (WS_CHILD | WS_POPUP))
736 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
738 cs->x = pdb->env_db->startup_info->dwX;
739 cs->y = pdb->env_db->startup_info->dwY;
741 else
743 cs->x = 0;
744 cs->y = 0;
747 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
749 PDB *pdb = PROCESS_Current();
750 if ( !(cs->style & (WS_CHILD | WS_POPUP))
751 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
753 cs->cx = pdb->env_db->startup_info->dwXSize;
754 cs->cy = pdb->env_db->startup_info->dwYSize;
756 else
758 cs->cx = 600; /* FIXME */
759 cs->cy = 400;
763 /* Create the window structure */
765 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
766 - sizeof(wndPtr->wExtra) )))
768 TRACE_(win)("out of memory\n" );
769 return 0;
772 /* Fill the window structure */
774 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
775 wndPtr->next = NULL;
776 wndPtr->child = NULL;
778 if ((cs->style & WS_CHILD) && cs->hwndParent)
780 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
781 wndPtr->owner = NULL;
782 WIN_ReleaseWndPtr(wndPtr->parent);
784 else
786 wndPtr->parent = pWndDesktop;
787 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
788 wndPtr->owner = NULL;
789 else
791 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
792 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
793 WIN_ReleaseWndPtr(wndPtr->owner);
794 WIN_ReleaseWndPtr(tmpWnd);
799 wndPtr->pDriver = wndPtr->parent->pDriver;
800 wndPtr->pDriver->pInitialize(wndPtr);
802 wndPtr->class = classPtr;
803 wndPtr->winproc = classPtr->winproc;
804 wndPtr->dwMagic = WND_MAGIC;
805 wndPtr->hwndSelf = hwnd;
806 wndPtr->hInstance = cs->hInstance;
807 wndPtr->text = NULL;
808 wndPtr->hmemTaskQ = GetFastQueue16();
809 wndPtr->hrgnUpdate = 0;
810 wndPtr->hwndLastActive = hwnd;
811 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
812 wndPtr->dwExStyle = cs->dwExStyle;
813 wndPtr->wIDmenu = 0;
814 wndPtr->helpContext = 0;
815 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
816 wndPtr->pVScroll = NULL;
817 wndPtr->pHScroll = NULL;
818 wndPtr->pProp = NULL;
819 wndPtr->userdata = 0;
820 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
821 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
822 wndPtr->irefCount = 1;
824 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
826 /* Call the WH_CBT hook */
828 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
829 ? HWND_BOTTOM : HWND_TOP;
831 if (HOOK_IsHooked( WH_CBT ))
833 CBT_CREATEWNDA cbtc;
834 LRESULT ret;
836 cbtc.lpcs = cs;
837 cbtc.hwndInsertAfter = hwndLinkAfter;
838 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
839 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
840 if (ret)
842 TRACE_(win)("CBT-hook returned 0\n");
843 wndPtr->pDriver->pFinalize(wndPtr);
844 USER_HEAP_FREE( hwnd );
845 retvalue = 0;
846 goto end;
850 /* Increment class window counter */
852 classPtr->cWindows++;
854 /* Correct the window style */
856 if (!(cs->style & WS_CHILD))
858 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
859 if (!(cs->style & WS_POPUP))
861 wndPtr->dwStyle |= WS_CAPTION;
862 wndPtr->flags |= WIN_NEED_SIZE;
866 /* Get class or window DC if needed */
868 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
869 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
870 else wndPtr->dce = NULL;
872 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
874 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
876 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
877 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
878 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
879 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
880 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
883 if(cs->style & WS_CHILD)
885 if(cs->cx < 0) cs->cx = 0;
886 if(cs->cy < 0) cs->cy = 0;
888 else
890 if (cs->cx <= 0) cs->cx = 1;
891 if (cs->cy <= 0) cs->cy = 1;
894 wndPtr->rectWindow.left = cs->x;
895 wndPtr->rectWindow.top = cs->y;
896 wndPtr->rectWindow.right = cs->x + cs->cx;
897 wndPtr->rectWindow.bottom = cs->y + cs->cy;
898 wndPtr->rectClient = wndPtr->rectWindow;
900 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
902 retvalue = FALSE;
903 goto end;
906 /* Set the window menu */
908 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
910 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
911 else
913 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
914 if (classPtr->menuNameA)
915 cs->hMenu = HIWORD(classPtr->menuNameA) ?
916 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
917 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
918 #else
919 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
920 if (menuName)
922 if (HIWORD(cs->hInstance))
923 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
924 else
925 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
927 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
929 #endif
932 else wndPtr->wIDmenu = (UINT)cs->hMenu;
934 /* Send the WM_CREATE message
935 * Perhaps we shouldn't allow width/height changes as well.
936 * See p327 in "Internals".
939 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
941 localSend32 = unicode ? SendMessageW : SendMessageA;
942 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
944 /* Insert the window in the linked list */
946 WIN_LinkWindow( hwnd, hwndLinkAfter );
948 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
949 NULL, NULL, 0, &wndPtr->rectClient );
950 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
951 maxPos.y - wndPtr->rectWindow.top);
952 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
954 /* Send the size messages */
956 if (!(wndPtr->flags & WIN_NEED_SIZE))
958 /* send it anyway */
959 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
960 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
961 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
962 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
963 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
964 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
965 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
966 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
967 SendMessageA( hwnd, WM_MOVE, 0,
968 MAKELONG( wndPtr->rectClient.left,
969 wndPtr->rectClient.top ) );
972 /* Show the window, maximizing or minimizing if needed */
974 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
976 RECT16 newPos;
977 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
978 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
979 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
980 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
981 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
982 : SWP_NOZORDER | SWP_FRAMECHANGED;
983 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
984 newPos.right, newPos.bottom, swFlag );
987 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
989 /* Notify the parent window only */
991 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
992 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
993 if( !IsWindow(hwnd) )
995 retvalue = 0;
996 goto end;
1000 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
1002 /* Call WH_SHELL hook */
1004 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1005 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1007 TRACE_(win)("created window %04x\n", hwnd);
1008 retvalue = hwnd;
1009 goto end;
1011 WIN_UnlinkWindow( hwnd );
1014 /* Abort window creation */
1016 WARN_(win)("aborted by WM_xxCREATE!\n");
1017 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1018 retvalue = 0;
1019 end:
1020 WIN_ReleaseWndPtr(wndPtr);
1022 return retvalue;
1026 /***********************************************************************
1027 * CreateWindow16 (USER.41)
1029 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1030 DWORD style, INT16 x, INT16 y, INT16 width,
1031 INT16 height, HWND16 parent, HMENU16 menu,
1032 HINSTANCE16 instance, LPVOID data )
1034 return CreateWindowEx16( 0, className, windowName, style,
1035 x, y, width, height, parent, menu, instance, data );
1039 /***********************************************************************
1040 * CreateWindowEx16 (USER.452)
1042 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1043 LPCSTR windowName, DWORD style, INT16 x,
1044 INT16 y, INT16 width, INT16 height,
1045 HWND16 parent, HMENU16 menu,
1046 HINSTANCE16 instance, LPVOID data )
1048 ATOM classAtom;
1049 CREATESTRUCTA cs;
1051 /* Find the class atom */
1053 if (!(classAtom = GlobalFindAtomA( className )))
1055 fprintf( stderr, "CreateWindowEx16: bad class name " );
1056 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1057 else fprintf( stderr, "'%s'\n", className );
1058 return 0;
1061 /* Fix the coordinates */
1063 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1064 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1065 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1066 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1068 /* Create the window */
1070 cs.lpCreateParams = data;
1071 cs.hInstance = (HINSTANCE)instance;
1072 cs.hMenu = (HMENU)menu;
1073 cs.hwndParent = (HWND)parent;
1074 cs.style = style;
1075 cs.lpszName = windowName;
1076 cs.lpszClass = className;
1077 cs.dwExStyle = exStyle;
1078 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1082 /***********************************************************************
1083 * CreateWindowEx32A (USER32.83)
1085 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1086 LPCSTR windowName, DWORD style, INT x,
1087 INT y, INT width, INT height,
1088 HWND parent, HMENU menu,
1089 HINSTANCE instance, LPVOID data )
1091 ATOM classAtom;
1092 CREATESTRUCTA cs;
1094 if(exStyle & WS_EX_MDICHILD)
1095 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1096 /* Find the class atom */
1098 if (!(classAtom = GlobalFindAtomA( className )))
1100 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1101 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1102 else fprintf( stderr, "'%s'\n", className );
1103 return 0;
1106 /* Create the window */
1108 cs.lpCreateParams = data;
1109 cs.hInstance = instance;
1110 cs.hMenu = menu;
1111 cs.hwndParent = parent;
1112 cs.x = x;
1113 cs.y = y;
1114 cs.cx = width;
1115 cs.cy = height;
1116 cs.style = style;
1117 cs.lpszName = windowName;
1118 cs.lpszClass = className;
1119 cs.dwExStyle = exStyle;
1120 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1124 /***********************************************************************
1125 * CreateWindowEx32W (USER32.84)
1127 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1128 LPCWSTR windowName, DWORD style, INT x,
1129 INT y, INT width, INT height,
1130 HWND parent, HMENU menu,
1131 HINSTANCE instance, LPVOID data )
1133 ATOM classAtom;
1134 CREATESTRUCTW cs;
1136 if(exStyle & WS_EX_MDICHILD)
1137 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1139 /* Find the class atom */
1141 if (!(classAtom = GlobalFindAtomW( className )))
1143 if (HIWORD(className))
1145 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1146 WARN_(win)("Bad class name '%s'\n",cn);
1147 HeapFree( GetProcessHeap(), 0, cn );
1149 else
1150 WARN_(win)("Bad class name %p\n", className );
1151 return 0;
1154 /* Create the window */
1156 cs.lpCreateParams = data;
1157 cs.hInstance = instance;
1158 cs.hMenu = menu;
1159 cs.hwndParent = parent;
1160 cs.x = x;
1161 cs.y = y;
1162 cs.cx = width;
1163 cs.cy = height;
1164 cs.style = style;
1165 cs.lpszName = windowName;
1166 cs.lpszClass = className;
1167 cs.dwExStyle = exStyle;
1168 /* Note: we rely on the fact that CREATESTRUCT32A and */
1169 /* CREATESTRUCT32W have the same layout. */
1170 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1174 /***********************************************************************
1175 * WIN_CheckFocus
1177 static void WIN_CheckFocus( WND* pWnd )
1179 if( GetFocus16() == pWnd->hwndSelf )
1180 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1183 /***********************************************************************
1184 * WIN_SendDestroyMsg
1186 static void WIN_SendDestroyMsg( WND* pWnd )
1188 WIN_CheckFocus(pWnd);
1190 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1191 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1194 * Send the WM_DESTROY to the window.
1196 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1199 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1200 * make sure that the window still exists when we come back.
1202 if (IsWindow(pWnd->hwndSelf))
1204 HWND* pWndArray = NULL;
1205 WND* pChild = NULL;
1206 int nKidCount = 0;
1209 * Now, if the window has kids, we have to send WM_DESTROY messages
1210 * recursively to it's kids. It seems that those calls can also
1211 * trigger re-entrant calls to DestroyWindow for the kids so we must
1212 * protect against corruption of the list of siblings. We first build
1213 * a list of HWNDs representing all the kids.
1215 pChild = WIN_LockWndPtr(pWnd->child);
1216 while( pChild )
1218 nKidCount++;
1219 WIN_UpdateWndPtr(&pChild,pChild->next);
1223 * If there are no kids, we're done.
1225 if (nKidCount==0)
1226 return;
1228 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1231 * Sanity check
1233 if (pWndArray==NULL)
1234 return;
1237 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1238 * call, our linked list of siblings should be safe.
1240 nKidCount = 0;
1241 pChild = WIN_LockWndPtr(pWnd->child);
1242 while( pChild )
1244 pWndArray[nKidCount] = pChild->hwndSelf;
1245 nKidCount++;
1246 WIN_UpdateWndPtr(&pChild,pChild->next);
1250 * Now that we have a list, go through that list again and send the destroy
1251 * message to those windows. We are using the HWND to retrieve the
1252 * WND pointer so we are effectively checking that all the kid windows are
1253 * still valid before sending the message.
1255 while (nKidCount>0)
1257 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1259 if (pChild!=NULL)
1261 WIN_SendDestroyMsg( pChild );
1262 WIN_ReleaseWndPtr(pChild);
1267 * Cleanup
1269 HeapFree(GetProcessHeap(), 0, pWndArray);
1270 WIN_CheckFocus(pWnd);
1272 else
1273 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1277 /***********************************************************************
1278 * DestroyWindow16 (USER.53)
1280 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1282 return DestroyWindow(hwnd);
1286 /***********************************************************************
1287 * DestroyWindow32 (USER32.135)
1289 BOOL WINAPI DestroyWindow( HWND hwnd )
1291 WND * wndPtr;
1292 BOOL retvalue;
1294 TRACE_(win)("(%04x)\n", hwnd);
1296 /* Initialization */
1298 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1299 if (wndPtr == pWndDesktop)
1301 WIN_ReleaseWndPtr(wndPtr);
1302 return FALSE; /* Can't destroy desktop */
1305 /* Call hooks */
1307 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1309 retvalue = FALSE;
1310 goto end;
1313 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1315 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1316 /* FIXME: clean up palette - see "Internals" p.352 */
1319 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1320 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1322 /* Notify the parent window only */
1323 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1324 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1325 if( !IsWindow(hwnd) )
1327 retvalue = TRUE;
1328 goto end;
1332 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1334 /* Hide the window */
1336 if (wndPtr->dwStyle & WS_VISIBLE)
1338 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1339 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1340 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1341 if (!IsWindow(hwnd))
1343 retvalue = TRUE;
1344 goto end;
1348 /* Recursively destroy owned windows */
1350 if( !(wndPtr->dwStyle & WS_CHILD) )
1352 /* make sure top menu popup doesn't get destroyed */
1353 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1355 for (;;)
1357 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1358 while (siblingPtr)
1360 if (siblingPtr->owner == wndPtr)
1362 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1363 break;
1364 else
1365 siblingPtr->owner = NULL;
1367 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1369 if (siblingPtr)
1371 DestroyWindow( siblingPtr->hwndSelf );
1372 WIN_ReleaseWndPtr(siblingPtr);
1374 else break;
1377 if( !Options.managed || EVENT_CheckFocus() )
1378 WINPOS_ActivateOtherWindow(wndPtr);
1380 if( wndPtr->owner &&
1381 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1382 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1385 /* Send destroy messages */
1387 WIN_SendDestroyMsg( wndPtr );
1388 if (!IsWindow(hwnd))
1390 retvalue = TRUE;
1391 goto end;
1394 /* Unlink now so we won't bother with the children later on */
1396 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1398 /* Destroy the window storage */
1400 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1401 retvalue = TRUE;
1402 end:
1403 WIN_ReleaseWndPtr(wndPtr);
1404 return retvalue;
1408 /***********************************************************************
1409 * CloseWindow16 (USER.43)
1411 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1413 return CloseWindow( hwnd );
1417 /***********************************************************************
1418 * CloseWindow32 (USER32.56)
1420 BOOL WINAPI CloseWindow( HWND hwnd )
1422 WND * wndPtr = WIN_FindWndPtr( hwnd );
1423 BOOL retvalue;
1425 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1427 retvalue = FALSE;
1428 goto end;
1430 ShowWindow( hwnd, SW_MINIMIZE );
1431 retvalue = TRUE;
1432 end:
1433 WIN_ReleaseWndPtr(wndPtr);
1434 return retvalue;
1439 /***********************************************************************
1440 * OpenIcon16 (USER.44)
1442 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1444 return OpenIcon( hwnd );
1448 /***********************************************************************
1449 * OpenIcon32 (USER32.410)
1451 BOOL WINAPI OpenIcon( HWND hwnd )
1453 if (!IsIconic( hwnd )) return FALSE;
1454 ShowWindow( hwnd, SW_SHOWNORMAL );
1455 return TRUE;
1459 /***********************************************************************
1460 * WIN_FindWindow
1462 * Implementation of FindWindow() and FindWindowEx().
1464 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1465 LPCSTR title )
1467 WND *pWnd;
1468 HWND retvalue;
1469 CLASS *pClass = NULL;
1471 if (child)
1473 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1474 if (parent)
1476 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1478 retvalue = 0;
1479 goto end;
1482 else if (pWnd->parent != pWndDesktop)
1484 retvalue = 0;
1485 goto end;
1487 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1489 else
1491 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1493 retvalue = 0;
1494 goto end;
1496 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1498 if (!pWnd)
1500 retvalue = 0;
1501 goto end;
1504 /* For a child window, all siblings will have the same hInstance, */
1505 /* so we can look for the class once and for all. */
1507 if (className && (pWnd->dwStyle & WS_CHILD))
1509 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1511 retvalue = 0;
1512 goto end;
1517 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1519 if (className && !(pWnd->dwStyle & WS_CHILD))
1521 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1522 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1524 continue; /* Skip this window */
1527 if (pClass && (pWnd->class != pClass))
1528 continue; /* Not the right class */
1530 /* Now check the title */
1532 if (!title)
1534 retvalue = pWnd->hwndSelf;
1535 goto end;
1537 if (pWnd->text && !strcmp( pWnd->text, title ))
1539 retvalue = pWnd->hwndSelf;
1540 goto end;
1543 retvalue = 0;
1544 end:
1545 WIN_ReleaseWndPtr(pWnd);
1546 return retvalue;
1551 /***********************************************************************
1552 * FindWindow16 (USER.50)
1554 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1556 return FindWindowEx16( 0, 0, className, title );
1560 /***********************************************************************
1561 * FindWindowEx16 (USER.427)
1563 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1564 SEGPTR className, LPCSTR title )
1566 ATOM atom = 0;
1568 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1569 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1570 title ? title : "");
1572 if (className)
1574 /* If the atom doesn't exist, then no class */
1575 /* with this name exists either. */
1576 if (!(atom = GlobalFindAtom16( className ))) return 0;
1578 return WIN_FindWindow( parent, child, atom, title );
1582 /***********************************************************************
1583 * FindWindow32A (USER32.198)
1585 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1587 HWND ret = FindWindowExA( 0, 0, className, title );
1588 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1589 return ret;
1593 /***********************************************************************
1594 * FindWindowEx32A (USER32.199)
1596 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1597 LPCSTR className, LPCSTR title )
1599 ATOM atom = 0;
1601 if (className)
1603 /* If the atom doesn't exist, then no class */
1604 /* with this name exists either. */
1605 if (!(atom = GlobalFindAtomA( className )))
1607 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1608 return 0;
1611 return WIN_FindWindow( parent, child, atom, title );
1615 /***********************************************************************
1616 * FindWindowEx32W (USER32.200)
1618 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1619 LPCWSTR className, LPCWSTR title )
1621 ATOM atom = 0;
1622 char *buffer;
1623 HWND hwnd;
1625 if (className)
1627 /* If the atom doesn't exist, then no class */
1628 /* with this name exists either. */
1629 if (!(atom = GlobalFindAtomW( className )))
1631 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1632 return 0;
1635 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1636 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1637 HeapFree( GetProcessHeap(), 0, buffer );
1638 return hwnd;
1642 /***********************************************************************
1643 * FindWindow32W (USER32.201)
1645 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1647 return FindWindowExW( 0, 0, className, title );
1651 /**********************************************************************
1652 * WIN_GetDesktop
1653 * returns a locked pointer
1655 WND *WIN_GetDesktop(void)
1657 return WIN_LockWndPtr(pWndDesktop);
1659 /**********************************************************************
1660 * WIN_ReleaseDesktop
1661 * unlock the desktop pointer
1663 void WIN_ReleaseDesktop(void)
1665 WIN_ReleaseWndPtr(pWndDesktop);
1669 /**********************************************************************
1670 * GetDesktopWindow16 (USER.286)
1672 HWND16 WINAPI GetDesktopWindow16(void)
1674 return (HWND16)pWndDesktop->hwndSelf;
1678 /**********************************************************************
1679 * GetDesktopWindow32 (USER32.232)
1681 HWND WINAPI GetDesktopWindow(void)
1683 return pWndDesktop->hwndSelf;
1687 /**********************************************************************
1688 * GetDesktopHwnd (USER.278)
1690 * Exactly the same thing as GetDesktopWindow(), but not documented.
1691 * Don't ask me why...
1693 HWND16 WINAPI GetDesktopHwnd16(void)
1695 return (HWND16)pWndDesktop->hwndSelf;
1699 /*******************************************************************
1700 * EnableWindow16 (USER.34)
1702 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1704 return EnableWindow( hwnd, enable );
1708 /*******************************************************************
1709 * EnableWindow32 (USER32.172)
1711 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1713 WND *wndPtr;
1714 BOOL retvalue;
1716 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1718 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1719 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1721 /* Enable window */
1722 wndPtr->dwStyle &= ~WS_DISABLED;
1724 if( wndPtr->flags & WIN_NATIVE )
1725 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1727 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1728 retvalue = TRUE;
1729 goto end;
1731 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1733 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1735 /* Disable window */
1736 wndPtr->dwStyle |= WS_DISABLED;
1738 if( wndPtr->flags & WIN_NATIVE )
1739 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1741 if (hwnd == GetFocus())
1743 SetFocus( 0 ); /* A disabled window can't have the focus */
1745 if (hwnd == GetCapture())
1747 ReleaseCapture(); /* A disabled window can't capture the mouse */
1749 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1750 retvalue = FALSE;
1751 goto end;
1753 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1754 end:
1755 WIN_ReleaseWndPtr(wndPtr);
1756 return retvalue;
1760 /***********************************************************************
1761 * IsWindowEnabled16 (USER.35)
1763 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1765 return IsWindowEnabled(hWnd);
1769 /***********************************************************************
1770 * IsWindowEnabled32 (USER32.349)
1772 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1774 WND * wndPtr;
1775 BOOL retvalue;
1777 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1778 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1779 WIN_ReleaseWndPtr(wndPtr);
1780 return retvalue;
1785 /***********************************************************************
1786 * IsWindowUnicode (USER32.350)
1788 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1790 WND * wndPtr;
1791 BOOL retvalue;
1793 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1794 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1795 WIN_ReleaseWndPtr(wndPtr);
1796 return retvalue;
1800 /**********************************************************************
1801 * GetWindowWord16 (USER.133)
1803 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1805 return GetWindowWord( hwnd, offset );
1809 /**********************************************************************
1810 * GetWindowWord32 (USER32.314)
1812 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1814 WORD retvalue;
1815 WND * wndPtr = WIN_FindWndPtr( hwnd );
1816 if (!wndPtr) return 0;
1817 if (offset >= 0)
1819 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1821 WARN_(win)("Invalid offset %d\n", offset );
1822 retvalue = 0;
1823 goto end;
1825 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1826 goto end;
1828 switch(offset)
1830 case GWW_ID:
1831 if (HIWORD(wndPtr->wIDmenu))
1832 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1833 wndPtr->wIDmenu);
1834 retvalue = (WORD)wndPtr->wIDmenu;
1835 goto end;
1836 case GWW_HWNDPARENT:
1837 retvalue = GetParent(hwnd);
1838 goto end;
1839 case GWW_HINSTANCE:
1840 if (HIWORD(wndPtr->hInstance))
1841 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1842 wndPtr->hInstance);
1843 retvalue = (WORD)wndPtr->hInstance;
1844 goto end;
1845 default:
1846 WARN_(win)("Invalid offset %d\n", offset );
1847 retvalue = 0;
1848 goto end;
1850 end:
1851 WIN_ReleaseWndPtr(wndPtr);
1852 return retvalue;
1855 /**********************************************************************
1856 * SetWindowWord16 (USER.134)
1858 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1860 return SetWindowWord( hwnd, offset, newval );
1864 /**********************************************************************
1865 * SetWindowWord32 (USER32.524)
1867 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1869 WORD *ptr, retval;
1870 WND * wndPtr = WIN_FindWndPtr( hwnd );
1871 if (!wndPtr) return 0;
1872 if (offset >= 0)
1874 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1876 WARN_(win)("Invalid offset %d\n", offset );
1877 retval = 0;
1878 goto end;
1880 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1882 else switch(offset)
1884 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1885 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1886 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1887 goto end;
1888 default:
1889 WARN_(win)("Invalid offset %d\n", offset );
1890 retval = 0;
1891 goto end;
1893 retval = *ptr;
1894 *ptr = newval;
1895 end:
1896 WIN_ReleaseWndPtr(wndPtr);
1897 return retval;
1901 /**********************************************************************
1902 * WIN_GetWindowLong
1904 * Helper function for GetWindowLong().
1906 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1908 LONG retvalue;
1909 WND * wndPtr = WIN_FindWndPtr( hwnd );
1910 if (!wndPtr) return 0;
1911 if (offset >= 0)
1913 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1915 WARN_(win)("Invalid offset %d\n", offset );
1916 retvalue = 0;
1917 goto end;
1919 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1920 /* Special case for dialog window procedure */
1921 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1923 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1924 goto end;
1926 goto end;
1928 switch(offset)
1930 case GWL_USERDATA: retvalue = wndPtr->userdata;
1931 goto end;
1932 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1933 goto end;
1934 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1935 goto end;
1936 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1937 goto end;
1938 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1939 type );
1940 goto end;
1941 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1942 goto end;
1943 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1944 goto end;
1945 default:
1946 WARN_(win)("Unknown offset %d\n", offset );
1948 retvalue = 0;
1949 end:
1950 WIN_ReleaseWndPtr(wndPtr);
1951 return retvalue;
1955 /**********************************************************************
1956 * WIN_SetWindowLong
1958 * Helper function for SetWindowLong().
1960 * 0 is the failure code. However, in the case of failure SetLastError
1961 * must be set to distinguish between a 0 return value and a failure.
1963 * FIXME: The error values for SetLastError may not be right. Can
1964 * someone check with the real thing?
1966 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1967 WINDOWPROCTYPE type )
1969 LONG *ptr, retval;
1970 WND * wndPtr = WIN_FindWndPtr( hwnd );
1971 STYLESTRUCT style;
1973 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1975 if (!wndPtr)
1977 /* Is this the right error? */
1978 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1979 return 0;
1982 if (offset >= 0)
1984 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1986 WARN_(win)("Invalid offset %d\n", offset );
1988 /* Is this the right error? */
1989 SetLastError( ERROR_OUTOFMEMORY );
1991 retval = 0;
1992 goto end;
1994 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1995 /* Special case for dialog window procedure */
1996 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1998 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1999 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2000 type, WIN_PROC_WINDOW );
2001 goto end;
2004 else switch(offset)
2006 case GWL_ID:
2007 ptr = (DWORD*)&wndPtr->wIDmenu;
2008 break;
2009 case GWL_HINSTANCE:
2010 retval = SetWindowWord( hwnd, offset, newval );
2011 goto end;
2012 case GWL_WNDPROC:
2013 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2014 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2015 type, WIN_PROC_WINDOW );
2016 goto end;;
2017 case GWL_STYLE:
2018 style.styleOld = wndPtr->dwStyle;
2019 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2020 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2022 if (wndPtr->flags & WIN_ISWIN32)
2023 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2024 wndPtr->dwStyle = style.styleNew;
2025 if (wndPtr->flags & WIN_ISWIN32)
2026 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2027 retval = style.styleOld;
2028 goto end;
2030 case GWL_USERDATA:
2031 ptr = &wndPtr->userdata;
2032 break;
2033 case GWL_EXSTYLE:
2034 style.styleOld = wndPtr->dwExStyle;
2035 style.styleNew = newval;
2036 if (wndPtr->flags & WIN_ISWIN32)
2037 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2038 wndPtr->dwExStyle = newval;
2039 if (wndPtr->flags & WIN_ISWIN32)
2040 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2041 retval = style.styleOld;
2042 goto end;
2044 default:
2045 WARN_(win)("Invalid offset %d\n", offset );
2047 /* Don't think this is right error but it should do */
2048 SetLastError( ERROR_OUTOFMEMORY );
2050 retval = 0;
2051 goto end;
2053 retval = *ptr;
2054 *ptr = newval;
2055 end:
2056 WIN_ReleaseWndPtr(wndPtr);
2057 return retval;
2061 /**********************************************************************
2062 * GetWindowLong16 (USER.135)
2064 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2066 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2070 /**********************************************************************
2071 * GetWindowLong32A (USER32.305)
2073 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2075 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2079 /**********************************************************************
2080 * GetWindowLong32W (USER32.306)
2082 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2084 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2088 /**********************************************************************
2089 * SetWindowLong16 (USER.136)
2091 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2093 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2097 /**********************************************************************
2098 * SetWindowLong32A (USER32.517)
2100 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2102 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2106 /**********************************************************************
2107 * SetWindowLong32W (USER32.518) Set window attribute
2109 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2110 * value in a window's extra memory.
2112 * The _hwnd_ parameter specifies the window. is the handle to a
2113 * window that has extra memory. The _newval_ parameter contains the
2114 * new attribute or extra memory value. If positive, the _offset_
2115 * parameter is the byte-addressed location in the window's extra
2116 * memory to set. If negative, _offset_ specifies the window
2117 * attribute to set, and should be one of the following values:
2119 * GWL_EXSTYLE The window's extended window style
2121 * GWL_STYLE The window's window style.
2123 * GWL_WNDPROC Pointer to the window's window procedure.
2125 * GWL_HINSTANCE The window's pplication instance handle.
2127 * GWL_ID The window's identifier.
2129 * GWL_USERDATA The window's user-specified data.
2131 * If the window is a dialog box, the _offset_ parameter can be one of
2132 * the following values:
2134 * DWL_DLGPROC The address of the window's dialog box procedure.
2136 * DWL_MSGRESULT The return value of a message
2137 * that the dialog box procedure processed.
2139 * DWL_USER Application specific information.
2141 * RETURNS
2143 * If successful, returns the previous value located at _offset_. Otherwise,
2144 * returns 0.
2146 * NOTES
2148 * Extra memory for a window class is specified by a nonzero cbWndExtra
2149 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2150 * time of class creation.
2152 * Using GWL_WNDPROC to set a new window procedure effectively creates
2153 * a window subclass. Use CallWindowProc() in the new windows procedure
2154 * to pass messages to the superclass's window procedure.
2156 * The user data is reserved for use by the application which created
2157 * the window.
2159 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2160 * instead, call the EnableWindow() function to change the window's
2161 * disabled state.
2163 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2164 * SetParent() instead.
2166 * Win95:
2167 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2168 * it sends WM_STYLECHANGING before changing the settings
2169 * and WM_STYLECHANGED afterwards.
2170 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2172 * BUGS
2174 * GWL_STYLE does not dispatch WM_STYLE... messages.
2176 * CONFORMANCE
2178 * ECMA-234, Win32
2181 LONG WINAPI SetWindowLongW(
2182 HWND hwnd, /* window to alter */
2183 INT offset, /* offset, in bytes, of location to alter */
2184 LONG newval /* new value of location */
2186 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2190 /*******************************************************************
2191 * GetWindowText16 (USER.36)
2193 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2195 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2199 /*******************************************************************
2200 * GetWindowText32A (USER32.309)
2202 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2204 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2205 (LPARAM)lpString );
2208 /*******************************************************************
2209 * InternalGetWindowText (USER32.326)
2211 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2213 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2214 return GetWindowTextW(hwnd,lpString,nMaxCount);
2218 /*******************************************************************
2219 * GetWindowText32W (USER32.312)
2221 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2223 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2224 (LPARAM)lpString );
2228 /*******************************************************************
2229 * SetWindowText16 (USER.37)
2231 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2233 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2237 /*******************************************************************
2238 * SetWindowText32A (USER32.521)
2240 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2242 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2246 /*******************************************************************
2247 * SetWindowText32W (USER32.523)
2249 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2251 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2255 /*******************************************************************
2256 * GetWindowTextLength16 (USER.38)
2258 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2260 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2264 /*******************************************************************
2265 * GetWindowTextLength32A (USER32.310)
2267 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2269 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2272 /*******************************************************************
2273 * GetWindowTextLength32W (USER32.311)
2275 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2277 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2281 /*******************************************************************
2282 * IsWindow16 (USER.47)
2284 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2286 CURRENT_STACK16->es = USER_HeapSel;
2287 return IsWindow( hwnd );
2291 /*******************************************************************
2292 * IsWindow32 (USER32.348)
2294 BOOL WINAPI IsWindow( HWND hwnd )
2296 WND * wndPtr;
2297 BOOL retvalue;
2299 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2300 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2301 WIN_ReleaseWndPtr(wndPtr);
2302 return retvalue;
2307 /*****************************************************************
2308 * GetParent16 (USER.46)
2310 HWND16 WINAPI GetParent16( HWND16 hwnd )
2312 return (HWND16)GetParent( hwnd );
2316 /*****************************************************************
2317 * GetParent32 (USER32.278)
2319 HWND WINAPI GetParent( HWND hwnd )
2321 WND *wndPtr;
2322 HWND retvalue;
2324 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2325 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2327 WIN_ReleaseWndPtr(wndPtr);
2328 return 0;
2330 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2331 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2333 WIN_ReleaseWndPtr(wndPtr);
2334 return retvalue;
2338 /*****************************************************************
2339 * WIN_GetTopParent
2341 * Get the top-level parent for a child window.
2342 * returns a locked pointer
2344 WND* WIN_GetTopParentPtr( WND* pWnd )
2346 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2348 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2350 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2352 return tmpWnd;
2355 /*****************************************************************
2356 * WIN_GetTopParent
2358 * Get the top-level parent for a child window.
2360 HWND WIN_GetTopParent( HWND hwnd )
2362 HWND retvalue;
2363 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2364 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2366 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2367 WIN_ReleaseWndPtr(tmpPtr);
2368 WIN_ReleaseWndPtr(wndPtr);
2369 return retvalue;
2373 /*****************************************************************
2374 * SetParent16 (USER.233)
2376 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2378 return SetParent( hwndChild, hwndNewParent );
2382 /*****************************************************************
2383 * SetParent32 (USER32.495)
2385 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2387 WND *wndPtr;
2388 DWORD dwStyle;
2389 WND *pWndNewParent;
2390 WND *pWndOldParent;
2391 HWND retvalue;
2394 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2396 dwStyle = wndPtr->dwStyle;
2398 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2399 : WIN_LockWndPtr(pWndDesktop);
2401 /* Windows hides the window first, then shows it again
2402 * including the WM_SHOWWINDOW messages and all */
2403 if (dwStyle & WS_VISIBLE)
2404 ShowWindow( hwndChild, SW_HIDE );
2406 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2408 /* SetParent32 additionally needs to make hwndChild the topmost window
2409 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2410 WM_WINDOWPOSCHANGED notification messages.
2412 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2413 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2414 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2415 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2417 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2419 WIN_ReleaseWndPtr(pWndOldParent);
2420 WIN_ReleaseWndPtr(pWndNewParent);
2421 WIN_ReleaseWndPtr(wndPtr);
2423 return retvalue;
2427 /*******************************************************************
2428 * IsChild16 (USER.48)
2430 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2432 return IsChild(parent,child);
2436 /*******************************************************************
2437 * IsChild32 (USER32.339)
2439 BOOL WINAPI IsChild( HWND parent, HWND child )
2441 WND * wndPtr = WIN_FindWndPtr( child );
2442 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2444 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2445 if (wndPtr->hwndSelf == parent)
2447 WIN_ReleaseWndPtr(wndPtr);
2448 return TRUE;
2451 WIN_ReleaseWndPtr(wndPtr);
2452 return FALSE;
2456 /***********************************************************************
2457 * IsWindowVisible16 (USER.49)
2459 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2461 return IsWindowVisible(hwnd);
2465 /***********************************************************************
2466 * IsWindowVisible32 (USER32.351)
2468 BOOL WINAPI IsWindowVisible( HWND hwnd )
2470 BOOL retval;
2471 WND *wndPtr = WIN_FindWndPtr( hwnd );
2472 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2474 if (!(wndPtr->dwStyle & WS_VISIBLE))
2476 WIN_ReleaseWndPtr(wndPtr);
2477 return FALSE;
2479 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2481 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2482 WIN_ReleaseWndPtr(wndPtr);
2483 return retval;
2488 /***********************************************************************
2489 * WIN_IsWindowDrawable
2491 * hwnd is drawable when it is visible, all parents are not
2492 * minimized, and it is itself not minimized unless we are
2493 * trying to draw its default class icon.
2495 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2497 if( (wnd->dwStyle & WS_MINIMIZE &&
2498 icon && wnd->class->hIcon) ||
2499 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2500 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2501 if( wnd->dwStyle & WS_MINIMIZE ||
2502 !(wnd->dwStyle & WS_VISIBLE) ) break;
2503 return (wnd == NULL);
2507 /*******************************************************************
2508 * GetTopWindow16 (USER.229)
2510 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2512 return GetTopWindow(hwnd);
2516 /*******************************************************************
2517 * GetTopWindow32 (USER.229)
2519 HWND WINAPI GetTopWindow( HWND hwnd )
2521 HWND retval;
2522 WND * wndPtr = NULL;
2524 if (hwnd!=0)
2525 wndPtr = WIN_FindWndPtr( hwnd );
2526 else
2527 wndPtr = WIN_GetDesktop();
2529 if (wndPtr && wndPtr->child)
2531 retval = wndPtr->child->hwndSelf;
2533 else retval = 0;
2534 WIN_ReleaseWndPtr(wndPtr);
2535 return retval;
2539 /*******************************************************************
2540 * GetWindow16 (USER.262)
2542 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2544 return GetWindow( hwnd,rel );
2548 /*******************************************************************
2549 * GetWindow32 (USER32.302)
2551 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2553 HWND retval;
2555 WND * wndPtr = WIN_FindWndPtr( hwnd );
2556 if (!wndPtr) return 0;
2557 switch(rel)
2559 case GW_HWNDFIRST:
2560 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2561 else retval = 0;
2562 goto end;
2564 case GW_HWNDLAST:
2565 if (!wndPtr->parent)
2567 retval = 0; /* Desktop window */
2568 goto end;
2570 while (wndPtr->next)
2572 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2574 retval = wndPtr->hwndSelf;
2575 goto end;
2577 case GW_HWNDNEXT:
2578 if (!wndPtr->next) retval = 0;
2579 else retval = wndPtr->next->hwndSelf;
2580 goto end;
2582 case GW_HWNDPREV:
2583 if (!wndPtr->parent)
2585 retval = 0; /* Desktop window */
2586 goto end;
2588 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2589 if (wndPtr->hwndSelf == hwnd)
2591 retval = 0; /* First in list */
2592 goto end;
2594 while (wndPtr->next)
2596 if (wndPtr->next->hwndSelf == hwnd)
2598 retval = wndPtr->hwndSelf;
2599 goto end;
2601 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2603 retval = 0;
2604 goto end;
2606 case GW_OWNER:
2607 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2608 goto end;
2610 case GW_CHILD:
2611 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2612 goto end;
2614 retval = 0;
2615 end:
2616 WIN_ReleaseWndPtr(wndPtr);
2617 return retval;
2621 /*******************************************************************
2622 * GetNextWindow16 (USER.230)
2624 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2626 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2627 return GetWindow16( hwnd, flag );
2630 /*******************************************************************
2631 * ShowOwnedPopups16 (USER.265)
2633 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2635 ShowOwnedPopups( owner, fShow );
2639 /*******************************************************************
2640 * ShowOwnedPopups32 (USER32.531)
2642 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2644 WND *pWnd;
2645 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2646 while (pWnd)
2648 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2649 (pWnd->dwStyle & WS_POPUP))
2650 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2651 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2653 return TRUE;
2657 /*******************************************************************
2658 * GetLastActivePopup16 (USER.287)
2660 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2662 return GetLastActivePopup( hwnd );
2665 /*******************************************************************
2666 * GetLastActivePopup32 (USER32.256)
2668 HWND WINAPI GetLastActivePopup( HWND hwnd )
2670 WND *wndPtr;
2671 HWND retval;
2672 wndPtr = WIN_FindWndPtr(hwnd);
2673 if (!wndPtr) return hwnd;
2674 retval = wndPtr->hwndLastActive;
2675 WIN_ReleaseWndPtr(wndPtr);
2676 return retval;
2680 /*******************************************************************
2681 * WIN_BuildWinArray
2683 * Build an array of pointers to the children of a given window.
2684 * The array must be freed with HeapFree(SystemHeap). Return NULL
2685 * when no windows are found.
2687 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2689 /* Future : this function will lock all windows associated with this array */
2691 WND **list, **ppWnd;
2692 WND *pWnd;
2693 UINT count = 0, skipOwned, skipHidden;
2694 DWORD skipFlags;
2696 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2697 skipOwned = bwaFlags & BWA_SKIPOWNED;
2698 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2699 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2701 /* First count the windows */
2703 if (!wndPtr)
2704 wndPtr = WIN_GetDesktop();
2706 pWnd = WIN_LockWndPtr(wndPtr->child);
2707 while (pWnd)
2709 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2710 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2711 count++;
2712 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2715 if( count )
2717 /* Now build the list of all windows */
2719 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2721 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2723 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2724 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2726 *ppWnd++ = pWnd;
2727 count++;
2730 WIN_ReleaseWndPtr(pWnd);
2731 *ppWnd = NULL;
2733 else count = 0;
2734 } else list = NULL;
2736 if( pTotal ) *pTotal = count;
2737 return list;
2739 /*******************************************************************
2740 * WIN_ReleaseWinArray
2742 void WIN_ReleaseWinArray(WND **wndArray)
2744 /* Future : this function will also unlock all windows associated with wndArray */
2745 HeapFree( SystemHeap, 0, wndArray );
2749 /*******************************************************************
2750 * EnumWindows16 (USER.54)
2752 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2754 WND **list, **ppWnd;
2756 /* We have to build a list of all windows first, to avoid */
2757 /* unpleasant side-effects, for instance if the callback */
2758 /* function changes the Z-order of the windows. */
2760 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2762 WIN_ReleaseDesktop();
2763 return FALSE;
2766 /* Now call the callback function for every window */
2768 for (ppWnd = list; *ppWnd; ppWnd++)
2770 LRESULT lpEnumFuncRetval;
2771 int iWndsLocks = 0;
2772 /* Make sure that the window still exists */
2773 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2775 /* To avoid any deadlocks, all the locks on the windows
2776 structures must be suspended before the control
2777 is passed to the application */
2778 iWndsLocks = WIN_SuspendWndsLock();
2779 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2780 WIN_RestoreWndsLock(iWndsLocks);
2782 if (!lpEnumFuncRetval) break;
2784 WIN_ReleaseWinArray(list);
2785 WIN_ReleaseDesktop();
2786 return TRUE;
2790 /*******************************************************************
2791 * EnumWindows32 (USER32.193)
2793 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2795 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2799 /**********************************************************************
2800 * EnumTaskWindows16 (USER.225)
2802 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2803 LPARAM lParam )
2805 WND **list, **ppWnd;
2807 /* This function is the same as EnumWindows(), */
2808 /* except for an added check on the window's task. */
2810 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2812 WIN_ReleaseDesktop();
2813 return FALSE;
2816 /* Now call the callback function for every window */
2818 for (ppWnd = list; *ppWnd; ppWnd++)
2820 LRESULT funcRetval;
2821 int iWndsLocks = 0;
2822 /* Make sure that the window still exists */
2823 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2824 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2826 /* To avoid any deadlocks, all the locks on the windows
2827 structures must be suspended before the control
2828 is passed to the application */
2829 iWndsLocks = WIN_SuspendWndsLock();
2830 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2831 WIN_RestoreWndsLock(iWndsLocks);
2833 if (!funcRetval) break;
2835 WIN_ReleaseWinArray(list);
2836 WIN_ReleaseDesktop();
2837 return TRUE;
2841 /**********************************************************************
2842 * EnumThreadWindows (USER32.190)
2844 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2846 TEB *teb = THREAD_IdToTEB(id);
2848 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2852 /**********************************************************************
2853 * WIN_EnumChildWindows
2855 * Helper function for EnumChildWindows().
2857 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2858 LPARAM lParam )
2860 WND **childList;
2861 BOOL16 ret = FALSE;
2863 for ( ; *ppWnd; ppWnd++)
2865 int iWndsLocks = 0;
2867 /* Make sure that the window still exists */
2868 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2869 /* Build children list first */
2870 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2872 /* To avoid any deadlocks, all the locks on the windows
2873 structures must be suspended before the control
2874 is passed to the application */
2875 iWndsLocks = WIN_SuspendWndsLock();
2876 ret = func( (*ppWnd)->hwndSelf, lParam );
2877 WIN_RestoreWndsLock(iWndsLocks);
2879 if (childList)
2881 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2882 WIN_ReleaseWinArray(childList);
2884 if (!ret) return FALSE;
2886 return TRUE;
2890 /**********************************************************************
2891 * EnumChildWindows16 (USER.55)
2893 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2894 LPARAM lParam )
2896 WND **list, *pParent;
2898 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2899 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2901 WIN_ReleaseWndPtr(pParent);
2902 return FALSE;
2904 WIN_EnumChildWindows( list, func, lParam );
2905 WIN_ReleaseWinArray(list);
2906 WIN_ReleaseWndPtr(pParent);
2907 return TRUE;
2911 /**********************************************************************
2912 * EnumChildWindows32 (USER32.178)
2914 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2915 LPARAM lParam )
2917 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2918 lParam );
2922 /*******************************************************************
2923 * AnyPopup16 (USER.52)
2925 BOOL16 WINAPI AnyPopup16(void)
2927 return AnyPopup();
2931 /*******************************************************************
2932 * AnyPopup32 (USER32.4)
2934 BOOL WINAPI AnyPopup(void)
2936 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2937 BOOL retvalue;
2939 while (wndPtr)
2941 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2943 retvalue = TRUE;
2944 goto end;
2946 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2948 retvalue = FALSE;
2949 end:
2950 WIN_ReleaseWndPtr(wndPtr);
2951 return retvalue;
2955 /*******************************************************************
2956 * FlashWindow16 (USER.105)
2958 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2960 return FlashWindow( hWnd, bInvert );
2964 /*******************************************************************
2965 * FlashWindow32 (USER32.202)
2967 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2969 WND *wndPtr = WIN_FindWndPtr(hWnd);
2971 TRACE_(win)("%04x\n", hWnd);
2973 if (!wndPtr) return FALSE;
2975 if (wndPtr->dwStyle & WS_MINIMIZE)
2977 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2979 HDC hDC = GetDC(hWnd);
2981 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2982 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2984 ReleaseDC( hWnd, hDC );
2985 wndPtr->flags |= WIN_NCACTIVATED;
2987 else
2989 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2990 RDW_UPDATENOW | RDW_FRAME, 0 );
2991 wndPtr->flags &= ~WIN_NCACTIVATED;
2993 WIN_ReleaseWndPtr(wndPtr);
2994 return TRUE;
2996 else
2998 WPARAM16 wparam;
2999 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3000 else wparam = (hWnd == GetActiveWindow());
3002 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3003 WIN_ReleaseWndPtr(wndPtr);
3004 return wparam;
3009 /*******************************************************************
3010 * SetSysModalWindow16 (USER.188)
3012 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3014 HWND hWndOldModal = hwndSysModal;
3015 hwndSysModal = hWnd;
3016 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3017 return hWndOldModal;
3021 /*******************************************************************
3022 * GetSysModalWindow16 (USER.52)
3024 HWND16 WINAPI GetSysModalWindow16(void)
3026 return hwndSysModal;
3030 /*******************************************************************
3031 * GetWindowContextHelpId (USER32.303)
3033 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3035 DWORD retval;
3036 WND *wnd = WIN_FindWndPtr( hwnd );
3037 if (!wnd) return 0;
3038 retval = wnd->helpContext;
3039 WIN_ReleaseWndPtr(wnd);
3040 return retval;
3044 /*******************************************************************
3045 * SetWindowContextHelpId (USER32.515)
3047 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3049 WND *wnd = WIN_FindWndPtr( hwnd );
3050 if (!wnd) return FALSE;
3051 wnd->helpContext = id;
3052 WIN_ReleaseWndPtr(wnd);
3053 return TRUE;
3057 /*******************************************************************
3058 * DRAG_QueryUpdate
3060 * recursively find a child that contains spDragInfo->pt point
3061 * and send WM_QUERYDROPOBJECT
3063 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3065 BOOL16 wParam,bResult = 0;
3066 POINT pt;
3067 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3068 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3069 RECT tempRect;
3071 if( !ptrQueryWnd || !ptrDragInfo )
3073 WIN_ReleaseWndPtr(ptrQueryWnd);
3074 return 0;
3077 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3079 GetWindowRect(hQueryWnd,&tempRect);
3081 if( !PtInRect(&tempRect,pt) ||
3082 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3084 WIN_ReleaseWndPtr(ptrQueryWnd);
3085 return 0;
3088 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3090 tempRect = ptrQueryWnd->rectClient;
3091 if(ptrQueryWnd->dwStyle & WS_CHILD)
3092 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3093 (LPPOINT)&tempRect, 2 );
3095 if (PtInRect( &tempRect, pt))
3097 wParam = 0;
3099 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3101 if( ptrWnd->dwStyle & WS_VISIBLE )
3103 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3104 if (PtInRect( &tempRect, pt )) break;
3108 if(ptrWnd)
3110 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3111 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3112 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3113 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3114 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3116 WIN_ReleaseWndPtr(ptrWnd);
3119 if(bResult)
3121 WIN_ReleaseWndPtr(ptrQueryWnd);
3122 return bResult;
3125 else wParam = 1;
3127 else wParam = 1;
3129 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3131 ptrDragInfo->hScope = hQueryWnd;
3133 bResult = ( bNoSend )
3134 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3135 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3136 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3137 if( !bResult )
3138 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3140 WIN_ReleaseWndPtr(ptrQueryWnd);
3141 return bResult;
3145 /*******************************************************************
3146 * DragDetect (USER.465)
3148 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3150 POINT pt32;
3151 CONV_POINT16TO32( &pt, &pt32 );
3152 return DragDetect( hWnd, pt32 );
3155 /*******************************************************************
3156 * DragDetect32 (USER32.151)
3158 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3160 MSG16 msg;
3161 RECT16 rect;
3163 rect.left = pt.x - wDragWidth;
3164 rect.right = pt.x + wDragWidth;
3166 rect.top = pt.y - wDragHeight;
3167 rect.bottom = pt.y + wDragHeight;
3169 SetCapture(hWnd);
3171 while(1)
3173 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3175 if( msg.message == WM_LBUTTONUP )
3177 ReleaseCapture();
3178 return 0;
3180 if( msg.message == WM_MOUSEMOVE )
3182 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3184 ReleaseCapture();
3185 return 1;
3189 WaitMessage();
3191 return 0;
3194 /******************************************************************************
3195 * DragObject16 (USER.464)
3197 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3198 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3200 MSG16 msg;
3201 LPDRAGINFO lpDragInfo;
3202 SEGPTR spDragInfo;
3203 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3204 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3205 WND *wndPtr = WIN_FindWndPtr(hWnd);
3206 HCURSOR16 hCurrentCursor = 0;
3207 HWND16 hCurrentWnd = 0;
3209 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3210 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3212 if( !lpDragInfo || !spDragInfo )
3214 WIN_ReleaseWndPtr(wndPtr);
3215 return 0L;
3218 hBummer = LoadCursor16(0, IDC_BUMMER16);
3220 if( !hBummer || !wndPtr )
3222 GlobalFree16(hDragInfo);
3223 WIN_ReleaseWndPtr(wndPtr);
3224 return 0L;
3227 if(hCursor)
3229 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3231 GlobalFree16(hDragInfo);
3232 WIN_ReleaseWndPtr(wndPtr);
3233 return 0L;
3236 if( hDragCursor == hCursor ) hDragCursor = 0;
3237 else hCursor = hDragCursor;
3239 hOldCursor = SetCursor(hDragCursor);
3242 lpDragInfo->hWnd = hWnd;
3243 lpDragInfo->hScope = 0;
3244 lpDragInfo->wFlags = wObj;
3245 lpDragInfo->hList = szList; /* near pointer! */
3246 lpDragInfo->hOfStruct = hOfStruct;
3247 lpDragInfo->l = 0L;
3249 SetCapture(hWnd);
3250 ShowCursor( TRUE );
3254 do{ WaitMessage(); }
3255 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3257 *(lpDragInfo+1) = *lpDragInfo;
3259 lpDragInfo->pt = msg.pt;
3261 /* update DRAGINFO struct */
3262 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3264 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3265 hCurrentCursor = hCursor;
3266 else
3268 hCurrentCursor = hBummer;
3269 lpDragInfo->hScope = 0;
3271 if( hCurrentCursor )
3272 SetCursor(hCurrentCursor);
3274 /* send WM_DRAGLOOP */
3275 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3276 (LPARAM) spDragInfo );
3277 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3278 if( hCurrentWnd != lpDragInfo->hScope )
3280 if( hCurrentWnd )
3281 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3282 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3283 HIWORD(spDragInfo)) );
3284 hCurrentWnd = lpDragInfo->hScope;
3285 if( hCurrentWnd )
3286 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3288 else
3289 if( hCurrentWnd )
3290 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3292 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3294 ReleaseCapture();
3295 ShowCursor( FALSE );
3297 if( hCursor )
3299 SetCursor( hOldCursor );
3300 if (hDragCursor) DestroyCursor( hDragCursor );
3303 if( hCurrentCursor != hBummer )
3304 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3305 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3306 else
3307 msg.lParam = 0;
3308 GlobalFree16(hDragInfo);
3309 WIN_ReleaseWndPtr(wndPtr);
3311 return (DWORD)(msg.lParam);