Moved SystemHeap allocations to the process heap.
[wine.git] / windows / win.c
blob938b48c62c9c9704bf65ac816fbd7270cae70372
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "options.h"
14 #include "class.h"
15 #include "win.h"
16 #include "heap.h"
17 #include "user.h"
18 #include "dce.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "clipboard.h"
27 #include "winproc.h"
28 #include "task.h"
29 #include "thread.h"
30 #include "process.h"
31 #include "winerror.h"
32 #include "mdi.h"
33 #include "local.h"
34 #include "desktop.h"
35 #include "syslevel.h"
36 #include "stackframe.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(win)
40 DECLARE_DEBUG_CHANNEL(msg)
42 /**********************************************************************/
44 WND_DRIVER *WND_Driver = NULL;
46 /* Desktop window */
47 static WND *pWndDesktop = NULL;
49 static HWND hwndSysModal = 0;
51 static WORD wDragWidth = 4;
52 static WORD wDragHeight= 3;
54 /* thread safeness */
55 static SYSLEVEL WIN_SysLevel;
57 /***********************************************************************
58 * WIN_Init
59 */
60 void WIN_Init( void )
62 /* Initialisation of the critical section for thread safeness */
63 _CreateSysLevel( &WIN_SysLevel, 2 );
66 /***********************************************************************
67 * WIN_LockWnds
69 * Locks access to all WND structures for thread safeness
71 void WIN_LockWnds( void )
73 _EnterSysLevel( &WIN_SysLevel );
76 /***********************************************************************
77 * WIN_UnlockWnds
79 * Unlocks access to all WND structures
81 void WIN_UnlockWnds( void )
83 _LeaveSysLevel( &WIN_SysLevel );
86 /***********************************************************************
87 * WIN_SuspendWndsLock
89 * Suspend the lock on WND structures.
90 * Returns the number of locks suspended
92 int WIN_SuspendWndsLock( void )
94 int isuspendedLocks = _ConfirmSysLevel( &WIN_SysLevel );
95 int count = isuspendedLocks;
97 while ( count-- > 0 )
98 _LeaveSysLevel( &WIN_SysLevel );
100 return isuspendedLocks;
103 /***********************************************************************
104 * WIN_RestoreWndsLock
106 * Restore the suspended locks on WND structures
108 void WIN_RestoreWndsLock( int ipreviousLocks )
110 while ( ipreviousLocks-- > 0 )
111 _EnterSysLevel( &WIN_SysLevel );
114 /***********************************************************************
115 * WIN_FindWndPtr
117 * Return a pointer to the WND structure corresponding to a HWND.
119 WND * WIN_FindWndPtr( HWND hwnd )
121 WND * ptr;
123 if (!hwnd || HIWORD(hwnd)) goto error2;
124 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
125 /* Lock all WND structures for thread safeness*/
126 WIN_LockWnds();
127 /*and increment destruction monitoring*/
128 ptr->irefCount++;
130 if (ptr->dwMagic != WND_MAGIC) goto error;
131 if (ptr->hwndSelf != hwnd)
133 ERR("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
134 goto error;
136 /* returns a locked pointer */
137 return ptr;
138 error:
139 /* Unlock all WND structures for thread safeness*/
140 WIN_UnlockWnds();
141 /* and decrement destruction monitoring value */
142 ptr->irefCount--;
144 error2:
145 if ( hwnd!=0 )
146 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
147 return NULL;
150 /***********************************************************************
151 * WIN_LockWndPtr
153 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
154 * but by initWndPtr;
155 * Returns the locked initialisation pointer
157 WND *WIN_LockWndPtr(WND *initWndPtr)
159 if(!initWndPtr) return 0;
161 /* Lock all WND structures for thread safeness*/
162 WIN_LockWnds();
163 /*and increment destruction monitoring*/
164 initWndPtr->irefCount++;
166 return initWndPtr;
170 /***********************************************************************
171 * WIN_ReleaseWndPtr
173 * Release the pointer to the WND structure.
175 void WIN_ReleaseWndPtr(WND *wndPtr)
177 if(!wndPtr) return;
179 /*Decrement destruction monitoring value*/
180 wndPtr->irefCount--;
181 /* Check if it's time to release the memory*/
182 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
184 /* Release memory */
185 USER_HEAP_FREE( wndPtr->hwndSelf);
186 wndPtr->hwndSelf = 0;
188 else if(wndPtr->irefCount < 0)
190 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
191 ERR("forgot a Lock on %p somewhere\n",wndPtr);
193 /*unlock all WND structures for thread safeness*/
194 WIN_UnlockWnds();
197 /***********************************************************************
198 * WIN_UpdateWndPtr
200 * Updates the value of oldPtr to newPtr.
202 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
204 WND *tmpWnd = NULL;
206 tmpWnd = WIN_LockWndPtr(newPtr);
207 WIN_ReleaseWndPtr(*oldPtr);
208 *oldPtr = tmpWnd;
212 /***********************************************************************
213 * WIN_DumpWindow
215 * Dump the content of a window structure to stderr.
217 void WIN_DumpWindow( HWND hwnd )
219 WND *ptr;
220 char className[80];
221 int i;
223 if (!(ptr = WIN_FindWndPtr( hwnd )))
225 WARN("%04x is not a window handle\n", hwnd );
226 return;
229 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
230 strcpy( className, "#NULL#" );
232 TRACE("Window %04x (%p):\n", hwnd, ptr );
233 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
234 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
235 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
236 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
237 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
238 ptr->next, ptr->child, ptr->parent, ptr->owner,
239 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
240 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
241 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
242 ptr->text ? ptr->text : "",
243 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
244 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
245 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
246 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
248 if (ptr->class->cbWndExtra)
250 DPRINTF( "extra bytes:" );
251 for (i = 0; i < ptr->class->cbWndExtra; i++)
252 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
253 DPRINTF( "\n" );
255 DPRINTF( "\n" );
256 WIN_ReleaseWndPtr(ptr);
260 /***********************************************************************
261 * WIN_WalkWindows
263 * Walk the windows tree and print each window on stderr.
265 void WIN_WalkWindows( HWND hwnd, int indent )
267 WND *ptr;
268 char className[80];
270 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
272 if (!ptr)
274 WARN("Invalid window handle %04x\n", hwnd );
275 return;
278 if (!indent) /* first time around */
279 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
280 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
281 " Text");
283 while (ptr)
285 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
287 GlobalGetAtomNameA(ptr->class->atomName,className,sizeof(className));
289 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
290 (DWORD)ptr, ptr->hmemTaskQ, className,
291 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
292 ptr->text?ptr->text:"<null>");
294 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
295 WIN_UpdateWndPtr(&ptr,ptr->next);
301 /***********************************************************************
302 * WIN_UnlinkWindow
304 * Remove a window from the siblings linked list.
306 BOOL WIN_UnlinkWindow( HWND hwnd )
308 WND *wndPtr, **ppWnd;
309 BOOL ret = FALSE;
311 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
312 else if(!wndPtr->parent)
314 WIN_ReleaseWndPtr(wndPtr);
315 return FALSE;
318 ppWnd = &wndPtr->parent->child;
319 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
320 if (*ppWnd)
322 *ppWnd = wndPtr->next;
323 ret = TRUE;
325 WIN_ReleaseWndPtr(wndPtr);
326 return ret;
330 /***********************************************************************
331 * WIN_LinkWindow
333 * Insert a window into the siblings linked list.
334 * The window is inserted after the specified window, which can also
335 * be specified as HWND_TOP or HWND_BOTTOM.
337 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
339 WND *wndPtr, **ppWnd;
341 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
342 else if(!wndPtr->parent)
344 WIN_ReleaseWndPtr(wndPtr);
345 return FALSE;
347 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
349 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
350 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
351 while (*ppWnd) ppWnd = &(*ppWnd)->next;
353 else /* Normal case */
355 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
356 if (!afterPtr)
358 WIN_ReleaseWndPtr(wndPtr);
359 return FALSE;
361 ppWnd = &afterPtr->next;
362 WIN_ReleaseWndPtr(afterPtr);
364 wndPtr->next = *ppWnd;
365 *ppWnd = wndPtr;
366 WIN_ReleaseWndPtr(wndPtr);
367 return TRUE;
371 /***********************************************************************
372 * WIN_FindWinToRepaint
374 * Find a window that needs repaint.
376 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
378 HWND hwndRet;
379 WND *pWnd;
381 /* Note: the desktop window never gets WM_PAINT messages
382 * The real reason why is because Windows DesktopWndProc
383 * does ValidateRgn inside WM_ERASEBKGND handler.
386 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
388 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
390 if (!(pWnd->dwStyle & WS_VISIBLE))
392 TRACE("skipping window %04x\n",
393 pWnd->hwndSelf );
395 else if ((pWnd->hmemTaskQ == hQueue) &&
396 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
397 break;
399 else if (pWnd->child )
400 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
402 WIN_ReleaseWndPtr(pWnd);
403 return hwndRet;
408 if(!pWnd)
410 return 0;
413 hwndRet = pWnd->hwndSelf;
415 /* look among siblings if we got a transparent window */
416 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
417 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
419 WIN_UpdateWndPtr(&pWnd,pWnd->next);
421 if (pWnd)
423 hwndRet = pWnd->hwndSelf;
424 WIN_ReleaseWndPtr(pWnd);
426 TRACE("found %04x\n",hwndRet);
427 return hwndRet;
431 /***********************************************************************
432 * WIN_DestroyWindow
434 * Destroy storage associated to a window. "Internals" p.358
435 * returns a locked wndPtr->next
437 static WND* WIN_DestroyWindow( WND* wndPtr )
439 HWND hwnd = wndPtr->hwndSelf;
440 WND *pWnd;
442 TRACE("%04x\n", wndPtr->hwndSelf );
444 /* free child windows */
445 WIN_LockWndPtr(wndPtr->child);
446 while ((pWnd = wndPtr->child))
448 wndPtr->child = WIN_DestroyWindow( pWnd );
449 WIN_ReleaseWndPtr(pWnd);
453 * Clear the update region to make sure no WM_PAINT messages will be
454 * generated for this window while processing the WM_NCDESTROY.
456 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
458 if (wndPtr->hrgnUpdate > 1)
459 DeleteObject( wndPtr->hrgnUpdate );
461 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
463 wndPtr->hrgnUpdate = 0;
467 * Send the WM_NCDESTROY to the window being destroyed.
469 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
471 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
473 WINPOS_CheckInternalPos( wndPtr );
474 if( hwnd == GetCapture()) ReleaseCapture();
476 /* free resources associated with the window */
478 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
479 PROPERTY_RemoveWindowProps( wndPtr );
481 wndPtr->dwMagic = 0; /* Mark it as invalid */
483 /* toss stale messages from the queue */
485 if( wndPtr->hmemTaskQ )
487 BOOL bPostQuit = FALSE;
488 WPARAM wQuitParam = 0;
489 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
490 QMSG *qmsg;
492 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
494 if( qmsg->msg.message == WM_QUIT )
496 bPostQuit = TRUE;
497 wQuitParam = qmsg->msg.wParam;
499 QUEUE_RemoveMsg(msgQ, qmsg);
502 QUEUE_Unlock(msgQ);
504 /* repost WM_QUIT to make sure this app exits its message loop */
505 if( bPostQuit ) PostQuitMessage(wQuitParam);
506 wndPtr->hmemTaskQ = 0;
509 if (!(wndPtr->dwStyle & WS_CHILD))
510 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
511 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
512 wndPtr->pDriver->pDestroyWindow( wndPtr );
513 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
514 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
515 wndPtr->class->cWindows--;
516 wndPtr->class = NULL;
518 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
520 wndPtr->pDriver->pFinalize(wndPtr);
522 return pWnd;
525 /***********************************************************************
526 * WIN_ResetQueueWindows
528 * Reset the queue of all the children of a given window.
529 * Return TRUE if something was done.
531 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
533 BOOL ret = FALSE;
535 if (hNew) /* Set a new queue */
537 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
539 if (wnd->hmemTaskQ == hQueue)
541 wnd->hmemTaskQ = hNew;
542 ret = TRUE;
544 if (wnd->child)
546 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
550 else /* Queue is being destroyed */
552 while (wnd->child)
554 WND *tmp = WIN_LockWndPtr(wnd->child);
555 WND *tmp2;
556 ret = FALSE;
557 while (tmp)
559 if (tmp->hmemTaskQ == hQueue)
561 DestroyWindow( tmp->hwndSelf );
562 ret = TRUE;
563 break;
565 tmp2 = WIN_LockWndPtr(tmp->child);
566 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
567 ret = TRUE;
568 else
570 WIN_UpdateWndPtr(&tmp,tmp->next);
572 WIN_ReleaseWndPtr(tmp2);
574 WIN_ReleaseWndPtr(tmp);
575 if (!ret) break;
578 return ret;
581 /***********************************************************************
582 * WIN_CreateDesktopWindow
584 * Create the desktop window.
586 BOOL WIN_CreateDesktopWindow(void)
588 CLASS *class;
589 HWND hwndDesktop;
590 DESKTOP *pDesktop;
592 TRACE("Creating desktop window\n");
595 if (!ICONTITLE_Init() ||
596 !WINPOS_CreateInternalPosAtom() ||
597 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
598 return FALSE;
600 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
601 if (!hwndDesktop) return FALSE;
602 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
604 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
605 pDesktop->pDriver = DESKTOP_Driver;
606 pWndDesktop->pDriver = WND_Driver;
608 pDesktop->pDriver->pInitialize(pDesktop);
609 pWndDesktop->pDriver->pInitialize(pWndDesktop);
611 pWndDesktop->next = NULL;
612 pWndDesktop->child = NULL;
613 pWndDesktop->parent = NULL;
614 pWndDesktop->owner = NULL;
615 pWndDesktop->class = class;
616 pWndDesktop->dwMagic = WND_MAGIC;
617 pWndDesktop->hwndSelf = hwndDesktop;
618 pWndDesktop->hInstance = 0;
619 pWndDesktop->rectWindow.left = 0;
620 pWndDesktop->rectWindow.top = 0;
621 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
622 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
623 pWndDesktop->rectClient = pWndDesktop->rectWindow;
624 pWndDesktop->text = NULL;
625 pWndDesktop->hmemTaskQ = GetFastQueue16();
626 pWndDesktop->hrgnUpdate = 0;
627 pWndDesktop->hwndLastActive = hwndDesktop;
628 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
629 WS_CLIPSIBLINGS;
630 pWndDesktop->dwExStyle = 0;
631 pWndDesktop->dce = NULL;
632 pWndDesktop->pVScroll = NULL;
633 pWndDesktop->pHScroll = NULL;
634 pWndDesktop->pProp = NULL;
635 pWndDesktop->wIDmenu = 0;
636 pWndDesktop->helpContext = 0;
637 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
638 pWndDesktop->hSysMenu = 0;
639 pWndDesktop->userdata = 0;
640 pWndDesktop->winproc = (WNDPROC16)class->winproc;
641 pWndDesktop->irefCount = 0;
643 /* FIXME: How do we know if it should be Unicode or not */
644 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
645 return FALSE;
647 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
648 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
649 return TRUE;
653 /***********************************************************************
654 * WIN_CreateWindowEx
656 * Implementation of CreateWindowEx().
658 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
659 BOOL win32, BOOL unicode )
661 INT sw = SW_SHOW;
662 CLASS *classPtr;
663 WND *wndPtr;
664 HWND retvalue;
665 HWND16 hwnd, hwndLinkAfter;
666 POINT maxSize, maxPos, minTrack, maxTrack;
667 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
669 TRACE("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
670 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
671 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
672 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
673 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
675 /* Find the parent window */
677 if (cs->hwndParent)
679 /* Make sure parent is valid */
680 if (!IsWindow( cs->hwndParent ))
682 WARN("Bad parent %04x\n", cs->hwndParent );
683 return 0;
685 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
686 WARN("No parent for child window\n" );
687 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
690 /* Find the window class */
691 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
693 WARN("Bad class '%s'\n", cs->lpszClass );
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 (HIWORD(className))
1043 if (!(classAtom = GlobalFindAtomA( className )))
1045 ERR( "bad class name %s\n", debugres_a(className) );
1046 return 0;
1049 else
1051 classAtom = LOWORD(className);
1052 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1054 ERR( "bad atom %x\n", classAtom);
1055 return 0;
1057 className = buffer;
1060 /* Fix the coordinates */
1062 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1063 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1064 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1065 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1067 /* Create the window */
1069 cs.lpCreateParams = data;
1070 cs.hInstance = (HINSTANCE)instance;
1071 cs.hMenu = (HMENU)menu;
1072 cs.hwndParent = (HWND)parent;
1073 cs.style = style;
1074 cs.lpszName = windowName;
1075 cs.lpszClass = className;
1076 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;
1093 char buffer[256];
1095 if(!instance)
1096 instance=GetModuleHandleA(NULL);
1098 if(exStyle & WS_EX_MDICHILD)
1099 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1101 /* Find the class atom */
1103 if (HIWORD(className))
1105 if (!(classAtom = GlobalFindAtomA( className )))
1107 ERR( "bad class name %s\n", debugres_a(className) );
1108 return 0;
1111 else
1113 classAtom = LOWORD(className);
1114 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1116 ERR( "bad atom %x\n", classAtom);
1117 return 0;
1119 className = buffer;
1122 /* Create the window */
1124 cs.lpCreateParams = data;
1125 cs.hInstance = instance;
1126 cs.hMenu = menu;
1127 cs.hwndParent = parent;
1128 cs.x = x;
1129 cs.y = y;
1130 cs.cx = width;
1131 cs.cy = height;
1132 cs.style = style;
1133 cs.lpszName = windowName;
1134 cs.lpszClass = className;
1135 cs.dwExStyle = exStyle;
1137 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1141 /***********************************************************************
1142 * CreateWindowEx32W (USER32.84)
1144 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1145 LPCWSTR windowName, DWORD style, INT x,
1146 INT y, INT width, INT height,
1147 HWND parent, HMENU menu,
1148 HINSTANCE instance, LPVOID data )
1150 ATOM classAtom;
1151 CREATESTRUCTW cs;
1152 WCHAR buffer[256];
1154 if(!instance)
1155 instance=GetModuleHandleA(NULL);
1157 if(exStyle & WS_EX_MDICHILD)
1158 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1160 /* Find the class atom */
1162 if (HIWORD(className))
1164 if (!(classAtom = GlobalFindAtomW( className )))
1166 ERR( "bad class name %s\n", debugres_w(className) );
1167 return 0;
1170 else
1172 classAtom = LOWORD(className);
1173 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1175 ERR( "bad atom %x\n", classAtom);
1176 return 0;
1178 className = buffer;
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = instance;
1185 cs.hMenu = menu;
1186 cs.hwndParent = parent;
1187 cs.x = x;
1188 cs.y = y;
1189 cs.cx = width;
1190 cs.cy = height;
1191 cs.style = style;
1192 cs.lpszName = windowName;
1193 cs.lpszClass = className;
1194 cs.dwExStyle = exStyle;
1196 /* Note: we rely on the fact that CREATESTRUCT32A and */
1197 /* CREATESTRUCT32W have the same layout. */
1198 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1202 /***********************************************************************
1203 * WIN_CheckFocus
1205 static void WIN_CheckFocus( WND* pWnd )
1207 if( GetFocus16() == pWnd->hwndSelf )
1208 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1211 /***********************************************************************
1212 * WIN_SendDestroyMsg
1214 static void WIN_SendDestroyMsg( WND* pWnd )
1216 WIN_CheckFocus(pWnd);
1218 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1219 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1222 * Send the WM_DESTROY to the window.
1224 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1227 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1228 * make sure that the window still exists when we come back.
1230 if (IsWindow(pWnd->hwndSelf))
1232 HWND* pWndArray = NULL;
1233 WND* pChild = NULL;
1234 int nKidCount = 0;
1237 * Now, if the window has kids, we have to send WM_DESTROY messages
1238 * recursively to it's kids. It seems that those calls can also
1239 * trigger re-entrant calls to DestroyWindow for the kids so we must
1240 * protect against corruption of the list of siblings. We first build
1241 * a list of HWNDs representing all the kids.
1243 pChild = WIN_LockWndPtr(pWnd->child);
1244 while( pChild )
1246 nKidCount++;
1247 WIN_UpdateWndPtr(&pChild,pChild->next);
1251 * If there are no kids, we're done.
1253 if (nKidCount==0)
1254 return;
1256 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1259 * Sanity check
1261 if (pWndArray==NULL)
1262 return;
1265 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1266 * call, our linked list of siblings should be safe.
1268 nKidCount = 0;
1269 pChild = WIN_LockWndPtr(pWnd->child);
1270 while( pChild )
1272 pWndArray[nKidCount] = pChild->hwndSelf;
1273 nKidCount++;
1274 WIN_UpdateWndPtr(&pChild,pChild->next);
1278 * Now that we have a list, go through that list again and send the destroy
1279 * message to those windows. We are using the HWND to retrieve the
1280 * WND pointer so we are effectively checking that all the kid windows are
1281 * still valid before sending the message.
1283 while (nKidCount>0)
1285 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1287 if (pChild!=NULL)
1289 WIN_SendDestroyMsg( pChild );
1290 WIN_ReleaseWndPtr(pChild);
1295 * Cleanup
1297 HeapFree(GetProcessHeap(), 0, pWndArray);
1298 WIN_CheckFocus(pWnd);
1300 else
1301 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1305 /***********************************************************************
1306 * DestroyWindow16 (USER.53)
1308 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1310 return DestroyWindow(hwnd);
1314 /***********************************************************************
1315 * DestroyWindow32 (USER32.135)
1317 BOOL WINAPI DestroyWindow( HWND hwnd )
1319 WND * wndPtr;
1320 BOOL retvalue;
1322 TRACE("(%04x)\n", hwnd);
1324 /* Initialization */
1326 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1327 if (wndPtr == pWndDesktop)
1329 WIN_ReleaseWndPtr(wndPtr);
1330 return FALSE; /* Can't destroy desktop */
1333 /* Call hooks */
1335 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1337 retvalue = FALSE;
1338 goto end;
1341 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1343 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1344 /* FIXME: clean up palette - see "Internals" p.352 */
1347 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1348 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1350 /* Notify the parent window only */
1351 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1352 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1353 if( !IsWindow(hwnd) )
1355 retvalue = TRUE;
1356 goto end;
1360 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1362 /* Hide the window */
1364 if (wndPtr->dwStyle & WS_VISIBLE)
1366 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1367 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1368 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1369 if (!IsWindow(hwnd))
1371 retvalue = TRUE;
1372 goto end;
1376 /* Recursively destroy owned windows */
1378 if( !(wndPtr->dwStyle & WS_CHILD) )
1380 /* make sure top menu popup doesn't get destroyed */
1381 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1383 for (;;)
1385 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1386 while (siblingPtr)
1388 if (siblingPtr->owner == wndPtr)
1390 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1391 break;
1392 else
1393 siblingPtr->owner = NULL;
1395 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1397 if (siblingPtr)
1399 DestroyWindow( siblingPtr->hwndSelf );
1400 WIN_ReleaseWndPtr(siblingPtr);
1402 else break;
1405 if( !Options.managed || EVENT_CheckFocus() )
1406 WINPOS_ActivateOtherWindow(wndPtr);
1408 if( wndPtr->owner &&
1409 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1410 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1413 /* Send destroy messages */
1415 WIN_SendDestroyMsg( wndPtr );
1416 if (!IsWindow(hwnd))
1418 retvalue = TRUE;
1419 goto end;
1422 /* Unlink now so we won't bother with the children later on */
1424 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1426 /* Destroy the window storage */
1428 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1429 retvalue = TRUE;
1430 end:
1431 WIN_ReleaseWndPtr(wndPtr);
1432 return retvalue;
1436 /***********************************************************************
1437 * CloseWindow16 (USER.43)
1439 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1441 return CloseWindow( hwnd );
1445 /***********************************************************************
1446 * CloseWindow32 (USER32.56)
1448 BOOL WINAPI CloseWindow( HWND hwnd )
1450 WND * wndPtr = WIN_FindWndPtr( hwnd );
1451 BOOL retvalue;
1453 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1455 retvalue = FALSE;
1456 goto end;
1458 ShowWindow( hwnd, SW_MINIMIZE );
1459 retvalue = TRUE;
1460 end:
1461 WIN_ReleaseWndPtr(wndPtr);
1462 return retvalue;
1467 /***********************************************************************
1468 * OpenIcon16 (USER.44)
1470 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1472 return OpenIcon( hwnd );
1476 /***********************************************************************
1477 * OpenIcon32 (USER32.410)
1479 BOOL WINAPI OpenIcon( HWND hwnd )
1481 if (!IsIconic( hwnd )) return FALSE;
1482 ShowWindow( hwnd, SW_SHOWNORMAL );
1483 return TRUE;
1487 /***********************************************************************
1488 * WIN_FindWindow
1490 * Implementation of FindWindow() and FindWindowEx().
1492 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1493 LPCSTR title )
1495 WND *pWnd;
1496 HWND retvalue;
1497 CLASS *pClass = NULL;
1499 if (child)
1501 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1502 if (parent)
1504 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1506 retvalue = 0;
1507 goto end;
1510 else if (pWnd->parent != pWndDesktop)
1512 retvalue = 0;
1513 goto end;
1515 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1517 else
1519 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1521 retvalue = 0;
1522 goto end;
1524 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1526 if (!pWnd)
1528 retvalue = 0;
1529 goto end;
1532 /* For a child window, all siblings will have the same hInstance, */
1533 /* so we can look for the class once and for all. */
1535 if (className && (pWnd->dwStyle & WS_CHILD))
1537 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1539 retvalue = 0;
1540 goto end;
1545 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1547 if (className && !(pWnd->dwStyle & WS_CHILD))
1549 if (!((pClass = CLASS_FindClassByAtom( className, pWnd->hInstance))
1550 ||(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1552 continue; /* Skip this window */
1555 if (pClass && (pWnd->class != pClass))
1556 continue; /* Not the right class */
1558 /* Now check the title */
1560 if (!title)
1562 retvalue = pWnd->hwndSelf;
1563 goto end;
1565 if (pWnd->text && !strcmp( pWnd->text, title ))
1567 retvalue = pWnd->hwndSelf;
1568 goto end;
1571 retvalue = 0;
1572 end:
1573 WIN_ReleaseWndPtr(pWnd);
1574 return retvalue;
1579 /***********************************************************************
1580 * FindWindow16 (USER.50)
1582 HWND16 WINAPI FindWindow16( LPCSTR className, LPCSTR title )
1584 return FindWindowA( className, title );
1588 /***********************************************************************
1589 * FindWindowEx16 (USER.427)
1591 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child, LPCSTR className, LPCSTR title )
1593 return FindWindowExA( parent, child, className, title );
1597 /***********************************************************************
1598 * FindWindow32A (USER32.198)
1600 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1602 HWND ret = FindWindowExA( 0, 0, className, title );
1603 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1604 return ret;
1608 /***********************************************************************
1609 * FindWindowEx32A (USER32.199)
1611 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1612 LPCSTR className, LPCSTR title )
1614 ATOM atom = 0;
1616 if (className)
1618 /* If the atom doesn't exist, then no class */
1619 /* with this name exists either. */
1620 if (!(atom = GlobalFindAtomA( className )))
1622 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1623 return 0;
1626 return WIN_FindWindow( parent, child, atom, title );
1630 /***********************************************************************
1631 * FindWindowEx32W (USER32.200)
1633 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1634 LPCWSTR className, LPCWSTR title )
1636 ATOM atom = 0;
1637 char *buffer;
1638 HWND hwnd;
1640 if (className)
1642 /* If the atom doesn't exist, then no class */
1643 /* with this name exists either. */
1644 if (!(atom = GlobalFindAtomW( className )))
1646 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1647 return 0;
1650 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1651 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1652 HeapFree( GetProcessHeap(), 0, buffer );
1653 return hwnd;
1657 /***********************************************************************
1658 * FindWindow32W (USER32.201)
1660 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1662 return FindWindowExW( 0, 0, className, title );
1666 /**********************************************************************
1667 * WIN_GetDesktop
1668 * returns a locked pointer
1670 WND *WIN_GetDesktop(void)
1672 return WIN_LockWndPtr(pWndDesktop);
1674 /**********************************************************************
1675 * WIN_ReleaseDesktop
1676 * unlock the desktop pointer
1678 void WIN_ReleaseDesktop(void)
1680 WIN_ReleaseWndPtr(pWndDesktop);
1684 /**********************************************************************
1685 * GetDesktopWindow16 (USER.286)
1687 HWND16 WINAPI GetDesktopWindow16(void)
1689 return (HWND16)pWndDesktop->hwndSelf;
1693 /**********************************************************************
1694 * GetDesktopWindow32 (USER32.232)
1696 HWND WINAPI GetDesktopWindow(void)
1698 if (pWndDesktop) return pWndDesktop->hwndSelf;
1699 ERR( "You need the -desktop option when running with native USER\n" );
1700 ExitProcess(1);
1701 return 0;
1705 /**********************************************************************
1706 * GetDesktopHwnd (USER.278)
1708 * Exactly the same thing as GetDesktopWindow(), but not documented.
1709 * Don't ask me why...
1711 HWND16 WINAPI GetDesktopHwnd16(void)
1713 return (HWND16)pWndDesktop->hwndSelf;
1717 /*******************************************************************
1718 * EnableWindow16 (USER.34)
1720 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1722 return EnableWindow( hwnd, enable );
1726 /*******************************************************************
1727 * EnableWindow32 (USER32.172)
1729 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1731 WND *wndPtr;
1732 BOOL retvalue;
1734 TRACE("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1736 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1737 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1739 /* Enable window */
1740 wndPtr->dwStyle &= ~WS_DISABLED;
1742 if( wndPtr->flags & WIN_NATIVE )
1743 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1745 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1746 retvalue = TRUE;
1747 goto end;
1749 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1751 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1753 /* Disable window */
1754 wndPtr->dwStyle |= WS_DISABLED;
1756 if( wndPtr->flags & WIN_NATIVE )
1757 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1759 if (hwnd == GetFocus())
1761 SetFocus( 0 ); /* A disabled window can't have the focus */
1763 if (hwnd == GetCapture())
1765 ReleaseCapture(); /* A disabled window can't capture the mouse */
1767 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1768 retvalue = FALSE;
1769 goto end;
1771 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1772 end:
1773 WIN_ReleaseWndPtr(wndPtr);
1774 return retvalue;
1778 /***********************************************************************
1779 * IsWindowEnabled16 (USER.35)
1781 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1783 return IsWindowEnabled(hWnd);
1787 /***********************************************************************
1788 * IsWindowEnabled32 (USER32.349)
1790 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1792 WND * wndPtr;
1793 BOOL retvalue;
1795 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1796 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1797 WIN_ReleaseWndPtr(wndPtr);
1798 return retvalue;
1803 /***********************************************************************
1804 * IsWindowUnicode (USER32.350)
1806 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1808 WND * wndPtr;
1809 BOOL retvalue;
1811 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1812 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1813 WIN_ReleaseWndPtr(wndPtr);
1814 return retvalue;
1818 /**********************************************************************
1819 * GetWindowWord16 (USER.133)
1821 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1823 return GetWindowWord( hwnd, offset );
1827 /**********************************************************************
1828 * GetWindowWord32 (USER32.314)
1830 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1832 WORD retvalue;
1833 WND * wndPtr = WIN_FindWndPtr( hwnd );
1834 if (!wndPtr) return 0;
1835 if (offset >= 0)
1837 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1839 WARN("Invalid offset %d\n", offset );
1840 retvalue = 0;
1841 goto end;
1843 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1844 goto end;
1846 switch(offset)
1848 case GWW_ID:
1849 if (HIWORD(wndPtr->wIDmenu))
1850 WARN("GWW_ID: discards high bits of 0x%08x!\n",
1851 wndPtr->wIDmenu);
1852 retvalue = (WORD)wndPtr->wIDmenu;
1853 goto end;
1854 case GWW_HWNDPARENT:
1855 retvalue = GetParent(hwnd);
1856 goto end;
1857 case GWW_HINSTANCE:
1858 if (HIWORD(wndPtr->hInstance))
1859 WARN("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1860 wndPtr->hInstance);
1861 retvalue = (WORD)wndPtr->hInstance;
1862 goto end;
1863 default:
1864 WARN("Invalid offset %d\n", offset );
1865 retvalue = 0;
1866 goto end;
1868 end:
1869 WIN_ReleaseWndPtr(wndPtr);
1870 return retvalue;
1873 /**********************************************************************
1874 * SetWindowWord16 (USER.134)
1876 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1878 return SetWindowWord( hwnd, offset, newval );
1882 /**********************************************************************
1883 * SetWindowWord32 (USER32.524)
1885 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1887 WORD *ptr, retval;
1888 WND * wndPtr = WIN_FindWndPtr( hwnd );
1889 if (!wndPtr) return 0;
1890 if (offset >= 0)
1892 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1894 WARN("Invalid offset %d\n", offset );
1895 retval = 0;
1896 goto end;
1898 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1900 else switch(offset)
1902 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1903 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1904 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1905 goto end;
1906 default:
1907 WARN("Invalid offset %d\n", offset );
1908 retval = 0;
1909 goto end;
1911 retval = *ptr;
1912 *ptr = newval;
1913 end:
1914 WIN_ReleaseWndPtr(wndPtr);
1915 return retval;
1919 /**********************************************************************
1920 * WIN_GetWindowLong
1922 * Helper function for GetWindowLong().
1924 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1926 LONG retvalue;
1927 WND * wndPtr = WIN_FindWndPtr( hwnd );
1928 if (!wndPtr) return 0;
1929 if (offset >= 0)
1931 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1933 WARN("Invalid offset %d\n", offset );
1934 retvalue = 0;
1935 goto end;
1937 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1938 /* Special case for dialog window procedure */
1939 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1941 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1942 goto end;
1944 goto end;
1946 switch(offset)
1948 case GWL_USERDATA: retvalue = wndPtr->userdata;
1949 goto end;
1950 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1951 goto end;
1952 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1953 goto end;
1954 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1955 goto end;
1956 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1957 type );
1958 goto end;
1959 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1960 goto end;
1961 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1962 goto end;
1963 default:
1964 WARN("Unknown offset %d\n", offset );
1966 retvalue = 0;
1967 end:
1968 WIN_ReleaseWndPtr(wndPtr);
1969 return retvalue;
1973 /**********************************************************************
1974 * WIN_SetWindowLong
1976 * Helper function for SetWindowLong().
1978 * 0 is the failure code. However, in the case of failure SetLastError
1979 * must be set to distinguish between a 0 return value and a failure.
1981 * FIXME: The error values for SetLastError may not be right. Can
1982 * someone check with the real thing?
1984 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1985 WINDOWPROCTYPE type )
1987 LONG *ptr, retval;
1988 WND * wndPtr = WIN_FindWndPtr( hwnd );
1989 STYLESTRUCT style;
1991 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1993 if (!wndPtr)
1995 /* Is this the right error? */
1996 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1997 return 0;
2000 if (offset >= 0)
2002 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
2004 WARN("Invalid offset %d\n", offset );
2006 /* Is this the right error? */
2007 SetLastError( ERROR_OUTOFMEMORY );
2009 retval = 0;
2010 goto end;
2012 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
2013 /* Special case for dialog window procedure */
2014 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2016 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2017 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2018 type, WIN_PROC_WINDOW );
2019 goto end;
2022 else switch(offset)
2024 case GWL_ID:
2025 ptr = (DWORD*)&wndPtr->wIDmenu;
2026 break;
2027 case GWL_HINSTANCE:
2028 retval = SetWindowWord( hwnd, offset, newval );
2029 goto end;
2030 case GWL_WNDPROC:
2031 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2032 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2033 type, WIN_PROC_WINDOW );
2034 goto end;;
2035 case GWL_STYLE:
2036 style.styleOld = wndPtr->dwStyle;
2037 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2038 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2040 if (wndPtr->flags & WIN_ISWIN32)
2041 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2042 wndPtr->dwStyle = style.styleNew;
2043 if (wndPtr->flags & WIN_ISWIN32)
2044 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2045 retval = style.styleOld;
2046 goto end;
2048 case GWL_USERDATA:
2049 ptr = &wndPtr->userdata;
2050 break;
2051 case GWL_EXSTYLE:
2052 style.styleOld = wndPtr->dwExStyle;
2053 style.styleNew = newval;
2054 if (wndPtr->flags & WIN_ISWIN32)
2055 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2056 wndPtr->dwExStyle = newval;
2057 if (wndPtr->flags & WIN_ISWIN32)
2058 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2059 retval = style.styleOld;
2060 goto end;
2062 default:
2063 WARN("Invalid offset %d\n", offset );
2065 /* Don't think this is right error but it should do */
2066 SetLastError( ERROR_OUTOFMEMORY );
2068 retval = 0;
2069 goto end;
2071 retval = *ptr;
2072 *ptr = newval;
2073 end:
2074 WIN_ReleaseWndPtr(wndPtr);
2075 return retval;
2079 /**********************************************************************
2080 * GetWindowLong16 (USER.135)
2082 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2084 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2088 /**********************************************************************
2089 * GetWindowLong32A (USER32.305)
2091 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2093 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2097 /**********************************************************************
2098 * GetWindowLong32W (USER32.306)
2100 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2102 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2106 /**********************************************************************
2107 * SetWindowLong16 (USER.136)
2109 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2111 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2115 /**********************************************************************
2116 * SetWindowLong32A (USER32.517)
2118 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2120 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2124 /**********************************************************************
2125 * SetWindowLong32W (USER32.518) Set window attribute
2127 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2128 * value in a window's extra memory.
2130 * The _hwnd_ parameter specifies the window. is the handle to a
2131 * window that has extra memory. The _newval_ parameter contains the
2132 * new attribute or extra memory value. If positive, the _offset_
2133 * parameter is the byte-addressed location in the window's extra
2134 * memory to set. If negative, _offset_ specifies the window
2135 * attribute to set, and should be one of the following values:
2137 * GWL_EXSTYLE The window's extended window style
2139 * GWL_STYLE The window's window style.
2141 * GWL_WNDPROC Pointer to the window's window procedure.
2143 * GWL_HINSTANCE The window's pplication instance handle.
2145 * GWL_ID The window's identifier.
2147 * GWL_USERDATA The window's user-specified data.
2149 * If the window is a dialog box, the _offset_ parameter can be one of
2150 * the following values:
2152 * DWL_DLGPROC The address of the window's dialog box procedure.
2154 * DWL_MSGRESULT The return value of a message
2155 * that the dialog box procedure processed.
2157 * DWL_USER Application specific information.
2159 * RETURNS
2161 * If successful, returns the previous value located at _offset_. Otherwise,
2162 * returns 0.
2164 * NOTES
2166 * Extra memory for a window class is specified by a nonzero cbWndExtra
2167 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2168 * time of class creation.
2170 * Using GWL_WNDPROC to set a new window procedure effectively creates
2171 * a window subclass. Use CallWindowProc() in the new windows procedure
2172 * to pass messages to the superclass's window procedure.
2174 * The user data is reserved for use by the application which created
2175 * the window.
2177 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2178 * instead, call the EnableWindow() function to change the window's
2179 * disabled state.
2181 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2182 * SetParent() instead.
2184 * Win95:
2185 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2186 * it sends WM_STYLECHANGING before changing the settings
2187 * and WM_STYLECHANGED afterwards.
2188 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2190 * BUGS
2192 * GWL_STYLE does not dispatch WM_STYLE... messages.
2194 * CONFORMANCE
2196 * ECMA-234, Win32
2199 LONG WINAPI SetWindowLongW(
2200 HWND hwnd, /* window to alter */
2201 INT offset, /* offset, in bytes, of location to alter */
2202 LONG newval /* new value of location */
2204 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2208 /*******************************************************************
2209 * GetWindowText16 (USER.36)
2211 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2213 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2217 /*******************************************************************
2218 * GetWindowText32A (USER32.309)
2220 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2222 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2223 (LPARAM)lpString );
2226 /*******************************************************************
2227 * InternalGetWindowText (USER32.326)
2229 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2231 FIXME("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2232 return GetWindowTextW(hwnd,lpString,nMaxCount);
2236 /*******************************************************************
2237 * GetWindowText32W (USER32.312)
2239 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2241 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2242 (LPARAM)lpString );
2246 /*******************************************************************
2247 * SetWindowText16 (USER.37)
2249 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2251 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2255 /*******************************************************************
2256 * SetWindowText32A (USER32.521)
2258 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2260 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2264 /*******************************************************************
2265 * SetWindowText32W (USER32.523)
2267 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2269 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2273 /*******************************************************************
2274 * GetWindowTextLength16 (USER.38)
2276 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2278 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2282 /*******************************************************************
2283 * GetWindowTextLength32A (USER32.310)
2285 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2287 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2290 /*******************************************************************
2291 * GetWindowTextLength32W (USER32.311)
2293 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2295 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2299 /*******************************************************************
2300 * IsWindow16 (USER.47)
2302 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2304 CURRENT_STACK16->es = USER_HeapSel;
2305 return IsWindow( hwnd );
2309 /*******************************************************************
2310 * IsWindow32 (USER32.348)
2312 BOOL WINAPI IsWindow( HWND hwnd )
2314 WND * wndPtr;
2315 BOOL retvalue;
2317 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2318 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2319 WIN_ReleaseWndPtr(wndPtr);
2320 return retvalue;
2325 /*****************************************************************
2326 * GetParent16 (USER.46)
2328 HWND16 WINAPI GetParent16( HWND16 hwnd )
2330 return (HWND16)GetParent( hwnd );
2334 /*****************************************************************
2335 * GetParent32 (USER32.278)
2337 HWND WINAPI GetParent( HWND hwnd )
2339 WND *wndPtr;
2340 HWND retvalue;
2342 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2343 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2345 WIN_ReleaseWndPtr(wndPtr);
2346 return 0;
2348 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2349 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2351 WIN_ReleaseWndPtr(wndPtr);
2352 return retvalue;
2356 /*****************************************************************
2357 * WIN_GetTopParent
2359 * Get the top-level parent for a child window.
2360 * returns a locked pointer
2362 WND* WIN_GetTopParentPtr( WND* pWnd )
2364 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2366 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2368 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2370 return tmpWnd;
2373 /*****************************************************************
2374 * WIN_GetTopParent
2376 * Get the top-level parent for a child window.
2378 HWND WIN_GetTopParent( HWND hwnd )
2380 HWND retvalue;
2381 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2382 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2384 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2385 WIN_ReleaseWndPtr(tmpPtr);
2386 WIN_ReleaseWndPtr(wndPtr);
2387 return retvalue;
2391 /*****************************************************************
2392 * SetParent16 (USER.233)
2394 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2396 return SetParent( hwndChild, hwndNewParent );
2400 /*****************************************************************
2401 * SetParent32 (USER32.495)
2403 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2405 WND *wndPtr;
2406 DWORD dwStyle;
2407 WND *pWndNewParent;
2408 WND *pWndOldParent;
2409 HWND retvalue;
2412 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2414 dwStyle = wndPtr->dwStyle;
2416 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2417 : WIN_LockWndPtr(pWndDesktop);
2419 /* Windows hides the window first, then shows it again
2420 * including the WM_SHOWWINDOW messages and all */
2421 if (dwStyle & WS_VISIBLE)
2422 ShowWindow( hwndChild, SW_HIDE );
2424 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2426 /* SetParent32 additionally needs to make hwndChild the topmost window
2427 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2428 WM_WINDOWPOSCHANGED notification messages.
2430 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2431 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2432 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2433 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2435 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2437 WIN_ReleaseWndPtr(pWndOldParent);
2438 WIN_ReleaseWndPtr(pWndNewParent);
2439 WIN_ReleaseWndPtr(wndPtr);
2441 return retvalue;
2445 /*******************************************************************
2446 * IsChild16 (USER.48)
2448 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2450 return IsChild(parent,child);
2454 /*******************************************************************
2455 * IsChild32 (USER32.339)
2457 BOOL WINAPI IsChild( HWND parent, HWND child )
2459 WND * wndPtr = WIN_FindWndPtr( child );
2460 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2462 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2463 if (wndPtr->hwndSelf == parent)
2465 WIN_ReleaseWndPtr(wndPtr);
2466 return TRUE;
2469 WIN_ReleaseWndPtr(wndPtr);
2470 return FALSE;
2474 /***********************************************************************
2475 * IsWindowVisible16 (USER.49)
2477 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2479 return IsWindowVisible(hwnd);
2483 /***********************************************************************
2484 * IsWindowVisible32 (USER32.351)
2486 BOOL WINAPI IsWindowVisible( HWND hwnd )
2488 BOOL retval;
2489 WND *wndPtr = WIN_FindWndPtr( hwnd );
2490 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2492 if (!(wndPtr->dwStyle & WS_VISIBLE))
2494 WIN_ReleaseWndPtr(wndPtr);
2495 return FALSE;
2497 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2499 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2500 WIN_ReleaseWndPtr(wndPtr);
2501 return retval;
2506 /***********************************************************************
2507 * WIN_IsWindowDrawable
2509 * hwnd is drawable when it is visible, all parents are not
2510 * minimized, and it is itself not minimized unless we are
2511 * trying to draw its default class icon.
2513 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2515 if( (wnd->dwStyle & WS_MINIMIZE &&
2516 icon && wnd->class->hIcon) ||
2517 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2518 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2519 if( wnd->dwStyle & WS_MINIMIZE ||
2520 !(wnd->dwStyle & WS_VISIBLE) ) break;
2521 return (wnd == NULL);
2525 /*******************************************************************
2526 * GetTopWindow16 (USER.229)
2528 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2530 return GetTopWindow(hwnd);
2534 /*******************************************************************
2535 * GetTopWindow32 (USER.229)
2537 HWND WINAPI GetTopWindow( HWND hwnd )
2539 HWND retval;
2540 WND * wndPtr = NULL;
2542 if (hwnd!=0)
2543 wndPtr = WIN_FindWndPtr( hwnd );
2544 else
2545 wndPtr = WIN_GetDesktop();
2547 if (wndPtr && wndPtr->child)
2549 retval = wndPtr->child->hwndSelf;
2551 else retval = 0;
2552 WIN_ReleaseWndPtr(wndPtr);
2553 return retval;
2557 /*******************************************************************
2558 * GetWindow16 (USER.262)
2560 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2562 return GetWindow( hwnd,rel );
2566 /*******************************************************************
2567 * GetWindow32 (USER32.302)
2569 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2571 HWND retval;
2573 WND * wndPtr = WIN_FindWndPtr( hwnd );
2574 if (!wndPtr) return 0;
2575 switch(rel)
2577 case GW_HWNDFIRST:
2578 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2579 else retval = 0;
2580 goto end;
2582 case GW_HWNDLAST:
2583 if (!wndPtr->parent)
2585 retval = 0; /* Desktop window */
2586 goto end;
2588 while (wndPtr->next)
2590 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2592 retval = wndPtr->hwndSelf;
2593 goto end;
2595 case GW_HWNDNEXT:
2596 if (!wndPtr->next) retval = 0;
2597 else retval = wndPtr->next->hwndSelf;
2598 goto end;
2600 case GW_HWNDPREV:
2601 if (!wndPtr->parent)
2603 retval = 0; /* Desktop window */
2604 goto end;
2606 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2607 if (wndPtr->hwndSelf == hwnd)
2609 retval = 0; /* First in list */
2610 goto end;
2612 while (wndPtr->next)
2614 if (wndPtr->next->hwndSelf == hwnd)
2616 retval = wndPtr->hwndSelf;
2617 goto end;
2619 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2621 retval = 0;
2622 goto end;
2624 case GW_OWNER:
2625 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2626 goto end;
2628 case GW_CHILD:
2629 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2630 goto end;
2632 retval = 0;
2633 end:
2634 WIN_ReleaseWndPtr(wndPtr);
2635 return retval;
2639 /*******************************************************************
2640 * GetNextWindow16 (USER.230)
2642 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2644 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2645 return GetWindow16( hwnd, flag );
2648 /*******************************************************************
2649 * ShowOwnedPopups16 (USER.265)
2651 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2653 ShowOwnedPopups( owner, fShow );
2657 /*******************************************************************
2658 * ShowOwnedPopups32 (USER32.531)
2660 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2662 UINT totalChild=0, count=0;
2664 WND **pWnd = WIN_BuildWinArray(WIN_GetDesktop(), 0, &totalChild);
2666 if (!pWnd) return TRUE;
2668 for (; count < totalChild; count++)
2670 if (pWnd[count]->owner && (pWnd[count]->owner->hwndSelf == owner) && (pWnd[count]->dwStyle & WS_POPUP))
2671 SendMessageA(pWnd[count]->hwndSelf, WM_SHOWWINDOW, fShow ? SW_SHOW : SW_HIDE,IsIconic(owner) ? SW_PARENTOPENING : SW_PARENTCLOSING);
2674 WIN_ReleaseDesktop();
2675 WIN_ReleaseWinArray(pWnd);
2676 return TRUE;
2680 /*******************************************************************
2681 * GetLastActivePopup16 (USER.287)
2683 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2685 return GetLastActivePopup( hwnd );
2688 /*******************************************************************
2689 * GetLastActivePopup32 (USER32.256)
2691 HWND WINAPI GetLastActivePopup( HWND hwnd )
2693 WND *wndPtr;
2694 HWND retval;
2695 wndPtr = WIN_FindWndPtr(hwnd);
2696 if (!wndPtr) return hwnd;
2697 retval = wndPtr->hwndLastActive;
2698 WIN_ReleaseWndPtr(wndPtr);
2699 return retval;
2703 /*******************************************************************
2704 * WIN_BuildWinArray
2706 * Build an array of pointers to the children of a given window.
2707 * The array must be freed with WIN_ReleaseWinArray. Return NULL
2708 * when no windows are found.
2710 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2712 /* Future : this function will lock all windows associated with this array */
2714 WND **list, **ppWnd;
2715 WND *pWnd;
2716 UINT count = 0, skipOwned, skipHidden;
2717 DWORD skipFlags;
2719 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2720 skipOwned = bwaFlags & BWA_SKIPOWNED;
2721 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2722 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2724 /* First count the windows */
2726 if (!wndPtr)
2727 wndPtr = WIN_GetDesktop();
2729 pWnd = WIN_LockWndPtr(wndPtr->child);
2730 while (pWnd)
2732 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2733 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2734 count++;
2735 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2738 if( count )
2740 /* Now build the list of all windows */
2742 if ((list = (WND **)HeapAlloc( GetProcessHeap(), 0, sizeof(WND *) * (count + 1))))
2744 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2746 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2747 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2749 *ppWnd++ = pWnd;
2750 count++;
2753 WIN_ReleaseWndPtr(pWnd);
2754 *ppWnd = NULL;
2756 else count = 0;
2757 } else list = NULL;
2759 if( pTotal ) *pTotal = count;
2760 return list;
2762 /*******************************************************************
2763 * WIN_ReleaseWinArray
2765 void WIN_ReleaseWinArray(WND **wndArray)
2767 /* Future : this function will also unlock all windows associated with wndArray */
2768 HeapFree( GetProcessHeap(), 0, wndArray );
2772 /*******************************************************************
2773 * EnumWindows16 (USER.54)
2775 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2777 WND **list, **ppWnd;
2779 /* We have to build a list of all windows first, to avoid */
2780 /* unpleasant side-effects, for instance if the callback */
2781 /* function changes the Z-order of the windows. */
2783 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2785 WIN_ReleaseDesktop();
2786 return FALSE;
2789 /* Now call the callback function for every window */
2791 for (ppWnd = list; *ppWnd; ppWnd++)
2793 LRESULT lpEnumFuncRetval;
2794 int iWndsLocks = 0;
2795 /* Make sure that the window still exists */
2796 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2798 /* To avoid any deadlocks, all the locks on the windows
2799 structures must be suspended before the control
2800 is passed to the application */
2801 iWndsLocks = WIN_SuspendWndsLock();
2802 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2803 WIN_RestoreWndsLock(iWndsLocks);
2805 if (!lpEnumFuncRetval) break;
2807 WIN_ReleaseWinArray(list);
2808 WIN_ReleaseDesktop();
2809 return TRUE;
2813 /*******************************************************************
2814 * EnumWindows32 (USER32.193)
2816 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2818 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2822 /**********************************************************************
2823 * EnumTaskWindows16 (USER.225)
2825 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2826 LPARAM lParam )
2828 WND **list, **ppWnd;
2830 /* This function is the same as EnumWindows(), */
2831 /* except for an added check on the window's task. */
2833 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2835 WIN_ReleaseDesktop();
2836 return FALSE;
2839 /* Now call the callback function for every window */
2841 for (ppWnd = list; *ppWnd; ppWnd++)
2843 LRESULT funcRetval;
2844 int iWndsLocks = 0;
2845 /* Make sure that the window still exists */
2846 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2847 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2849 /* To avoid any deadlocks, all the locks on the windows
2850 structures must be suspended before the control
2851 is passed to the application */
2852 iWndsLocks = WIN_SuspendWndsLock();
2853 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2854 WIN_RestoreWndsLock(iWndsLocks);
2856 if (!funcRetval) break;
2858 WIN_ReleaseWinArray(list);
2859 WIN_ReleaseDesktop();
2860 return TRUE;
2864 /**********************************************************************
2865 * EnumThreadWindows (USER32.190)
2867 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2869 TEB *teb = THREAD_IdToTEB(id);
2871 return (BOOL16)EnumTaskWindows16(teb->htask16, (WNDENUMPROC16)func, lParam);
2875 /**********************************************************************
2876 * WIN_EnumChildWindows
2878 * Helper function for EnumChildWindows().
2880 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2881 LPARAM lParam )
2883 WND **childList;
2884 BOOL16 ret = FALSE;
2886 for ( ; *ppWnd; ppWnd++)
2888 int iWndsLocks = 0;
2890 /* Make sure that the window still exists */
2891 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2892 /* Build children list first */
2893 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2895 /* To avoid any deadlocks, all the locks on the windows
2896 structures must be suspended before the control
2897 is passed to the application */
2898 iWndsLocks = WIN_SuspendWndsLock();
2899 ret = func( (*ppWnd)->hwndSelf, lParam );
2900 WIN_RestoreWndsLock(iWndsLocks);
2902 if (childList)
2904 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2905 WIN_ReleaseWinArray(childList);
2907 if (!ret) return FALSE;
2909 return TRUE;
2913 /**********************************************************************
2914 * EnumChildWindows16 (USER.55)
2916 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2917 LPARAM lParam )
2919 WND **list, *pParent;
2921 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2922 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2924 WIN_ReleaseWndPtr(pParent);
2925 return FALSE;
2927 WIN_EnumChildWindows( list, func, lParam );
2928 WIN_ReleaseWinArray(list);
2929 WIN_ReleaseWndPtr(pParent);
2930 return TRUE;
2934 /**********************************************************************
2935 * EnumChildWindows32 (USER32.178)
2937 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2938 LPARAM lParam )
2940 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2941 lParam );
2945 /*******************************************************************
2946 * AnyPopup16 (USER.52)
2948 BOOL16 WINAPI AnyPopup16(void)
2950 return AnyPopup();
2954 /*******************************************************************
2955 * AnyPopup32 (USER32.4)
2957 BOOL WINAPI AnyPopup(void)
2959 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2960 BOOL retvalue;
2962 while (wndPtr)
2964 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2966 retvalue = TRUE;
2967 goto end;
2969 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2971 retvalue = FALSE;
2972 end:
2973 WIN_ReleaseWndPtr(wndPtr);
2974 return retvalue;
2978 /*******************************************************************
2979 * FlashWindow16 (USER.105)
2981 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2983 return FlashWindow( hWnd, bInvert );
2987 /*******************************************************************
2988 * FlashWindow32 (USER32.202)
2990 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2992 WND *wndPtr = WIN_FindWndPtr(hWnd);
2994 TRACE("%04x\n", hWnd);
2996 if (!wndPtr) return FALSE;
2998 if (wndPtr->dwStyle & WS_MINIMIZE)
3000 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3002 HDC hDC = GetDC(hWnd);
3004 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3005 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3007 ReleaseDC( hWnd, hDC );
3008 wndPtr->flags |= WIN_NCACTIVATED;
3010 else
3012 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3013 RDW_UPDATENOW | RDW_FRAME, 0 );
3014 wndPtr->flags &= ~WIN_NCACTIVATED;
3016 WIN_ReleaseWndPtr(wndPtr);
3017 return TRUE;
3019 else
3021 WPARAM16 wparam;
3022 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3023 else wparam = (hWnd == GetActiveWindow());
3025 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3026 WIN_ReleaseWndPtr(wndPtr);
3027 return wparam;
3032 /*******************************************************************
3033 * SetSysModalWindow16 (USER.188)
3035 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3037 HWND hWndOldModal = hwndSysModal;
3038 hwndSysModal = hWnd;
3039 FIXME("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3040 return hWndOldModal;
3044 /*******************************************************************
3045 * GetSysModalWindow16 (USER.52)
3047 HWND16 WINAPI GetSysModalWindow16(void)
3049 return hwndSysModal;
3053 /*******************************************************************
3054 * GetWindowContextHelpId (USER32.303)
3056 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3058 DWORD retval;
3059 WND *wnd = WIN_FindWndPtr( hwnd );
3060 if (!wnd) return 0;
3061 retval = wnd->helpContext;
3062 WIN_ReleaseWndPtr(wnd);
3063 return retval;
3067 /*******************************************************************
3068 * SetWindowContextHelpId (USER32.515)
3070 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3072 WND *wnd = WIN_FindWndPtr( hwnd );
3073 if (!wnd) return FALSE;
3074 wnd->helpContext = id;
3075 WIN_ReleaseWndPtr(wnd);
3076 return TRUE;
3080 /*******************************************************************
3081 * DRAG_QueryUpdate
3083 * recursively find a child that contains spDragInfo->pt point
3084 * and send WM_QUERYDROPOBJECT
3086 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3088 BOOL16 wParam,bResult = 0;
3089 POINT pt;
3090 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3091 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3092 RECT tempRect;
3094 if( !ptrQueryWnd || !ptrDragInfo )
3096 WIN_ReleaseWndPtr(ptrQueryWnd);
3097 return 0;
3100 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3102 GetWindowRect(hQueryWnd,&tempRect);
3104 if( !PtInRect(&tempRect,pt) ||
3105 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3107 WIN_ReleaseWndPtr(ptrQueryWnd);
3108 return 0;
3111 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3113 tempRect = ptrQueryWnd->rectClient;
3114 if(ptrQueryWnd->dwStyle & WS_CHILD)
3115 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3116 (LPPOINT)&tempRect, 2 );
3118 if (PtInRect( &tempRect, pt))
3120 wParam = 0;
3122 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3124 if( ptrWnd->dwStyle & WS_VISIBLE )
3126 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3127 if (PtInRect( &tempRect, pt )) break;
3131 if(ptrWnd)
3133 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3134 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3135 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3136 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3137 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3139 WIN_ReleaseWndPtr(ptrWnd);
3142 if(bResult)
3144 WIN_ReleaseWndPtr(ptrQueryWnd);
3145 return bResult;
3148 else wParam = 1;
3150 else wParam = 1;
3152 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3154 ptrDragInfo->hScope = hQueryWnd;
3156 bResult = ( bNoSend )
3157 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3158 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3159 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3160 if( !bResult )
3161 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3163 WIN_ReleaseWndPtr(ptrQueryWnd);
3164 return bResult;
3168 /*******************************************************************
3169 * DragDetect (USER.465)
3171 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3173 POINT pt32;
3174 CONV_POINT16TO32( &pt, &pt32 );
3175 return DragDetect( hWnd, pt32 );
3178 /*******************************************************************
3179 * DragDetect32 (USER32.151)
3181 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3183 MSG16 msg;
3184 RECT16 rect;
3186 rect.left = pt.x - wDragWidth;
3187 rect.right = pt.x + wDragWidth;
3189 rect.top = pt.y - wDragHeight;
3190 rect.bottom = pt.y + wDragHeight;
3192 SetCapture(hWnd);
3194 while(1)
3196 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3198 if( msg.message == WM_LBUTTONUP )
3200 ReleaseCapture();
3201 return 0;
3203 if( msg.message == WM_MOUSEMOVE )
3205 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3207 ReleaseCapture();
3208 return 1;
3212 WaitMessage();
3214 return 0;
3217 /******************************************************************************
3218 * DragObject16 (USER.464)
3220 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3221 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3223 MSG16 msg;
3224 LPDRAGINFO lpDragInfo;
3225 SEGPTR spDragInfo;
3226 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3227 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3228 WND *wndPtr = WIN_FindWndPtr(hWnd);
3229 HCURSOR16 hCurrentCursor = 0;
3230 HWND16 hCurrentWnd = 0;
3232 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3233 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3235 if( !lpDragInfo || !spDragInfo )
3237 WIN_ReleaseWndPtr(wndPtr);
3238 return 0L;
3241 hBummer = LoadCursor16(0, IDC_BUMMER16);
3243 if( !hBummer || !wndPtr )
3245 GlobalFree16(hDragInfo);
3246 WIN_ReleaseWndPtr(wndPtr);
3247 return 0L;
3250 if(hCursor)
3252 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3254 GlobalFree16(hDragInfo);
3255 WIN_ReleaseWndPtr(wndPtr);
3256 return 0L;
3259 if( hDragCursor == hCursor ) hDragCursor = 0;
3260 else hCursor = hDragCursor;
3262 hOldCursor = SetCursor(hDragCursor);
3265 lpDragInfo->hWnd = hWnd;
3266 lpDragInfo->hScope = 0;
3267 lpDragInfo->wFlags = wObj;
3268 lpDragInfo->hList = szList; /* near pointer! */
3269 lpDragInfo->hOfStruct = hOfStruct;
3270 lpDragInfo->l = 0L;
3272 SetCapture(hWnd);
3273 ShowCursor( TRUE );
3277 do{ WaitMessage(); }
3278 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3280 *(lpDragInfo+1) = *lpDragInfo;
3282 lpDragInfo->pt = msg.pt;
3284 /* update DRAGINFO struct */
3285 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3287 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3288 hCurrentCursor = hCursor;
3289 else
3291 hCurrentCursor = hBummer;
3292 lpDragInfo->hScope = 0;
3294 if( hCurrentCursor )
3295 SetCursor(hCurrentCursor);
3297 /* send WM_DRAGLOOP */
3298 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3299 (LPARAM) spDragInfo );
3300 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3301 if( hCurrentWnd != lpDragInfo->hScope )
3303 if( hCurrentWnd )
3304 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3305 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3306 HIWORD(spDragInfo)) );
3307 hCurrentWnd = lpDragInfo->hScope;
3308 if( hCurrentWnd )
3309 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3311 else
3312 if( hCurrentWnd )
3313 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3315 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3317 ReleaseCapture();
3318 ShowCursor( FALSE );
3320 if( hCursor )
3322 SetCursor( hOldCursor );
3323 if (hDragCursor) DestroyCursor( hDragCursor );
3326 if( hCurrentCursor != hBummer )
3327 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3328 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3329 else
3330 msg.lParam = 0;
3331 GlobalFree16(hDragInfo);
3332 WIN_ReleaseWndPtr(wndPtr);
3334 return (DWORD)(msg.lParam);