Add some null checking in the Get/SetBitmapBits functions.
[wine/wine64.git] / windows / win.c
blob5c8b78d8005818947148e0c11390364ab448fad3
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 while (WIN_CritSection.RecursionCount > 1) WIN_UnlockWnds();
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 while (WIN_CritSection.RecursionCount < ipreviousLocks) WIN_LockWnds();
131 /***********************************************************************
132 * WIN_FindWndPtr
134 * Return a pointer to the WND structure corresponding to a HWND.
136 WND * WIN_FindWndPtr( HWND hwnd )
138 WND * ptr;
140 if (!hwnd || HIWORD(hwnd)) goto error2;
141 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
142 /* Lock all WND structures for thread safeness*/
143 WIN_LockWnds();
144 /*and increment destruction monitoring*/
145 ptr->irefCount++;
147 if (ptr->dwMagic != WND_MAGIC) goto error;
148 if (ptr->hwndSelf != hwnd)
150 ERR_(win)("Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf );
151 goto error;
153 /* returns a locked pointer */
154 return ptr;
155 error:
156 /* Unlock all WND structures for thread safeness*/
157 WIN_UnlockWnds();
158 /* and decrement destruction monitoring value */
159 ptr->irefCount--;
161 error2:
162 if ( hwnd!=0 )
163 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
164 return NULL;
167 /***********************************************************************
168 * WIN_LockWndPtr
170 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
171 * but by initWndPtr;
172 * Returns the locked initialisation pointer
174 WND *WIN_LockWndPtr(WND *initWndPtr)
176 if(!initWndPtr) return 0;
178 /* Lock all WND structures for thread safeness*/
179 WIN_LockWnds();
180 /*and increment destruction monitoring*/
181 initWndPtr->irefCount++;
183 return initWndPtr;
187 /***********************************************************************
188 * WIN_ReleaseWndPtr
190 * Release the pointer to the WND structure.
192 void WIN_ReleaseWndPtr(WND *wndPtr)
194 if(!wndPtr) return;
196 /*Decrement destruction monitoring value*/
197 wndPtr->irefCount--;
198 /* Check if it's time to release the memory*/
199 /* Check if it's time to release the memory*/
200 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
202 /* Release memory */
203 USER_HEAP_FREE( wndPtr->hwndSelf);
205 else if(wndPtr->irefCount < 0)
207 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
208 TRACE_(win)("forgot a Lock on %p somewhere\n",wndPtr);
210 /*unlock all WND structures for thread safeness*/
211 WIN_UnlockWnds();
214 /***********************************************************************
215 * WIN_UpdateWndPtr
217 * Updates the value of oldPtr to newPtr.
219 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
221 WND *tmpWnd = NULL;
223 tmpWnd = WIN_LockWndPtr(newPtr);
224 WIN_ReleaseWndPtr(*oldPtr);
225 *oldPtr = tmpWnd;
229 /***********************************************************************
230 * WIN_DumpWindow
232 * Dump the content of a window structure to stderr.
234 void WIN_DumpWindow( HWND hwnd )
236 WND *ptr;
237 char className[80];
238 int i;
240 if (!(ptr = WIN_FindWndPtr( hwnd )))
242 WARN_(win)("%04x is not a window handle\n", hwnd );
243 return;
246 if (!GetClassNameA( hwnd, className, sizeof(className ) ))
247 strcpy( className, "#NULL#" );
249 TRACE_(win)("Window %04x (%p):\n", hwnd, ptr );
250 DPRINTF( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
251 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
252 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
253 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
254 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
255 ptr->next, ptr->child, ptr->parent, ptr->owner,
256 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
257 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
258 ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
259 ptr->text ? ptr->text : "",
260 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
261 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
262 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
263 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
265 if (ptr->class->cbWndExtra)
267 DPRINTF( "extra bytes:" );
268 for (i = 0; i < ptr->class->cbWndExtra; i++)
269 DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
270 DPRINTF( "\n" );
272 DPRINTF( "\n" );
273 WIN_ReleaseWndPtr(ptr);
277 /***********************************************************************
278 * WIN_WalkWindows
280 * Walk the windows tree and print each window on stderr.
282 void WIN_WalkWindows( HWND hwnd, int indent )
284 WND *ptr;
285 char className[80];
287 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : WIN_GetDesktop();
289 if (!ptr)
291 WARN_(win)("Invalid window handle %04x\n", hwnd );
292 return;
295 if (!indent) /* first time around */
296 DPRINTF( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
297 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
298 " Text");
300 while (ptr)
302 DPRINTF( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
304 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
306 DPRINTF( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
307 (DWORD)ptr, ptr->hmemTaskQ, className,
308 (UINT)ptr->dwStyle, (UINT)ptr->winproc,
309 ptr->text?ptr->text:"<null>");
311 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
312 WIN_UpdateWndPtr(&ptr,ptr->next);
318 /***********************************************************************
319 * WIN_UnlinkWindow
321 * Remove a window from the siblings linked list.
323 BOOL WIN_UnlinkWindow( HWND hwnd )
325 WND *wndPtr, **ppWnd;
326 BOOL ret = FALSE;
328 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
329 else if(!wndPtr->parent)
331 WIN_ReleaseWndPtr(wndPtr);
332 return FALSE;
335 ppWnd = &wndPtr->parent->child;
336 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
337 if (*ppWnd)
339 *ppWnd = wndPtr->next;
340 ret = TRUE;
342 WIN_ReleaseWndPtr(wndPtr);
343 return ret;
347 /***********************************************************************
348 * WIN_LinkWindow
350 * Insert a window into the siblings linked list.
351 * The window is inserted after the specified window, which can also
352 * be specified as HWND_TOP or HWND_BOTTOM.
354 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
356 WND *wndPtr, **ppWnd;
358 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
359 else if(!wndPtr->parent)
361 WIN_ReleaseWndPtr(wndPtr);
362 return FALSE;
364 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
366 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
367 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
368 while (*ppWnd) ppWnd = &(*ppWnd)->next;
370 else /* Normal case */
372 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
373 if (!afterPtr)
375 WIN_ReleaseWndPtr(wndPtr);
376 return FALSE;
378 ppWnd = &afterPtr->next;
379 WIN_ReleaseWndPtr(afterPtr);
381 wndPtr->next = *ppWnd;
382 *ppWnd = wndPtr;
383 WIN_ReleaseWndPtr(wndPtr);
384 return TRUE;
388 /***********************************************************************
389 * WIN_FindWinToRepaint
391 * Find a window that needs repaint.
393 HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue )
395 HWND hwndRet;
396 WND *pWnd;
398 /* Note: the desktop window never gets WM_PAINT messages
399 * The real reason why is because Windows DesktopWndProc
400 * does ValidateRgn inside WM_ERASEBKGND handler.
403 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
405 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
407 if (!(pWnd->dwStyle & WS_VISIBLE))
409 TRACE_(win)("skipping window %04x\n",
410 pWnd->hwndSelf );
412 else if ((pWnd->hmemTaskQ == hQueue) &&
413 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)))
414 break;
416 else if (pWnd->child )
417 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
419 WIN_ReleaseWndPtr(pWnd);
420 return hwndRet;
425 if(!pWnd)
427 return 0;
430 hwndRet = pWnd->hwndSelf;
432 /* look among siblings if we got a transparent window */
433 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
434 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
436 WIN_UpdateWndPtr(&pWnd,pWnd->next);
438 if (pWnd)
440 hwndRet = pWnd->hwndSelf;
441 WIN_ReleaseWndPtr(pWnd);
443 TRACE_(win)("found %04x\n",hwndRet);
444 return hwndRet;
448 /***********************************************************************
449 * WIN_DestroyWindow
451 * Destroy storage associated to a window. "Internals" p.358
452 * returns a locked wndPtr->next
454 static WND* WIN_DestroyWindow( WND* wndPtr )
456 HWND hwnd = wndPtr->hwndSelf;
457 WND *pWnd;
459 TRACE_(win)("%04x\n", wndPtr->hwndSelf );
461 #ifdef CONFIG_IPC
462 if (main_block)
463 DDE_DestroyWindow(wndPtr->hwndSelf);
464 #endif /* CONFIG_IPC */
466 /* free child windows */
467 WIN_LockWndPtr(wndPtr->child);
468 while ((pWnd = wndPtr->child))
470 wndPtr->child = WIN_DestroyWindow( pWnd );
471 WIN_ReleaseWndPtr(pWnd);
475 * Clear the update region to make sure no WM_PAINT messages will be
476 * generated for this window while processing the WM_NCDESTROY.
478 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
480 if (wndPtr->hrgnUpdate > 1)
481 DeleteObject( wndPtr->hrgnUpdate );
483 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
485 wndPtr->hrgnUpdate = 0;
489 * Send the WM_NCDESTROY to the window being destroyed.
491 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
493 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
495 WINPOS_CheckInternalPos( wndPtr );
496 if( hwnd == GetCapture()) ReleaseCapture();
498 /* free resources associated with the window */
500 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
501 PROPERTY_RemoveWindowProps( wndPtr );
503 wndPtr->dwMagic = 0; /* Mark it as invalid */
505 /* toss stale messages from the queue */
507 if( wndPtr->hmemTaskQ )
509 BOOL bPostQuit = FALSE;
510 WPARAM wQuitParam = 0;
511 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) QUEUE_Lock(wndPtr->hmemTaskQ);
512 QMSG *qmsg;
514 while( (qmsg = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != 0 )
516 if( qmsg->msg.message == WM_QUIT )
518 bPostQuit = TRUE;
519 wQuitParam = qmsg->msg.wParam;
521 QUEUE_RemoveMsg(msgQ, qmsg);
524 QUEUE_Unlock(msgQ);
526 /* repost WM_QUIT to make sure this app exits its message loop */
527 if( bPostQuit ) PostQuitMessage(wQuitParam);
528 wndPtr->hmemTaskQ = 0;
531 if (!(wndPtr->dwStyle & WS_CHILD))
532 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
533 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
534 wndPtr->pDriver->pDestroyWindow( wndPtr );
535 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
536 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
537 wndPtr->hwndSelf = 0;
538 wndPtr->class->cWindows--;
539 wndPtr->class = NULL;
541 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
543 wndPtr->pDriver->pFinalize(wndPtr);
545 return pWnd;
548 /***********************************************************************
549 * WIN_ResetQueueWindows
551 * Reset the queue of all the children of a given window.
552 * Return TRUE if something was done.
554 BOOL WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
556 BOOL ret = FALSE;
558 if (hNew) /* Set a new queue */
560 for (wnd = WIN_LockWndPtr(wnd->child); (wnd);WIN_UpdateWndPtr(&wnd,wnd->next))
562 if (wnd->hmemTaskQ == hQueue)
564 wnd->hmemTaskQ = hNew;
565 ret = TRUE;
567 if (wnd->child)
569 ret |= WIN_ResetQueueWindows( wnd, hQueue, hNew );
573 else /* Queue is being destroyed */
575 while (wnd->child)
577 WND *tmp = WIN_LockWndPtr(wnd->child);
578 WND *tmp2;
579 ret = FALSE;
580 while (tmp)
582 if (tmp->hmemTaskQ == hQueue)
584 DestroyWindow( tmp->hwndSelf );
585 ret = TRUE;
586 break;
588 tmp2 = WIN_LockWndPtr(tmp->child);
589 if (tmp2 && WIN_ResetQueueWindows(tmp2,hQueue,0))
590 ret = TRUE;
591 else
593 WIN_UpdateWndPtr(&tmp,tmp->next);
595 WIN_ReleaseWndPtr(tmp2);
597 WIN_ReleaseWndPtr(tmp);
598 if (!ret) break;
601 return ret;
604 /***********************************************************************
605 * WIN_CreateDesktopWindow
607 * Create the desktop window.
609 BOOL WIN_CreateDesktopWindow(void)
611 CLASS *class;
612 HWND hwndDesktop;
613 DESKTOP *pDesktop;
615 TRACE_(win)("Creating desktop window\n");
618 if (!ICONTITLE_Init() ||
619 !WINPOS_CreateInternalPosAtom() ||
620 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
621 return FALSE;
623 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
624 if (!hwndDesktop) return FALSE;
625 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
627 pDesktop = (DESKTOP *) pWndDesktop->wExtra;
628 pDesktop->pDriver = DESKTOP_Driver;
629 pWndDesktop->pDriver = WND_Driver;
631 pDesktop->pDriver->pInitialize(pDesktop);
632 pWndDesktop->pDriver->pInitialize(pWndDesktop);
634 pWndDesktop->next = NULL;
635 pWndDesktop->child = NULL;
636 pWndDesktop->parent = NULL;
637 pWndDesktop->owner = NULL;
638 pWndDesktop->class = class;
639 pWndDesktop->dwMagic = WND_MAGIC;
640 pWndDesktop->hwndSelf = hwndDesktop;
641 pWndDesktop->hInstance = 0;
642 pWndDesktop->rectWindow.left = 0;
643 pWndDesktop->rectWindow.top = 0;
644 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
645 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
646 pWndDesktop->rectClient = pWndDesktop->rectWindow;
647 pWndDesktop->text = NULL;
648 pWndDesktop->hmemTaskQ = GetFastQueue16();
649 pWndDesktop->hrgnUpdate = 0;
650 pWndDesktop->hwndLastActive = hwndDesktop;
651 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
652 WS_CLIPSIBLINGS;
653 pWndDesktop->dwExStyle = 0;
654 pWndDesktop->dce = NULL;
655 pWndDesktop->pVScroll = NULL;
656 pWndDesktop->pHScroll = NULL;
657 pWndDesktop->pProp = NULL;
658 pWndDesktop->wIDmenu = 0;
659 pWndDesktop->helpContext = 0;
660 pWndDesktop->flags = Options.desktopGeometry ? WIN_NATIVE : 0;
661 pWndDesktop->hSysMenu = 0;
662 pWndDesktop->userdata = 0;
663 pWndDesktop->winproc = (WNDPROC16)class->winproc;
664 pWndDesktop->irefCount = 0;
666 /* FIXME: How do we know if it should be Unicode or not */
667 if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE))
668 return FALSE;
670 SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 );
671 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
672 return TRUE;
676 /***********************************************************************
677 * WIN_CreateWindowEx
679 * Implementation of CreateWindowEx().
681 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
682 BOOL win32, BOOL unicode )
684 CLASS *classPtr;
685 WND *wndPtr;
686 HWND retvalue;
687 HWND16 hwnd, hwndLinkAfter;
688 POINT maxSize, maxPos, minTrack, maxTrack;
689 LRESULT (CALLBACK *localSend32)(HWND, UINT, WPARAM, LPARAM);
690 char buffer[256];
692 TRACE_(win)("%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
693 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
694 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
695 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
696 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
698 /* Find the parent window */
700 if (cs->hwndParent)
702 /* Make sure parent is valid */
703 if (!IsWindow( cs->hwndParent ))
705 WARN_(win)("Bad parent %04x\n", cs->hwndParent );
706 return 0;
708 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
709 WARN_(win)("No parent for child window\n" );
710 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
713 /* Find the window class */
714 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
716 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
717 WARN_(win)("Bad class '%s'\n", buffer );
718 return 0;
721 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
722 * with an atom as the class name, put some programs expect to have a *REAL* string in
723 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
725 if ( !HIWORD(cs->lpszClass) ) {
726 if (unicode) {
727 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
728 } else {
729 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
731 cs->lpszClass = buffer;
734 /* Fix the coordinates */
736 if (cs->x == CW_USEDEFAULT)
738 PDB *pdb = PROCESS_Current();
739 if ( !(cs->style & (WS_CHILD | WS_POPUP))
740 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
742 cs->x = pdb->env_db->startup_info->dwX;
743 cs->y = pdb->env_db->startup_info->dwY;
745 else
747 cs->x = 0;
748 cs->y = 0;
751 if (cs->cx == CW_USEDEFAULT)
753 PDB *pdb = PROCESS_Current();
754 if ( !(cs->style & (WS_CHILD | WS_POPUP))
755 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
757 cs->cx = pdb->env_db->startup_info->dwXSize;
758 cs->cy = pdb->env_db->startup_info->dwYSize;
760 else
762 cs->cx = 600; /* FIXME */
763 cs->cy = 400;
767 /* Create the window structure */
769 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
770 - sizeof(wndPtr->wExtra) )))
772 TRACE_(win)("out of memory\n" );
773 return 0;
776 /* Fill the window structure */
778 wndPtr = WIN_LockWndPtr((WND *) USER_HEAP_LIN_ADDR( hwnd ));
779 wndPtr->next = NULL;
780 wndPtr->child = NULL;
782 if ((cs->style & WS_CHILD) && cs->hwndParent)
784 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
785 wndPtr->owner = NULL;
786 WIN_ReleaseWndPtr(wndPtr->parent);
788 else
790 wndPtr->parent = pWndDesktop;
791 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
792 wndPtr->owner = NULL;
793 else
795 WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
796 wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
797 WIN_ReleaseWndPtr(wndPtr->owner);
798 WIN_ReleaseWndPtr(tmpWnd);
802 wndPtr->pDriver = wndPtr->parent->pDriver;
803 wndPtr->pDriver->pInitialize(wndPtr);
805 wndPtr->class = classPtr;
806 wndPtr->winproc = classPtr->winproc;
807 wndPtr->dwMagic = WND_MAGIC;
808 wndPtr->hwndSelf = hwnd;
809 wndPtr->hInstance = cs->hInstance;
810 wndPtr->text = NULL;
811 wndPtr->hmemTaskQ = GetFastQueue16();
812 wndPtr->hrgnUpdate = 0;
813 wndPtr->hwndLastActive = hwnd;
814 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
815 wndPtr->dwExStyle = cs->dwExStyle;
816 wndPtr->wIDmenu = 0;
817 wndPtr->helpContext = 0;
818 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
819 wndPtr->pVScroll = NULL;
820 wndPtr->pHScroll = NULL;
821 wndPtr->pProp = NULL;
822 wndPtr->userdata = 0;
823 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
824 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
825 wndPtr->irefCount = 1;
827 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
829 /* Call the WH_CBT hook */
831 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
832 ? HWND_BOTTOM : HWND_TOP;
834 if (HOOK_IsHooked( WH_CBT ))
836 CBT_CREATEWNDA cbtc;
837 LRESULT ret;
839 cbtc.lpcs = cs;
840 cbtc.hwndInsertAfter = hwndLinkAfter;
841 ret = unicode ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
842 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
843 if (ret)
845 TRACE_(win)("CBT-hook returned 0\n");
846 wndPtr->pDriver->pFinalize(wndPtr);
847 USER_HEAP_FREE( hwnd );
848 retvalue = 0;
849 goto end;
853 /* Increment class window counter */
855 classPtr->cWindows++;
857 /* Correct the window style */
859 if (!(cs->style & WS_CHILD))
861 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
862 if (!(cs->style & WS_POPUP))
864 wndPtr->dwStyle |= WS_CAPTION;
865 wndPtr->flags |= WIN_NEED_SIZE;
868 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
870 /* Get class or window DC if needed */
872 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
873 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
874 else wndPtr->dce = NULL;
876 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
878 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
880 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
881 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
882 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
883 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
884 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
887 if(cs->style & WS_CHILD)
889 if(cs->cx < 0) cs->cx = 0;
890 if(cs->cy < 0) cs->cy = 0;
892 else
894 if (cs->cx <= 0) cs->cx = 1;
895 if (cs->cy <= 0) cs->cy = 1;
898 wndPtr->rectWindow.left = cs->x;
899 wndPtr->rectWindow.top = cs->y;
900 wndPtr->rectWindow.right = cs->x + cs->cx;
901 wndPtr->rectWindow.bottom = cs->y + cs->cy;
902 wndPtr->rectClient = wndPtr->rectWindow;
904 if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode))
906 retvalue = FALSE;
907 goto end;
910 /* Set the window menu */
912 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
914 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
915 else
917 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
918 if (classPtr->menuNameA)
919 cs->hMenu = HIWORD(classPtr->menuNameA) ?
920 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
921 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
922 #else
923 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
924 if (menuName)
926 if (HIWORD(cs->hInstance))
927 cs->hMenu = LoadMenuA(cs->hInstance,PTR_SEG_TO_LIN(menuName));
928 else
929 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
931 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
933 #endif
936 else wndPtr->wIDmenu = (UINT)cs->hMenu;
938 /* Send the WM_CREATE message
939 * Perhaps we shouldn't allow width/height changes as well.
940 * See p327 in "Internals".
943 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
945 localSend32 = unicode ? SendMessageW : SendMessageA;
946 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
948 /* Insert the window in the linked list */
950 WIN_LinkWindow( hwnd, hwndLinkAfter );
952 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
953 NULL, NULL, 0, &wndPtr->rectClient );
954 OffsetRect(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
955 maxPos.y - wndPtr->rectWindow.top);
956 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
958 /* Send the size messages */
960 if (!(wndPtr->flags & WIN_NEED_SIZE))
962 /* send it anyway */
963 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
964 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
965 WARN_(win)("sending bogus WM_SIZE message 0x%08lx\n",
966 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
967 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
968 SendMessageA( hwnd, WM_SIZE, SIZE_RESTORED,
969 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
970 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
971 SendMessageA( hwnd, WM_MOVE, 0,
972 MAKELONG( wndPtr->rectClient.left,
973 wndPtr->rectClient.top ) );
976 /* Show the window, maximizing or minimizing if needed */
978 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
980 RECT16 newPos;
981 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
982 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
983 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
984 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
985 ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
986 : SWP_NOZORDER | SWP_FRAMECHANGED;
987 SetWindowPos( hwnd, 0, newPos.left, newPos.top,
988 newPos.right, newPos.bottom, swFlag );
991 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
993 /* Notify the parent window only */
995 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
996 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
997 if( !IsWindow(hwnd) )
999 retvalue = 0;
1000 goto end;
1004 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
1006 /* Call WH_SHELL hook */
1008 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1009 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
1011 TRACE_(win)("created window %04x\n", hwnd);
1012 retvalue = hwnd;
1013 goto end;
1015 WIN_UnlinkWindow( hwnd );
1018 /* Abort window creation */
1020 WARN_(win)("aborted by WM_xxCREATE!\n");
1021 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1022 retvalue = 0;
1023 end:
1024 WIN_ReleaseWndPtr(wndPtr);
1026 return retvalue;
1030 /***********************************************************************
1031 * CreateWindow16 (USER.41)
1033 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1034 DWORD style, INT16 x, INT16 y, INT16 width,
1035 INT16 height, HWND16 parent, HMENU16 menu,
1036 HINSTANCE16 instance, LPVOID data )
1038 return CreateWindowEx16( 0, className, windowName, style,
1039 x, y, width, height, parent, menu, instance, data );
1043 /***********************************************************************
1044 * CreateWindowEx16 (USER.452)
1046 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1047 LPCSTR windowName, DWORD style, INT16 x,
1048 INT16 y, INT16 width, INT16 height,
1049 HWND16 parent, HMENU16 menu,
1050 HINSTANCE16 instance, LPVOID data )
1052 ATOM classAtom;
1053 CREATESTRUCTA cs;
1055 /* Find the class atom */
1057 if (!(classAtom = GlobalFindAtomA( className )))
1059 fprintf( stderr, "CreateWindowEx16: bad class name " );
1060 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1061 else fprintf( stderr, "'%s'\n", className );
1062 return 0;
1065 /* Fix the coordinates */
1067 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1068 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1069 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1070 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1072 /* Create the window */
1074 cs.lpCreateParams = data;
1075 cs.hInstance = (HINSTANCE)instance;
1076 cs.hMenu = (HMENU)menu;
1077 cs.hwndParent = (HWND)parent;
1078 cs.style = style;
1079 cs.lpszName = windowName;
1080 cs.lpszClass = className;
1081 cs.dwExStyle = exStyle;
1082 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
1086 /***********************************************************************
1087 * CreateWindowEx32A (USER32.83)
1089 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1090 LPCSTR windowName, DWORD style, INT x,
1091 INT y, INT width, INT height,
1092 HWND parent, HMENU menu,
1093 HINSTANCE instance, LPVOID data )
1095 ATOM classAtom;
1096 CREATESTRUCTA cs;
1098 if(exStyle & WS_EX_MDICHILD)
1099 return MDI_CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1100 /* Find the class atom */
1102 if (!(classAtom = GlobalFindAtomA( className )))
1104 fprintf( stderr, "CreateWindowEx32A: bad class name " );
1105 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
1106 else fprintf( stderr, "'%s'\n", className );
1107 return 0;
1110 /* Create the window */
1112 cs.lpCreateParams = data;
1113 cs.hInstance = instance;
1114 cs.hMenu = menu;
1115 cs.hwndParent = parent;
1116 cs.x = x;
1117 cs.y = y;
1118 cs.cx = width;
1119 cs.cy = height;
1120 cs.style = style;
1121 cs.lpszName = windowName;
1122 cs.lpszClass = className;
1123 cs.dwExStyle = exStyle;
1124 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
1128 /***********************************************************************
1129 * CreateWindowEx32W (USER32.84)
1131 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1132 LPCWSTR windowName, DWORD style, INT x,
1133 INT y, INT width, INT height,
1134 HWND parent, HMENU menu,
1135 HINSTANCE instance, LPVOID data )
1137 ATOM classAtom;
1138 CREATESTRUCTW cs;
1140 if(exStyle & WS_EX_MDICHILD)
1141 return MDI_CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1143 /* Find the class atom */
1145 if (!(classAtom = GlobalFindAtomW( className )))
1147 if (HIWORD(className))
1149 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
1150 WARN_(win)("Bad class name '%s'\n",cn);
1151 HeapFree( GetProcessHeap(), 0, cn );
1153 else
1154 WARN_(win)("Bad class name %p\n", className );
1155 return 0;
1158 /* Create the window */
1160 cs.lpCreateParams = data;
1161 cs.hInstance = instance;
1162 cs.hMenu = menu;
1163 cs.hwndParent = parent;
1164 cs.x = x;
1165 cs.y = y;
1166 cs.cx = width;
1167 cs.cy = height;
1168 cs.style = style;
1169 cs.lpszName = windowName;
1170 cs.lpszClass = className;
1171 cs.dwExStyle = exStyle;
1172 /* Note: we rely on the fact that CREATESTRUCT32A and */
1173 /* CREATESTRUCT32W have the same layout. */
1174 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, TRUE, TRUE );
1178 /***********************************************************************
1179 * WIN_CheckFocus
1181 static void WIN_CheckFocus( WND* pWnd )
1183 if( GetFocus16() == pWnd->hwndSelf )
1184 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
1187 /***********************************************************************
1188 * WIN_SendDestroyMsg
1190 static void WIN_SendDestroyMsg( WND* pWnd )
1192 WIN_CheckFocus(pWnd);
1194 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
1195 CLIPBOARD_Driver->pResetOwner( pWnd, TRUE );
1198 * Send the WM_DESTROY to the window.
1200 SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
1203 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1204 * make sure that the window still exists when we come back.
1206 if (IsWindow(pWnd->hwndSelf))
1208 HWND* pWndArray = NULL;
1209 WND* pChild = NULL;
1210 int nKidCount = 0;
1213 * Now, if the window has kids, we have to send WM_DESTROY messages
1214 * recursively to it's kids. It seems that those calls can also
1215 * trigger re-entrant calls to DestroyWindow for the kids so we must
1216 * protect against corruption of the list of siblings. We first build
1217 * a list of HWNDs representing all the kids.
1219 pChild = WIN_LockWndPtr(pWnd->child);
1220 while( pChild )
1222 nKidCount++;
1223 WIN_UpdateWndPtr(&pChild,pChild->next);
1227 * If there are no kids, we're done.
1229 if (nKidCount==0)
1230 return;
1232 pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
1235 * Sanity check
1237 if (pWndArray==NULL)
1238 return;
1241 * Now, enumerate all the kids in a list, since we wait to make the SendMessage
1242 * call, our linked list of siblings should be safe.
1244 nKidCount = 0;
1245 pChild = WIN_LockWndPtr(pWnd->child);
1246 while( pChild )
1248 pWndArray[nKidCount] = pChild->hwndSelf;
1249 nKidCount++;
1250 WIN_UpdateWndPtr(&pChild,pChild->next);
1254 * Now that we have a list, go through that list again and send the destroy
1255 * message to those windows. We are using the HWND to retrieve the
1256 * WND pointer so we are effectively checking that all the kid windows are
1257 * still valid before sending the message.
1259 while (nKidCount>0)
1261 pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
1263 if (pChild!=NULL)
1265 WIN_SendDestroyMsg( pChild );
1266 WIN_ReleaseWndPtr(pChild);
1271 * Cleanup
1273 HeapFree(GetProcessHeap(), 0, pWndArray);
1274 WIN_CheckFocus(pWnd);
1276 else
1277 WARN_(win)("\tdestroyed itself while in WM_DESTROY!\n");
1281 /***********************************************************************
1282 * DestroyWindow16 (USER.53)
1284 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1286 return DestroyWindow(hwnd);
1290 /***********************************************************************
1291 * DestroyWindow32 (USER32.135)
1293 BOOL WINAPI DestroyWindow( HWND hwnd )
1295 WND * wndPtr;
1296 BOOL retvalue;
1298 TRACE_(win)("(%04x)\n", hwnd);
1300 /* Initialization */
1302 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1303 if (wndPtr == pWndDesktop)
1305 WIN_ReleaseWndPtr(wndPtr);
1306 return FALSE; /* Can't destroy desktop */
1309 /* Call hooks */
1311 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1313 retvalue = FALSE;
1314 goto end;
1317 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1319 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1320 /* FIXME: clean up palette - see "Internals" p.352 */
1323 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1324 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1326 /* Notify the parent window only */
1327 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1328 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1329 if( !IsWindow(hwnd) )
1331 retvalue = TRUE;
1332 goto end;
1336 CLIPBOARD_Driver->pResetOwner( wndPtr, FALSE ); /* before the window is unmapped */
1338 /* Hide the window */
1340 if (wndPtr->dwStyle & WS_VISIBLE)
1342 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1343 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1344 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1345 if (!IsWindow(hwnd))
1347 retvalue = TRUE;
1348 goto end;
1352 /* Recursively destroy owned windows */
1354 if( !(wndPtr->dwStyle & WS_CHILD) )
1356 /* make sure top menu popup doesn't get destroyed */
1357 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1359 for (;;)
1361 WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child); /* First sibling */
1362 while (siblingPtr)
1364 if (siblingPtr->owner == wndPtr)
1366 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1367 break;
1368 else
1369 siblingPtr->owner = NULL;
1371 WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
1373 if (siblingPtr)
1375 DestroyWindow( siblingPtr->hwndSelf );
1376 WIN_ReleaseWndPtr(siblingPtr);
1378 else break;
1381 if( !Options.managed || EVENT_CheckFocus() )
1382 WINPOS_ActivateOtherWindow(wndPtr);
1384 if( wndPtr->owner &&
1385 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1386 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1389 /* Send destroy messages */
1391 WIN_SendDestroyMsg( wndPtr );
1392 if (!IsWindow(hwnd))
1394 retvalue = TRUE;
1395 goto end;
1398 /* Unlink now so we won't bother with the children later on */
1400 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1402 /* Destroy the window storage */
1404 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1405 retvalue = TRUE;
1406 end:
1407 WIN_ReleaseWndPtr(wndPtr);
1408 return retvalue;
1412 /***********************************************************************
1413 * CloseWindow16 (USER.43)
1415 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1417 return CloseWindow( hwnd );
1421 /***********************************************************************
1422 * CloseWindow32 (USER32.56)
1424 BOOL WINAPI CloseWindow( HWND hwnd )
1426 WND * wndPtr = WIN_FindWndPtr( hwnd );
1427 BOOL retvalue;
1429 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1431 retvalue = FALSE;
1432 goto end;
1434 ShowWindow( hwnd, SW_MINIMIZE );
1435 retvalue = TRUE;
1436 end:
1437 WIN_ReleaseWndPtr(wndPtr);
1438 return retvalue;
1443 /***********************************************************************
1444 * OpenIcon16 (USER.44)
1446 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1448 return OpenIcon( hwnd );
1452 /***********************************************************************
1453 * OpenIcon32 (USER32.410)
1455 BOOL WINAPI OpenIcon( HWND hwnd )
1457 if (!IsIconic( hwnd )) return FALSE;
1458 ShowWindow( hwnd, SW_SHOWNORMAL );
1459 return TRUE;
1463 /***********************************************************************
1464 * WIN_FindWindow
1466 * Implementation of FindWindow() and FindWindowEx().
1468 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1469 LPCSTR title )
1471 WND *pWnd;
1472 HWND retvalue;
1473 CLASS *pClass = NULL;
1475 if (child)
1477 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1478 if (parent)
1480 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
1482 retvalue = 0;
1483 goto end;
1486 else if (pWnd->parent != pWndDesktop)
1488 retvalue = 0;
1489 goto end;
1491 WIN_UpdateWndPtr(&pWnd,pWnd->next);
1493 else
1495 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
1497 retvalue = 0;
1498 goto end;
1500 WIN_UpdateWndPtr(&pWnd,pWnd->child);
1502 if (!pWnd)
1504 retvalue = 0;
1505 goto end;
1508 /* For a child window, all siblings will have the same hInstance, */
1509 /* so we can look for the class once and for all. */
1511 if (className && (pWnd->dwStyle & WS_CHILD))
1513 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1515 retvalue = 0;
1516 goto end;
1521 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
1523 if (className && !(pWnd->dwStyle & WS_CHILD))
1525 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1526 continue; /* Skip this window */
1529 if (pClass && (pWnd->class != pClass))
1530 continue; /* Not the right class */
1532 /* Now check the title */
1534 if (!title)
1536 retvalue = pWnd->hwndSelf;
1537 goto end;
1539 if (pWnd->text && !strcmp( pWnd->text, title ))
1541 retvalue = pWnd->hwndSelf;
1542 goto end;
1545 retvalue = 0;
1546 end:
1547 WIN_ReleaseWndPtr(pWnd);
1548 return retvalue;
1553 /***********************************************************************
1554 * FindWindow16 (USER.50)
1556 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1558 return FindWindowEx16( 0, 0, className, title );
1562 /***********************************************************************
1563 * FindWindowEx16 (USER.427)
1565 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1566 SEGPTR className, LPCSTR title )
1568 ATOM atom = 0;
1570 TRACE_(win)("%04x %04x '%s' '%s'\n", parent,
1571 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1572 title ? title : "");
1574 if (className)
1576 /* If the atom doesn't exist, then no class */
1577 /* with this name exists either. */
1578 if (!(atom = GlobalFindAtom16( className ))) return 0;
1580 return WIN_FindWindow( parent, child, atom, title );
1584 /***********************************************************************
1585 * FindWindow32A (USER32.198)
1587 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1589 HWND ret = FindWindowExA( 0, 0, className, title );
1590 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1591 return ret;
1595 /***********************************************************************
1596 * FindWindowEx32A (USER32.199)
1598 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1599 LPCSTR className, LPCSTR title )
1601 ATOM atom = 0;
1603 if (className)
1605 /* If the atom doesn't exist, then no class */
1606 /* with this name exists either. */
1607 if (!(atom = GlobalFindAtomA( className )))
1609 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1610 return 0;
1613 return WIN_FindWindow( parent, child, atom, title );
1617 /***********************************************************************
1618 * FindWindowEx32W (USER32.200)
1620 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1621 LPCWSTR className, LPCWSTR title )
1623 ATOM atom = 0;
1624 char *buffer;
1625 HWND hwnd;
1627 if (className)
1629 /* If the atom doesn't exist, then no class */
1630 /* with this name exists either. */
1631 if (!(atom = GlobalFindAtomW( className )))
1633 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1634 return 0;
1637 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1638 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1639 HeapFree( GetProcessHeap(), 0, buffer );
1640 return hwnd;
1644 /***********************************************************************
1645 * FindWindow32W (USER32.201)
1647 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1649 return FindWindowExW( 0, 0, className, title );
1653 /**********************************************************************
1654 * WIN_GetDesktop
1655 * returns a locked pointer
1657 WND *WIN_GetDesktop(void)
1659 return WIN_LockWndPtr(pWndDesktop);
1661 /**********************************************************************
1662 * WIN_ReleaseDesktop
1663 * unlock the desktop pointer
1665 void WIN_ReleaseDesktop(void)
1667 WIN_ReleaseWndPtr(pWndDesktop);
1671 /**********************************************************************
1672 * GetDesktopWindow16 (USER.286)
1674 HWND16 WINAPI GetDesktopWindow16(void)
1676 return (HWND16)pWndDesktop->hwndSelf;
1680 /**********************************************************************
1681 * GetDesktopWindow32 (USER32.232)
1683 HWND WINAPI GetDesktopWindow(void)
1685 return pWndDesktop->hwndSelf;
1689 /**********************************************************************
1690 * GetDesktopHwnd (USER.278)
1692 * Exactly the same thing as GetDesktopWindow(), but not documented.
1693 * Don't ask me why...
1695 HWND16 WINAPI GetDesktopHwnd16(void)
1697 return (HWND16)pWndDesktop->hwndSelf;
1701 /*******************************************************************
1702 * EnableWindow16 (USER.34)
1704 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1706 return EnableWindow( hwnd, enable );
1710 /*******************************************************************
1711 * EnableWindow32 (USER32.172)
1713 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1715 WND *wndPtr;
1716 BOOL retvalue;
1718 TRACE_(win)("EnableWindow32: ( %x, %d )\n", hwnd, enable);
1720 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1721 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1723 /* Enable window */
1724 wndPtr->dwStyle &= ~WS_DISABLED;
1726 if( wndPtr->flags & WIN_NATIVE )
1727 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, TRUE );
1729 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1730 retvalue = TRUE;
1731 goto end;
1733 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1735 SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0);
1737 /* Disable window */
1738 wndPtr->dwStyle |= WS_DISABLED;
1740 if( wndPtr->flags & WIN_NATIVE )
1741 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ACCEPTFOCUS, FALSE );
1743 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1745 SetFocus( 0 ); /* A disabled window can't have the focus */
1747 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1749 ReleaseCapture(); /* A disabled window can't capture the mouse */
1751 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1752 retvalue = FALSE;
1753 goto end;
1755 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1756 end:
1757 WIN_ReleaseWndPtr(wndPtr);
1758 return retvalue;
1762 /***********************************************************************
1763 * IsWindowEnabled16 (USER.35)
1765 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1767 return IsWindowEnabled(hWnd);
1771 /***********************************************************************
1772 * IsWindowEnabled32 (USER32.349)
1774 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1776 WND * wndPtr;
1777 BOOL retvalue;
1779 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1780 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1781 WIN_ReleaseWndPtr(wndPtr);
1782 return retvalue;
1787 /***********************************************************************
1788 * IsWindowUnicode (USER32.350)
1790 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1792 WND * wndPtr;
1793 BOOL retvalue;
1795 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1796 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1797 WIN_ReleaseWndPtr(wndPtr);
1798 return retvalue;
1802 /**********************************************************************
1803 * GetWindowWord16 (USER.133)
1805 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1807 return GetWindowWord( hwnd, offset );
1811 /**********************************************************************
1812 * GetWindowWord32 (USER32.314)
1814 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1816 WORD retvalue;
1817 WND * wndPtr = WIN_FindWndPtr( hwnd );
1818 if (!wndPtr) return 0;
1819 if (offset >= 0)
1821 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1823 WARN_(win)("Invalid offset %d\n", offset );
1824 retvalue = 0;
1825 goto end;
1827 retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1828 goto end;
1830 switch(offset)
1832 case GWW_ID:
1833 if (HIWORD(wndPtr->wIDmenu))
1834 WARN_(win)("GWW_ID: discards high bits of 0x%08x!\n",
1835 wndPtr->wIDmenu);
1836 retvalue = (WORD)wndPtr->wIDmenu;
1837 goto end;
1838 case GWW_HWNDPARENT:
1839 retvalue = GetParent(hwnd);
1840 goto end;
1841 case GWW_HINSTANCE:
1842 if (HIWORD(wndPtr->hInstance))
1843 WARN_(win)("GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1844 wndPtr->hInstance);
1845 retvalue = (WORD)wndPtr->hInstance;
1846 goto end;
1847 default:
1848 WARN_(win)("Invalid offset %d\n", offset );
1849 retvalue = 0;
1850 goto end;
1852 end:
1853 WIN_ReleaseWndPtr(wndPtr);
1854 return retvalue;
1857 /**********************************************************************
1858 * SetWindowWord16 (USER.134)
1860 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1862 return SetWindowWord( hwnd, offset, newval );
1866 /**********************************************************************
1867 * SetWindowWord32 (USER32.524)
1869 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1871 WORD *ptr, retval;
1872 WND * wndPtr = WIN_FindWndPtr( hwnd );
1873 if (!wndPtr) return 0;
1874 if (offset >= 0)
1876 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1878 WARN_(win)("Invalid offset %d\n", offset );
1879 retval = 0;
1880 goto end;
1882 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1884 else switch(offset)
1886 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1887 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1888 case GWW_HWNDPARENT: retval = SetParent( hwnd, newval );
1889 goto end;
1890 default:
1891 WARN_(win)("Invalid offset %d\n", offset );
1892 retval = 0;
1893 goto end;
1895 retval = *ptr;
1896 *ptr = newval;
1897 end:
1898 WIN_ReleaseWndPtr(wndPtr);
1899 return retval;
1903 /**********************************************************************
1904 * WIN_GetWindowLong
1906 * Helper function for GetWindowLong().
1908 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1910 LONG retvalue;
1911 WND * wndPtr = WIN_FindWndPtr( hwnd );
1912 if (!wndPtr) return 0;
1913 if (offset >= 0)
1915 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1917 WARN_(win)("Invalid offset %d\n", offset );
1918 retvalue = 0;
1919 goto end;
1921 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1922 /* Special case for dialog window procedure */
1923 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1925 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1926 goto end;
1928 goto end;
1930 switch(offset)
1932 case GWL_USERDATA: retvalue = wndPtr->userdata;
1933 goto end;
1934 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1935 goto end;
1936 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1937 goto end;
1938 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1939 goto end;
1940 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1941 type );
1942 goto end;
1943 case GWL_HWNDPARENT: retvalue = GetParent(hwnd);
1944 goto end;
1945 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1946 goto end;
1947 default:
1948 WARN_(win)("Unknown offset %d\n", offset );
1950 retvalue = 0;
1951 end:
1952 WIN_ReleaseWndPtr(wndPtr);
1953 return retvalue;
1957 /**********************************************************************
1958 * WIN_SetWindowLong
1960 * Helper function for SetWindowLong().
1962 * 0 is the failure code. However, in the case of failure SetLastError
1963 * must be set to distinguish between a 0 return value and a failure.
1965 * FIXME: The error values for SetLastError may not be right. Can
1966 * someone check with the real thing?
1968 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1969 WINDOWPROCTYPE type )
1971 LONG *ptr, retval;
1972 WND * wndPtr = WIN_FindWndPtr( hwnd );
1973 STYLESTRUCT style;
1975 TRACE_(win)("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1977 if (!wndPtr)
1979 /* Is this the right error? */
1980 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1981 return 0;
1984 if (offset >= 0)
1986 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1988 WARN_(win)("Invalid offset %d\n", offset );
1990 /* Is this the right error? */
1991 SetLastError( ERROR_OUTOFMEMORY );
1993 retval = 0;
1994 goto end;
1996 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1997 /* Special case for dialog window procedure */
1998 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2000 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
2001 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
2002 type, WIN_PROC_WINDOW );
2003 goto end;
2006 else switch(offset)
2008 case GWL_ID:
2009 ptr = (DWORD*)&wndPtr->wIDmenu;
2010 break;
2011 case GWL_HINSTANCE:
2012 retval = SetWindowWord( hwnd, offset, newval );
2013 goto end;
2014 case GWL_WNDPROC:
2015 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
2016 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
2017 type, WIN_PROC_WINDOW );
2018 goto end;;
2019 case GWL_STYLE:
2020 style.styleOld = wndPtr->dwStyle;
2021 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
2022 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
2024 if (wndPtr->flags & WIN_ISWIN32)
2025 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
2026 wndPtr->dwStyle = style.styleNew;
2027 if (wndPtr->flags & WIN_ISWIN32)
2028 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
2029 retval = style.styleOld;
2030 goto end;
2032 case GWL_USERDATA:
2033 ptr = &wndPtr->userdata;
2034 break;
2035 case GWL_EXSTYLE:
2036 style.styleOld = wndPtr->dwExStyle;
2037 style.styleNew = newval;
2038 if (wndPtr->flags & WIN_ISWIN32)
2039 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
2040 wndPtr->dwExStyle = newval;
2041 if (wndPtr->flags & WIN_ISWIN32)
2042 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
2043 retval = style.styleOld;
2044 goto end;
2046 default:
2047 WARN_(win)("Invalid offset %d\n", offset );
2049 /* Don't think this is right error but it should do */
2050 SetLastError( ERROR_OUTOFMEMORY );
2052 retval = 0;
2053 goto end;
2055 retval = *ptr;
2056 *ptr = newval;
2057 end:
2058 WIN_ReleaseWndPtr(wndPtr);
2059 return retval;
2063 /**********************************************************************
2064 * GetWindowLong16 (USER.135)
2066 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2068 return WIN_GetWindowLong( (HWND)hwnd, offset, WIN_PROC_16 );
2072 /**********************************************************************
2073 * GetWindowLong32A (USER32.305)
2075 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2077 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2081 /**********************************************************************
2082 * GetWindowLong32W (USER32.306)
2084 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2086 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2090 /**********************************************************************
2091 * SetWindowLong16 (USER.136)
2093 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2095 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
2099 /**********************************************************************
2100 * SetWindowLong32A (USER32.517)
2102 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2104 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2108 /**********************************************************************
2109 * SetWindowLong32W (USER32.518) Set window attribute
2111 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2112 * value in a window's extra memory.
2114 * The _hwnd_ parameter specifies the window. is the handle to a
2115 * window that has extra memory. The _newval_ parameter contains the
2116 * new attribute or extra memory value. If positive, the _offset_
2117 * parameter is the byte-addressed location in the window's extra
2118 * memory to set. If negative, _offset_ specifies the window
2119 * attribute to set, and should be one of the following values:
2121 * GWL_EXSTYLE The window's extended window style
2123 * GWL_STYLE The window's window style.
2125 * GWL_WNDPROC Pointer to the window's window procedure.
2127 * GWL_HINSTANCE The window's pplication instance handle.
2129 * GWL_ID The window's identifier.
2131 * GWL_USERDATA The window's user-specified data.
2133 * If the window is a dialog box, the _offset_ parameter can be one of
2134 * the following values:
2136 * DWL_DLGPROC The address of the window's dialog box procedure.
2138 * DWL_MSGRESULT The return value of a message
2139 * that the dialog box procedure processed.
2141 * DWL_USER Application specific information.
2143 * RETURNS
2145 * If successful, returns the previous value located at _offset_. Otherwise,
2146 * returns 0.
2148 * NOTES
2150 * Extra memory for a window class is specified by a nonzero cbWndExtra
2151 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2152 * time of class creation.
2154 * Using GWL_WNDPROC to set a new window procedure effectively creates
2155 * a window subclass. Use CallWindowProc() in the new windows procedure
2156 * to pass messages to the superclass's window procedure.
2158 * The user data is reserved for use by the application which created
2159 * the window.
2161 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
2162 * instead, call the EnableWindow() function to change the window's
2163 * disabled state.
2165 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2166 * SetParent() instead.
2168 * Win95:
2169 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2170 * it sends WM_STYLECHANGING before changing the settings
2171 * and WM_STYLECHANGED afterwards.
2172 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2174 * BUGS
2176 * GWL_STYLE does not dispatch WM_STYLE... messages.
2178 * CONFORMANCE
2180 * ECMA-234, Win32
2183 LONG WINAPI SetWindowLongW(
2184 HWND hwnd, /* window to alter */
2185 INT offset, /* offset, in bytes, of location to alter */
2186 LONG newval /* new value of location */
2188 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2192 /*******************************************************************
2193 * GetWindowText16 (USER.36)
2195 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
2197 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
2201 /*******************************************************************
2202 * GetWindowText32A (USER32.309)
2204 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2206 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
2207 (LPARAM)lpString );
2210 /*******************************************************************
2211 * InternalGetWindowText (USER32.326)
2213 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2215 FIXME_(win)("(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
2216 return GetWindowTextW(hwnd,lpString,nMaxCount);
2220 /*******************************************************************
2221 * GetWindowText32W (USER32.312)
2223 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2225 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
2226 (LPARAM)lpString );
2230 /*******************************************************************
2231 * SetWindowText16 (USER.37)
2233 BOOL16 WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
2235 return (BOOL16)SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2239 /*******************************************************************
2240 * SetWindowText32A (USER32.521)
2242 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2244 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2248 /*******************************************************************
2249 * SetWindowText32W (USER32.523)
2251 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2253 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2257 /*******************************************************************
2258 * GetWindowTextLength16 (USER.38)
2260 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
2262 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2266 /*******************************************************************
2267 * GetWindowTextLength32A (USER32.310)
2269 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2271 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2274 /*******************************************************************
2275 * GetWindowTextLength32W (USER32.311)
2277 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2279 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2283 /*******************************************************************
2284 * IsWindow16 (USER.47)
2286 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
2288 return IsWindow( hwnd );
2291 void WINAPI WIN16_IsWindow16( CONTEXT *context )
2293 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
2294 HWND16 hwnd = (HWND16)stack[2];
2296 AX_reg(context) = IsWindow( hwnd );
2297 ES_reg(context) = USER_HeapSel;
2301 /*******************************************************************
2302 * IsWindow32 (USER32.348)
2304 BOOL WINAPI IsWindow( HWND hwnd )
2306 WND * wndPtr;
2307 BOOL retvalue;
2309 if(!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2310 retvalue = (wndPtr->dwMagic == WND_MAGIC);
2311 WIN_ReleaseWndPtr(wndPtr);
2312 return retvalue;
2317 /*****************************************************************
2318 * GetParent16 (USER.46)
2320 HWND16 WINAPI GetParent16( HWND16 hwnd )
2322 return (HWND16)GetParent( hwnd );
2326 /*****************************************************************
2327 * GetParent32 (USER32.278)
2329 HWND WINAPI GetParent( HWND hwnd )
2331 WND *wndPtr;
2332 HWND retvalue;
2334 if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2335 if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
2337 WIN_ReleaseWndPtr(wndPtr);
2338 return 0;
2340 WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
2341 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2343 WIN_ReleaseWndPtr(wndPtr);
2344 return retvalue;
2348 /*****************************************************************
2349 * WIN_GetTopParent
2351 * Get the top-level parent for a child window.
2352 * returns a locked pointer
2354 WND* WIN_GetTopParentPtr( WND* pWnd )
2356 WND *tmpWnd = WIN_LockWndPtr(pWnd);
2358 while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
2360 WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
2362 return tmpWnd;
2365 /*****************************************************************
2366 * WIN_GetTopParent
2368 * Get the top-level parent for a child window.
2370 HWND WIN_GetTopParent( HWND hwnd )
2372 HWND retvalue;
2373 WND *tmpPtr = WIN_FindWndPtr(hwnd);
2374 WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
2376 retvalue = wndPtr ? wndPtr->hwndSelf : 0;
2377 WIN_ReleaseWndPtr(tmpPtr);
2378 WIN_ReleaseWndPtr(wndPtr);
2379 return retvalue;
2383 /*****************************************************************
2384 * SetParent16 (USER.233)
2386 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
2388 return SetParent( hwndChild, hwndNewParent );
2392 /*****************************************************************
2393 * SetParent32 (USER32.495)
2395 HWND WINAPI SetParent( HWND hwndChild, HWND hwndNewParent )
2397 WND *wndPtr;
2398 DWORD dwStyle;
2399 WND *pWndNewParent;
2400 WND *pWndOldParent;
2401 HWND retvalue;
2404 if(!(wndPtr = WIN_FindWndPtr(hwndChild))) return 0;
2406 dwStyle = wndPtr->dwStyle;
2408 pWndNewParent = hwndNewParent ? WIN_FindWndPtr(hwndNewParent)
2409 : WIN_LockWndPtr(pWndDesktop);
2411 /* Windows hides the window first, then shows it again
2412 * including the WM_SHOWWINDOW messages and all */
2413 if (dwStyle & WS_VISIBLE)
2414 ShowWindow( hwndChild, SW_HIDE );
2416 pWndOldParent = WIN_LockWndPtr((*wndPtr->pDriver->pSetParent)(wndPtr, pWndNewParent));
2418 /* SetParent32 additionally needs to make hwndChild the topmost window
2419 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2420 WM_WINDOWPOSCHANGED notification messages.
2422 SetWindowPos( hwndChild, HWND_TOPMOST, 0, 0, 0, 0,
2423 SWP_NOMOVE|SWP_NOSIZE|((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2424 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2425 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2427 retvalue = pWndOldParent?pWndOldParent->hwndSelf:0;
2429 WIN_ReleaseWndPtr(pWndOldParent);
2430 WIN_ReleaseWndPtr(pWndNewParent);
2431 WIN_ReleaseWndPtr(wndPtr);
2433 return retvalue;
2437 /*******************************************************************
2438 * IsChild16 (USER.48)
2440 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2442 return IsChild(parent,child);
2446 /*******************************************************************
2447 * IsChild32 (USER32.339)
2449 BOOL WINAPI IsChild( HWND parent, HWND child )
2451 WND * wndPtr = WIN_FindWndPtr( child );
2452 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2454 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2455 if (wndPtr->hwndSelf == parent)
2457 WIN_ReleaseWndPtr(wndPtr);
2458 return TRUE;
2461 WIN_ReleaseWndPtr(wndPtr);
2462 return FALSE;
2466 /***********************************************************************
2467 * IsWindowVisible16 (USER.49)
2469 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2471 return IsWindowVisible(hwnd);
2475 /***********************************************************************
2476 * IsWindowVisible32 (USER32.351)
2478 BOOL WINAPI IsWindowVisible( HWND hwnd )
2480 BOOL retval;
2481 WND *wndPtr = WIN_FindWndPtr( hwnd );
2482 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2484 if (!(wndPtr->dwStyle & WS_VISIBLE))
2486 WIN_ReleaseWndPtr(wndPtr);
2487 return FALSE;
2489 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
2491 retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2492 WIN_ReleaseWndPtr(wndPtr);
2493 return retval;
2498 /***********************************************************************
2499 * WIN_IsWindowDrawable
2501 * hwnd is drawable when it is visible, all parents are not
2502 * minimized, and it is itself not minimized unless we are
2503 * trying to draw its default class icon.
2505 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2507 if( (wnd->dwStyle & WS_MINIMIZE &&
2508 icon && wnd->class->hIcon) ||
2509 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2510 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2511 if( wnd->dwStyle & WS_MINIMIZE ||
2512 !(wnd->dwStyle & WS_VISIBLE) ) break;
2513 return (wnd == NULL);
2517 /*******************************************************************
2518 * GetTopWindow16 (USER.229)
2520 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2522 return GetTopWindow(hwnd);
2526 /*******************************************************************
2527 * GetTopWindow32 (USER.229)
2529 HWND WINAPI GetTopWindow( HWND hwnd )
2531 HWND retval;
2532 WND * wndPtr = WIN_FindWndPtr( hwnd );
2533 if (wndPtr && wndPtr->child)
2535 retval = wndPtr->child->hwndSelf;
2537 else retval = 0;
2538 WIN_ReleaseWndPtr(wndPtr);
2539 return retval;
2543 /*******************************************************************
2544 * GetWindow16 (USER.262)
2546 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2548 return GetWindow( hwnd,rel );
2552 /*******************************************************************
2553 * GetWindow32 (USER32.302)
2555 HWND WINAPI GetWindow( HWND hwnd, WORD rel )
2557 HWND retval;
2559 WND * wndPtr = WIN_FindWndPtr( hwnd );
2560 if (!wndPtr) return 0;
2561 switch(rel)
2563 case GW_HWNDFIRST:
2564 if (wndPtr->parent) retval = wndPtr->parent->child->hwndSelf;
2565 else retval = 0;
2566 goto end;
2568 case GW_HWNDLAST:
2569 if (!wndPtr->parent)
2571 retval = 0; /* Desktop window */
2572 goto end;
2574 while (wndPtr->next)
2576 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2578 retval = wndPtr->hwndSelf;
2579 goto end;
2581 case GW_HWNDNEXT:
2582 if (!wndPtr->next) retval = 0;
2583 else retval = wndPtr->next->hwndSelf;
2584 goto end;
2586 case GW_HWNDPREV:
2587 if (!wndPtr->parent)
2589 retval = 0; /* Desktop window */
2590 goto end;
2592 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */
2593 if (wndPtr->hwndSelf == hwnd)
2595 retval = 0; /* First in list */
2596 goto end;
2598 while (wndPtr->next)
2600 if (wndPtr->next->hwndSelf == hwnd)
2602 retval = wndPtr->hwndSelf;
2603 goto end;
2605 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2607 retval = 0;
2608 goto end;
2610 case GW_OWNER:
2611 retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2612 goto end;
2614 case GW_CHILD:
2615 retval = wndPtr->child ? wndPtr->child->hwndSelf : 0;
2616 goto end;
2618 retval = 0;
2619 end:
2620 WIN_ReleaseWndPtr(wndPtr);
2621 return retval;
2625 /*******************************************************************
2626 * GetNextWindow16 (USER.230)
2628 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2630 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2631 return GetWindow16( hwnd, flag );
2634 /*******************************************************************
2635 * ShowOwnedPopups16 (USER.265)
2637 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2639 ShowOwnedPopups( owner, fShow );
2643 /*******************************************************************
2644 * ShowOwnedPopups32 (USER32.531)
2646 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2648 WND *pWnd;
2649 pWnd = WIN_LockWndPtr(pWndDesktop->child);
2650 while (pWnd)
2652 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2653 (pWnd->dwStyle & WS_POPUP))
2654 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2655 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2657 return TRUE;
2661 /*******************************************************************
2662 * GetLastActivePopup16 (USER.287)
2664 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2666 return GetLastActivePopup( hwnd );
2669 /*******************************************************************
2670 * GetLastActivePopup32 (USER32.256)
2672 HWND WINAPI GetLastActivePopup( HWND hwnd )
2674 WND *wndPtr;
2675 HWND retval;
2676 wndPtr = WIN_FindWndPtr(hwnd);
2677 if (!wndPtr) return hwnd;
2678 retval = wndPtr->hwndLastActive;
2679 WIN_ReleaseWndPtr(wndPtr);
2680 return retval;
2684 /*******************************************************************
2685 * WIN_BuildWinArray
2687 * Build an array of pointers to the children of a given window.
2688 * The array must be freed with HeapFree(SystemHeap). Return NULL
2689 * when no windows are found.
2691 WND **WIN_BuildWinArray( WND *wndPtr, UINT bwaFlags, UINT* pTotal )
2693 /* Future : this function will lock all windows associated with this array */
2695 WND **list, **ppWnd;
2696 WND *pWnd;
2697 UINT count = 0, skipOwned, skipHidden;
2698 DWORD skipFlags;
2700 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2701 skipOwned = bwaFlags & BWA_SKIPOWNED;
2702 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2703 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2705 /* First count the windows */
2707 if (!wndPtr)
2708 wndPtr = WIN_GetDesktop();
2710 pWnd = WIN_LockWndPtr(wndPtr->child);
2711 while (pWnd)
2713 if( !(pWnd->dwStyle & skipFlags) && !(skipOwned && pWnd->owner) &&
2714 (!skipHidden || (pWnd->dwStyle & WS_VISIBLE)) )
2715 count++;
2716 WIN_UpdateWndPtr(&pWnd,pWnd->next);
2719 if( count )
2721 /* Now build the list of all windows */
2723 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2725 for (pWnd = WIN_LockWndPtr(wndPtr->child), ppWnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
2727 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) );
2728 else if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2730 *ppWnd++ = pWnd;
2731 count++;
2734 WIN_ReleaseWndPtr(pWnd);
2735 *ppWnd = NULL;
2737 else count = 0;
2738 } else list = NULL;
2740 if( pTotal ) *pTotal = count;
2741 return list;
2743 /*******************************************************************
2744 * WIN_ReleaseWinArray
2746 void WIN_ReleaseWinArray(WND **wndArray)
2748 /* Future : this function will also unlock all windows associated with wndArray */
2749 HeapFree( SystemHeap, 0, wndArray );
2753 /*******************************************************************
2754 * EnumWindows16 (USER.54)
2756 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2758 WND **list, **ppWnd;
2760 /* We have to build a list of all windows first, to avoid */
2761 /* unpleasant side-effects, for instance if the callback */
2762 /* function changes the Z-order of the windows. */
2764 if (!(list = WIN_BuildWinArray(WIN_GetDesktop(), 0, NULL )))
2766 WIN_ReleaseDesktop();
2767 return FALSE;
2770 /* Now call the callback function for every window */
2772 for (ppWnd = list; *ppWnd; ppWnd++)
2774 LRESULT lpEnumFuncRetval;
2775 int iWndsLocks = 0;
2776 /* Make sure that the window still exists */
2777 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2779 /* To avoid any deadlocks, all the locks on the windows
2780 structures must be suspended before the control
2781 is passed to the application */
2782 iWndsLocks = WIN_SuspendWndsLock();
2783 lpEnumFuncRetval = lpEnumFunc( (*ppWnd)->hwndSelf, lParam);
2784 WIN_RestoreWndsLock(iWndsLocks);
2786 if (!lpEnumFuncRetval) break;
2788 WIN_ReleaseWinArray(list);
2789 WIN_ReleaseDesktop();
2790 return TRUE;
2794 /*******************************************************************
2795 * EnumWindows32 (USER32.193)
2797 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2799 return (BOOL)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2803 /**********************************************************************
2804 * EnumTaskWindows16 (USER.225)
2806 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2807 LPARAM lParam )
2809 WND **list, **ppWnd;
2811 /* This function is the same as EnumWindows(), */
2812 /* except for an added check on the window's task. */
2814 if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
2816 WIN_ReleaseDesktop();
2817 return FALSE;
2820 /* Now call the callback function for every window */
2822 for (ppWnd = list; *ppWnd; ppWnd++)
2824 LRESULT funcRetval;
2825 int iWndsLocks = 0;
2826 /* Make sure that the window still exists */
2827 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2828 if (QUEUE_GetQueueTask((*ppWnd)->hmemTaskQ) != hTask) continue;
2830 /* To avoid any deadlocks, all the locks on the windows
2831 structures must be suspended before the control
2832 is passed to the application */
2833 iWndsLocks = WIN_SuspendWndsLock();
2834 funcRetval = func( (*ppWnd)->hwndSelf, lParam );
2835 WIN_RestoreWndsLock(iWndsLocks);
2837 if (!funcRetval) break;
2839 WIN_ReleaseWinArray(list);
2840 WIN_ReleaseDesktop();
2841 return TRUE;
2845 /**********************************************************************
2846 * EnumThreadWindows (USER32.190)
2848 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2850 THDB *tdb = THREAD_IdToTHDB(id);
2852 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2856 /**********************************************************************
2857 * WIN_EnumChildWindows
2859 * Helper function for EnumChildWindows().
2861 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2862 LPARAM lParam )
2864 WND **childList;
2865 BOOL16 ret = FALSE;
2867 for ( ; *ppWnd; ppWnd++)
2869 int iWndsLocks = 0;
2871 /* Make sure that the window still exists */
2872 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
2873 /* Build children list first */
2874 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2876 /* To avoid any deadlocks, all the locks on the windows
2877 structures must be suspended before the control
2878 is passed to the application */
2879 iWndsLocks = WIN_SuspendWndsLock();
2880 ret = func( (*ppWnd)->hwndSelf, lParam );
2881 WIN_RestoreWndsLock(iWndsLocks);
2883 if (childList)
2885 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2886 WIN_ReleaseWinArray(childList);
2888 if (!ret) return FALSE;
2890 return TRUE;
2894 /**********************************************************************
2895 * EnumChildWindows16 (USER.55)
2897 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2898 LPARAM lParam )
2900 WND **list, *pParent;
2902 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2903 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL )))
2905 WIN_ReleaseWndPtr(pParent);
2906 return FALSE;
2908 WIN_EnumChildWindows( list, func, lParam );
2909 WIN_ReleaseWinArray(list);
2910 WIN_ReleaseWndPtr(pParent);
2911 return TRUE;
2915 /**********************************************************************
2916 * EnumChildWindows32 (USER32.178)
2918 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func,
2919 LPARAM lParam )
2921 return (BOOL)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2922 lParam );
2926 /*******************************************************************
2927 * AnyPopup16 (USER.52)
2929 BOOL16 WINAPI AnyPopup16(void)
2931 return AnyPopup();
2935 /*******************************************************************
2936 * AnyPopup32 (USER32.4)
2938 BOOL WINAPI AnyPopup(void)
2940 WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
2941 BOOL retvalue;
2943 while (wndPtr)
2945 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
2947 retvalue = TRUE;
2948 goto end;
2950 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
2952 retvalue = FALSE;
2953 end:
2954 WIN_ReleaseWndPtr(wndPtr);
2955 return retvalue;
2959 /*******************************************************************
2960 * FlashWindow16 (USER.105)
2962 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2964 return FlashWindow( hWnd, bInvert );
2968 /*******************************************************************
2969 * FlashWindow32 (USER32.202)
2971 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2973 WND *wndPtr = WIN_FindWndPtr(hWnd);
2975 TRACE_(win)("%04x\n", hWnd);
2977 if (!wndPtr) return FALSE;
2979 if (wndPtr->dwStyle & WS_MINIMIZE)
2981 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2983 HDC hDC = GetDC(hWnd);
2985 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2986 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2988 ReleaseDC( hWnd, hDC );
2989 wndPtr->flags |= WIN_NCACTIVATED;
2991 else
2993 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2994 RDW_UPDATENOW | RDW_FRAME, 0 );
2995 wndPtr->flags &= ~WIN_NCACTIVATED;
2997 WIN_ReleaseWndPtr(wndPtr);
2998 return TRUE;
3000 else
3002 WPARAM16 wparam;
3003 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3004 else wparam = (hWnd == GetActiveWindow());
3006 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3007 WIN_ReleaseWndPtr(wndPtr);
3008 return wparam;
3013 /*******************************************************************
3014 * SetSysModalWindow16 (USER.188)
3016 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
3018 HWND hWndOldModal = hwndSysModal;
3019 hwndSysModal = hWnd;
3020 FIXME_(win)("EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
3021 return hWndOldModal;
3025 /*******************************************************************
3026 * GetSysModalWindow16 (USER.52)
3028 HWND16 WINAPI GetSysModalWindow16(void)
3030 return hwndSysModal;
3034 /*******************************************************************
3035 * GetWindowContextHelpId (USER32.303)
3037 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3039 DWORD retval;
3040 WND *wnd = WIN_FindWndPtr( hwnd );
3041 if (!wnd) return 0;
3042 retval = wnd->helpContext;
3043 WIN_ReleaseWndPtr(wnd);
3044 return retval;
3048 /*******************************************************************
3049 * SetWindowContextHelpId (USER32.515)
3051 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3053 WND *wnd = WIN_FindWndPtr( hwnd );
3054 if (!wnd) return FALSE;
3055 wnd->helpContext = id;
3056 WIN_ReleaseWndPtr(wnd);
3057 return TRUE;
3061 /*******************************************************************
3062 * DRAG_QueryUpdate
3064 * recursively find a child that contains spDragInfo->pt point
3065 * and send WM_QUERYDROPOBJECT
3067 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3069 BOOL16 wParam,bResult = 0;
3070 POINT pt;
3071 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
3072 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
3073 RECT tempRect;
3075 if( !ptrQueryWnd || !ptrDragInfo )
3077 WIN_ReleaseWndPtr(ptrQueryWnd);
3078 return 0;
3081 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3083 GetWindowRect(hQueryWnd,&tempRect);
3085 if( !PtInRect(&tempRect,pt) ||
3086 (ptrQueryWnd->dwStyle & WS_DISABLED) )
3088 WIN_ReleaseWndPtr(ptrQueryWnd);
3089 return 0;
3092 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
3094 tempRect = ptrQueryWnd->rectClient;
3095 if(ptrQueryWnd->dwStyle & WS_CHILD)
3096 MapWindowPoints( ptrQueryWnd->parent->hwndSelf, 0,
3097 (LPPOINT)&tempRect, 2 );
3099 if (PtInRect( &tempRect, pt))
3101 wParam = 0;
3103 for (ptrWnd = WIN_LockWndPtr(ptrQueryWnd->child); ptrWnd ;WIN_UpdateWndPtr(&ptrWnd,ptrWnd->next))
3105 if( ptrWnd->dwStyle & WS_VISIBLE )
3107 GetWindowRect( ptrWnd->hwndSelf, &tempRect );
3108 if (PtInRect( &tempRect, pt )) break;
3112 if(ptrWnd)
3114 TRACE_(msg)("hwnd = %04x, %d %d - %d %d\n",
3115 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
3116 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
3117 if( !(ptrWnd->dwStyle & WS_DISABLED) )
3118 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
3120 WIN_ReleaseWndPtr(ptrWnd);
3123 if(bResult)
3125 WIN_ReleaseWndPtr(ptrQueryWnd);
3126 return bResult;
3129 else wParam = 1;
3131 else wParam = 1;
3133 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3135 ptrDragInfo->hScope = hQueryWnd;
3137 bResult = ( bNoSend )
3138 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
3139 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
3140 (WPARAM16)wParam ,(LPARAM) spDragInfo );
3141 if( !bResult )
3142 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3144 WIN_ReleaseWndPtr(ptrQueryWnd);
3145 return bResult;
3149 /*******************************************************************
3150 * DragDetect (USER.465)
3152 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
3154 POINT pt32;
3155 CONV_POINT16TO32( &pt, &pt32 );
3156 return DragDetect( hWnd, pt32 );
3159 /*******************************************************************
3160 * DragDetect32 (USER32.151)
3162 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3164 MSG16 msg;
3165 RECT16 rect;
3167 rect.left = pt.x - wDragWidth;
3168 rect.right = pt.x + wDragWidth;
3170 rect.top = pt.y - wDragHeight;
3171 rect.bottom = pt.y + wDragHeight;
3173 SetCapture(hWnd);
3175 while(1)
3177 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3179 if( msg.message == WM_LBUTTONUP )
3181 ReleaseCapture();
3182 return 0;
3184 if( msg.message == WM_MOUSEMOVE )
3186 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
3188 ReleaseCapture();
3189 return 1;
3193 WaitMessage();
3195 return 0;
3198 /******************************************************************************
3199 * DragObject16 (USER.464)
3201 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3202 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3204 MSG16 msg;
3205 LPDRAGINFO lpDragInfo;
3206 SEGPTR spDragInfo;
3207 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3208 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
3209 WND *wndPtr = WIN_FindWndPtr(hWnd);
3210 HCURSOR16 hCurrentCursor = 0;
3211 HWND16 hCurrentWnd = 0;
3213 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
3214 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
3216 if( !lpDragInfo || !spDragInfo )
3218 WIN_ReleaseWndPtr(wndPtr);
3219 return 0L;
3222 hBummer = LoadCursor16(0, IDC_BUMMER16);
3224 if( !hBummer || !wndPtr )
3226 GlobalFree16(hDragInfo);
3227 WIN_ReleaseWndPtr(wndPtr);
3228 return 0L;
3231 if(hCursor)
3233 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3235 GlobalFree16(hDragInfo);
3236 WIN_ReleaseWndPtr(wndPtr);
3237 return 0L;
3240 if( hDragCursor == hCursor ) hDragCursor = 0;
3241 else hCursor = hDragCursor;
3243 hOldCursor = SetCursor(hDragCursor);
3246 lpDragInfo->hWnd = hWnd;
3247 lpDragInfo->hScope = 0;
3248 lpDragInfo->wFlags = wObj;
3249 lpDragInfo->hList = szList; /* near pointer! */
3250 lpDragInfo->hOfStruct = hOfStruct;
3251 lpDragInfo->l = 0L;
3253 SetCapture(hWnd);
3254 ShowCursor( TRUE );
3258 do{ WaitMessage(); }
3259 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
3261 *(lpDragInfo+1) = *lpDragInfo;
3263 lpDragInfo->pt = msg.pt;
3265 /* update DRAGINFO struct */
3266 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3268 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3269 hCurrentCursor = hCursor;
3270 else
3272 hCurrentCursor = hBummer;
3273 lpDragInfo->hScope = 0;
3275 if( hCurrentCursor )
3276 SetCursor(hCurrentCursor);
3278 /* send WM_DRAGLOOP */
3279 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3280 (LPARAM) spDragInfo );
3281 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3282 if( hCurrentWnd != lpDragInfo->hScope )
3284 if( hCurrentWnd )
3285 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3286 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
3287 HIWORD(spDragInfo)) );
3288 hCurrentWnd = lpDragInfo->hScope;
3289 if( hCurrentWnd )
3290 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3292 else
3293 if( hCurrentWnd )
3294 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3296 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3298 ReleaseCapture();
3299 ShowCursor( FALSE );
3301 if( hCursor )
3303 SetCursor( hOldCursor );
3304 if (hDragCursor) DestroyCursor( hDragCursor );
3307 if( hCurrentCursor != hBummer )
3308 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3309 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3310 else
3311 msg.lParam = 0;
3312 GlobalFree16(hDragInfo);
3313 WIN_ReleaseWndPtr(wndPtr);
3315 return (DWORD)(msg.lParam);