Added RtlUnwind in ntdll, and made kernel32 spec entry a forward to
[wine/multimedia.git] / windows / win.c
blobec4e749544b948d92dd5d2fca5093572a20766cd
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 "sysmetrics.h"
18 #include "cursoricon.h"
19 #include "hook.h"
20 #include "menu.h"
21 #include "message.h"
22 #include "nonclient.h"
23 #include "queue.h"
24 #include "winpos.h"
25 #include "shm_main_blk.h"
26 #include "dde_proc.h"
27 #include "clipboard.h"
28 #include "winproc.h"
29 #include "task.h"
30 #include "thread.h"
31 #include "process.h"
32 #include "debugtools.h"
33 #include "winerror.h"
34 #include "mdi.h"
35 #include "local.h"
36 #include "desktop.h"
38 DECLARE_DEBUG_CHANNEL(msg)
39 DECLARE_DEBUG_CHANNEL(win)
41 /**********************************************************************/
43 WND_DRIVER *WND_Driver = NULL;
45 /* Desktop window */
46 static WND *pWndDesktop = NULL;
48 static HWND hwndSysModal = 0;
50 static WORD wDragWidth = 4;
51 static WORD wDragHeight= 3;
53 /* thread safeness */
54 static CRITICAL_SECTION WIN_CritSection;
56 /***********************************************************************
57 * WIN_Init
58 */
59 void WIN_Init( void )
61 /* Initialisation of the critical section for thread safeness */
62 InitializeCriticalSection(&WIN_CritSection);
63 MakeCriticalSectionGlobal(&WIN_CritSection);
66 /***********************************************************************
67 * WIN_LockWnds
69 * Locks access to all WND structures for thread safeness
71 void WIN_LockWnds()
73 EnterCriticalSection(&WIN_CritSection);
76 /***********************************************************************
77 * WIN_UnlockWnds
79 * Unlocks access to all WND structures
81 void WIN_UnlockWnds()
83 LeaveCriticalSection(&WIN_CritSection);
85 /***********************************************************************
86 * WIN_SuspendWndsLock
88 * Suspend the lock on WND structures.
89 * Returns the number of locks suspended
91 int WIN_SuspendWndsLock()
93 int isuspendedLocks = 0;
95 /* make sure that the lock is not suspended by different thread than
96 the owning thread */
97 if(WIN_CritSection.OwningThread != GetCurrentThreadId())
99 return 0;
101 /* set the value of isuspendedlock to the actual recursion count
102 of the critical section */
103 isuspendedLocks = WIN_CritSection.RecursionCount;
104 /* set the recursion count of the critical section to 1
105 so the owning thread will be able to leave it */
106 WIN_CritSection.RecursionCount = 1;
107 /* leave critical section*/
108 WIN_UnlockWnds();
110 return isuspendedLocks;
113 /***********************************************************************
114 * WIN_RestoreWndsLock
116 * Restore the suspended locks on WND structures
118 void WIN_RestoreWndsLock(int ipreviousLocks)
120 if(!ipreviousLocks)
122 return;
124 /* restore the lock */
125 WIN_LockWnds();
126 /* set the recursion count of the critical section to the
127 value of suspended locks (given by WIN_SuspendWndsLock())*/
128 WIN_CritSection.RecursionCount = ipreviousLocks;
132 /***********************************************************************
133 * WIN_FindWndPtr
135 * Return a pointer to the WND structure corresponding to a HWND.
137 WND * WIN_FindWndPtr( HWND hwnd )
139 WND * ptr;
141 if (!hwnd || HIWORD(hwnd)) goto error2;
142 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
143 /* Lock all WND structures for thread safeness*/
144 WIN_LockWnds();
145 /*and increment destruction monitoring*/
146 ptr->irefCount++;
148 if (ptr->dwMagic != WND_MAGIC) goto error;
149 if (ptr->hwndSelf != hwnd)
151 ERR_(win)("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
152 goto error;
154 /* returns a locked pointer */
155 return ptr;
156 error:
157 /* Unlock all WND structures for thread safeness*/
158 WIN_UnlockWnds();
159 /* and decrement destruction monitoring value */
160 ptr->irefCount--;
162 error2:
163 if ( hwnd!=0 )
164 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
165 return NULL;
168 /***********************************************************************
169 * WIN_LockWndPtr
171 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
172 * but by initWndPtr;
173 * Returns the locked initialisation pointer
175 WND *WIN_LockWndPtr(WND *initWndPtr)
177 if(!initWndPtr) return 0;
179 /* Lock all WND structures for thread safeness*/
180 WIN_LockWnds();
181 /*and increment destruction monitoring*/
182 initWndPtr->irefCount++;
184 return initWndPtr;
188 /***********************************************************************
189 * WIN_ReleaseWndPtr
191 * Release the pointer to the WND structure.
193 void WIN_ReleaseWndPtr(WND *wndPtr)
195 if(!wndPtr) return;
197 /*Decrement destruction monitoring value*/
198 wndPtr->irefCount--;
199 /* Check if it's time to release the memory*/
200 /* Check if it's time to release the memory*/
201 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
203 /* Release memory */
204 USER_HEAP_FREE( wndPtr->hwndSelf);
206 else if(wndPtr->irefCount < 0)
208 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
209 TRACE_(win)("forgot a Lock on %p somewhere\n",wndPtr);
211 /*unlock all WND structures for thread safeness*/
212 WIN_UnlockWnds();
215 /***********************************************************************
216 * WIN_UpdateWndPtr
218 * Updates the value of oldPtr to newPtr.
220 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
222 WND *tmpWnd = NULL;
224 tmpWnd = WIN_LockWndPtr(newPtr);
225 WIN_ReleaseWndPtr(*oldPtr);
226 *oldPtr = tmpWnd;
230 /***********************************************************************
231 * WIN_DumpWindow
233 * Dump the content of a window structure to stderr.
235 void WIN_DumpWindow( HWND hwnd )
237 WND *ptr;
238 char className[80];
239 int i;
241 if (!(ptr = WIN_FindWndPtr( hwnd )))
243 WARN_(win)("%04x is not a window handle\n", hwnd );
244 return;
247 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
248 strcpy( className, "#NULL#" );
250 TRACE_(win)("Window %04x (%p):\n", hwnd, ptr );
251 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
252 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
253 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
254 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
255 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
256 ptr->next, ptr->child, ptr->parent, ptr->owner,
257 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
258 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
259 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
260 ptr->text ? ptr->text : "",
261 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
262 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
263 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
264 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
266 if (ptr->class->cbWndExtra)
268 DPRINTF( "extra bytes:" );
269 for (i = 0; i < ptr->class->cbWndExtra; i++)
270 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
271 DPRINTF( "\n" );
273 DPRINTF( "\n" );
274 WIN_ReleaseWndPtr(ptr);
278 /***********************************************************************
279 * WIN_WalkWindows
281 * Walk the windows tree and print each window on stderr.
283 void WIN_WalkWindows( HWND hwnd, int indent )
285 WND *ptr;
286 char className[80];
288 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
290 if (!ptr)
292 WARN_(win)("Invalid window handle %04x\n", hwnd );
293 return;
296 if (!indent) /* first time around */
297 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
298 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
299 " Text");
301 while (ptr)
303 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
305 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
307 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
308 (DWORD)ptr, ptr->hmemTaskQ, className,
309 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
310 ptr->text?ptr->text:"<null>");
312 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
313 WIN_UpdateWndPtr(&ptr,ptr->next);
319 /***********************************************************************
320 * WIN_UnlinkWindow
322 * Remove a window from the siblings linked list.
324 BOOL WIN_UnlinkWindow( HWND hwnd )
326 WND *wndPtr, **ppWnd;
327 BOOL ret = FALSE;
329 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
330 else if(!wndPtr->parent)
332 WIN_ReleaseWndPtr(wndPtr);
333 return FALSE;
336 ppWnd = &wndPtr->parent->child;
337 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
338 if (*ppWnd)
340 *ppWnd = wndPtr->next;
341 ret = TRUE;
343 WIN_ReleaseWndPtr(wndPtr);
344 return ret;
348 /***********************************************************************
349 * WIN_LinkWindow
351 * Insert a window into the siblings linked list.
352 * The window is inserted after the specified window, which can also
353 * be specified as HWND_TOP or HWND_BOTTOM.
355 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
357 WND *wndPtr, **ppWnd;
359 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
360 else if(!wndPtr->parent)
362 WIN_ReleaseWndPtr(wndPtr);
363 return FALSE;
365 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
367 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
368 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
369 while (*ppWnd) ppWnd = &(*ppWnd)->next;
371 else /* Normal case */
373 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
374 if (!afterPtr)
376 WIN_ReleaseWndPtr(wndPtr);
377 return FALSE;
379 ppWnd = &afterPtr->next;
380 WIN_ReleaseWndPtr(afterPtr);
382 wndPtr->next = *ppWnd;
383 *ppWnd = wndPtr;
384 WIN_ReleaseWndPtr(wndPtr);
385 return TRUE;
389 /***********************************************************************
390 * WIN_FindWinToRepaint
392 * Find a window that needs repaint.
394 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
396 HWND hwndRet;
397 WND *pWnd;
399 /* Note: the desktop window never gets WM_PAINT messages
400 * The real reason why is because Windows DesktopWndProc
401 * does ValidateRgn inside WM_ERASEBKGND handler.
404 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
406 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
408 if (!(pWnd->dwStyle & WS_VISIBLE))
410 TRACE_(win)("skipping window %04x\n",
411 pWnd->hwndSelf );
413 else if ((pWnd->hmemTaskQ == hQueue) &&
414 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
415 break;
417 else if (pWnd->child )
418 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
420 WIN_ReleaseWndPtr(pWnd);
421 return hwndRet;
426 if(!pWnd)
428 return 0;
431 hwndRet = pWnd->hwndSelf;
433 /* look among siblings if we got a transparent window */
434 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
435 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
437 WIN_UpdateWndPtr(&pWnd,pWnd->next);
439 if (pWnd)
441 hwndRet = pWnd->hwndSelf;
442 WIN_ReleaseWndPtr(pWnd);
444 TRACE_(win)("found %04x\n",hwndRet);
445 return hwndRet;
449 /***********************************************************************
450 * WIN_DestroyWindow
452 * Destroy storage associated to a window. "Internals" p.358
453 * returns a locked wndPtr->next
455 static WND* WIN_DestroyWindow( WND* wndPtr )
457 HWND hwnd = wndPtr->hwndSelf;
458 WND *pWnd;
460 TRACE_(win)("%04x\n", wndPtr->hwndSelf );
462 #ifdef CONFIG_IPC
463 if (main_block)
464 DDE_DestroyWindow(wndPtr->hwndSelf);
465 #endif /* CONFIG_IPC */
467 /* free child windows */
468 WIN_LockWndPtr(wndPtr->child);
469 while ((pWnd = wndPtr->child))
471 wndPtr->child = WIN_DestroyWindow( pWnd );
472 WIN_ReleaseWndPtr(pWnd);
476 * Clear the update region to make sure no WM_PAINT messages will be
477 * generated for this window while processing the WM_NCDESTROY.
479 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
481 if (wndPtr->hrgnUpdate > 1)
482 DeleteObject( wndPtr->hrgnUpdate );
484 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
486 wndPtr->hrgnUpdate = 0;
490 * Send the WM_NCDESTROY to the window being destroyed.
492 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
494 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
496 WINPOS_CheckInternalPos( wndPtr );
497 if( hwnd == GetCapture()) ReleaseCapture();
499 /* free resources associated with the window */
501 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
502 PROPERTY_RemoveWindowProps( wndPtr );
504 wndPtr->dwMagic = 0; /* Mark it as invalid */
506 /* toss stale messages from the queue */
508 if( wndPtr->hmemTaskQ )
510 BOOL bPostQuit = FALSE;
511 WPARAM wQuitParam = 0;
512 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
513 QMSG *qmsg;
515 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
517 if( qmsg->msg.message == WM_QUIT )
519 bPostQuit = TRUE;
520 wQuitParam = qmsg->msg.wParam;
522 QUEUE_RemoveMsg(msgQ, qmsg);
525 QUEUE_Unlock(msgQ);
527 /* repost WM_QUIT to make sure this app exits its message loop */
528 if( bPostQuit ) PostQuitMessage(wQuitParam);
529 wndPtr->hmemTaskQ = 0;
532 if (!(wndPtr->dwStyle & WS_CHILD))
533 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
534 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
535 wndPtr->pDriver->pDestroyWindow( wndPtr );
536 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
537 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
538 wndPtr->hwndSelf = 0;
539 wndPtr->class->cWindows--;
540 wndPtr->class = NULL;
542 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
544 wndPtr->pDriver->pFinalize(wndPtr);
546 return pWnd;
549 /***********************************************************************
550 * WIN_ResetQueueWindows
552 * Reset the queue of all the children of a given window.
553 * Return TRUE if something was done.
555 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
557 BOOL ret = FALSE;
559 if (hNew) /* Set a new queue */
561 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
563 if (wnd->hmemTaskQ == hQueue)
565 wnd->hmemTaskQ = hNew;
566 ret = TRUE;
568 if (wnd->child)
570 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
574 else /* Queue is being destroyed */
576 while (wnd->child)
578 WND *tmp = WIN_LockWndPtr(wnd->child);
579 WND *tmp2;
580 ret = FALSE;
581 while (tmp)
583 if (tmp->hmemTaskQ == hQueue)
585 DestroyWindow( tmp->hwndSelf );
586 ret = TRUE;
587 break;
589 tmp2 = WIN_LockWndPtr(tmp->child);
590 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
591 ret = TRUE;
592 else
594 WIN_UpdateWndPtr(&tmp,tmp->next);
596 WIN_ReleaseWndPtr(tmp2);
598 WIN_ReleaseWndPtr(tmp);
599 if (!ret) break;
602 return ret;
605 /***********************************************************************
606 * WIN_CreateDesktopWindow
608 * Create the desktop window.
610 BOOL WIN_CreateDesktopWindow(void)
612 CLASS *class;
613 HWND hwndDesktop;
614 DESKTOP *pDesktop;
616 TRACE_(win)("Creating desktop window\n");
619 if (!ICONTITLE_Init() ||
620 !WINPOS_CreateInternalPosAtom() ||
621 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
622 return FALSE;
624 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
625 if (!hwndDesktop) return FALSE;
626 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
628 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
629 pDesktop->pDriver = DESKTOP_Driver;
630 pWndDesktop->pDriver = WND_Driver;
632 pDesktop->pDriver->pInitialize(pDesktop);
633 pWndDesktop->pDriver->pInitialize(pWndDesktop);
635 pWndDesktop->next = NULL;
636 pWndDesktop->child = NULL;
637 pWndDesktop->parent = NULL;
638 pWndDesktop->owner = NULL;
639 pWndDesktop->class = class;
640 pWndDesktop->dwMagic = WND_MAGIC;
641 pWndDesktop->hwndSelf = hwndDesktop;
642 pWndDesktop->hInstance = 0;
643 pWndDesktop->rectWindow.left = 0;
644 pWndDesktop->rectWindow.top = 0;
645 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
646 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
647 pWndDesktop->rectClient = pWndDesktop->rectWindow;
648 pWndDesktop->text = NULL;
649 pWndDesktop->hmemTaskQ = GetFastQueue16();
650 pWndDesktop->hrgnUpdate = 0;
651 pWndDesktop->hwndLastActive = hwndDesktop;
652 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
653 WS_CLIPSIBLINGS;
654 pWndDesktop->dwExStyle = 0;
655 pWndDesktop->dce = NULL;
656 pWndDesktop->pVScroll = NULL;
657 pWndDesktop->pHScroll = NULL;
658 pWndDesktop->pProp = NULL;
659 pWndDesktop->wIDmenu = 0;
660 pWndDesktop->helpContext = 0;
661 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
662 pWndDesktop->hSysMenu = 0;
663 pWndDesktop->userdata = 0;
664 pWndDesktop->winproc = (WNDPROC16)class->winproc;
665 pWndDesktop->irefCount = 0;
667 /* FIXME: How do we know if it should be Unicode or not */
668 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
669 return FALSE;
671 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
672 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
673 return TRUE;
677 /***********************************************************************
678 * WIN_CreateWindowEx
680 * Implementation of CreateWindowEx().
682 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
683 BOOL win32, BOOL unicode )
685 CLASS *classPtr;
686 WND *wndPtr;
687 HWND retvalue;
688 HWND16 hwnd, hwndLinkAfter;
689 POINT maxSize, maxPos, minTrack, maxTrack;
690 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
691 char buffer[256];
693 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
694 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
695 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
696 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
697 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
699 /* Find the parent window */
701 if (cs->hwndParent)
703 /* Make sure parent is valid */
704 if (!IsWindow( cs->hwndParent ))
706 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
707 return 0;
709 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
710 WARN_(win)("No parent for child window\n" );
711 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
714 /* Find the window class */
715 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
717 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
718 WARN_(win)("Bad class '%s'\n", buffer );
719 return 0;
722 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
723 * with an atom as the class name, put some programs expect to have a *REAL* string in
724 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
726 if ( !HIWORD(cs->lpszClass) ) {
727 if (unicode) {
728 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
729 } else {
730 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
732 cs->lpszClass = buffer;
735 /* Fix the coordinates */
737 if (cs->x == CW_USEDEFAULT)
739 PDB *pdb = PROCESS_Current();
740 if ( !(cs->style & (WS_CHILD | WS_POPUP))
741 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
743 cs->x = pdb->env_db->startup_info->dwX;
744 cs->y = pdb->env_db->startup_info->dwY;
746 else
748 cs->x = 0;
749 cs->y = 0;
752 if (cs->cx == CW_USEDEFAULT)
754 PDB *pdb = PROCESS_Current();
755 if ( !(cs->style & (WS_CHILD | WS_POPUP))
756 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
758 cs->cx = pdb->env_db->startup_info->dwXSize;
759 cs->cy = pdb->env_db->startup_info->dwYSize;
761 else
763 cs->cx = 600; /* FIXME */
764 cs->cy = 400;
768 /* Create the window structure */
770 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
771 - sizeof(wndPtr->wExtra) )))
773 TRACE_(win)("out of memory\n" );
774 return 0;
777 /* Fill the window structure */
779 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
780 wndPtr->next = NULL;
781 wndPtr->child = NULL;
783 if ((cs->style & WS_CHILD) && cs->hwndParent)
785 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
786 wndPtr->owner = NULL;
787 WIN_ReleaseWndPtr(wndPtr->parent);
789 else
791 wndPtr->parent = pWndDesktop;
792 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
793 wndPtr->owner = NULL;
794 else
796 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
797 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
798 WIN_ReleaseWndPtr(wndPtr->owner);
799 WIN_ReleaseWndPtr(tmpWnd);
803 wndPtr->pDriver = wndPtr->parent->pDriver;
804 wndPtr->pDriver->pInitialize(wndPtr);
806 wndPtr->class = classPtr;
807 wndPtr->winproc = classPtr->winproc;
808 wndPtr->dwMagic = WND_MAGIC;
809 wndPtr->hwndSelf = hwnd;
810 wndPtr->hInstance = cs->hInstance;
811 wndPtr->text = NULL;
812 wndPtr->hmemTaskQ = GetFastQueue16();
813 wndPtr->hrgnUpdate = 0;
814 wndPtr->hwndLastActive = hwnd;
815 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
816 wndPtr->dwExStyle = cs->dwExStyle;
817 wndPtr->wIDmenu = 0;
818 wndPtr->helpContext = 0;
819 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
820 wndPtr->pVScroll = NULL;
821 wndPtr->pHScroll = NULL;
822 wndPtr->pProp = NULL;
823 wndPtr->userdata = 0;
824 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
825 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
826 wndPtr->irefCount = 1;
828 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
830 /* Call the WH_CBT hook */
832 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
833 ? HWND_BOTTOM : HWND_TOP;
835 if (HOOK_IsHooked( WH_CBT ))
837 CBT_CREATEWNDA cbtc;
838 LRESULT ret;
840 cbtc.lpcs = cs;
841 cbtc.hwndInsertAfter = hwndLinkAfter;
842 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
843 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
844 if (ret)
846 TRACE_(win)("CBT-hook returned 0\n");
847 wndPtr->pDriver->pFinalize(wndPtr);
848 USER_HEAP_FREE( hwnd );
849 retvalue = 0;
850 goto end;
854 /* Increment class window counter */
856 classPtr->cWindows++;
858 /* Correct the window style */
860 if (!(cs->style & WS_CHILD))
862 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
863 if (!(cs->style & WS_POPUP))
865 wndPtr->dwStyle |= WS_CAPTION;
866 wndPtr->flags |= WIN_NEED_SIZE;
869 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
871 /* Get class or window DC if needed */
873 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
874 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
875 else wndPtr->dce = NULL;
877 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
879 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
881 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
882 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
883 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
884 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
885 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
888 if(cs->style & WS_CHILD)
890 if(cs->cx < 0) cs->cx = 0;
891 if(cs->cy < 0) cs->cy = 0;
893 else
895 if (cs->cx <= 0) cs->cx = 1;
896 if (cs->cy <= 0) cs->cy = 1;
899 wndPtr->rectWindow.left = cs->x;
900 wndPtr->rectWindow.top = cs->y;
901 wndPtr->rectWindow.right = cs->x + cs->cx;
902 wndPtr->rectWindow.bottom = cs->y + cs->cy;
903 wndPtr->rectClient = wndPtr->rectWindow;
905 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
907 retvalue = FALSE;
908 goto end;
911 /* Set the window menu */
913 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
915 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
916 else
918 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
919 if (classPtr->menuNameA)
920 cs->hMenu = HIWORD(classPtr->menuNameA) ?
921 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
922 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
923 #else
924 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
925 if (menuName)
927 if (HIWORD(cs->hInstance))
928 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
929 else
930 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
932 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
934 #endif
937 else wndPtr->wIDmenu = (UINT)cs->hMenu;
939 /* Send the WM_CREATE message
940 * Perhaps we shouldn't allow width/height changes as well.
941 * See p327 in "Internals".
944 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
946 localSend32 = unicode ? SendMessageW : SendMessageA;
947 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
949 /* Insert the window in the linked list */
951 WIN_LinkWindow( hwnd, hwndLinkAfter );
953 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
954 NULL, NULL, 0, &wndPtr->rectClient );
955 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
956 maxPos.y - wndPtr->rectWindow.top);
957 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
959 /* Send the size messages */
961 if (!(wndPtr->flags & WIN_NEED_SIZE))
963 /* send it anyway */
964 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
965 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
966 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
967 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
968 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
969 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
970 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
971 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
972 SendMessageA( hwnd, WM_MOVE, 0,
973 MAKELONG( wndPtr->rectClient.left,
974 wndPtr->rectClient.top ) );
977 /* Show the window, maximizing or minimizing if needed */
979 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
981 RECT16 newPos;
982 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
983 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
984 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
985 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
986 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
987 : SWP_NOZORDER | SWP_FRAMECHANGED;
988 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
989 newPos.right, newPos.bottom, swFlag );
992 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
994 /* Notify the parent window only */
996 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
997 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
998 if( !IsWindow(hwnd) )
1000 retvalue = 0;
1001 goto end;
1005 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
1007 /* Call WH_SHELL hook */
1009 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1010 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1012 TRACE_(win)("created window %04x\n", hwnd);
1013 retvalue = hwnd;
1014 goto end;
1016 WIN_UnlinkWindow( hwnd );
1019 /* Abort window creation */
1021 WARN_(win)("aborted by WM_xxCREATE!\n");
1022 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1023 retvalue = 0;
1024 end:
1025 WIN_ReleaseWndPtr(wndPtr);
1027 return retvalue;
1031 /***********************************************************************
1032 * CreateWindow16 (USER.41)
1034 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1035 DWORD style, INT16 x, INT16 y, INT16 width,
1036 INT16 height, HWND16 parent, HMENU16 menu,
1037 HINSTANCE16 instance, LPVOID data )
1039 return CreateWindowEx16( 0, className, windowName, style,
1040 x, y, width, height, parent, menu, instance, data );
1044 /***********************************************************************
1045 * CreateWindowEx16 (USER.452)
1047 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1048 LPCSTR windowName, DWORD style, INT16 x,
1049 INT16 y, INT16 width, INT16 height,
1050 HWND16 parent, HMENU16 menu,
1051 HINSTANCE16 instance, LPVOID data )
1053 ATOM classAtom;
1054 CREATESTRUCTA cs;
1056 /* Find the class atom */
1058 if (!(classAtom = GlobalFindAtomA( className )))
1060 fprintf( stderr, "CreateWindowEx16: bad class name " );
1061 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1062 else fprintf( stderr, "'%s'\n", className );
1063 return 0;
1066 /* Fix the coordinates */
1068 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1069 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1070 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1071 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1073 /* Create the window */
1075 cs.lpCreateParams = data;
1076 cs.hInstance = (HINSTANCE)instance;
1077 cs.hMenu = (HMENU)menu;
1078 cs.hwndParent = (HWND)parent;
1079 cs.style = style;
1080 cs.lpszName = windowName;
1081 cs.lpszClass = className;
1082 cs.dwExStyle = exStyle;
1083 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1087 /***********************************************************************
1088 * CreateWindowEx32A (USER32.83)
1090 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1091 LPCSTR windowName, DWORD style, INT x,
1092 INT y, INT width, INT height,
1093 HWND parent, HMENU menu,
1094 HINSTANCE instance, LPVOID data )
1096 ATOM classAtom;
1097 CREATESTRUCTA cs;
1099 if(exStyle & WS_EX_MDICHILD)
1100 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1101 /* Find the class atom */
1103 if (!(classAtom = GlobalFindAtomA( className )))
1105 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1106 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1107 else fprintf( stderr, "'%s'\n", className );
1108 return 0;
1111 /* Create the window */
1113 cs.lpCreateParams = data;
1114 cs.hInstance = instance;
1115 cs.hMenu = menu;
1116 cs.hwndParent = parent;
1117 cs.x = x;
1118 cs.y = y;
1119 cs.cx = width;
1120 cs.cy = height;
1121 cs.style = style;
1122 cs.lpszName = windowName;
1123 cs.lpszClass = className;
1124 cs.dwExStyle = exStyle;
1125 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1129 /***********************************************************************
1130 * CreateWindowEx32W (USER32.84)
1132 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1133 LPCWSTR windowName, DWORD style, INT x,
1134 INT y, INT width, INT height,
1135 HWND parent, HMENU menu,
1136 HINSTANCE instance, LPVOID data )
1138 ATOM classAtom;
1139 CREATESTRUCTW cs;
1141 if(exStyle & WS_EX_MDICHILD)
1142 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1144 /* Find the class atom */
1146 if (!(classAtom = GlobalFindAtomW( className )))
1148 if (HIWORD(className))
1150 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1151 WARN_(win)("Bad class name '%s'\n",cn);
1152 HeapFree( GetProcessHeap(), 0, cn );
1154 else
1155 WARN_(win)("Bad class name %p\n", className );
1156 return 0;
1159 /* Create the window */
1161 cs.lpCreateParams = data;
1162 cs.hInstance = instance;
1163 cs.hMenu = menu;
1164 cs.hwndParent = parent;
1165 cs.x = x;
1166 cs.y = y;
1167 cs.cx = width;
1168 cs.cy = height;
1169 cs.style = style;
1170 cs.lpszName = windowName;
1171 cs.lpszClass = className;
1172 cs.dwExStyle = exStyle;
1173 /* Note: we rely on the fact that CREATESTRUCT32A and */
1174 /* CREATESTRUCT32W have the same layout. */
1175 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1179 /***********************************************************************
1180 * WIN_CheckFocus
1182 static void WIN_CheckFocus( WND* pWnd )
1184 if( GetFocus16() == pWnd->hwndSelf )
1185 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1188 /***********************************************************************
1189 * WIN_SendDestroyMsg
1191 static void WIN_SendDestroyMsg( WND* pWnd )
1193 WIN_CheckFocus(pWnd);
1195 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1196 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1199 * Send the WM_DESTROY to the window.
1201 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1204 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1205 * make sure that the window still exists when we come back.
1207 if (IsWindow(pWnd->hwndSelf))
1209 HWND* pWndArray = NULL;
1210 WND* pChild = NULL;
1211 int nKidCount = 0;
1214 * Now, if the window has kids, we have to send WM_DESTROY messages
1215 * recursively to it's kids. It seems that those calls can also
1216 * trigger re-entrant calls to DestroyWindow for the kids so we must
1217 * protect against corruption of the list of siblings. We first build
1218 * a list of HWNDs representing all the kids.
1220 pChild = WIN_LockWndPtr(pWnd->child);
1221 while( pChild )
1223 nKidCount++;
1224 WIN_UpdateWndPtr(&pChild,pChild->next);
1228 * If there are no kids, we're done.
1230 if (nKidCount==0)
1231 return;
1233 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1236 * Sanity check
1238 if (pWndArray==NULL)
1239 return;
1242 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1243 * call, our linked list of siblings should be safe.
1245 nKidCount = 0;
1246 pChild = WIN_LockWndPtr(pWnd->child);
1247 while( pChild )
1249 pWndArray[nKidCount] = pChild->hwndSelf;
1250 nKidCount++;
1251 WIN_UpdateWndPtr(&pChild,pChild->next);
1255 * Now that we have a list, go through that list again and send the destroy
1256 * message to those windows. We are using the HWND to retrieve the
1257 * WND pointer so we are effectively checking that all the kid windows are
1258 * still valid before sending the message.
1260 while (nKidCount>0)
1262 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1264 if (pChild!=NULL)
1266 WIN_SendDestroyMsg( pChild );
1267 WIN_ReleaseWndPtr(pChild);
1272 * Cleanup
1274 HeapFree(GetProcessHeap(), 0, pWndArray);
1275 WIN_CheckFocus(pWnd);
1277 else
1278 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1282 /***********************************************************************
1283 * DestroyWindow16 (USER.53)
1285 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1287 return DestroyWindow(hwnd);
1291 /***********************************************************************
1292 * DestroyWindow32 (USER32.135)
1294 BOOL WINAPI DestroyWindow( HWND hwnd )
1296 WND * wndPtr;
1297 BOOL retvalue;
1299 TRACE_(win)("(%04x)\n", hwnd);
1301 /* Initialization */
1303 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1304 if (wndPtr == pWndDesktop)
1306 WIN_ReleaseWndPtr(wndPtr);
1307 return FALSE; /* Can't destroy desktop */
1310 /* Call hooks */
1312 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1314 retvalue = FALSE;
1315 goto end;
1318 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1320 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1321 /* FIXME: clean up palette - see "Internals" p.352 */
1324 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1325 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1327 /* Notify the parent window only */
1328 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1329 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1330 if( !IsWindow(hwnd) )
1332 retvalue = TRUE;
1333 goto end;
1337 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1339 /* Hide the window */
1341 if (wndPtr->dwStyle & WS_VISIBLE)
1343 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1344 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1345 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1346 if (!IsWindow(hwnd))
1348 retvalue = TRUE;
1349 goto end;
1353 /* Recursively destroy owned windows */
1355 if( !(wndPtr->dwStyle & WS_CHILD) )
1357 /* make sure top menu popup doesn't get destroyed */
1358 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1360 for (;;)
1362 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1363 while (siblingPtr)
1365 if (siblingPtr->owner == wndPtr)
1367 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1368 break;
1369 else
1370 siblingPtr->owner = NULL;
1372 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1374 if (siblingPtr)
1376 DestroyWindow( siblingPtr->hwndSelf );
1377 WIN_ReleaseWndPtr(siblingPtr);
1379 else break;
1382 if( !Options.managed || EVENT_CheckFocus() )
1383 WINPOS_ActivateOtherWindow(wndPtr);
1385 if( wndPtr->owner &&
1386 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1387 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1390 /* Send destroy messages */
1392 WIN_SendDestroyMsg( wndPtr );
1393 if (!IsWindow(hwnd))
1395 retvalue = TRUE;
1396 goto end;
1399 /* Unlink now so we won't bother with the children later on */
1401 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1403 /* Destroy the window storage */
1405 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1406 retvalue = TRUE;
1407 end:
1408 WIN_ReleaseWndPtr(wndPtr);
1409 return retvalue;
1413 /***********************************************************************
1414 * CloseWindow16 (USER.43)
1416 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1418 return CloseWindow( hwnd );
1422 /***********************************************************************
1423 * CloseWindow32 (USER32.56)
1425 BOOL WINAPI CloseWindow( HWND hwnd )
1427 WND * wndPtr = WIN_FindWndPtr( hwnd );
1428 BOOL retvalue;
1430 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1432 retvalue = FALSE;
1433 goto end;
1435 ShowWindow( hwnd, SW_MINIMIZE );
1436 retvalue = TRUE;
1437 end:
1438 WIN_ReleaseWndPtr(wndPtr);
1439 return retvalue;
1444 /***********************************************************************
1445 * OpenIcon16 (USER.44)
1447 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1449 return OpenIcon( hwnd );
1453 /***********************************************************************
1454 * OpenIcon32 (USER32.410)
1456 BOOL WINAPI OpenIcon( HWND hwnd )
1458 if (!IsIconic( hwnd )) return FALSE;
1459 ShowWindow( hwnd, SW_SHOWNORMAL );
1460 return TRUE;
1464 /***********************************************************************
1465 * WIN_FindWindow
1467 * Implementation of FindWindow() and FindWindowEx().
1469 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1470 LPCSTR title )
1472 WND *pWnd;
1473 HWND retvalue;
1474 CLASS *pClass = NULL;
1476 if (child)
1478 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1479 if (parent)
1481 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1483 retvalue = 0;
1484 goto end;
1487 else if (pWnd->parent != pWndDesktop)
1489 retvalue = 0;
1490 goto end;
1492 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1494 else
1496 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1498 retvalue = 0;
1499 goto end;
1501 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1503 if (!pWnd)
1505 retvalue = 0;
1506 goto end;
1509 /* For a child window, all siblings will have the same hInstance, */
1510 /* so we can look for the class once and for all. */
1512 if (className && (pWnd->dwStyle & WS_CHILD))
1514 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1516 retvalue = 0;
1517 goto end;
1522 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1524 if (className && !(pWnd->dwStyle & WS_CHILD))
1526 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1527 continue; /* Skip this window */
1530 if (pClass && (pWnd->class != pClass))
1531 continue; /* Not the right class */
1533 /* Now check the title */
1535 if (!title)
1537 retvalue = pWnd->hwndSelf;
1538 goto end;
1540 if (pWnd->text && !strcmp( pWnd->text, title ))
1542 retvalue = pWnd->hwndSelf;
1543 goto end;
1546 retvalue = 0;
1547 end:
1548 WIN_ReleaseWndPtr(pWnd);
1549 return retvalue;
1554 /***********************************************************************
1555 * FindWindow16 (USER.50)
1557 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1559 return FindWindowEx16( 0, 0, className, title );
1563 /***********************************************************************
1564 * FindWindowEx16 (USER.427)
1566 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1567 SEGPTR className, LPCSTR title )
1569 ATOM atom = 0;
1571 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1572 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1573 title ? title : "");
1575 if (className)
1577 /* If the atom doesn't exist, then no class */
1578 /* with this name exists either. */
1579 if (!(atom = GlobalFindAtom16( className ))) return 0;
1581 return WIN_FindWindow( parent, child, atom, title );
1585 /***********************************************************************
1586 * FindWindow32A (USER32.198)
1588 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1590 HWND ret = FindWindowExA( 0, 0, className, title );
1591 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1592 return ret;
1596 /***********************************************************************
1597 * FindWindowEx32A (USER32.199)
1599 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1600 LPCSTR className, LPCSTR title )
1602 ATOM atom = 0;
1604 if (className)
1606 /* If the atom doesn't exist, then no class */
1607 /* with this name exists either. */
1608 if (!(atom = GlobalFindAtomA( className )))
1610 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1611 return 0;
1614 return WIN_FindWindow( parent, child, atom, title );
1618 /***********************************************************************
1619 * FindWindowEx32W (USER32.200)
1621 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1622 LPCWSTR className, LPCWSTR title )
1624 ATOM atom = 0;
1625 char *buffer;
1626 HWND hwnd;
1628 if (className)
1630 /* If the atom doesn't exist, then no class */
1631 /* with this name exists either. */
1632 if (!(atom = GlobalFindAtomW( className )))
1634 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1635 return 0;
1638 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1639 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1640 HeapFree( GetProcessHeap(), 0, buffer );
1641 return hwnd;
1645 /***********************************************************************
1646 * FindWindow32W (USER32.201)
1648 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1650 return FindWindowExW( 0, 0, className, title );
1654 /**********************************************************************
1655 * WIN_GetDesktop
1656 * returns a locked pointer
1658 WND *WIN_GetDesktop(void)
1660 return WIN_LockWndPtr(pWndDesktop);
1662 /**********************************************************************
1663 * WIN_ReleaseDesktop
1664 * unlock the desktop pointer
1666 void WIN_ReleaseDesktop(void)
1668 WIN_ReleaseWndPtr(pWndDesktop);
1672 /**********************************************************************
1673 * GetDesktopWindow16 (USER.286)
1675 HWND16 WINAPI GetDesktopWindow16(void)
1677 return (HWND16)pWndDesktop->hwndSelf;
1681 /**********************************************************************
1682 * GetDesktopWindow32 (USER32.232)
1684 HWND WINAPI GetDesktopWindow(void)
1686 return pWndDesktop->hwndSelf;
1690 /**********************************************************************
1691 * GetDesktopHwnd (USER.278)
1693 * Exactly the same thing as GetDesktopWindow(), but not documented.
1694 * Don't ask me why...
1696 HWND16 WINAPI GetDesktopHwnd16(void)
1698 return (HWND16)pWndDesktop->hwndSelf;
1702 /*******************************************************************
1703 * EnableWindow16 (USER.34)
1705 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1707 return EnableWindow( hwnd, enable );
1711 /*******************************************************************
1712 * EnableWindow32 (USER32.172)
1714 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1716 WND *wndPtr;
1717 BOOL retvalue;
1719 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1721 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1722 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1724 /* Enable window */
1725 wndPtr->dwStyle &= ~WS_DISABLED;
1727 if( wndPtr->flags & WIN_NATIVE )
1728 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1730 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1731 retvalue = TRUE;
1732 goto end;
1734 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1736 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1738 /* Disable window */
1739 wndPtr->dwStyle |= WS_DISABLED;
1741 if( wndPtr->flags & WIN_NATIVE )
1742 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1744 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1746 SetFocus( 0 ); /* A disabled window can't have the focus */
1748 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1750 ReleaseCapture(); /* A disabled window can't capture the mouse */
1752 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1753 retvalue = FALSE;
1754 goto end;
1756 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1757 end:
1758 WIN_ReleaseWndPtr(wndPtr);
1759 return retvalue;
1763 /***********************************************************************
1764 * IsWindowEnabled16 (USER.35)
1766 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1768 return IsWindowEnabled(hWnd);
1772 /***********************************************************************
1773 * IsWindowEnabled32 (USER32.349)
1775 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1777 WND * wndPtr;
1778 BOOL retvalue;
1780 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1781 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1782 WIN_ReleaseWndPtr(wndPtr);
1783 return retvalue;
1788 /***********************************************************************
1789 * IsWindowUnicode (USER32.350)
1791 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1793 WND * wndPtr;
1794 BOOL retvalue;
1796 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1797 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1798 WIN_ReleaseWndPtr(wndPtr);
1799 return retvalue;
1803 /**********************************************************************
1804 * GetWindowWord16 (USER.133)
1806 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1808 return GetWindowWord( hwnd, offset );
1812 /**********************************************************************
1813 * GetWindowWord32 (USER32.314)
1815 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1817 WORD retvalue;
1818 WND * wndPtr = WIN_FindWndPtr( hwnd );
1819 if (!wndPtr) return 0;
1820 if (offset >= 0)
1822 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1824 WARN_(win)("Invalid offset %d\n", offset );
1825 retvalue = 0;
1826 goto end;
1828 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1829 goto end;
1831 switch(offset)
1833 case GWW_ID:
1834 if (HIWORD(wndPtr->wIDmenu))
1835 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1836 wndPtr->wIDmenu);
1837 retvalue = (WORD)wndPtr->wIDmenu;
1838 goto end;
1839 case GWW_HWNDPARENT:
1840 retvalue = GetParent(hwnd);
1841 goto end;
1842 case GWW_HINSTANCE:
1843 if (HIWORD(wndPtr->hInstance))
1844 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1845 wndPtr->hInstance);
1846 retvalue = (WORD)wndPtr->hInstance;
1847 goto end;
1848 default:
1849 WARN_(win)("Invalid offset %d\n", offset );
1850 retvalue = 0;
1851 goto end;
1853 end:
1854 WIN_ReleaseWndPtr(wndPtr);
1855 return retvalue;
1859 /**********************************************************************
1860 * WIN_GetWindowInstance
1862 HINSTANCE WIN_GetWindowInstance( HWND hwnd )
1865 WND * wndPtr = WIN_FindWndPtr( hwnd );
1866 if (!wndPtr) return (HINSTANCE)0;
1867 WIN_ReleaseWndPtr(wndPtr);
1868 return wndPtr->hInstance;
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_(win)("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_(win)("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_(win)("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_(win)("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_(win)("%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_(win)("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_(win)("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_(win)("(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 return IsWindow( hwnd );
2307 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2309 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2310 HWND16 hwnd = (HWND16)stack[2];
2312 AX_reg(context) = IsWindow( hwnd );
2313 ES_reg(context) = USER_HeapSel;
2317 /*******************************************************************
2318 * IsWindow32 (USER32.348)
2320 BOOL WINAPI IsWindow( HWND hwnd )
2322 WND * wndPtr;
2323 BOOL retvalue;
2325 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2326 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2327 WIN_ReleaseWndPtr(wndPtr);
2328 return retvalue;
2333 /*****************************************************************
2334 * GetParent16 (USER.46)
2336 HWND16 WINAPI GetParent16( HWND16 hwnd )
2338 return (HWND16)GetParent( hwnd );
2342 /*****************************************************************
2343 * GetParent32 (USER32.278)
2345 HWND WINAPI GetParent( HWND hwnd )
2347 WND *wndPtr;
2348 HWND retvalue;
2350 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2351 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2353 WIN_ReleaseWndPtr(wndPtr);
2354 return 0;
2356 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2357 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2359 WIN_ReleaseWndPtr(wndPtr);
2360 return retvalue;
2364 /*****************************************************************
2365 * WIN_GetTopParent
2367 * Get the top-level parent for a child window.
2368 * returns a locked pointer
2370 WND* WIN_GetTopParentPtr( WND* pWnd )
2372 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2374 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2376 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2378 return tmpWnd;
2381 /*****************************************************************
2382 * WIN_GetTopParent
2384 * Get the top-level parent for a child window.
2386 HWND WIN_GetTopParent( HWND hwnd )
2388 HWND retvalue;
2389 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2390 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2392 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2393 WIN_ReleaseWndPtr(tmpPtr);
2394 WIN_ReleaseWndPtr(wndPtr);
2395 return retvalue;
2399 /*****************************************************************
2400 * SetParent16 (USER.233)
2402 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2404 return SetParent( hwndChild, hwndNewParent );
2408 /*****************************************************************
2409 * SetParent32 (USER32.495)
2411 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2413 WND *wndPtr;
2414 DWORD dwStyle;
2415 WND *pWndNewParent;
2416 WND *pWndOldParent;
2417 HWND retvalue;
2420 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2422 dwStyle = wndPtr->dwStyle;
2424 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2425 : WIN_LockWndPtr(pWndDesktop);
2427 /* Windows hides the window first, then shows it again
2428 * including the WM_SHOWWINDOW messages and all */
2429 if (dwStyle & WS_VISIBLE)
2430 ShowWindow( hwndChild, SW_HIDE );
2432 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2434 /* SetParent32 additionally needs to make hwndChild the topmost window
2435 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2436 WM_WINDOWPOSCHANGED notification messages.
2438 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2439 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2440 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2441 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2443 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2445 WIN_ReleaseWndPtr(pWndOldParent);
2446 WIN_ReleaseWndPtr(pWndNewParent);
2447 WIN_ReleaseWndPtr(wndPtr);
2449 return retvalue;
2453 /*******************************************************************
2454 * IsChild16 (USER.48)
2456 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2458 return IsChild(parent,child);
2462 /*******************************************************************
2463 * IsChild32 (USER32.339)
2465 BOOL WINAPI IsChild( HWND parent, HWND child )
2467 WND * wndPtr = WIN_FindWndPtr( child );
2468 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2470 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2471 if (wndPtr->hwndSelf == parent)
2473 WIN_ReleaseWndPtr(wndPtr);
2474 return TRUE;
2477 WIN_ReleaseWndPtr(wndPtr);
2478 return FALSE;
2482 /***********************************************************************
2483 * IsWindowVisible16 (USER.49)
2485 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2487 return IsWindowVisible(hwnd);
2491 /***********************************************************************
2492 * IsWindowVisible32 (USER32.351)
2494 BOOL WINAPI IsWindowVisible( HWND hwnd )
2496 BOOL retval;
2497 WND *wndPtr = WIN_FindWndPtr( hwnd );
2498 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2500 if (!(wndPtr->dwStyle & WS_VISIBLE))
2502 WIN_ReleaseWndPtr(wndPtr);
2503 return FALSE;
2505 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2507 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2508 WIN_ReleaseWndPtr(wndPtr);
2509 return retval;
2514 /***********************************************************************
2515 * WIN_IsWindowDrawable
2517 * hwnd is drawable when it is visible, all parents are not
2518 * minimized, and it is itself not minimized unless we are
2519 * trying to draw its default class icon.
2521 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2523 if( (wnd->dwStyle & WS_MINIMIZE &&
2524 icon && wnd->class->hIcon) ||
2525 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2526 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2527 if( wnd->dwStyle & WS_MINIMIZE ||
2528 !(wnd->dwStyle & WS_VISIBLE) ) break;
2529 return (wnd == NULL);
2533 /*******************************************************************
2534 * GetTopWindow16 (USER.229)
2536 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2538 return GetTopWindow(hwnd);
2542 /*******************************************************************
2543 * GetTopWindow32 (USER.229)
2545 HWND WINAPI GetTopWindow( HWND hwnd )
2547 HWND retval;
2548 WND * wndPtr = WIN_FindWndPtr( hwnd );
2549 if (wndPtr && wndPtr->child)
2551 retval = wndPtr->child->hwndSelf;
2553 else retval = 0;
2554 WIN_ReleaseWndPtr(wndPtr);
2555 return retval;
2559 /*******************************************************************
2560 * GetWindow16 (USER.262)
2562 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2564 return GetWindow( hwnd,rel );
2568 /*******************************************************************
2569 * GetWindow32 (USER32.302)
2571 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2573 HWND retval;
2575 WND * wndPtr = WIN_FindWndPtr( hwnd );
2576 if (!wndPtr) return 0;
2577 switch(rel)
2579 case GW_HWNDFIRST:
2580 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2581 else retval = 0;
2582 goto end;
2584 case GW_HWNDLAST:
2585 if (!wndPtr->parent)
2587 retval = 0; /* Desktop window */
2588 goto end;
2590 while (wndPtr->next)
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2594 retval = wndPtr->hwndSelf;
2595 goto end;
2597 case GW_HWNDNEXT:
2598 if (!wndPtr->next) retval = 0;
2599 else retval = wndPtr->next->hwndSelf;
2600 goto end;
2602 case GW_HWNDPREV:
2603 if (!wndPtr->parent)
2605 retval = 0; /* Desktop window */
2606 goto end;
2608 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2609 if (wndPtr->hwndSelf == hwnd)
2611 retval = 0; /* First in list */
2612 goto end;
2614 while (wndPtr->next)
2616 if (wndPtr->next->hwndSelf == hwnd)
2618 retval = wndPtr->hwndSelf;
2619 goto end;
2621 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2623 retval = 0;
2624 goto end;
2626 case GW_OWNER:
2627 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2628 goto end;
2630 case GW_CHILD:
2631 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2632 goto end;
2634 retval = 0;
2635 end:
2636 WIN_ReleaseWndPtr(wndPtr);
2637 return retval;
2641 /*******************************************************************
2642 * GetNextWindow16 (USER.230)
2644 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2646 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2647 return GetWindow16( hwnd, flag );
2650 /*******************************************************************
2651 * ShowOwnedPopups16 (USER.265)
2653 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2655 ShowOwnedPopups( owner, fShow );
2659 /*******************************************************************
2660 * ShowOwnedPopups32 (USER32.531)
2662 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2664 WND *pWnd;
2665 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2666 while (pWnd)
2668 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2669 (pWnd->dwStyle & WS_POPUP))
2670 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2671 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2673 return TRUE;
2677 /*******************************************************************
2678 * GetLastActivePopup16 (USER.287)
2680 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2682 return GetLastActivePopup( hwnd );
2685 /*******************************************************************
2686 * GetLastActivePopup32 (USER32.256)
2688 HWND WINAPI GetLastActivePopup( HWND hwnd )
2690 WND *wndPtr;
2691 HWND retval;
2692 wndPtr = WIN_FindWndPtr(hwnd);
2693 if (!wndPtr) return hwnd;
2694 retval = wndPtr->hwndLastActive;
2695 WIN_ReleaseWndPtr(wndPtr);
2696 return retval;
2700 /*******************************************************************
2701 * WIN_BuildWinArray
2703 * Build an array of pointers to the children of a given window.
2704 * The array must be freed with HeapFree(SystemHeap). Return NULL
2705 * when no windows are found.
2707 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2709 /* Future : this function will lock all windows associated with this array */
2711 WND **list, **ppWnd;
2712 WND *pWnd;
2713 UINT count = 0, skipOwned, skipHidden;
2714 DWORD skipFlags;
2716 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2717 skipOwned = bwaFlags & BWA_SKIPOWNED;
2718 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2719 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2721 /* First count the windows */
2723 if (!wndPtr)
2724 wndPtr = WIN_GetDesktop();
2726 pWnd = WIN_LockWndPtr(wndPtr->child);
2727 while (pWnd)
2729 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2730 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2731 count++;
2732 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2735 if( count )
2737 /* Now build the list of all windows */
2739 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2741 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2743 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2744 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2746 *ppWnd++ = pWnd;
2747 count++;
2750 WIN_ReleaseWndPtr(pWnd);
2751 *ppWnd = NULL;
2753 else count = 0;
2754 } else list = NULL;
2756 if( pTotal ) *pTotal = count;
2757 return list;
2759 /*******************************************************************
2760 * WIN_ReleaseWinArray
2762 void WIN_ReleaseWinArray(WND **wndArray)
2764 /* Future : this function will also unlock all windows associated with wndArray */
2765 HeapFree( SystemHeap, 0, wndArray );
2769 /*******************************************************************
2770 * EnumWindows16 (USER.54)
2772 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2774 WND **list, **ppWnd;
2776 /* We have to build a list of all windows first, to avoid */
2777 /* unpleasant side-effects, for instance if the callback */
2778 /* function changes the Z-order of the windows. */
2780 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2782 WIN_ReleaseDesktop();
2783 return FALSE;
2786 /* Now call the callback function for every window */
2788 for (ppWnd = list; *ppWnd; ppWnd++)
2790 LRESULT lpEnumFuncRetval;
2791 int iWndsLocks = 0;
2792 /* Make sure that the window still exists */
2793 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2795 /* To avoid any deadlocks, all the locks on the windows
2796 structures must be suspended before the control
2797 is passed to the application */
2798 iWndsLocks = WIN_SuspendWndsLock();
2799 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2800 WIN_RestoreWndsLock(iWndsLocks);
2802 if (!lpEnumFuncRetval) break;
2804 WIN_ReleaseWinArray(list);
2805 WIN_ReleaseDesktop();
2806 return TRUE;
2810 /*******************************************************************
2811 * EnumWindows32 (USER32.193)
2813 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2815 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2819 /**********************************************************************
2820 * EnumTaskWindows16 (USER.225)
2822 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2823 LPARAM lParam )
2825 WND **list, **ppWnd;
2827 /* This function is the same as EnumWindows(), */
2828 /* except for an added check on the window's task. */
2830 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2832 WIN_ReleaseDesktop();
2833 return FALSE;
2836 /* Now call the callback function for every window */
2838 for (ppWnd = list; *ppWnd; ppWnd++)
2840 LRESULT funcRetval;
2841 int iWndsLocks = 0;
2842 /* Make sure that the window still exists */
2843 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2844 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2846 /* To avoid any deadlocks, all the locks on the windows
2847 structures must be suspended before the control
2848 is passed to the application */
2849 iWndsLocks = WIN_SuspendWndsLock();
2850 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2851 WIN_RestoreWndsLock(iWndsLocks);
2853 if (!funcRetval) break;
2855 WIN_ReleaseWinArray(list);
2856 WIN_ReleaseDesktop();
2857 return TRUE;
2861 /**********************************************************************
2862 * EnumThreadWindows (USER32.190)
2864 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2866 THDB *tdb = THREAD_IdToTHDB(id);
2868 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2872 /**********************************************************************
2873 * WIN_EnumChildWindows
2875 * Helper function for EnumChildWindows().
2877 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2878 LPARAM lParam )
2880 WND **childList;
2881 BOOL16 ret = FALSE;
2883 for ( ; *ppWnd; ppWnd++)
2885 int iWndsLocks = 0;
2887 /* Make sure that the window still exists */
2888 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2889 /* Build children list first */
2890 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2892 /* To avoid any deadlocks, all the locks on the windows
2893 structures must be suspended before the control
2894 is passed to the application */
2895 iWndsLocks = WIN_SuspendWndsLock();
2896 ret = func( (*ppWnd)->hwndSelf, lParam );
2897 WIN_RestoreWndsLock(iWndsLocks);
2899 if (childList)
2901 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2902 WIN_ReleaseWinArray(childList);
2904 if (!ret) return FALSE;
2906 return TRUE;
2910 /**********************************************************************
2911 * EnumChildWindows16 (USER.55)
2913 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2914 LPARAM lParam )
2916 WND **list, *pParent;
2918 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2919 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2921 WIN_ReleaseWndPtr(pParent);
2922 return FALSE;
2924 WIN_EnumChildWindows( list, func, lParam );
2925 WIN_ReleaseWinArray(list);
2926 WIN_ReleaseWndPtr(pParent);
2927 return TRUE;
2931 /**********************************************************************
2932 * EnumChildWindows32 (USER32.178)
2934 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2935 LPARAM lParam )
2937 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2938 lParam );
2942 /*******************************************************************
2943 * AnyPopup16 (USER.52)
2945 BOOL16 WINAPI AnyPopup16(void)
2947 return AnyPopup();
2951 /*******************************************************************
2952 * AnyPopup32 (USER32.4)
2954 BOOL WINAPI AnyPopup(void)
2956 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2957 BOOL retvalue;
2959 while (wndPtr)
2961 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2963 retvalue = TRUE;
2964 goto end;
2966 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2968 retvalue = FALSE;
2969 end:
2970 WIN_ReleaseWndPtr(wndPtr);
2971 return retvalue;
2975 /*******************************************************************
2976 * FlashWindow16 (USER.105)
2978 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2980 return FlashWindow( hWnd, bInvert );
2984 /*******************************************************************
2985 * FlashWindow32 (USER32.202)
2987 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2989 WND *wndPtr = WIN_FindWndPtr(hWnd);
2991 TRACE_(win)("%04x\n", hWnd);
2993 if (!wndPtr) return FALSE;
2995 if (wndPtr->dwStyle & WS_MINIMIZE)
2997 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2999 HDC hDC = GetDC(hWnd);
3001 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3002 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3004 ReleaseDC( hWnd, hDC );
3005 wndPtr->flags |= WIN_NCACTIVATED;
3007 else
3009 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
3010 RDW_UPDATENOW | RDW_FRAME, 0 );
3011 wndPtr->flags &= ~WIN_NCACTIVATED;
3013 WIN_ReleaseWndPtr(wndPtr);
3014 return TRUE;
3016 else
3018 WPARAM16 wparam;
3019 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3020 else wparam = (hWnd == GetActiveWindow());
3022 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3023 WIN_ReleaseWndPtr(wndPtr);
3024 return wparam;
3029 /*******************************************************************
3030 * SetSysModalWindow16 (USER.188)
3032 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3034 HWND hWndOldModal = hwndSysModal;
3035 hwndSysModal = hWnd;
3036 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3037 return hWndOldModal;
3041 /*******************************************************************
3042 * GetSysModalWindow16 (USER.52)
3044 HWND16 WINAPI GetSysModalWindow16(void)
3046 return hwndSysModal;
3050 /*******************************************************************
3051 * GetWindowContextHelpId (USER32.303)
3053 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3055 DWORD retval;
3056 WND *wnd = WIN_FindWndPtr( hwnd );
3057 if (!wnd) return 0;
3058 retval = wnd->helpContext;
3059 WIN_ReleaseWndPtr(wnd);
3060 return retval;
3064 /*******************************************************************
3065 * SetWindowContextHelpId (USER32.515)
3067 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3069 WND *wnd = WIN_FindWndPtr( hwnd );
3070 if (!wnd) return FALSE;
3071 wnd->helpContext = id;
3072 WIN_ReleaseWndPtr(wnd);
3073 return TRUE;
3077 /*******************************************************************
3078 * DRAG_QueryUpdate
3080 * recursively find a child that contains spDragInfo->pt point
3081 * and send WM_QUERYDROPOBJECT
3083 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3085 BOOL16 wParam,bResult = 0;
3086 POINT pt;
3087 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3088 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3089 RECT tempRect;
3091 if( !ptrQueryWnd || !ptrDragInfo )
3093 WIN_ReleaseWndPtr(ptrQueryWnd);
3094 return 0;
3097 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3099 GetWindowRect(hQueryWnd,&tempRect);
3101 if( !PtInRect(&tempRect,pt) ||
3102 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3104 WIN_ReleaseWndPtr(ptrQueryWnd);
3105 return 0;
3108 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3110 tempRect = ptrQueryWnd->rectClient;
3111 if(ptrQueryWnd->dwStyle & WS_CHILD)
3112 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3113 (LPPOINT)&tempRect, 2 );
3115 if (PtInRect( &tempRect, pt))
3117 wParam = 0;
3119 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3121 if( ptrWnd->dwStyle & WS_VISIBLE )
3123 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3124 if (PtInRect( &tempRect, pt )) break;
3128 if(ptrWnd)
3130 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3131 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3132 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3133 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3134 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3136 WIN_ReleaseWndPtr(ptrWnd);
3139 if(bResult)
3141 WIN_ReleaseWndPtr(ptrQueryWnd);
3142 return bResult;
3145 else wParam = 1;
3147 else wParam = 1;
3149 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3151 ptrDragInfo->hScope = hQueryWnd;
3153 bResult = ( bNoSend )
3154 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3155 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3156 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3157 if( !bResult )
3158 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3160 WIN_ReleaseWndPtr(ptrQueryWnd);
3161 return bResult;
3165 /*******************************************************************
3166 * DragDetect (USER.465)
3168 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3170 POINT pt32;
3171 CONV_POINT16TO32( &pt, &pt32 );
3172 return DragDetect( hWnd, pt32 );
3175 /*******************************************************************
3176 * DragDetect32 (USER32.151)
3178 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3180 MSG16 msg;
3181 RECT16 rect;
3183 rect.left = pt.x - wDragWidth;
3184 rect.right = pt.x + wDragWidth;
3186 rect.top = pt.y - wDragHeight;
3187 rect.bottom = pt.y + wDragHeight;
3189 SetCapture(hWnd);
3191 while(1)
3193 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3195 if( msg.message == WM_LBUTTONUP )
3197 ReleaseCapture();
3198 return 0;
3200 if( msg.message == WM_MOUSEMOVE )
3202 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3204 ReleaseCapture();
3205 return 1;
3209 WaitMessage();
3211 return 0;
3214 /******************************************************************************
3215 * DragObject16 (USER.464)
3217 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3218 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3220 MSG16 msg;
3221 LPDRAGINFO lpDragInfo;
3222 SEGPTR spDragInfo;
3223 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3224 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3225 WND *wndPtr = WIN_FindWndPtr(hWnd);
3226 HCURSOR16 hCurrentCursor = 0;
3227 HWND16 hCurrentWnd = 0;
3229 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3230 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3232 if( !lpDragInfo || !spDragInfo )
3234 WIN_ReleaseWndPtr(wndPtr);
3235 return 0L;
3238 hBummer = LoadCursor16(0, IDC_BUMMER16);
3240 if( !hBummer || !wndPtr )
3242 GlobalFree16(hDragInfo);
3243 WIN_ReleaseWndPtr(wndPtr);
3244 return 0L;
3247 if(hCursor)
3249 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3251 GlobalFree16(hDragInfo);
3252 WIN_ReleaseWndPtr(wndPtr);
3253 return 0L;
3256 if( hDragCursor == hCursor ) hDragCursor = 0;
3257 else hCursor = hDragCursor;
3259 hOldCursor = SetCursor(hDragCursor);
3262 lpDragInfo->hWnd = hWnd;
3263 lpDragInfo->hScope = 0;
3264 lpDragInfo->wFlags = wObj;
3265 lpDragInfo->hList = szList; /* near pointer! */
3266 lpDragInfo->hOfStruct = hOfStruct;
3267 lpDragInfo->l = 0L;
3269 SetCapture(hWnd);
3270 ShowCursor( TRUE );
3274 do{ WaitMessage(); }
3275 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3277 *(lpDragInfo+1) = *lpDragInfo;
3279 lpDragInfo->pt = msg.pt;
3281 /* update DRAGINFO struct */
3282 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3284 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3285 hCurrentCursor = hCursor;
3286 else
3288 hCurrentCursor = hBummer;
3289 lpDragInfo->hScope = 0;
3291 if( hCurrentCursor )
3292 SetCursor(hCurrentCursor);
3294 /* send WM_DRAGLOOP */
3295 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3296 (LPARAM) spDragInfo );
3297 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3298 if( hCurrentWnd != lpDragInfo->hScope )
3300 if( hCurrentWnd )
3301 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3302 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3303 HIWORD(spDragInfo)) );
3304 hCurrentWnd = lpDragInfo->hScope;
3305 if( hCurrentWnd )
3306 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3308 else
3309 if( hCurrentWnd )
3310 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3312 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3314 ReleaseCapture();
3315 ShowCursor( FALSE );
3317 if( hCursor )
3319 SetCursor( hOldCursor );
3320 if (hDragCursor) DestroyCursor( hDragCursor );
3323 if( hCurrentCursor != hBummer )
3324 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3325 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3326 else
3327 msg.lParam = 0;
3328 GlobalFree16(hDragInfo);
3329 WIN_ReleaseWndPtr(wndPtr);
3331 return (DWORD)(msg.lParam);