Overlay indices are signed shorts (-1 means no overlay)
[wine/testsucceed.git] / windows / win.c
blobbe2f0c05d821a481afd62ab6e588e3d85a4dc92c
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 DEFAULT_DEBUG_CHANNEL(win)
38 DECLARE_DEBUG_CHANNEL(msg)
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("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("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("%04x is not a window handle\n", hwnd );
224 return;
227 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
228 strcpy( className, "#NULL#" );
230 TRACE("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("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("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("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("%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("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);
667 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
668 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
669 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
670 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
671 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
673 /* Find the parent window */
675 if (cs->hwndParent)
677 /* Make sure parent is valid */
678 if (!IsWindow( cs->hwndParent ))
680 WARN("Bad parent %04x\n", cs->hwndParent );
681 return 0;
683 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
684 WARN("No parent for child window\n" );
685 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
688 /* Find the window class */
689 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
691 char buffer[256];
692 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
693 WARN("Bad class '%s'\n", buffer );
694 return 0;
697 /* Fix the coordinates */
699 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
701 PDB *pdb = PROCESS_Current();
703 /* Never believe Microsoft's documentation... CreateWindowEx doc says
704 * that if an overlapped window is created with WS_VISIBLE style bit
705 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
706 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
707 * reveals that
709 * 1) not only if checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
710 * 2) it does not ignore the y parameter as the docs claim; instead, it
711 * uses it as second parameter to ShowWindow() unless y is either
712 * CW_USEDEFAULT or CW_USEDEFAULT16.
714 * The fact that we didn't do 2) caused bogus windows pop up when wine
715 * was running apps that were using this obscure feature. Example -
716 * calc.exe that comes with Win98 (only Win98, it's different from
717 * the one that comes with Win95 and NT)
719 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) sw = cs->y;
721 /* We have saved cs->y, now we can trash it */
722 if ( !(cs->style & (WS_CHILD | WS_POPUP))
723 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
725 cs->x = pdb->env_db->startup_info->dwX;
726 cs->y = pdb->env_db->startup_info->dwY;
728 else
730 cs->x = 0;
731 cs->y = 0;
734 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
736 PDB *pdb = PROCESS_Current();
737 if ( !(cs->style & (WS_CHILD | WS_POPUP))
738 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
740 cs->cx = pdb->env_db->startup_info->dwXSize;
741 cs->cy = pdb->env_db->startup_info->dwYSize;
743 else
745 cs->cx = 600; /* FIXME */
746 cs->cy = 400;
750 /* Create the window structure */
752 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
753 - sizeof(wndPtr->wExtra) )))
755 TRACE("out of memory\n" );
756 return 0;
759 /* Fill the window structure */
761 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
762 wndPtr->next = NULL;
763 wndPtr->child = NULL;
765 if ((cs->style & WS_CHILD) && cs->hwndParent)
767 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
768 wndPtr->owner = NULL;
769 WIN_ReleaseWndPtr(wndPtr->parent);
771 else
773 wndPtr->parent = pWndDesktop;
774 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
775 wndPtr->owner = NULL;
776 else
778 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
779 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
780 WIN_ReleaseWndPtr(wndPtr->owner);
781 WIN_ReleaseWndPtr(tmpWnd);
786 wndPtr->pDriver = wndPtr->parent->pDriver;
787 wndPtr->pDriver->pInitialize(wndPtr);
789 wndPtr->class = classPtr;
790 wndPtr->winproc = classPtr->winproc;
791 wndPtr->dwMagic = WND_MAGIC;
792 wndPtr->hwndSelf = hwnd;
793 wndPtr->hInstance = cs->hInstance;
794 wndPtr->text = NULL;
795 wndPtr->hmemTaskQ = GetFastQueue16();
796 wndPtr->hrgnUpdate = 0;
797 wndPtr->hwndLastActive = hwnd;
798 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
799 wndPtr->dwExStyle = cs->dwExStyle;
800 wndPtr->wIDmenu = 0;
801 wndPtr->helpContext = 0;
802 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
803 wndPtr->pVScroll = NULL;
804 wndPtr->pHScroll = NULL;
805 wndPtr->pProp = NULL;
806 wndPtr->userdata = 0;
807 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
808 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
809 wndPtr->irefCount = 1;
811 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
813 /* Call the WH_CBT hook */
815 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
816 ? HWND_BOTTOM : HWND_TOP;
818 if (HOOK_IsHooked( WH_CBT ))
820 CBT_CREATEWNDA cbtc;
821 LRESULT ret;
823 cbtc.lpcs = cs;
824 cbtc.hwndInsertAfter = hwndLinkAfter;
825 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
826 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
827 if (ret)
829 TRACE("CBT-hook returned 0\n");
830 wndPtr->pDriver->pFinalize(wndPtr);
831 USER_HEAP_FREE( hwnd );
832 retvalue = 0;
833 goto end;
837 /* Increment class window counter */
839 classPtr->cWindows++;
841 /* Correct the window style */
843 if (!(cs->style & WS_CHILD))
845 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
846 if (!(cs->style & WS_POPUP))
848 wndPtr->dwStyle |= WS_CAPTION;
849 wndPtr->flags |= WIN_NEED_SIZE;
853 /* Get class or window DC if needed */
855 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
856 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
857 else wndPtr->dce = NULL;
859 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
861 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
863 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
864 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
865 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
866 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
867 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
870 if(cs->style & WS_CHILD)
872 if(cs->cx < 0) cs->cx = 0;
873 if(cs->cy < 0) cs->cy = 0;
875 else
877 if (cs->cx <= 0) cs->cx = 1;
878 if (cs->cy <= 0) cs->cy = 1;
881 wndPtr->rectWindow.left = cs->x;
882 wndPtr->rectWindow.top = cs->y;
883 wndPtr->rectWindow.right = cs->x + cs->cx;
884 wndPtr->rectWindow.bottom = cs->y + cs->cy;
885 wndPtr->rectClient = wndPtr->rectWindow;
887 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
889 retvalue = FALSE;
890 goto end;
893 /* Set the window menu */
895 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
897 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
898 else
900 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
901 if (classPtr->menuNameA)
902 cs->hMenu = HIWORD(classPtr->menuNameA) ?
903 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
904 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
905 #else
906 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
907 if (menuName)
909 if (HIWORD(cs->hInstance))
910 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
911 else
912 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
914 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
916 #endif
919 else wndPtr->wIDmenu = (UINT)cs->hMenu;
921 /* Send the WM_CREATE message
922 * Perhaps we shouldn't allow width/height changes as well.
923 * See p327 in "Internals".
926 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
928 localSend32 = unicode ? SendMessageW : SendMessageA;
929 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
931 /* Insert the window in the linked list */
933 WIN_LinkWindow( hwnd, hwndLinkAfter );
935 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
936 NULL, NULL, 0, &wndPtr->rectClient );
937 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
938 maxPos.y - wndPtr->rectWindow.top);
939 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
941 /* Send the size messages */
943 if (!(wndPtr->flags & WIN_NEED_SIZE))
945 /* send it anyway */
946 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
947 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
948 WARN("sending bogus WM_SIZE message 0x%08lx\n",
949 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
950 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
951 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
952 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
953 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
954 SendMessageA( hwnd, WM_MOVE, 0,
955 MAKELONG( wndPtr->rectClient.left,
956 wndPtr->rectClient.top ) );
959 /* Show the window, maximizing or minimizing if needed */
961 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
963 RECT16 newPos;
964 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
965 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
966 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
967 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
968 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
969 : SWP_NOZORDER | SWP_FRAMECHANGED;
970 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
971 newPos.right, newPos.bottom, swFlag );
974 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
976 /* Notify the parent window only */
978 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
979 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
980 if( !IsWindow(hwnd) )
982 retvalue = 0;
983 goto end;
987 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, sw );
989 /* Call WH_SHELL hook */
991 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
992 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
994 TRACE("created window %04x\n", hwnd);
995 retvalue = hwnd;
996 goto end;
998 WIN_UnlinkWindow( hwnd );
1001 /* Abort window creation */
1003 WARN("aborted by WM_xxCREATE!\n");
1004 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1005 retvalue = 0;
1006 end:
1007 WIN_ReleaseWndPtr(wndPtr);
1009 return retvalue;
1013 /***********************************************************************
1014 * CreateWindow16 (USER.41)
1016 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1017 DWORD style, INT16 x, INT16 y, INT16 width,
1018 INT16 height, HWND16 parent, HMENU16 menu,
1019 HINSTANCE16 instance, LPVOID data )
1021 return CreateWindowEx16( 0, className, windowName, style,
1022 x, y, width, height, parent, menu, instance, data );
1026 /***********************************************************************
1027 * CreateWindowEx16 (USER.452)
1029 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1030 LPCSTR windowName, DWORD style, INT16 x,
1031 INT16 y, INT16 width, INT16 height,
1032 HWND16 parent, HMENU16 menu,
1033 HINSTANCE16 instance, LPVOID data )
1035 ATOM classAtom;
1036 CREATESTRUCTA cs;
1037 char buffer[256];
1039 /* Find the class atom */
1041 if (!(classAtom = GlobalFindAtomA( className )))
1043 fprintf( stderr, "CreateWindowEx16: bad class name " );
1044 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1045 else fprintf( stderr, "'%s'\n", className );
1046 return 0;
1049 /* Fix the coordinates */
1051 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1052 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1053 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1054 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1056 /* Create the window */
1058 cs.lpCreateParams = data;
1059 cs.hInstance = (HINSTANCE)instance;
1060 cs.hMenu = (HMENU)menu;
1061 cs.hwndParent = (HWND)parent;
1062 cs.style = style;
1063 cs.lpszName = windowName;
1064 cs.lpszClass = className;
1065 cs.dwExStyle = exStyle;
1067 /* make sure lpszClass is a string */
1068 if (!HIWORD(cs.lpszClass))
1070 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
1071 cs.lpszClass = buffer;
1073 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1077 /***********************************************************************
1078 * CreateWindowEx32A (USER32.83)
1080 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1081 LPCSTR windowName, DWORD style, INT x,
1082 INT y, INT width, INT height,
1083 HWND parent, HMENU menu,
1084 HINSTANCE instance, LPVOID data )
1086 ATOM classAtom;
1087 CREATESTRUCTA cs;
1088 char buffer[256];
1090 if(!instance)
1091 instance=GetModuleHandleA(NULL);
1093 if(exStyle & WS_EX_MDICHILD)
1094 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1095 /* Find the class atom */
1097 if (!(classAtom = GlobalFindAtomA( className )))
1099 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1100 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1101 else fprintf( stderr, "'%s'\n", className );
1102 return 0;
1105 /* Create the window */
1107 cs.lpCreateParams = data;
1108 cs.hInstance = instance;
1109 cs.hMenu = menu;
1110 cs.hwndParent = parent;
1111 cs.x = x;
1112 cs.y = y;
1113 cs.cx = width;
1114 cs.cy = height;
1115 cs.style = style;
1116 cs.lpszName = windowName;
1117 cs.lpszClass = className;
1118 cs.dwExStyle = exStyle;
1120 /* make sure lpszClass is a string */
1121 if (!HIWORD(cs.lpszClass))
1123 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
1124 cs.lpszClass = buffer;
1126 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1130 /***********************************************************************
1131 * CreateWindowEx32W (USER32.84)
1133 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1134 LPCWSTR windowName, DWORD style, INT x,
1135 INT y, INT width, INT height,
1136 HWND parent, HMENU menu,
1137 HINSTANCE instance, LPVOID data )
1139 ATOM classAtom;
1140 CREATESTRUCTW cs;
1141 WCHAR buffer[256];
1143 if(!instance)
1144 instance=GetModuleHandleA(NULL);
1146 if(exStyle & WS_EX_MDICHILD)
1147 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1149 /* Find the class atom */
1151 if (!(classAtom = GlobalFindAtomW( className )))
1153 if (HIWORD(className))
1155 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1156 WARN("Bad class name '%s'\n",cn);
1157 HeapFree( GetProcessHeap(), 0, cn );
1159 else
1160 WARN("Bad class name %p\n", className );
1161 return 0;
1164 /* Create the window */
1166 cs.lpCreateParams = data;
1167 cs.hInstance = instance;
1168 cs.hMenu = menu;
1169 cs.hwndParent = parent;
1170 cs.x = x;
1171 cs.y = y;
1172 cs.cx = width;
1173 cs.cy = height;
1174 cs.style = style;
1175 cs.lpszName = windowName;
1176 cs.lpszClass = className;
1177 cs.dwExStyle = exStyle;
1179 /* make sure lpszClass is a string */
1180 if (!HIWORD(cs.lpszClass))
1182 GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) );
1183 cs.lpszClass = buffer;
1186 /* Note: we rely on the fact that CREATESTRUCT32A and */
1187 /* CREATESTRUCT32W have the same layout. */
1188 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1192 /***********************************************************************
1193 * WIN_CheckFocus
1195 static void WIN_CheckFocus( WND* pWnd )
1197 if( GetFocus16() == pWnd->hwndSelf )
1198 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1201 /***********************************************************************
1202 * WIN_SendDestroyMsg
1204 static void WIN_SendDestroyMsg( WND* pWnd )
1206 WIN_CheckFocus(pWnd);
1208 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1209 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1212 * Send the WM_DESTROY to the window.
1214 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1217 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1218 * make sure that the window still exists when we come back.
1220 if (IsWindow(pWnd->hwndSelf))
1222 HWND* pWndArray = NULL;
1223 WND* pChild = NULL;
1224 int nKidCount = 0;
1227 * Now, if the window has kids, we have to send WM_DESTROY messages
1228 * recursively to it's kids. It seems that those calls can also
1229 * trigger re-entrant calls to DestroyWindow for the kids so we must
1230 * protect against corruption of the list of siblings. We first build
1231 * a list of HWNDs representing all the kids.
1233 pChild = WIN_LockWndPtr(pWnd->child);
1234 while( pChild )
1236 nKidCount++;
1237 WIN_UpdateWndPtr(&pChild,pChild->next);
1241 * If there are no kids, we're done.
1243 if (nKidCount==0)
1244 return;
1246 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1249 * Sanity check
1251 if (pWndArray==NULL)
1252 return;
1255 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1256 * call, our linked list of siblings should be safe.
1258 nKidCount = 0;
1259 pChild = WIN_LockWndPtr(pWnd->child);
1260 while( pChild )
1262 pWndArray[nKidCount] = pChild->hwndSelf;
1263 nKidCount++;
1264 WIN_UpdateWndPtr(&pChild,pChild->next);
1268 * Now that we have a list, go through that list again and send the destroy
1269 * message to those windows. We are using the HWND to retrieve the
1270 * WND pointer so we are effectively checking that all the kid windows are
1271 * still valid before sending the message.
1273 while (nKidCount>0)
1275 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1277 if (pChild!=NULL)
1279 WIN_SendDestroyMsg( pChild );
1280 WIN_ReleaseWndPtr(pChild);
1285 * Cleanup
1287 HeapFree(GetProcessHeap(), 0, pWndArray);
1288 WIN_CheckFocus(pWnd);
1290 else
1291 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1295 /***********************************************************************
1296 * DestroyWindow16 (USER.53)
1298 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1300 return DestroyWindow(hwnd);
1304 /***********************************************************************
1305 * DestroyWindow32 (USER32.135)
1307 BOOL WINAPI DestroyWindow( HWND hwnd )
1309 WND * wndPtr;
1310 BOOL retvalue;
1312 TRACE("(%04x)\n", hwnd);
1314 /* Initialization */
1316 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1317 if (wndPtr == pWndDesktop)
1319 WIN_ReleaseWndPtr(wndPtr);
1320 return FALSE; /* Can't destroy desktop */
1323 /* Call hooks */
1325 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1327 retvalue = FALSE;
1328 goto end;
1331 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1333 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1334 /* FIXME: clean up palette - see "Internals" p.352 */
1337 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1338 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1340 /* Notify the parent window only */
1341 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1342 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1343 if( !IsWindow(hwnd) )
1345 retvalue = TRUE;
1346 goto end;
1350 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1352 /* Hide the window */
1354 if (wndPtr->dwStyle & WS_VISIBLE)
1356 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1357 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1358 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1359 if (!IsWindow(hwnd))
1361 retvalue = TRUE;
1362 goto end;
1366 /* Recursively destroy owned windows */
1368 if( !(wndPtr->dwStyle & WS_CHILD) )
1370 /* make sure top menu popup doesn't get destroyed */
1371 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1373 for (;;)
1375 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1376 while (siblingPtr)
1378 if (siblingPtr->owner == wndPtr)
1380 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1381 break;
1382 else
1383 siblingPtr->owner = NULL;
1385 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1387 if (siblingPtr)
1389 DestroyWindow( siblingPtr->hwndSelf );
1390 WIN_ReleaseWndPtr(siblingPtr);
1392 else break;
1395 if( !Options.managed || EVENT_CheckFocus() )
1396 WINPOS_ActivateOtherWindow(wndPtr);
1398 if( wndPtr->owner &&
1399 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1400 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1403 /* Send destroy messages */
1405 WIN_SendDestroyMsg( wndPtr );
1406 if (!IsWindow(hwnd))
1408 retvalue = TRUE;
1409 goto end;
1412 /* Unlink now so we won't bother with the children later on */
1414 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1416 /* Destroy the window storage */
1418 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1419 retvalue = TRUE;
1420 end:
1421 WIN_ReleaseWndPtr(wndPtr);
1422 return retvalue;
1426 /***********************************************************************
1427 * CloseWindow16 (USER.43)
1429 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1431 return CloseWindow( hwnd );
1435 /***********************************************************************
1436 * CloseWindow32 (USER32.56)
1438 BOOL WINAPI CloseWindow( HWND hwnd )
1440 WND * wndPtr = WIN_FindWndPtr( hwnd );
1441 BOOL retvalue;
1443 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1445 retvalue = FALSE;
1446 goto end;
1448 ShowWindow( hwnd, SW_MINIMIZE );
1449 retvalue = TRUE;
1450 end:
1451 WIN_ReleaseWndPtr(wndPtr);
1452 return retvalue;
1457 /***********************************************************************
1458 * OpenIcon16 (USER.44)
1460 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1462 return OpenIcon( hwnd );
1466 /***********************************************************************
1467 * OpenIcon32 (USER32.410)
1469 BOOL WINAPI OpenIcon( HWND hwnd )
1471 if (!IsIconic( hwnd )) return FALSE;
1472 ShowWindow( hwnd, SW_SHOWNORMAL );
1473 return TRUE;
1477 /***********************************************************************
1478 * WIN_FindWindow
1480 * Implementation of FindWindow() and FindWindowEx().
1482 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1483 LPCSTR title )
1485 WND *pWnd;
1486 HWND retvalue;
1487 CLASS *pClass = NULL;
1489 if (child)
1491 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1492 if (parent)
1494 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1496 retvalue = 0;
1497 goto end;
1500 else if (pWnd->parent != pWndDesktop)
1502 retvalue = 0;
1503 goto end;
1505 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1507 else
1509 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1511 retvalue = 0;
1512 goto end;
1514 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1516 if (!pWnd)
1518 retvalue = 0;
1519 goto end;
1522 /* For a child window, all siblings will have the same hInstance, */
1523 /* so we can look for the class once and for all. */
1525 if (className && (pWnd->dwStyle & WS_CHILD))
1527 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1529 retvalue = 0;
1530 goto end;
1535 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1537 if (className && !(pWnd->dwStyle & WS_CHILD))
1539 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1540 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1542 continue; /* Skip this window */
1545 if (pClass && (pWnd->class != pClass))
1546 continue; /* Not the right class */
1548 /* Now check the title */
1550 if (!title)
1552 retvalue = pWnd->hwndSelf;
1553 goto end;
1555 if (pWnd->text && !strcmp( pWnd->text, title ))
1557 retvalue = pWnd->hwndSelf;
1558 goto end;
1561 retvalue = 0;
1562 end:
1563 WIN_ReleaseWndPtr(pWnd);
1564 return retvalue;
1569 /***********************************************************************
1570 * FindWindow16 (USER.50)
1572 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1574 return FindWindowEx16( 0, 0, className, title );
1578 /***********************************************************************
1579 * FindWindowEx16 (USER.427)
1581 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1582 SEGPTR className, LPCSTR title )
1584 ATOM atom = 0;
1586 TRACE("%04x %04x '%s' '%s'\n", parent,
1587 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1588 title ? title : "");
1590 if (className)
1592 /* If the atom doesn't exist, then no class */
1593 /* with this name exists either. */
1594 if (!(atom = GlobalFindAtom16( className ))) return 0;
1596 return WIN_FindWindow( parent, child, atom, title );
1600 /***********************************************************************
1601 * FindWindow32A (USER32.198)
1603 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1605 HWND ret = FindWindowExA( 0, 0, className, title );
1606 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1607 return ret;
1611 /***********************************************************************
1612 * FindWindowEx32A (USER32.199)
1614 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1615 LPCSTR className, LPCSTR title )
1617 ATOM atom = 0;
1619 if (className)
1621 /* If the atom doesn't exist, then no class */
1622 /* with this name exists either. */
1623 if (!(atom = GlobalFindAtomA( className )))
1625 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1626 return 0;
1629 return WIN_FindWindow( parent, child, atom, title );
1633 /***********************************************************************
1634 * FindWindowEx32W (USER32.200)
1636 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1637 LPCWSTR className, LPCWSTR title )
1639 ATOM atom = 0;
1640 char *buffer;
1641 HWND hwnd;
1643 if (className)
1645 /* If the atom doesn't exist, then no class */
1646 /* with this name exists either. */
1647 if (!(atom = GlobalFindAtomW( className )))
1649 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1650 return 0;
1653 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1654 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1655 HeapFree( GetProcessHeap(), 0, buffer );
1656 return hwnd;
1660 /***********************************************************************
1661 * FindWindow32W (USER32.201)
1663 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1665 return FindWindowExW( 0, 0, className, title );
1669 /**********************************************************************
1670 * WIN_GetDesktop
1671 * returns a locked pointer
1673 WND *WIN_GetDesktop(void)
1675 return WIN_LockWndPtr(pWndDesktop);
1677 /**********************************************************************
1678 * WIN_ReleaseDesktop
1679 * unlock the desktop pointer
1681 void WIN_ReleaseDesktop(void)
1683 WIN_ReleaseWndPtr(pWndDesktop);
1687 /**********************************************************************
1688 * GetDesktopWindow16 (USER.286)
1690 HWND16 WINAPI GetDesktopWindow16(void)
1692 return (HWND16)pWndDesktop->hwndSelf;
1696 /**********************************************************************
1697 * GetDesktopWindow32 (USER32.232)
1699 HWND WINAPI GetDesktopWindow(void)
1701 if (pWndDesktop) return pWndDesktop->hwndSelf;
1702 ERR( "You need the -desktop option when running with native USER\n" );
1703 ExitProcess(1);
1704 return 0;
1708 /**********************************************************************
1709 * GetDesktopHwnd (USER.278)
1711 * Exactly the same thing as GetDesktopWindow(), but not documented.
1712 * Don't ask me why...
1714 HWND16 WINAPI GetDesktopHwnd16(void)
1716 return (HWND16)pWndDesktop->hwndSelf;
1720 /*******************************************************************
1721 * EnableWindow16 (USER.34)
1723 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1725 return EnableWindow( hwnd, enable );
1729 /*******************************************************************
1730 * EnableWindow32 (USER32.172)
1732 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1734 WND *wndPtr;
1735 BOOL retvalue;
1737 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1739 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1740 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1742 /* Enable window */
1743 wndPtr->dwStyle &= ~WS_DISABLED;
1745 if( wndPtr->flags & WIN_NATIVE )
1746 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1748 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1749 retvalue = TRUE;
1750 goto end;
1752 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1754 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1756 /* Disable window */
1757 wndPtr->dwStyle |= WS_DISABLED;
1759 if( wndPtr->flags & WIN_NATIVE )
1760 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1762 if (hwnd == GetFocus())
1764 SetFocus( 0 ); /* A disabled window can't have the focus */
1766 if (hwnd == GetCapture())
1768 ReleaseCapture(); /* A disabled window can't capture the mouse */
1770 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1771 retvalue = FALSE;
1772 goto end;
1774 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1775 end:
1776 WIN_ReleaseWndPtr(wndPtr);
1777 return retvalue;
1781 /***********************************************************************
1782 * IsWindowEnabled16 (USER.35)
1784 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1786 return IsWindowEnabled(hWnd);
1790 /***********************************************************************
1791 * IsWindowEnabled32 (USER32.349)
1793 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1795 WND * wndPtr;
1796 BOOL retvalue;
1798 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1799 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1800 WIN_ReleaseWndPtr(wndPtr);
1801 return retvalue;
1806 /***********************************************************************
1807 * IsWindowUnicode (USER32.350)
1809 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1811 WND * wndPtr;
1812 BOOL retvalue;
1814 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1815 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1816 WIN_ReleaseWndPtr(wndPtr);
1817 return retvalue;
1821 /**********************************************************************
1822 * GetWindowWord16 (USER.133)
1824 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1826 return GetWindowWord( hwnd, offset );
1830 /**********************************************************************
1831 * GetWindowWord32 (USER32.314)
1833 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1835 WORD retvalue;
1836 WND * wndPtr = WIN_FindWndPtr( hwnd );
1837 if (!wndPtr) return 0;
1838 if (offset >= 0)
1840 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1842 WARN("Invalid offset %d\n", offset );
1843 retvalue = 0;
1844 goto end;
1846 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1847 goto end;
1849 switch(offset)
1851 case GWW_ID:
1852 if (HIWORD(wndPtr->wIDmenu))
1853 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1854 wndPtr->wIDmenu);
1855 retvalue = (WORD)wndPtr->wIDmenu;
1856 goto end;
1857 case GWW_HWNDPARENT:
1858 retvalue = GetParent(hwnd);
1859 goto end;
1860 case GWW_HINSTANCE:
1861 if (HIWORD(wndPtr->hInstance))
1862 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1863 wndPtr->hInstance);
1864 retvalue = (WORD)wndPtr->hInstance;
1865 goto end;
1866 default:
1867 WARN("Invalid offset %d\n", offset );
1868 retvalue = 0;
1869 goto end;
1871 end:
1872 WIN_ReleaseWndPtr(wndPtr);
1873 return retvalue;
1876 /**********************************************************************
1877 * SetWindowWord16 (USER.134)
1879 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1881 return SetWindowWord( hwnd, offset, newval );
1885 /**********************************************************************
1886 * SetWindowWord32 (USER32.524)
1888 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1890 WORD *ptr, retval;
1891 WND * wndPtr = WIN_FindWndPtr( hwnd );
1892 if (!wndPtr) return 0;
1893 if (offset >= 0)
1895 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1897 WARN("Invalid offset %d\n", offset );
1898 retval = 0;
1899 goto end;
1901 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1903 else switch(offset)
1905 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1906 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1907 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1908 goto end;
1909 default:
1910 WARN("Invalid offset %d\n", offset );
1911 retval = 0;
1912 goto end;
1914 retval = *ptr;
1915 *ptr = newval;
1916 end:
1917 WIN_ReleaseWndPtr(wndPtr);
1918 return retval;
1922 /**********************************************************************
1923 * WIN_GetWindowLong
1925 * Helper function for GetWindowLong().
1927 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1929 LONG retvalue;
1930 WND * wndPtr = WIN_FindWndPtr( hwnd );
1931 if (!wndPtr) return 0;
1932 if (offset >= 0)
1934 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1936 WARN("Invalid offset %d\n", offset );
1937 retvalue = 0;
1938 goto end;
1940 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1941 /* Special case for dialog window procedure */
1942 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1944 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1945 goto end;
1947 goto end;
1949 switch(offset)
1951 case GWL_USERDATA: retvalue = wndPtr->userdata;
1952 goto end;
1953 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1954 goto end;
1955 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1956 goto end;
1957 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1958 goto end;
1959 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1960 type );
1961 goto end;
1962 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1963 goto end;
1964 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1965 goto end;
1966 default:
1967 WARN("Unknown offset %d\n", offset );
1969 retvalue = 0;
1970 end:
1971 WIN_ReleaseWndPtr(wndPtr);
1972 return retvalue;
1976 /**********************************************************************
1977 * WIN_SetWindowLong
1979 * Helper function for SetWindowLong().
1981 * 0 is the failure code. However, in the case of failure SetLastError
1982 * must be set to distinguish between a 0 return value and a failure.
1984 * FIXME: The error values for SetLastError may not be right. Can
1985 * someone check with the real thing?
1987 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1988 WINDOWPROCTYPE type )
1990 LONG *ptr, retval;
1991 WND * wndPtr = WIN_FindWndPtr( hwnd );
1992 STYLESTRUCT style;
1994 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1996 if (!wndPtr)
1998 /* Is this the right error? */
1999 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2000 return 0;
2003 if (offset >= 0)
2005 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2007 WARN("Invalid offset %d\n", offset );
2009 /* Is this the right error? */
2010 SetLastError( ERROR_OUTOFMEMORY );
2012 retval = 0;
2013 goto end;
2015 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2016 /* Special case for dialog window procedure */
2017 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2019 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2020 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2021 type, WIN_PROC_WINDOW );
2022 goto end;
2025 else switch(offset)
2027 case GWL_ID:
2028 ptr = (DWORD*)&wndPtr->wIDmenu;
2029 break;
2030 case GWL_HINSTANCE:
2031 retval = SetWindowWord( hwnd, offset, newval );
2032 goto end;
2033 case GWL_WNDPROC:
2034 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2035 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2036 type, WIN_PROC_WINDOW );
2037 goto end;;
2038 case GWL_STYLE:
2039 style.styleOld = wndPtr->dwStyle;
2040 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2041 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2043 if (wndPtr->flags & WIN_ISWIN32)
2044 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2045 wndPtr->dwStyle = style.styleNew;
2046 if (wndPtr->flags & WIN_ISWIN32)
2047 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2048 retval = style.styleOld;
2049 goto end;
2051 case GWL_USERDATA:
2052 ptr = &wndPtr->userdata;
2053 break;
2054 case GWL_EXSTYLE:
2055 style.styleOld = wndPtr->dwExStyle;
2056 style.styleNew = newval;
2057 if (wndPtr->flags & WIN_ISWIN32)
2058 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2059 wndPtr->dwExStyle = newval;
2060 if (wndPtr->flags & WIN_ISWIN32)
2061 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2062 retval = style.styleOld;
2063 goto end;
2065 default:
2066 WARN("Invalid offset %d\n", offset );
2068 /* Don't think this is right error but it should do */
2069 SetLastError( ERROR_OUTOFMEMORY );
2071 retval = 0;
2072 goto end;
2074 retval = *ptr;
2075 *ptr = newval;
2076 end:
2077 WIN_ReleaseWndPtr(wndPtr);
2078 return retval;
2082 /**********************************************************************
2083 * GetWindowLong16 (USER.135)
2085 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2087 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2091 /**********************************************************************
2092 * GetWindowLong32A (USER32.305)
2094 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2096 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2100 /**********************************************************************
2101 * GetWindowLong32W (USER32.306)
2103 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2105 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2109 /**********************************************************************
2110 * SetWindowLong16 (USER.136)
2112 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2114 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2118 /**********************************************************************
2119 * SetWindowLong32A (USER32.517)
2121 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2123 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2127 /**********************************************************************
2128 * SetWindowLong32W (USER32.518) Set window attribute
2130 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2131 * value in a window's extra memory.
2133 * The _hwnd_ parameter specifies the window. is the handle to a
2134 * window that has extra memory. The _newval_ parameter contains the
2135 * new attribute or extra memory value. If positive, the _offset_
2136 * parameter is the byte-addressed location in the window's extra
2137 * memory to set. If negative, _offset_ specifies the window
2138 * attribute to set, and should be one of the following values:
2140 * GWL_EXSTYLE The window's extended window style
2142 * GWL_STYLE The window's window style.
2144 * GWL_WNDPROC Pointer to the window's window procedure.
2146 * GWL_HINSTANCE The window's pplication instance handle.
2148 * GWL_ID The window's identifier.
2150 * GWL_USERDATA The window's user-specified data.
2152 * If the window is a dialog box, the _offset_ parameter can be one of
2153 * the following values:
2155 * DWL_DLGPROC The address of the window's dialog box procedure.
2157 * DWL_MSGRESULT The return value of a message
2158 * that the dialog box procedure processed.
2160 * DWL_USER Application specific information.
2162 * RETURNS
2164 * If successful, returns the previous value located at _offset_. Otherwise,
2165 * returns 0.
2167 * NOTES
2169 * Extra memory for a window class is specified by a nonzero cbWndExtra
2170 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2171 * time of class creation.
2173 * Using GWL_WNDPROC to set a new window procedure effectively creates
2174 * a window subclass. Use CallWindowProc() in the new windows procedure
2175 * to pass messages to the superclass's window procedure.
2177 * The user data is reserved for use by the application which created
2178 * the window.
2180 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2181 * instead, call the EnableWindow() function to change the window's
2182 * disabled state.
2184 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2185 * SetParent() instead.
2187 * Win95:
2188 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2189 * it sends WM_STYLECHANGING before changing the settings
2190 * and WM_STYLECHANGED afterwards.
2191 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2193 * BUGS
2195 * GWL_STYLE does not dispatch WM_STYLE... messages.
2197 * CONFORMANCE
2199 * ECMA-234, Win32
2202 LONG WINAPI SetWindowLongW(
2203 HWND hwnd, /* window to alter */
2204 INT offset, /* offset, in bytes, of location to alter */
2205 LONG newval /* new value of location */
2207 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2211 /*******************************************************************
2212 * GetWindowText16 (USER.36)
2214 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2216 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2220 /*******************************************************************
2221 * GetWindowText32A (USER32.309)
2223 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2225 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2226 (LPARAM)lpString );
2229 /*******************************************************************
2230 * InternalGetWindowText (USER32.326)
2232 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2234 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2235 return GetWindowTextW(hwnd,lpString,nMaxCount);
2239 /*******************************************************************
2240 * GetWindowText32W (USER32.312)
2242 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2244 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2245 (LPARAM)lpString );
2249 /*******************************************************************
2250 * SetWindowText16 (USER.37)
2252 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2254 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2258 /*******************************************************************
2259 * SetWindowText32A (USER32.521)
2261 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2263 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2267 /*******************************************************************
2268 * SetWindowText32W (USER32.523)
2270 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2272 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2276 /*******************************************************************
2277 * GetWindowTextLength16 (USER.38)
2279 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2281 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2285 /*******************************************************************
2286 * GetWindowTextLength32A (USER32.310)
2288 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2290 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2293 /*******************************************************************
2294 * GetWindowTextLength32W (USER32.311)
2296 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2298 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2302 /*******************************************************************
2303 * IsWindow16 (USER.47)
2305 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2307 CURRENT_STACK16->es = USER_HeapSel;
2308 return IsWindow( hwnd );
2312 /*******************************************************************
2313 * IsWindow32 (USER32.348)
2315 BOOL WINAPI IsWindow( HWND hwnd )
2317 WND * wndPtr;
2318 BOOL retvalue;
2320 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2321 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2322 WIN_ReleaseWndPtr(wndPtr);
2323 return retvalue;
2328 /*****************************************************************
2329 * GetParent16 (USER.46)
2331 HWND16 WINAPI GetParent16( HWND16 hwnd )
2333 return (HWND16)GetParent( hwnd );
2337 /*****************************************************************
2338 * GetParent32 (USER32.278)
2340 HWND WINAPI GetParent( HWND hwnd )
2342 WND *wndPtr;
2343 HWND retvalue;
2345 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2346 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2348 WIN_ReleaseWndPtr(wndPtr);
2349 return 0;
2351 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2352 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2354 WIN_ReleaseWndPtr(wndPtr);
2355 return retvalue;
2359 /*****************************************************************
2360 * WIN_GetTopParent
2362 * Get the top-level parent for a child window.
2363 * returns a locked pointer
2365 WND* WIN_GetTopParentPtr( WND* pWnd )
2367 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2369 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2371 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2373 return tmpWnd;
2376 /*****************************************************************
2377 * WIN_GetTopParent
2379 * Get the top-level parent for a child window.
2381 HWND WIN_GetTopParent( HWND hwnd )
2383 HWND retvalue;
2384 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2385 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2387 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2388 WIN_ReleaseWndPtr(tmpPtr);
2389 WIN_ReleaseWndPtr(wndPtr);
2390 return retvalue;
2394 /*****************************************************************
2395 * SetParent16 (USER.233)
2397 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2399 return SetParent( hwndChild, hwndNewParent );
2403 /*****************************************************************
2404 * SetParent32 (USER32.495)
2406 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2408 WND *wndPtr;
2409 DWORD dwStyle;
2410 WND *pWndNewParent;
2411 WND *pWndOldParent;
2412 HWND retvalue;
2415 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2417 dwStyle = wndPtr->dwStyle;
2419 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2420 : WIN_LockWndPtr(pWndDesktop);
2422 /* Windows hides the window first, then shows it again
2423 * including the WM_SHOWWINDOW messages and all */
2424 if (dwStyle & WS_VISIBLE)
2425 ShowWindow( hwndChild, SW_HIDE );
2427 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2429 /* SetParent32 additionally needs to make hwndChild the topmost window
2430 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2431 WM_WINDOWPOSCHANGED notification messages.
2433 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2434 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2435 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2436 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2438 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2440 WIN_ReleaseWndPtr(pWndOldParent);
2441 WIN_ReleaseWndPtr(pWndNewParent);
2442 WIN_ReleaseWndPtr(wndPtr);
2444 return retvalue;
2448 /*******************************************************************
2449 * IsChild16 (USER.48)
2451 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2453 return IsChild(parent,child);
2457 /*******************************************************************
2458 * IsChild32 (USER32.339)
2460 BOOL WINAPI IsChild( HWND parent, HWND child )
2462 WND * wndPtr = WIN_FindWndPtr( child );
2463 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2465 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2466 if (wndPtr->hwndSelf == parent)
2468 WIN_ReleaseWndPtr(wndPtr);
2469 return TRUE;
2472 WIN_ReleaseWndPtr(wndPtr);
2473 return FALSE;
2477 /***********************************************************************
2478 * IsWindowVisible16 (USER.49)
2480 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2482 return IsWindowVisible(hwnd);
2486 /***********************************************************************
2487 * IsWindowVisible32 (USER32.351)
2489 BOOL WINAPI IsWindowVisible( HWND hwnd )
2491 BOOL retval;
2492 WND *wndPtr = WIN_FindWndPtr( hwnd );
2493 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2495 if (!(wndPtr->dwStyle & WS_VISIBLE))
2497 WIN_ReleaseWndPtr(wndPtr);
2498 return FALSE;
2500 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2502 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2503 WIN_ReleaseWndPtr(wndPtr);
2504 return retval;
2509 /***********************************************************************
2510 * WIN_IsWindowDrawable
2512 * hwnd is drawable when it is visible, all parents are not
2513 * minimized, and it is itself not minimized unless we are
2514 * trying to draw its default class icon.
2516 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2518 if( (wnd->dwStyle & WS_MINIMIZE &&
2519 icon && wnd->class->hIcon) ||
2520 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2521 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2522 if( wnd->dwStyle & WS_MINIMIZE ||
2523 !(wnd->dwStyle & WS_VISIBLE) ) break;
2524 return (wnd == NULL);
2528 /*******************************************************************
2529 * GetTopWindow16 (USER.229)
2531 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2533 return GetTopWindow(hwnd);
2537 /*******************************************************************
2538 * GetTopWindow32 (USER.229)
2540 HWND WINAPI GetTopWindow( HWND hwnd )
2542 HWND retval;
2543 WND * wndPtr = NULL;
2545 if (hwnd!=0)
2546 wndPtr = WIN_FindWndPtr( hwnd );
2547 else
2548 wndPtr = WIN_GetDesktop();
2550 if (wndPtr && wndPtr->child)
2552 retval = wndPtr->child->hwndSelf;
2554 else retval = 0;
2555 WIN_ReleaseWndPtr(wndPtr);
2556 return retval;
2560 /*******************************************************************
2561 * GetWindow16 (USER.262)
2563 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2565 return GetWindow( hwnd,rel );
2569 /*******************************************************************
2570 * GetWindow32 (USER32.302)
2572 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2574 HWND retval;
2576 WND * wndPtr = WIN_FindWndPtr( hwnd );
2577 if (!wndPtr) return 0;
2578 switch(rel)
2580 case GW_HWNDFIRST:
2581 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2582 else retval = 0;
2583 goto end;
2585 case GW_HWNDLAST:
2586 if (!wndPtr->parent)
2588 retval = 0; /* Desktop window */
2589 goto end;
2591 while (wndPtr->next)
2593 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2595 retval = wndPtr->hwndSelf;
2596 goto end;
2598 case GW_HWNDNEXT:
2599 if (!wndPtr->next) retval = 0;
2600 else retval = wndPtr->next->hwndSelf;
2601 goto end;
2603 case GW_HWNDPREV:
2604 if (!wndPtr->parent)
2606 retval = 0; /* Desktop window */
2607 goto end;
2609 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2610 if (wndPtr->hwndSelf == hwnd)
2612 retval = 0; /* First in list */
2613 goto end;
2615 while (wndPtr->next)
2617 if (wndPtr->next->hwndSelf == hwnd)
2619 retval = wndPtr->hwndSelf;
2620 goto end;
2622 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2624 retval = 0;
2625 goto end;
2627 case GW_OWNER:
2628 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2629 goto end;
2631 case GW_CHILD:
2632 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2633 goto end;
2635 retval = 0;
2636 end:
2637 WIN_ReleaseWndPtr(wndPtr);
2638 return retval;
2642 /*******************************************************************
2643 * GetNextWindow16 (USER.230)
2645 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2647 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2648 return GetWindow16( hwnd, flag );
2651 /*******************************************************************
2652 * ShowOwnedPopups16 (USER.265)
2654 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2656 ShowOwnedPopups( owner, fShow );
2660 /*******************************************************************
2661 * ShowOwnedPopups32 (USER32.531)
2663 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2665 UINT totalChild=0, count=0;
2667 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2669 if (!pWnd) return TRUE;
2671 for (; count < totalChild; count++)
2673 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2674 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, fShow ? SW_SHOW : SW_HIDE,IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
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 * GetLastActivePopup32 (USER32.256)
2694 HWND WINAPI GetLastActivePopup( HWND hwnd )
2696 WND *wndPtr;
2697 HWND retval;
2698 wndPtr = WIN_FindWndPtr(hwnd);
2699 if (!wndPtr) return hwnd;
2700 retval = wndPtr->hwndLastActive;
2701 WIN_ReleaseWndPtr(wndPtr);
2702 return retval;
2706 /*******************************************************************
2707 * WIN_BuildWinArray
2709 * Build an array of pointers to the children of a given window.
2710 * The array must be freed with HeapFree(SystemHeap). Return NULL
2711 * when no windows are found.
2713 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2715 /* Future : this function will lock all windows associated with this array */
2717 WND **list, **ppWnd;
2718 WND *pWnd;
2719 UINT count = 0, skipOwned, skipHidden;
2720 DWORD skipFlags;
2722 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2723 skipOwned = bwaFlags & BWA_SKIPOWNED;
2724 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2725 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2727 /* First count the windows */
2729 if (!wndPtr)
2730 wndPtr = WIN_GetDesktop();
2732 pWnd = WIN_LockWndPtr(wndPtr->child);
2733 while (pWnd)
2735 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2736 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2737 count++;
2738 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2741 if( count )
2743 /* Now build the list of all windows */
2745 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2747 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2749 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2750 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2752 *ppWnd++ = pWnd;
2753 count++;
2756 WIN_ReleaseWndPtr(pWnd);
2757 *ppWnd = NULL;
2759 else count = 0;
2760 } else list = NULL;
2762 if( pTotal ) *pTotal = count;
2763 return list;
2765 /*******************************************************************
2766 * WIN_ReleaseWinArray
2768 void WIN_ReleaseWinArray(WND **wndArray)
2770 /* Future : this function will also unlock all windows associated with wndArray */
2771 HeapFree( SystemHeap, 0, wndArray );
2775 /*******************************************************************
2776 * EnumWindows16 (USER.54)
2778 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2780 WND **list, **ppWnd;
2782 /* We have to build a list of all windows first, to avoid */
2783 /* unpleasant side-effects, for instance if the callback */
2784 /* function changes the Z-order of the windows. */
2786 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2788 WIN_ReleaseDesktop();
2789 return FALSE;
2792 /* Now call the callback function for every window */
2794 for (ppWnd = list; *ppWnd; ppWnd++)
2796 LRESULT lpEnumFuncRetval;
2797 int iWndsLocks = 0;
2798 /* Make sure that the window still exists */
2799 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2801 /* To avoid any deadlocks, all the locks on the windows
2802 structures must be suspended before the control
2803 is passed to the application */
2804 iWndsLocks = WIN_SuspendWndsLock();
2805 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2806 WIN_RestoreWndsLock(iWndsLocks);
2808 if (!lpEnumFuncRetval) break;
2810 WIN_ReleaseWinArray(list);
2811 WIN_ReleaseDesktop();
2812 return TRUE;
2816 /*******************************************************************
2817 * EnumWindows32 (USER32.193)
2819 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2821 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2825 /**********************************************************************
2826 * EnumTaskWindows16 (USER.225)
2828 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2829 LPARAM lParam )
2831 WND **list, **ppWnd;
2833 /* This function is the same as EnumWindows(), */
2834 /* except for an added check on the window's task. */
2836 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2838 WIN_ReleaseDesktop();
2839 return FALSE;
2842 /* Now call the callback function for every window */
2844 for (ppWnd = list; *ppWnd; ppWnd++)
2846 LRESULT funcRetval;
2847 int iWndsLocks = 0;
2848 /* Make sure that the window still exists */
2849 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2850 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2852 /* To avoid any deadlocks, all the locks on the windows
2853 structures must be suspended before the control
2854 is passed to the application */
2855 iWndsLocks = WIN_SuspendWndsLock();
2856 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2857 WIN_RestoreWndsLock(iWndsLocks);
2859 if (!funcRetval) break;
2861 WIN_ReleaseWinArray(list);
2862 WIN_ReleaseDesktop();
2863 return TRUE;
2867 /**********************************************************************
2868 * EnumThreadWindows (USER32.190)
2870 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2872 TEB *teb = THREAD_IdToTEB(id);
2874 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2878 /**********************************************************************
2879 * WIN_EnumChildWindows
2881 * Helper function for EnumChildWindows().
2883 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2884 LPARAM lParam )
2886 WND **childList;
2887 BOOL16 ret = FALSE;
2889 for ( ; *ppWnd; ppWnd++)
2891 int iWndsLocks = 0;
2893 /* Make sure that the window still exists */
2894 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2895 /* Build children list first */
2896 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2898 /* To avoid any deadlocks, all the locks on the windows
2899 structures must be suspended before the control
2900 is passed to the application */
2901 iWndsLocks = WIN_SuspendWndsLock();
2902 ret = func( (*ppWnd)->hwndSelf, lParam );
2903 WIN_RestoreWndsLock(iWndsLocks);
2905 if (childList)
2907 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2908 WIN_ReleaseWinArray(childList);
2910 if (!ret) return FALSE;
2912 return TRUE;
2916 /**********************************************************************
2917 * EnumChildWindows16 (USER.55)
2919 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2920 LPARAM lParam )
2922 WND **list, *pParent;
2924 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2925 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2927 WIN_ReleaseWndPtr(pParent);
2928 return FALSE;
2930 WIN_EnumChildWindows( list, func, lParam );
2931 WIN_ReleaseWinArray(list);
2932 WIN_ReleaseWndPtr(pParent);
2933 return TRUE;
2937 /**********************************************************************
2938 * EnumChildWindows32 (USER32.178)
2940 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2941 LPARAM lParam )
2943 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2944 lParam );
2948 /*******************************************************************
2949 * AnyPopup16 (USER.52)
2951 BOOL16 WINAPI AnyPopup16(void)
2953 return AnyPopup();
2957 /*******************************************************************
2958 * AnyPopup32 (USER32.4)
2960 BOOL WINAPI AnyPopup(void)
2962 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2963 BOOL retvalue;
2965 while (wndPtr)
2967 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2969 retvalue = TRUE;
2970 goto end;
2972 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2974 retvalue = FALSE;
2975 end:
2976 WIN_ReleaseWndPtr(wndPtr);
2977 return retvalue;
2981 /*******************************************************************
2982 * FlashWindow16 (USER.105)
2984 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2986 return FlashWindow( hWnd, bInvert );
2990 /*******************************************************************
2991 * FlashWindow32 (USER32.202)
2993 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2995 WND *wndPtr = WIN_FindWndPtr(hWnd);
2997 TRACE("%04x\n", hWnd);
2999 if (!wndPtr) return FALSE;
3001 if (wndPtr->dwStyle & WS_MINIMIZE)
3003 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3005 HDC hDC = GetDC(hWnd);
3007 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3008 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3010 ReleaseDC( hWnd, hDC );
3011 wndPtr->flags |= WIN_NCACTIVATED;
3013 else
3015 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3016 RDW_UPDATENOW | RDW_FRAME, 0 );
3017 wndPtr->flags &= ~WIN_NCACTIVATED;
3019 WIN_ReleaseWndPtr(wndPtr);
3020 return TRUE;
3022 else
3024 WPARAM16 wparam;
3025 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3026 else wparam = (hWnd == GetActiveWindow());
3028 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3029 WIN_ReleaseWndPtr(wndPtr);
3030 return wparam;
3035 /*******************************************************************
3036 * SetSysModalWindow16 (USER.188)
3038 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3040 HWND hWndOldModal = hwndSysModal;
3041 hwndSysModal = hWnd;
3042 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3043 return hWndOldModal;
3047 /*******************************************************************
3048 * GetSysModalWindow16 (USER.52)
3050 HWND16 WINAPI GetSysModalWindow16(void)
3052 return hwndSysModal;
3056 /*******************************************************************
3057 * GetWindowContextHelpId (USER32.303)
3059 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3061 DWORD retval;
3062 WND *wnd = WIN_FindWndPtr( hwnd );
3063 if (!wnd) return 0;
3064 retval = wnd->helpContext;
3065 WIN_ReleaseWndPtr(wnd);
3066 return retval;
3070 /*******************************************************************
3071 * SetWindowContextHelpId (USER32.515)
3073 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3075 WND *wnd = WIN_FindWndPtr( hwnd );
3076 if (!wnd) return FALSE;
3077 wnd->helpContext = id;
3078 WIN_ReleaseWndPtr(wnd);
3079 return TRUE;
3083 /*******************************************************************
3084 * DRAG_QueryUpdate
3086 * recursively find a child that contains spDragInfo->pt point
3087 * and send WM_QUERYDROPOBJECT
3089 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3091 BOOL16 wParam,bResult = 0;
3092 POINT pt;
3093 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3094 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3095 RECT tempRect;
3097 if( !ptrQueryWnd || !ptrDragInfo )
3099 WIN_ReleaseWndPtr(ptrQueryWnd);
3100 return 0;
3103 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3105 GetWindowRect(hQueryWnd,&tempRect);
3107 if( !PtInRect(&tempRect,pt) ||
3108 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3110 WIN_ReleaseWndPtr(ptrQueryWnd);
3111 return 0;
3114 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3116 tempRect = ptrQueryWnd->rectClient;
3117 if(ptrQueryWnd->dwStyle & WS_CHILD)
3118 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3119 (LPPOINT)&tempRect, 2 );
3121 if (PtInRect( &tempRect, pt))
3123 wParam = 0;
3125 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3127 if( ptrWnd->dwStyle & WS_VISIBLE )
3129 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3130 if (PtInRect( &tempRect, pt )) break;
3134 if(ptrWnd)
3136 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3137 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3138 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3139 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3140 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3142 WIN_ReleaseWndPtr(ptrWnd);
3145 if(bResult)
3147 WIN_ReleaseWndPtr(ptrQueryWnd);
3148 return bResult;
3151 else wParam = 1;
3153 else wParam = 1;
3155 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3157 ptrDragInfo->hScope = hQueryWnd;
3159 bResult = ( bNoSend )
3160 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3161 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3162 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3163 if( !bResult )
3164 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3166 WIN_ReleaseWndPtr(ptrQueryWnd);
3167 return bResult;
3171 /*******************************************************************
3172 * DragDetect (USER.465)
3174 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3176 POINT pt32;
3177 CONV_POINT16TO32( &pt, &pt32 );
3178 return DragDetect( hWnd, pt32 );
3181 /*******************************************************************
3182 * DragDetect32 (USER32.151)
3184 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3186 MSG16 msg;
3187 RECT16 rect;
3189 rect.left = pt.x - wDragWidth;
3190 rect.right = pt.x + wDragWidth;
3192 rect.top = pt.y - wDragHeight;
3193 rect.bottom = pt.y + wDragHeight;
3195 SetCapture(hWnd);
3197 while(1)
3199 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3201 if( msg.message == WM_LBUTTONUP )
3203 ReleaseCapture();
3204 return 0;
3206 if( msg.message == WM_MOUSEMOVE )
3208 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3210 ReleaseCapture();
3211 return 1;
3215 WaitMessage();
3217 return 0;
3220 /******************************************************************************
3221 * DragObject16 (USER.464)
3223 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3224 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3226 MSG16 msg;
3227 LPDRAGINFO lpDragInfo;
3228 SEGPTR spDragInfo;
3229 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3230 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3231 WND *wndPtr = WIN_FindWndPtr(hWnd);
3232 HCURSOR16 hCurrentCursor = 0;
3233 HWND16 hCurrentWnd = 0;
3235 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3236 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3238 if( !lpDragInfo || !spDragInfo )
3240 WIN_ReleaseWndPtr(wndPtr);
3241 return 0L;
3244 hBummer = LoadCursor16(0, IDC_BUMMER16);
3246 if( !hBummer || !wndPtr )
3248 GlobalFree16(hDragInfo);
3249 WIN_ReleaseWndPtr(wndPtr);
3250 return 0L;
3253 if(hCursor)
3255 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3257 GlobalFree16(hDragInfo);
3258 WIN_ReleaseWndPtr(wndPtr);
3259 return 0L;
3262 if( hDragCursor == hCursor ) hDragCursor = 0;
3263 else hCursor = hDragCursor;
3265 hOldCursor = SetCursor(hDragCursor);
3268 lpDragInfo->hWnd = hWnd;
3269 lpDragInfo->hScope = 0;
3270 lpDragInfo->wFlags = wObj;
3271 lpDragInfo->hList = szList; /* near pointer! */
3272 lpDragInfo->hOfStruct = hOfStruct;
3273 lpDragInfo->l = 0L;
3275 SetCapture(hWnd);
3276 ShowCursor( TRUE );
3280 do{ WaitMessage(); }
3281 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3283 *(lpDragInfo+1) = *lpDragInfo;
3285 lpDragInfo->pt = msg.pt;
3287 /* update DRAGINFO struct */
3288 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3290 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3291 hCurrentCursor = hCursor;
3292 else
3294 hCurrentCursor = hBummer;
3295 lpDragInfo->hScope = 0;
3297 if( hCurrentCursor )
3298 SetCursor(hCurrentCursor);
3300 /* send WM_DRAGLOOP */
3301 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3302 (LPARAM) spDragInfo );
3303 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3304 if( hCurrentWnd != lpDragInfo->hScope )
3306 if( hCurrentWnd )
3307 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3308 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3309 HIWORD(spDragInfo)) );
3310 hCurrentWnd = lpDragInfo->hScope;
3311 if( hCurrentWnd )
3312 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3314 else
3315 if( hCurrentWnd )
3316 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3318 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3320 ReleaseCapture();
3321 ShowCursor( FALSE );
3323 if( hCursor )
3325 SetCursor( hOldCursor );
3326 if (hDragCursor) DestroyCursor( hDragCursor );
3329 if( hCurrentCursor != hBummer )
3330 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3331 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3332 else
3333 msg.lParam = 0;
3334 GlobalFree16(hDragInfo);
3335 WIN_ReleaseWndPtr(wndPtr);
3337 return (DWORD)(msg.lParam);